diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-04 15:33:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-04 15:33:36 -0400 |
commit | e3d98847ded1d183111ff7c4d1ef56b161c7f13e (patch) | |
tree | 8ec2b298eef4f1695ca612014b7f75b85badae45 /arch/arm/mach-exynos/platsmp.c | |
parent | 22b154365fbc096a46d936ec1f462ef8b9bd1f05 (diff) | |
parent | 721e0205b07589223343737a9c421d8118d87bba (diff) |
Merge tag 'firmware-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM platform specific firmware interfaces from Olof Johansson:
"Two platforms, bcm and exynos have their own firmware interfaces using
the "secure monitor call", this adds support for those.
We had originally planned to have a third set of patches in here,
which would extend support for the existing generic "psci" call that
is used on multiple platforms as well as Xen and KVM guests, but that
ended up getting dropped because the patches were not ready in time."
* tag 'firmware-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc:
ARM: bcm: mark bcm_kona_smc_init as __init
ARM: bcm281xx: Add DT support for SMC handler
ARM: bcm281xx: Add L2 cache enable code
ARM: EXYNOS: Add secure firmware support to secondary CPU bring-up
ARM: EXYNOS: Add IO mapping for non-secure SYSRAM.
ARM: EXYNOS: Add support for Exynos secure firmware
ARM: EXYNOS: Add support for secure monitor calls
ARM: Add interface for registering and calling firmware-specific operations
Diffstat (limited to 'arch/arm/mach-exynos/platsmp.c')
-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 95e04bd5813f..a0e8ff7758a4 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/cacheflush.h> | 24 | #include <asm/cacheflush.h> |
25 | #include <asm/smp_plat.h> | 25 | #include <asm/smp_plat.h> |
26 | #include <asm/smp_scu.h> | 26 | #include <asm/smp_scu.h> |
27 | #include <asm/firmware.h> | ||
27 | 28 | ||
28 | #include <mach/hardware.h> | 29 | #include <mach/hardware.h> |
29 | #include <mach/regs-clock.h> | 30 | #include <mach/regs-clock.h> |
@@ -137,10 +138,21 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct | |||
137 | 138 | ||
138 | timeout = jiffies + (1 * HZ); | 139 | timeout = jiffies + (1 * HZ); |
139 | while (time_before(jiffies, timeout)) { | 140 | while (time_before(jiffies, timeout)) { |
141 | unsigned long boot_addr; | ||
142 | |||
140 | smp_rmb(); | 143 | smp_rmb(); |
141 | 144 | ||
142 | __raw_writel(virt_to_phys(exynos4_secondary_startup), | 145 | boot_addr = virt_to_phys(exynos4_secondary_startup); |
143 | cpu_boot_reg(phys_cpu)); | 146 | |
147 | /* | ||
148 | * Try to set boot address using firmware first | ||
149 | * and fall back to boot register if it fails. | ||
150 | */ | ||
151 | if (call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr)) | ||
152 | __raw_writel(boot_addr, cpu_boot_reg(phys_cpu)); | ||
153 | |||
154 | call_firmware_op(cpu_boot, phys_cpu); | ||
155 | |||
144 | arch_send_wakeup_ipi_mask(cpumask_of(cpu)); | 156 | arch_send_wakeup_ipi_mask(cpumask_of(cpu)); |
145 | 157 | ||
146 | if (pen_release == -1) | 158 | if (pen_release == -1) |
@@ -196,10 +208,20 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) | |||
196 | * system-wide flags register. The boot monitor waits | 208 | * system-wide flags register. The boot monitor waits |
197 | * until it receives a soft interrupt, and then the | 209 | * until it receives a soft interrupt, and then the |
198 | * secondary CPU branches to this address. | 210 | * secondary CPU branches to this address. |
211 | * | ||
212 | * Try using firmware operation first and fall back to | ||
213 | * boot register if it fails. | ||
199 | */ | 214 | */ |
200 | for (i = 1; i < max_cpus; ++i) | 215 | for (i = 1; i < max_cpus; ++i) { |
201 | __raw_writel(virt_to_phys(exynos4_secondary_startup), | 216 | unsigned long phys_cpu; |
202 | cpu_boot_reg(cpu_logical_map(i))); | 217 | unsigned long boot_addr; |
218 | |||
219 | phys_cpu = cpu_logical_map(i); | ||
220 | boot_addr = virt_to_phys(exynos4_secondary_startup); | ||
221 | |||
222 | if (call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr)) | ||
223 | __raw_writel(boot_addr, cpu_boot_reg(phys_cpu)); | ||
224 | } | ||
203 | } | 225 | } |
204 | 226 | ||
205 | struct smp_operations exynos_smp_ops __initdata = { | 227 | struct smp_operations exynos_smp_ops __initdata = { |