diff options
author | Tomasz Figa <t.figa@samsung.com> | 2012-12-10 23:58:43 -0500 |
---|---|---|
committer | Kukjin Kim <kgene.kim@samsung.com> | 2013-04-08 12:52:30 -0400 |
commit | beddf63fc8e01f06799bd6d7a2dd879885bbc9c6 (patch) | |
tree | 449ab2a2f4298d7c79285d3830a2cdb73833a040 /arch | |
parent | 41de89860baf8e62fd74e83338058575398ad21f (diff) |
ARM: EXYNOS: Add secure firmware support to secondary CPU bring-up
Boards using secure firmware must use different CPU boot registers and
call secure firmware to boot the CPU.
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-exynos/platsmp.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index 60f7c5be057d..a083e0591a56 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/cacheflush.h> | 25 | #include <asm/cacheflush.h> |
26 | #include <asm/smp_plat.h> | 26 | #include <asm/smp_plat.h> |
27 | #include <asm/smp_scu.h> | 27 | #include <asm/smp_scu.h> |
28 | #include <asm/firmware.h> | ||
28 | 29 | ||
29 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
30 | #include <mach/regs-clock.h> | 31 | #include <mach/regs-clock.h> |
@@ -145,10 +146,21 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct | |||
145 | 146 | ||
146 | timeout = jiffies + (1 * HZ); | 147 | timeout = jiffies + (1 * HZ); |
147 | while (time_before(jiffies, timeout)) { | 148 | while (time_before(jiffies, timeout)) { |
149 | unsigned long boot_addr; | ||
150 | |||
148 | smp_rmb(); | 151 | smp_rmb(); |
149 | 152 | ||
150 | __raw_writel(virt_to_phys(exynos4_secondary_startup), | 153 | boot_addr = virt_to_phys(exynos4_secondary_startup); |
151 | cpu_boot_reg(phys_cpu)); | 154 | |
155 | /* | ||
156 | * Try to set boot address using firmware first | ||
157 | * and fall back to boot register if it fails. | ||
158 | */ | ||
159 | if (call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr)) | ||
160 | __raw_writel(boot_addr, cpu_boot_reg(phys_cpu)); | ||
161 | |||
162 | call_firmware_op(cpu_boot, phys_cpu); | ||
163 | |||
152 | arch_send_wakeup_ipi_mask(cpumask_of(cpu)); | 164 | arch_send_wakeup_ipi_mask(cpumask_of(cpu)); |
153 | 165 | ||
154 | if (pen_release == -1) | 166 | if (pen_release == -1) |
@@ -204,10 +216,20 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) | |||
204 | * system-wide flags register. The boot monitor waits | 216 | * system-wide flags register. The boot monitor waits |
205 | * until it receives a soft interrupt, and then the | 217 | * until it receives a soft interrupt, and then the |
206 | * secondary CPU branches to this address. | 218 | * secondary CPU branches to this address. |
219 | * | ||
220 | * Try using firmware operation first and fall back to | ||
221 | * boot register if it fails. | ||
207 | */ | 222 | */ |
208 | for (i = 1; i < max_cpus; ++i) | 223 | for (i = 1; i < max_cpus; ++i) { |
209 | __raw_writel(virt_to_phys(exynos4_secondary_startup), | 224 | unsigned long phys_cpu; |
210 | cpu_boot_reg(cpu_logical_map(i))); | 225 | unsigned long boot_addr; |
226 | |||
227 | phys_cpu = cpu_logical_map(i); | ||
228 | boot_addr = virt_to_phys(exynos4_secondary_startup); | ||
229 | |||
230 | if (call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr)) | ||
231 | __raw_writel(boot_addr, cpu_boot_reg(phys_cpu)); | ||
232 | } | ||
211 | } | 233 | } |
212 | 234 | ||
213 | struct smp_operations exynos_smp_ops __initdata = { | 235 | struct smp_operations exynos_smp_ops __initdata = { |