0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/init.h>
0011 #include <linux/errno.h>
0012 #include <linux/delay.h>
0013 #include <linux/device.h>
0014 #include <linux/smp.h>
0015 #include <linux/io.h>
0016 #include <linux/of.h>
0017 #include <linux/of_address.h>
0018
0019 #include <asm/cacheflush.h>
0020 #include <asm/smp_plat.h>
0021 #include <asm/smp_scu.h>
0022
0023 #include "db8500-regs.h"
0024
0025
0026 #define UX500_CPU1_JUMPADDR_OFFSET 0x1FF4
0027 #define UX500_CPU1_WAKEMAGIC_OFFSET 0x1FF0
0028
0029 static void __iomem *backupram;
0030
0031 static void __init ux500_smp_prepare_cpus(unsigned int max_cpus)
0032 {
0033 struct device_node *np;
0034 static void __iomem *scu_base;
0035 unsigned int ncores;
0036 int i;
0037
0038 np = of_find_compatible_node(NULL, NULL, "ste,dbx500-backupram");
0039 if (!np) {
0040 pr_err("No backupram base address\n");
0041 return;
0042 }
0043 backupram = of_iomap(np, 0);
0044 of_node_put(np);
0045 if (!backupram) {
0046 pr_err("No backupram remap\n");
0047 return;
0048 }
0049
0050 np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
0051 if (!np) {
0052 pr_err("No SCU base address\n");
0053 return;
0054 }
0055 scu_base = of_iomap(np, 0);
0056 of_node_put(np);
0057 if (!scu_base) {
0058 pr_err("No SCU remap\n");
0059 return;
0060 }
0061
0062 scu_enable(scu_base);
0063 ncores = scu_get_core_count(scu_base);
0064 for (i = 0; i < ncores; i++)
0065 set_cpu_possible(i, true);
0066 iounmap(scu_base);
0067 }
0068
0069 static int ux500_boot_secondary(unsigned int cpu, struct task_struct *idle)
0070 {
0071
0072
0073
0074
0075
0076
0077 writel(__pa_symbol(secondary_startup),
0078 backupram + UX500_CPU1_JUMPADDR_OFFSET);
0079 writel(0xA1FEED01,
0080 backupram + UX500_CPU1_WAKEMAGIC_OFFSET);
0081
0082
0083 mb();
0084 arch_send_wakeup_ipi_mask(cpumask_of(cpu));
0085 return 0;
0086 }
0087
0088 #ifdef CONFIG_HOTPLUG_CPU
0089 static void ux500_cpu_die(unsigned int cpu)
0090 {
0091 wfi();
0092 }
0093 #endif
0094
0095 static const struct smp_operations ux500_smp_ops __initconst = {
0096 .smp_prepare_cpus = ux500_smp_prepare_cpus,
0097 .smp_boot_secondary = ux500_boot_secondary,
0098 #ifdef CONFIG_HOTPLUG_CPU
0099 .cpu_die = ux500_cpu_die,
0100 #endif
0101 };
0102 CPU_METHOD_OF_DECLARE(ux500_smp, "ste,dbx500-smp", &ux500_smp_ops);