aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMagnus Damm <damm@opensource.se>2013-07-31 14:38:18 -0400
committerSimon Horman <horms+renesas@verge.net.au>2013-08-06 05:07:25 -0400
commitcc61591e45c0457139ddd4cd7e57f75928acaaf2 (patch)
treeacce46776785425c7882c2f00731fa5d418c495e
parente9e7c4fbf468e205387b21463dddacfe44da2d9a (diff)
ARM: shmobile: Introduce per-CPU SMP boot / sleep code
Add per-CPU SMP boot / sleep code that can be used by all SoCs included in mach-shmobile. The boot code reads out the per-CPU MPIDR id value and matches it with the value stored for any CPU number, and if there is a match and the boot function is set as well then the boot function will be executed. The sleep code simply uses WFI and then jumps back to the boot code to see if anyone has asked to wake up that CPU, if not it will sleep again. Signed-off-by: Magnus Damm <damm@opensource.se> [horms+renesas@verge.net.au: Remove trailing whitespace] Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-rw-r--r--arch/arm/mach-shmobile/headsmp.S49
-rw-r--r--arch/arm/mach-shmobile/include/mach/common.h4
-rw-r--r--arch/arm/mach-shmobile/platsmp.c18
3 files changed, 71 insertions, 0 deletions
diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S
index 559d1ce5f57e..2940fc97da37 100644
--- a/arch/arm/mach-shmobile/headsmp.S
+++ b/arch/arm/mach-shmobile/headsmp.S
@@ -38,3 +38,52 @@ shmobile_boot_fn:
38 .globl shmobile_boot_arg 38 .globl shmobile_boot_arg
39shmobile_boot_arg: 39shmobile_boot_arg:
402: .space 4 402: .space 4
41
42/*
43 * Per-CPU SMP boot function/argument selection code based on MPIDR
44 */
45
46ENTRY(shmobile_smp_boot)
47 @ r0 = MPIDR_HWID_BITMASK
48 mrc p15, 0, r1, c0, c0, 5 @ r1 = MPIDR
49 and r0, r1, r0 @ r0 = cpu_logical_map() value
50 mov r1, #0 @ r1 = CPU index
51 adr r5, 1f @ array of per-cpu mpidr values
52 adr r6, 2f @ array of per-cpu functions
53 adr r7, 3f @ array of per-cpu arguments
54
55shmobile_smp_boot_find_mpidr:
56 ldr r8, [r5, r1, lsl #2]
57 cmp r8, r0
58 bne shmobile_smp_boot_next
59
60 ldr r9, [r6, r1, lsl #2]
61 cmp r9, #0
62 bne shmobile_smp_boot_found
63
64shmobile_smp_boot_next:
65 add r1, r1, #1
66 cmp r1, #CONFIG_NR_CPUS
67 blo shmobile_smp_boot_find_mpidr
68
69 b shmobile_smp_sleep
70
71shmobile_smp_boot_found:
72 ldr r0, [r7, r1, lsl #2]
73 mov pc, r9
74ENDPROC(shmobile_smp_boot)
75
76ENTRY(shmobile_smp_sleep)
77 wfi
78 b shmobile_smp_boot
79ENDPROC(shmobile_smp_sleep)
80
81 .globl shmobile_smp_mpidr
82shmobile_smp_mpidr:
831: .space CONFIG_NR_CPUS * 4
84 .globl shmobile_smp_fn
85shmobile_smp_fn:
862: .space CONFIG_NR_CPUS * 4
87 .globl shmobile_smp_arg
88shmobile_smp_arg:
893: .space CONFIG_NR_CPUS * 4
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index 04209d5c0338..3880cf54b2b3 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -10,6 +10,10 @@ extern void shmobile_setup_console(void);
10extern void shmobile_boot_vector(void); 10extern void shmobile_boot_vector(void);
11extern unsigned long shmobile_boot_fn; 11extern unsigned long shmobile_boot_fn;
12extern unsigned long shmobile_boot_arg; 12extern unsigned long shmobile_boot_arg;
13extern void shmobile_smp_boot(void);
14extern void shmobile_smp_sleep(void);
15extern void shmobile_smp_hook(unsigned int cpu, unsigned long fn,
16 unsigned long arg);
13extern void shmobile_boot_scu(void); 17extern void shmobile_boot_scu(void);
14extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus); 18extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus);
15extern int shmobile_smp_scu_boot_secondary(unsigned int cpu, 19extern int shmobile_smp_scu_boot_secondary(unsigned int cpu,
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
index 1f958d7b0bac..d4ae616bcedb 100644
--- a/arch/arm/mach-shmobile/platsmp.c
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -12,6 +12,9 @@
12 */ 12 */
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/smp.h> 14#include <linux/smp.h>
15#include <asm/cacheflush.h>
16#include <asm/smp_plat.h>
17#include <mach/common.h>
15 18
16void __init shmobile_smp_init_cpus(unsigned int ncores) 19void __init shmobile_smp_init_cpus(unsigned int ncores)
17{ 20{
@@ -26,3 +29,18 @@ void __init shmobile_smp_init_cpus(unsigned int ncores)
26 for (i = 0; i < ncores; i++) 29 for (i = 0; i < ncores; i++)
27 set_cpu_possible(i, true); 30 set_cpu_possible(i, true);
28} 31}
32
33extern unsigned long shmobile_smp_fn[];
34extern unsigned long shmobile_smp_arg[];
35extern unsigned long shmobile_smp_mpidr[];
36
37void shmobile_smp_hook(unsigned int cpu, unsigned long fn, unsigned long arg)
38{
39 shmobile_smp_fn[cpu] = 0;
40 flush_cache_all();
41
42 shmobile_smp_mpidr[cpu] = cpu_logical_map(cpu);
43 shmobile_smp_fn[cpu] = fn;
44 shmobile_smp_arg[cpu] = arg;
45 flush_cache_all();
46}