root/arch/arm/mach-ux500/platsmp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ux500_smp_prepare_cpus
  2. ux500_boot_secondary
  3. ux500_cpu_die

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2002 ARM Ltd.
   4  * Copyright (C) 2008 STMicroelctronics.
   5  * Copyright (C) 2009 ST-Ericsson.
   6  * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
   7  *
   8  * This file is based on arm realview platform
   9  */
  10 #include <linux/init.h>
  11 #include <linux/errno.h>
  12 #include <linux/delay.h>
  13 #include <linux/device.h>
  14 #include <linux/smp.h>
  15 #include <linux/io.h>
  16 #include <linux/of.h>
  17 #include <linux/of_address.h>
  18 
  19 #include <asm/cacheflush.h>
  20 #include <asm/smp_plat.h>
  21 #include <asm/smp_scu.h>
  22 
  23 #include "db8500-regs.h"
  24 
  25 /* Magic triggers in backup RAM */
  26 #define UX500_CPU1_JUMPADDR_OFFSET 0x1FF4
  27 #define UX500_CPU1_WAKEMAGIC_OFFSET 0x1FF0
  28 
  29 static void __iomem *backupram;
  30 
  31 static void __init ux500_smp_prepare_cpus(unsigned int max_cpus)
  32 {
  33         struct device_node *np;
  34         static void __iomem *scu_base;
  35         unsigned int ncores;
  36         int i;
  37 
  38         np = of_find_compatible_node(NULL, NULL, "ste,dbx500-backupram");
  39         if (!np) {
  40                 pr_err("No backupram base address\n");
  41                 return;
  42         }
  43         backupram = of_iomap(np, 0);
  44         of_node_put(np);
  45         if (!backupram) {
  46                 pr_err("No backupram remap\n");
  47                 return;
  48         }
  49 
  50         np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
  51         if (!np) {
  52                 pr_err("No SCU base address\n");
  53                 return;
  54         }
  55         scu_base = of_iomap(np, 0);
  56         of_node_put(np);
  57         if (!scu_base) {
  58                 pr_err("No SCU remap\n");
  59                 return;
  60         }
  61 
  62         scu_enable(scu_base);
  63         ncores = scu_get_core_count(scu_base);
  64         for (i = 0; i < ncores; i++)
  65                 set_cpu_possible(i, true);
  66         iounmap(scu_base);
  67 }
  68 
  69 static int ux500_boot_secondary(unsigned int cpu, struct task_struct *idle)
  70 {
  71         /*
  72          * write the address of secondary startup into the backup ram register
  73          * at offset 0x1FF4, then write the magic number 0xA1FEED01 to the
  74          * backup ram register at offset 0x1FF0, which is what boot rom code
  75          * is waiting for. This will wake up the secondary core from WFE.
  76          */
  77         writel(__pa_symbol(secondary_startup),
  78                backupram + UX500_CPU1_JUMPADDR_OFFSET);
  79         writel(0xA1FEED01,
  80                backupram + UX500_CPU1_WAKEMAGIC_OFFSET);
  81 
  82         /* make sure write buffer is drained */
  83         mb();
  84         arch_send_wakeup_ipi_mask(cpumask_of(cpu));
  85         return 0;
  86 }
  87 
  88 #ifdef CONFIG_HOTPLUG_CPU
  89 void ux500_cpu_die(unsigned int cpu)
  90 {
  91         wfi();
  92 }
  93 #endif
  94 
  95 static const struct smp_operations ux500_smp_ops __initconst = {
  96         .smp_prepare_cpus       = ux500_smp_prepare_cpus,
  97         .smp_boot_secondary     = ux500_boot_secondary,
  98 #ifdef CONFIG_HOTPLUG_CPU
  99         .cpu_die                = ux500_cpu_die,
 100 #endif
 101 };
 102 CPU_METHOD_OF_DECLARE(ux500_smp, "ste,dbx500-smp", &ux500_smp_ops);

/* [<][>][^][v][top][bottom][index][help] */