diff options
Diffstat (limited to 'arch/arm/mach-sti/platsmp.c')
-rw-r--r-- | arch/arm/mach-sti/platsmp.c | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/arch/arm/mach-sti/platsmp.c b/arch/arm/mach-sti/platsmp.c index d4b624f8dfcb..c4ad6eae67fa 100644 --- a/arch/arm/mach-sti/platsmp.c +++ b/arch/arm/mach-sti/platsmp.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/of.h> | 21 | #include <linux/of.h> |
22 | #include <linux/of_address.h> | 22 | #include <linux/of_address.h> |
23 | #include <linux/memblock.h> | ||
23 | 24 | ||
24 | #include <asm/cacheflush.h> | 25 | #include <asm/cacheflush.h> |
25 | #include <asm/smp_plat.h> | 26 | #include <asm/smp_plat.h> |
@@ -38,8 +39,6 @@ static DEFINE_SPINLOCK(boot_lock); | |||
38 | 39 | ||
39 | static void sti_secondary_init(unsigned int cpu) | 40 | static void sti_secondary_init(unsigned int cpu) |
40 | { | 41 | { |
41 | trace_hardirqs_off(); | ||
42 | |||
43 | /* | 42 | /* |
44 | * let the primary processor know we're out of the | 43 | * let the primary processor know we're out of the |
45 | * pen, then head off into the C entry point | 44 | * pen, then head off into the C entry point |
@@ -99,14 +98,62 @@ static int sti_boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
99 | 98 | ||
100 | static void __init sti_smp_prepare_cpus(unsigned int max_cpus) | 99 | static void __init sti_smp_prepare_cpus(unsigned int max_cpus) |
101 | { | 100 | { |
102 | void __iomem *scu_base = NULL; | 101 | struct device_node *np; |
103 | struct device_node *np = of_find_compatible_node( | 102 | void __iomem *scu_base; |
104 | NULL, NULL, "arm,cortex-a9-scu"); | 103 | u32 __iomem *cpu_strt_ptr; |
104 | u32 release_phys; | ||
105 | int cpu; | ||
106 | unsigned long entry_pa = virt_to_phys(sti_secondary_startup); | ||
107 | |||
108 | np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu"); | ||
109 | |||
105 | if (np) { | 110 | if (np) { |
106 | scu_base = of_iomap(np, 0); | 111 | scu_base = of_iomap(np, 0); |
107 | scu_enable(scu_base); | 112 | scu_enable(scu_base); |
108 | of_node_put(np); | 113 | of_node_put(np); |
109 | } | 114 | } |
115 | |||
116 | if (max_cpus <= 1) | ||
117 | return; | ||
118 | |||
119 | for_each_possible_cpu(cpu) { | ||
120 | |||
121 | np = of_get_cpu_node(cpu, NULL); | ||
122 | |||
123 | if (!np) | ||
124 | continue; | ||
125 | |||
126 | if (of_property_read_u32(np, "cpu-release-addr", | ||
127 | &release_phys)) { | ||
128 | pr_err("CPU %d: missing or invalid cpu-release-addr " | ||
129 | "property\n", cpu); | ||
130 | continue; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * holding pen is usually configured in SBC DMEM but can also be | ||
135 | * in RAM. | ||
136 | */ | ||
137 | |||
138 | if (!memblock_is_memory(release_phys)) | ||
139 | cpu_strt_ptr = | ||
140 | ioremap(release_phys, sizeof(release_phys)); | ||
141 | else | ||
142 | cpu_strt_ptr = | ||
143 | (u32 __iomem *)phys_to_virt(release_phys); | ||
144 | |||
145 | __raw_writel(entry_pa, cpu_strt_ptr); | ||
146 | |||
147 | /* | ||
148 | * wmb so that data is actually written | ||
149 | * before cache flush is done | ||
150 | */ | ||
151 | smp_wmb(); | ||
152 | sync_cache_w(cpu_strt_ptr); | ||
153 | |||
154 | if (!memblock_is_memory(release_phys)) | ||
155 | iounmap(cpu_strt_ptr); | ||
156 | } | ||
110 | } | 157 | } |
111 | 158 | ||
112 | struct smp_operations __initdata sti_smp_ops = { | 159 | struct smp_operations __initdata sti_smp_ops = { |