0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/init.h>
0014 #include <linux/errno.h>
0015 #include <linux/delay.h>
0016 #include <linux/smp.h>
0017 #include <linux/io.h>
0018 #include <linux/of.h>
0019 #include <linux/of_address.h>
0020 #include <linux/memblock.h>
0021
0022 #include <asm/cacheflush.h>
0023 #include <asm/smp_plat.h>
0024 #include <asm/smp_scu.h>
0025
0026 #include "smp.h"
0027
0028 static u32 __iomem *cpu_strt_ptr;
0029
0030 static int sti_boot_secondary(unsigned int cpu, struct task_struct *idle)
0031 {
0032 unsigned long entry_pa = __pa_symbol(secondary_startup);
0033
0034
0035
0036
0037
0038
0039
0040 __raw_writel(entry_pa, cpu_strt_ptr);
0041
0042
0043 smp_wmb();
0044 sync_cache_w(cpu_strt_ptr);
0045
0046 return 0;
0047 }
0048
0049 static void __init sti_smp_prepare_cpus(unsigned int max_cpus)
0050 {
0051 struct device_node *np;
0052 void __iomem *scu_base;
0053 u32 release_phys;
0054 int cpu;
0055
0056 np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
0057
0058 if (np) {
0059 scu_base = of_iomap(np, 0);
0060 scu_enable(scu_base);
0061 of_node_put(np);
0062 }
0063
0064 if (max_cpus <= 1)
0065 return;
0066
0067 for_each_possible_cpu(cpu) {
0068
0069 np = of_get_cpu_node(cpu, NULL);
0070
0071 if (!np)
0072 continue;
0073
0074 if (of_property_read_u32(np, "cpu-release-addr",
0075 &release_phys)) {
0076 pr_err("CPU %d: missing or invalid cpu-release-addr "
0077 "property\n", cpu);
0078 continue;
0079 }
0080
0081
0082
0083
0084
0085
0086 if (!memblock_is_memory(release_phys))
0087 cpu_strt_ptr =
0088 ioremap(release_phys, sizeof(release_phys));
0089 else
0090 cpu_strt_ptr =
0091 (u32 __iomem *)phys_to_virt(release_phys);
0092
0093 set_cpu_possible(cpu, true);
0094 }
0095 }
0096
0097 const struct smp_operations sti_smp_ops __initconst = {
0098 .smp_prepare_cpus = sti_smp_prepare_cpus,
0099 .smp_boot_secondary = sti_boot_secondary,
0100 };