diff options
-rw-r--r-- | arch/arm/mach-mvebu/coherency.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/coherency_ll.S | 92 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/headsmp.S | 6 |
3 files changed, 71 insertions, 35 deletions
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index 944372a18ed6..9d5ccd372712 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c | |||
@@ -60,8 +60,9 @@ static struct of_device_id of_coherency_table[] = { | |||
60 | { /* end of list */ }, | 60 | { /* end of list */ }, |
61 | }; | 61 | }; |
62 | 62 | ||
63 | /* Function defined in coherency_ll.S */ | 63 | /* Functions defined in coherency_ll.S */ |
64 | int ll_set_cpu_coherent(void); | 64 | int ll_enable_coherency(void); |
65 | void ll_add_cpu_to_smp_group(void); | ||
65 | 66 | ||
66 | int set_cpu_coherent(void) | 67 | int set_cpu_coherent(void) |
67 | { | 68 | { |
@@ -71,7 +72,8 @@ int set_cpu_coherent(void) | |||
71 | return 1; | 72 | return 1; |
72 | } | 73 | } |
73 | 74 | ||
74 | return ll_set_cpu_coherent(); | 75 | ll_add_cpu_to_smp_group(); |
76 | return ll_enable_coherency(); | ||
75 | } | 77 | } |
76 | 78 | ||
77 | /* | 79 | /* |
diff --git a/arch/arm/mach-mvebu/coherency_ll.S b/arch/arm/mach-mvebu/coherency_ll.S index 98a0b73f909b..f2e2e8677c4b 100644 --- a/arch/arm/mach-mvebu/coherency_ll.S +++ b/arch/arm/mach-mvebu/coherency_ll.S | |||
@@ -24,52 +24,84 @@ | |||
24 | #include <asm/cp15.h> | 24 | #include <asm/cp15.h> |
25 | 25 | ||
26 | .text | 26 | .text |
27 | 27 | /* Returns with the coherency address in r1 (r0 is untouched)*/ | |
28 | ENTRY(ll_set_cpu_coherent) | 28 | ENTRY(ll_get_coherency_base) |
29 | mrc p15, 0, r1, c1, c0, 0 | 29 | mrc p15, 0, r1, c1, c0, 0 |
30 | tst r1, #CR_M @ Check MMU bit enabled | 30 | tst r1, #CR_M @ Check MMU bit enabled |
31 | bne 1f | 31 | bne 1f |
32 | 32 | ||
33 | /* use physical address of the coherency register*/ | 33 | /* use physical address of the coherency register */ |
34 | adr r0, 3f | 34 | adr r1, 3f |
35 | ldr r3, [r0] | 35 | ldr r3, [r1] |
36 | ldr r0, [r0, r3] | 36 | ldr r1, [r1, r3] |
37 | b 2f | 37 | b 2f |
38 | 1: | 38 | 1: |
39 | /* use virtual address of the coherency register*/ | 39 | /* use virtual address of the coherency register */ |
40 | ldr r0, =coherency_base | 40 | ldr r1, =coherency_base |
41 | ldr r0, [r0] | 41 | ldr r1, [r1] |
42 | 2: | 42 | 2: |
43 | /* Create bit by cpu index */ | 43 | mov pc, lr |
44 | mrc 15, 0, r1, cr0, cr0, 5 | 44 | ENDPROC(ll_get_coherency_base) |
45 | and r1, r1, #15 | 45 | |
46 | /* Returns with the CPU ID in r3 (r0 is untouched)*/ | ||
47 | ENTRY(ll_get_cpuid) | ||
48 | mrc 15, 0, r3, cr0, cr0, 5 | ||
49 | and r3, r3, #15 | ||
46 | mov r2, #(1 << 24) | 50 | mov r2, #(1 << 24) |
47 | lsl r1, r2, r1 | 51 | lsl r3, r2, r3 |
48 | ARM_BE8(rev r1, r1) | 52 | ARM_BE8(rev r1, r1) |
53 | mov pc, lr | ||
54 | ENDPROC(ll_get_cpuid) | ||
49 | 55 | ||
50 | /* Add CPU to SMP group - Atomic */ | 56 | /* ll_add_cpu_to_smp_group, ll_enable_coherency and |
51 | add r3, r0, #ARMADA_XP_CFB_CTL_REG_OFFSET | 57 | * ll_disable_coherency use strex/ldrex whereas MMU can be off. The |
52 | 1: | 58 | * Armada XP SoC has an exclusive monitor that can track transactions |
53 | ldrex r2, [r3] | 59 | * to Device and/or SO and as such also when MMU is disabled the |
54 | orr r2, r2, r1 | 60 | * exclusive transactions will be functional |
55 | strex r0, r2, [r3] | 61 | */ |
56 | cmp r0, #0 | ||
57 | bne 1b | ||
58 | 62 | ||
59 | /* Enable coherency on CPU - Atomic */ | 63 | ENTRY(ll_add_cpu_to_smp_group) |
60 | add r3, r3, #ARMADA_XP_CFB_CFG_REG_OFFSET | 64 | /* |
65 | * r0 being untouched in ll_get_coherency_base and | ||
66 | * ll_get_cpuid, we can use it to save lr modifing it with the | ||
67 | * following bl | ||
68 | */ | ||
69 | mov r0, lr | ||
70 | bl ll_get_coherency_base | ||
71 | bl ll_get_cpuid | ||
72 | mov lr, r0 | ||
73 | add r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET | ||
61 | 1: | 74 | 1: |
62 | ldrex r2, [r3] | 75 | ldrex r2, [r0] |
63 | orr r2, r2, r1 | 76 | orr r2, r2, r3 |
64 | strex r0, r2, [r3] | 77 | strex r1, r2, [r0] |
65 | cmp r0, #0 | 78 | cmp r1, #0 |
66 | bne 1b | 79 | bne 1b |
80 | mov pc, lr | ||
81 | ENDPROC(ll_add_cpu_to_smp_group) | ||
67 | 82 | ||
83 | ENTRY(ll_enable_coherency) | ||
84 | /* | ||
85 | * r0 being untouched in ll_get_coherency_base and | ||
86 | * ll_get_cpuid, we can use it to save lr modifing it with the | ||
87 | * following bl | ||
88 | */ | ||
89 | mov r0, lr | ||
90 | bl ll_get_coherency_base | ||
91 | bl ll_get_cpuid | ||
92 | mov lr, r0 | ||
93 | add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET | ||
94 | 1: | ||
95 | ldrex r2, [r0] | ||
96 | orr r2, r2, r3 | ||
97 | strex r1, r2, [r0] | ||
98 | cmp r1, #0 | ||
99 | bne 1b | ||
68 | dsb | 100 | dsb |
69 | |||
70 | mov r0, #0 | 101 | mov r0, #0 |
71 | mov pc, lr | 102 | mov pc, lr |
72 | ENDPROC(ll_set_cpu_coherent) | 103 | ENDPROC(ll_enable_coherency) |
104 | |||
73 | 105 | ||
74 | .align 2 | 106 | .align 2 |
75 | 3: | 107 | 3: |
diff --git a/arch/arm/mach-mvebu/headsmp.S b/arch/arm/mach-mvebu/headsmp.S index cf7abe6554f7..2c4032e368ba 100644 --- a/arch/arm/mach-mvebu/headsmp.S +++ b/arch/arm/mach-mvebu/headsmp.S | |||
@@ -31,8 +31,10 @@ | |||
31 | ENTRY(armada_xp_secondary_startup) | 31 | ENTRY(armada_xp_secondary_startup) |
32 | ARM_BE8(setend be ) @ go BE8 if entered LE | 32 | ARM_BE8(setend be ) @ go BE8 if entered LE |
33 | 33 | ||
34 | /* Add CPU to coherency fabric */ | 34 | bl ll_add_cpu_to_smp_group |
35 | bl ll_set_cpu_coherent | 35 | |
36 | bl ll_enable_coherency | ||
37 | |||
36 | b secondary_startup | 38 | b secondary_startup |
37 | 39 | ||
38 | ENDPROC(armada_xp_secondary_startup) | 40 | ENDPROC(armada_xp_secondary_startup) |