MCPM backends updates
Subsystems (4)
cover MCPM backends updates
Patch 1:
Fixes to the existing Vexpress DCSCB backend.
Patch 2:
Lorenzo's minimal SPC driver required by the TC2 MCPM backend. As discussed on the list, this is not considered to be a MFD driver. This hardly qualify as a bus driver either. Conceptually, this is a very platform specific register multiplex driver allowing subsystem drivers to hook into. I therefore moved it to drivers/platform/vexpress/.
Patch 3:
This is the MCPM backend enabling SMP secondary boot and CPU hotplug on the VExpress TC2 big.LITTLE platform.
Patch 4:
Add MCPM suspend method to the TC2 backend allowing basic CPU idle/suspend. The cpuidle driver that hooks into this will be submitted separately.
The TC2 MCPM patches have been reviewed here:
http://news.gmane.org/group/gmane.linux.ports.arm.kernel/thread=242408
The latest SPC driver discussion is here:
http://news.gmane.org/group/gmane.linux.kernel/thread=1525836
Nicolas
PATCH 1/4 ARM: vexpress/dcscb: fix cache disabling sequences
Unlike real A15/A7's, the RTSM simulation doesn't appear to hit the cache when the CTRL.C bit is cleared. Let's ensure there is no memory access within the disable and flush cache sequence, including to the stack.
--- arch/arm/mach-vexpress/dcscb.c | 58 +++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 21 deletions(-)
arch/arm/mach-vexpress/dcscb.c +37 -21
@@ -136,14 +136,29 @@ static void dcscb_power_down(void)/* * Flush all cache levels for this cluster. * -* A15/A7 can hit in the cache with SCTLR.C=0, so we don't need -* a preliminary flush here for those CPUs. At least, that's -* the theory -- without the extra flush, Linux explodes on -* RTSM (to be investigated). +* To do so we do: +* - Clear the CTLR.C bit to prevent further cache allocations +* - Flush the whole cache +* - Disable local coherency by clearing the ACTLR "SMP" bit +* +* Let's do it in the safest possible way i.e. with +* no memory access within the following sequence +* including the stack. */ -flush_cache_all (); -set_cr (get_cr () & ~CR_C ); -flush_cache_all (); + asmvolatile ( +"mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" + "bic r0, r0, #"__stringify(CR_C)" \n\t" +"mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" +"isb \n\t" +"bl v7_flush_dcache_all \n\t" +"clrex \n\t" +"mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" +"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" +"mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" +"isb \n\t" +"dsb " + : : : "r0","r1","r2","r3","r4","r5","r6","r7", + "r9","r10","r11","lr","memory");/* * This is a harmless no-op. On platforms with a real
@@ -152,9 +167,6 @@ static void dcscb_power_down(void)*/ outer_flush_all (); -/* Disable local coherency by clearing the ACTLR "SMP" bit: */ -set_auxcr (get_auxcr () & ~(1 <<6 )); -/* * Disable cluster-level coherency by masking * incoming snoops and DVM messages:
@@ -167,18 +179,22 @@ static void dcscb_power_down(void)/* * Flush the local CPU cache. -* -* A15/A7 can hit in the cache with SCTLR.C=0, so we don't need -* a preliminary flush here for those CPUs. At least, that's -* the theory -- without the extra flush, Linux explodes on -* RTSM (to be investigated). +* Let's do it in the safest possible way as above. */ -flush_cache_louis (); -set_cr (get_cr () & ~CR_C ); -flush_cache_louis (); - -/* Disable local coherency by clearing the ACTLR "SMP" bit: */ -set_auxcr (get_auxcr () & ~(1 <<6 )); + asmvolatile ( +"mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" + "bic r0, r0, #"__stringify(CR_C)" \n\t" +"mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" +"isb \n\t" +"bl v7_flush_dcache_louis \n\t" +"clrex \n\t" +"mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" +"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" +"mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" +"isb \n\t" +"dsb " + : : : "r0","r1","r2","r3","r4","r5","r6","r7", + "r9","r10","r11","lr","memory"); }__mcpm_cpu_down (cpu, cluster);
Signature · 1 line
1.8.1.2
PATCH 1/4 ARM: vexpress/dcscb: fix cache disabling sequences
Quoted 15 lines · Nicolas Pitre
Unlike real A15/A7's, the RTSM simulation doesn't appear to hit the cache when the CTRL.C bit is cleared. Let's ensure there is no memory access within the disable and flush cache sequence, including to the stack.
Signed-off-by Nicolas Pitre <[email protected]>--- arch/arm/mach-vexpress/dcscb.c | 58 +++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 21 deletions(-)arch/arm/mach-vexpress/dcscb.c +0
-0
arch/arm/mach-vexpress/dcscb.c static void dcscb_power_down(void) · line 140
Quoted 9 lines
arch/arm/mach-vexpress/dcscb.c +2
-4@@ -136,14 +136,29 @@ static void dcscb_power_down(void)/* * Flush all cache levels for this cluster. * -* A15/A7 can hit in the cache with SCTLR.C=0, so we don't need -* a preliminary flush here for those CPUs. At least, that's -* the theory -- without the extra flush, Linux explodes on -* RTSM (to be investigated). +* To do so we do: +* - Clear the CTLR.C bit to prevent further cache allocations
SCTLR
Quoted 14 lines
arch/arm/mach-vexpress/dcscb.c +10
-3+* - Flush the whole cache +* - Disable local coherency by clearing the ACTLR "SMP" bit +* +* Let's do it in the safest possible way i.e. with +* no memory access within the following sequence +* including the stack. */ -flush_cache_all (); -set_cr (get_cr () & ~CR_C ); -flush_cache_all (); + asmvolatile ( +"mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" + "bic r0, r0, #"__stringify(CR_C)" \n\t" +"mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t"
arch/arm/mach-vexpress/dcscb.c static void dcscb_power_down(void) · line 161
Quoted 10 lines
arch/arm/mach-vexpress/dcscb.c +10
-0+"isb \n\t" +"bl v7_flush_dcache_all \n\t" +"clrex \n\t" +"mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" +"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" +"mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" +"isb \n\t" +"dsb " + : : : "r0","r1","r2","r3","r4","r5","r6","r7", + "r9","r10","r11","lr","memory");
Along with the TC2 support, we now have 4 copies of this code sequence.
This is basically the A15/A7 native "exit coherency and flash and disable some levels of dcache" operation, whose only parameter is which cache levels to flush.
That's a big mouthful -- we can probably come up with a better name -- but we've pretty much concluded that there is no way to break this operation apart into bitesize pieces. Nonetheless, any native powerdown sequence for these processors will need to do this, or something closely related.
Is it worth consolidating, or is that premature?
Quoted 19 lines
arch/arm/mach-vexpress/dcscb.c +13
-0+"mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" + "bic r0, r0, #"__stringify(CR_C)" \n\t" +"mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" +"isb \n\t" +"bl v7_flush_dcache_all \n\t" +"clrex \n\t" +"mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" +"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" +"mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" +"isb \n\t" +"dsb " + : : : "r0","r1","r2","r3","r4","r5","r6","r7", + "r9","r10","r11","lr","memory");/* * This is a harmless no-op. On platforms with a real
arch/arm/mach-vexpress/dcscb.c static void dcscb_power_down(void) · line 168
Quoted 2 lines
arch/arm/mach-vexpress/dcscb.c +0
-0@@ -152,9 +167,6 @@ static void dcscb_power_down(void)*/ outer_flush_all ();
Do you have any opinion on whether we should leave that for educational purposes?
None of the relevant platforms has a non-architected outer cache, so there could be an argument for removing it. But that might mislead people who use this code as a reference.
Cheers
---Dave
Quoted 49 lines
arch/arm/mach-vexpress/dcscb.c +15
-14-/* Disable local coherency by clearing the ACTLR "SMP" bit: */ -set_auxcr (get_auxcr () & ~(1 <<6 )); -/* * Disable cluster-level coherency by masking * incoming snoops and DVM messages: @@ -167,18 +179,22 @@ static void dcscb_power_down(void)/* * Flush the local CPU cache. -* -* A15/A7 can hit in the cache with SCTLR.C=0, so we don't need -* a preliminary flush here for those CPUs. At least, that's -* the theory -- without the extra flush, Linux explodes on -* RTSM (to be investigated). +* Let's do it in the safest possible way as above. */ -flush_cache_louis (); -set_cr (get_cr () & ~CR_C ); -flush_cache_louis (); - -/* Disable local coherency by clearing the ACTLR "SMP" bit: */ -set_auxcr (get_auxcr () & ~(1 <<6 )); + asmvolatile ( +"mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" + "bic r0, r0, #"__stringify(CR_C)" \n\t" +"mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" +"isb \n\t" +"bl v7_flush_dcache_louis \n\t" +"clrex \n\t" +"mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" +"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" +"mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" +"isb \n\t" +"dsb " + : : : "r0","r1","r2","r3","r4","r5","r6","r7", + "r9","r10","r11","lr","memory"); }__mcpm_cpu_down (cpu, cluster);Signature · 7 lines
1.8.1.2 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel at lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
PATCH 1/4 ARM: vexpress/dcscb: fix cache disabling sequences
[ added Russell for his opinion on the patch below ]
Quoted 11 lines · Dave Martin
Quoted 10 lines · Nicolas Pitre
Unlike real A15/A7's, the RTSM simulation doesn't appear to hit the cache when the CTRL.C bit is cleared. Let's ensure there is no memory access within the disable and flush cache sequence, including to the stack.
Signed-off-by Nicolas Pitre <[email protected]>--- arch/arm/mach-vexpress/dcscb.c | 58 +++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 21 deletions(-)
Quoted 16 lines
Quoted 5 lines
arch/arm/mach-vexpress/dcscb.c +0
-0arch/arm/mach-vexpress/dcscb.c static void dcscb_power_down(void) · line 140
Quoted 9 lines
arch/arm/mach-vexpress/dcscb.c +2
-4@@ -136,14 +136,29 @@ static void dcscb_power_down(void)/* * Flush all cache levels for this cluster. * -* A15/A7 can hit in the cache with SCTLR.C=0, so we don't need -* a preliminary flush here for those CPUs. At least, that's -* the theory -- without the extra flush, Linux explodes on -* RTSM (to be investigated). +* To do so we do: +* - Clear the CTLR.C bit to prevent further cache allocations SCTLR
Fixed.
Quoted 31 lines
Quoted 14 lines
arch/arm/mach-vexpress/dcscb.c +10
-3+* - Flush the whole cache +* - Disable local coherency by clearing the ACTLR "SMP" bit +* +* Let's do it in the safest possible way i.e. with +* no memory access within the following sequence +* including the stack. */ -flush_cache_all (); -set_cr (get_cr () & ~CR_C ); -flush_cache_all (); + asmvolatile ( +"mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" + "bic r0, r0, #"__stringify(CR_C)" \n\t" +"mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" arch/arm/mach-vexpress/dcscb.c static void dcscb_power_down(void) · line 161
Quoted 10 lines
arch/arm/mach-vexpress/dcscb.c +10
-0+"isb \n\t" +"bl v7_flush_dcache_all \n\t" +"clrex \n\t" +"mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" +"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" +"mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" +"isb \n\t" +"dsb " + : : : "r0","r1","r2","r3","r4","r5","r6","r7", + "r9","r10","r11","lr","memory");Along with the TC2 support, we now have 4 copies of this code sequence.
This is basically the A15/A7 native "exit coherency and flash and disable some levels of dcache" operation, whose only parameter is which cache levels to flush.
Quoted 7 lines
That's a big mouthful -- we can probably come up with a better name -- but we've pretty much concluded that there is no way to break this operation apart into bitesize pieces. Nonetheless, any native powerdown sequence for these processors will need to do this, or something closely related.
Is it worth consolidating, or is that premature?
It is probably worth consolidating.
What about this:
commit 390cf8b9b83eeeebdfef51912f5003a6a9b84115
Author: Nicolas Pitre <[email protected]> Date: Thu Jul 18 13:12:48 2013 -0400
ARM: cacheflush: consolidate single-CPU ARMv7 cache disabling code
This code is becoming duplicated in many places. So let's consolidate it into a handy macro that is known to be right and available for reuse.
arch/arm/include/asm/cacheflush.h +29 -0
@@ -436,4 +436,33 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size)#define sync_cache_w (ptr) __sync_cache_range_w(ptr, sizeof *(ptr))#define sync_cache_r (ptr) __sync_cache_range_r(ptr, sizeof *(ptr)) +/* +* Disabling cache access for one CPU in an ARMv7 SMP system is tricky. +* To do so we must: +* +* - Clear the SCTLR.C bit to prevent further cache allocations +* - Flush the desired level of cache +* - Clear the ACTLR "SMP" bit to disable local coherency +* +* ... and so without any intervening memory access in between those steps, +* not even to the stack. +* +* The clobber list is dictated by the call to v7_flush_dcache_*. +*/ +#define v7_disable_flush_cache (level) \ + asm volatile( \ + "mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" \ + "bic r0, r0, #"__stringify(CR_C)" \n\t" \ + "mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" \ + "isb \n\t" \ + "bl v7_flush_dcache_"__stringify(level)" \n\t" \ + "clrex \n\t" \ + "mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" \ + "bic r0, r0, #(1 << 6) @ disable local coherency \n\t" \ + "mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" \ + "isb \n\t" \ + "dsb " \ + : : : "r0","r1","r2","r3","r4","r5","r6","r7", \ + "r9","r10","r11","lr","memory" ) +#endif
arch/arm/mach-vexpress/dcscb.c +4 -44
60 lines not on this page · raw message
arch/arm/mach-vexpress/tc2_pm.c +2 -38
@@ -134,26 +134,7 @@ static void tc2_pm_down(u64 residency) : : "r" (0x400) ); } -/* -* We need to disable and flush the whole (L1 and L2) cache. -* Let's do it in the safest possible way i.e. with -* no memory access within the following sequence -* including the stack. -*/ - asmvolatile ( -"mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" - "bic r0, r0, #"__stringify(CR_C)" \n\t" -"mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" -"isb \n\t" -"bl v7_flush_dcache_all \n\t" -"clrex \n\t" -"mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" -"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" -"mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" -"isb \n\t" -"dsb " - : : : "r0","r1","r2","r3","r4","r5","r6","r7", - "r9","r10","r11","lr","memory"); +v7_disable_flush_cache (all);cci_disable_port_by_cpu (mpidr);
@@ -169,24 +150,7 @@ static void tc2_pm_down(u64 residency)arch_spin_unlock (&tc2_pm_lock); -/* -* We need to disable and flush only the L1 cache. -* Let's do it in the safest possible way as above. -*/ - asmvolatile ( -"mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" - "bic r0, r0, #"__stringify(CR_C)" \n\t" -"mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" -"isb \n\t" -"bl v7_flush_dcache_louis \n\t" -"clrex \n\t" -"mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" -"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" -"mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" -"isb \n\t" -"dsb " - : : : "r0","r1","r2","r3","r4","r5","r6","r7", - "r9","r10","r11","lr","memory"); +v7_disable_flush_cache (louis); }__mcpm_cpu_down (cpu, cluster);
PATCH 1/4 ARM: vexpress/dcscb: fix cache disabling sequences
Quoted 1 line · Nicolas Pitre
[ added Russell for his opinion on the patch below ]
[...]
Quoted 39 lines
commit
390cf8b9b83eeeebdfef51912f5003a6a9b84115Author: Nicolas Pitre <[email protected]> Date: Thu Jul 18 13:12:48 2013 -0400ARM: cacheflush: consolidate single-CPU ARMv7 cache disabling code
This code is becoming duplicated in many places. So let's consolidate it into a handy macro that is known to be right and available for reuse.
Signed-off-by Nicolas Pitre <[email protected]>arch/arm/include/asm/cacheflush.h +20
-0@@ -436,4 +436,33 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size)#define sync_cache_w (ptr) __sync_cache_range_w(ptr, sizeof *(ptr))#define sync_cache_r (ptr) __sync_cache_range_r(ptr, sizeof *(ptr)) +/* +* Disabling cache access for one CPU in an ARMv7 SMP system is tricky. +* To do so we must: +* +* - Clear the SCTLR.C bit to prevent further cache allocations +* - Flush the desired level of cache +* - Clear the ACTLR "SMP" bit to disable local coherency +* +* ... and so without any intervening memory access in between those steps, +* not even to the stack. +* +* The clobber list is dictated by the call to v7_flush_dcache_*. +*/ +#define v7_disable_flush_cache (level) \ + asm volatile( \ + "mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" \ + "bic r0, r0, #"__stringify(CR_C)" \n\t" \ + "mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" \ + "isb \n\t" \ + "bl v7_flush_dcache_"__stringify(level)" \n\t" \
arch/arm/include/asm/cacheflush.h static inline void __sync_cache_range_r(volatile void *p, size_t size) · line 468
Quoted 10 lines
arch/arm/include/asm/cacheflush.h +9
-0+"clrex \n\t" \ +"mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" \ +"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" \ +"mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" \ +"isb \n\t" \ +"dsb " \ + : : : "r0","r1","r2","r3","r4","r5","r6","r7", \ + "r9","r10","r11","lr","memory" ) + #endif
That's roughly what I had in mind, though it might belong somewhere more obscure than cacheflush.h(?)
"disable_flush_cache" sounds a too general-purpose for my liking.
"v7" isn't really right because we touch the ACTLR. This only works on certain CPUs and when Linux is running Secure. Maybe saying "a15" instead of "a7" is reasonable, since a7 is supposed to be an a15 workalike in most places.
I had other names in mind, like "coherency_exit" or "cache_exit". Those are not very intelligible, but that might at least make people pause and think before blindly using it.
Really, it's for the very specific purpose of doing native low-level powerdown of an individual CPU in a multiprocessor system, when the platform as a whole is not being shut down, on A15 or A7 (+ possibly other future v7 CPUs)... it's not suitable for any other situation. Even kexec probably shouldn't be disabling the SMP bit.
Cheers
---Dave
PATCH 1/4 ARM: vexpress/dcscb: fix cache disabling sequences
Quoted 49 lines · Dave Martin
Quoted 1 line · Nicolas Pitre
[ added Russell for his opinion on the patch below ]
[...]
Quoted 44 lines
commit
390cf8b9b83eeeebdfef51912f5003a6a9b84115Author: Nicolas Pitre <[email protected]> Date: Thu Jul 18 13:12:48 2013 -0400ARM: cacheflush: consolidate single-CPU ARMv7 cache disabling code
This code is becoming duplicated in many places. So let's consolidate it into a handy macro that is known to be right and available for reuse.
Signed-off-by Nicolas Pitre <[email protected]>arch/arm/include/asm/cacheflush.h +25
-0@@ -436,4 +436,33 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size)#define sync_cache_w (ptr) __sync_cache_range_w(ptr, sizeof *(ptr))#define sync_cache_r (ptr) __sync_cache_range_r(ptr, sizeof *(ptr)) +/* +* Disabling cache access for one CPU in an ARMv7 SMP system is tricky. +* To do so we must: +* +* - Clear the SCTLR.C bit to prevent further cache allocations +* - Flush the desired level of cache +* - Clear the ACTLR "SMP" bit to disable local coherency +* +* ... and so without any intervening memory access in between those steps, +* not even to the stack. +* +* The clobber list is dictated by the call to v7_flush_dcache_*. +*/ +#define v7_disable_flush_cache (level) \ + asm volatile( \ + "mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" \ + "bic r0, r0, #"__stringify(CR_C)" \n\t" \ + "mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" \ + "isb \n\t" \ + "bl v7_flush_dcache_"__stringify(level)" \n\t" \ + "clrex \n\t" \ + "mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" \ + "bic r0, r0, #(1 << 6) @ disable local coherency \n\t" \ + "mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" \ + "isb \n\t" \
Quoted 8 lines
arch/arm/include/asm/cacheflush.h static inline void __sync_cache_range_r(volatile void *p, size_t size) · line 468
Quoted 5 lines
arch/arm/include/asm/cacheflush.h +4
-0+ "dsb " \ + : : : "r0","r1","r2","r3","r4","r5","r6","r7", \ + "r9","r10","r11","lr","memory" ) +#endif That's roughly what I had in mind, though it might belong somewhere more obscure than
cacheflush.h(?)
Any suggestions for that? Maybe asm/mcpm.h but that might be used in other circumstances as well.
Quoted 6 lines
"
disable_flush_cache" sounds a too general-purpose for my liking."v7" isn't really right because we touch the ACTLR. This only works on certain CPUs and when Linux is running Secure. Maybe saying "a15" instead of "a7" is reasonable, since a7 is supposed to be an a15 workalike in most places.
Isn't this how this should be done on an A9 too? Lorenzo asked me to do it this way, by fear of seeing people copy the previous implementation, so the same sequence works on A9 as well as A15.
Quoted 3 lines
I had other names in mind, like "
coherency_exit" or "cache_exit". Those are not very intelligible, but that might at least make people pause and think before blindly using it.
Good point. It should still embody the architecture name for which it is valid though.
Nicolas
PATCH 1/4 ARM: vexpress/dcscb: fix cache disabling sequences
Quoted 60 lines · Nicolas Pitre
Quoted 49 lines · Dave Martin
Quoted 1 line · Nicolas Pitre
[ added Russell for his opinion on the patch below ]
[...]
Quoted 44 lines
commit
390cf8b9b83eeeebdfef51912f5003a6a9b84115Author: Nicolas Pitre <[email protected]> Date: Thu Jul 18 13:12:48 2013 -0400ARM: cacheflush: consolidate single-CPU ARMv7 cache disabling code
This code is becoming duplicated in many places. So let's consolidate it into a handy macro that is known to be right and available for reuse.
Signed-off-by Nicolas Pitre <[email protected]>arch/arm/include/asm/cacheflush.h +25
-0@@ -436,4 +436,33 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size)#define sync_cache_w (ptr) __sync_cache_range_w(ptr, sizeof *(ptr))#define sync_cache_r (ptr) __sync_cache_range_r(ptr, sizeof *(ptr)) +/* +* Disabling cache access for one CPU in an ARMv7 SMP system is tricky. +* To do so we must: +* +* - Clear the SCTLR.C bit to prevent further cache allocations +* - Flush the desired level of cache +* - Clear the ACTLR "SMP" bit to disable local coherency +* +* ... and so without any intervening memory access in between those steps, +* not even to the stack. +* +* The clobber list is dictated by the call to v7_flush_dcache_*. +*/ +#define v7_disable_flush_cache (level) \ + asm volatile( \ + "mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" \ + "bic r0, r0, #"__stringify(CR_C)" \n\t" \ + "mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" \ + "isb \n\t" \ + "bl v7_flush_dcache_"__stringify(level)" \n\t" \ + "clrex \n\t" \ + "mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" \ + "bic r0, r0, #(1 << 6) @ disable local coherency \n\t" \ + "mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" \ + "isb \n\t" \Quoted 8 lines
arch/arm/include/asm/cacheflush.h static inline void __sync_cache_range_r(volatile void *p, size_t size) · line 468
Quoted 5 lines
arch/arm/include/asm/cacheflush.h +4
-0+ "dsb " \ + : : : "r0","r1","r2","r3","r4","r5","r6","r7", \ + "r9","r10","r11","lr","memory" ) +#endif That's roughly what I had in mind, though it might belong somewhere more obscure than
cacheflush.h(?)
Quoted 2 lines
Any suggestions for that? Maybe
asm/mcpm.hbut that might be used in other circumstances as well.
I don't really have a better idea... if nobody objects strongly to putting it in cacheflush.h, I happy to go with that.
Quoted 9 lines
Quoted 7 lines
"
disable_flush_cache" sounds a too general-purpose for my liking."v7" isn't really right because we touch the ACTLR. This only works on certain CPUs and when Linux is running Secure. Maybe saying "a15" instead of "a7" is reasonable, since a7 is supposed to be an a15 workalike in most places.
Isn't this how this should be done on an A9 too? Lorenzo asked me to do
Quite possibly -- the point is, it's not guaranteed that all v7 CPUs will
work the same way, especially the custom implementations. Third-party v7
implementations like Snapdragon etc. need not be in any way the same as ARM's CPUs with regard to details like the SMP bit.
Quoted 2 lines
it this way, by fear of seeing people copy the previous implementation, so the same sequence works on A9 as well as A15.
Would it make sense to have things like
#define a15_something() asm(volatile ... )
#define a7_something() a15_something()
#define a9_something() a15_something()
(where the correct one to call for a b.L system would probably be the one corresponding to the big cluster)
... or just call is something like
cortex_a_something()
with a big comment (or alias macros, as above) documenting which CPUs we know it works for, and warning people to stop and think before using it on some other CPU.
Quoted 6 lines
Quoted 3 lines
I had other names in mind, like "
coherency_exit" or "cache_exit". Those are not very intelligible, but that might at least make people pause and think before blindly using it.Good point. It should still embody the architecture name for which it is valid though.
Sure, I was assuming something would be pasted on the start of the name.
Cheers
---Dave
PATCH 1/4 ARM: vexpress/dcscb: fix cache disabling sequences
Quoted 74 lines · Dave Martin
Quoted 60 lines · Nicolas Pitre
Quoted 49 lines · Dave Martin
Quoted 1 line · Nicolas Pitre
[ added Russell for his opinion on the patch below ]
[...]
Quoted 44 lines
commit
390cf8b9b83eeeebdfef51912f5003a6a9b84115Author: Nicolas Pitre <[email protected]> Date: Thu Jul 18 13:12:48 2013 -0400ARM: cacheflush: consolidate single-CPU ARMv7 cache disabling code
This code is becoming duplicated in many places. So let's consolidate it into a handy macro that is known to be right and available for reuse.
Signed-off-by Nicolas Pitre <[email protected]>arch/arm/include/asm/cacheflush.h +25
-0@@ -436,4 +436,33 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size)#define sync_cache_w (ptr) __sync_cache_range_w(ptr, sizeof *(ptr))#define sync_cache_r (ptr) __sync_cache_range_r(ptr, sizeof *(ptr)) +/* +* Disabling cache access for one CPU in an ARMv7 SMP system is tricky. +* To do so we must: +* +* - Clear the SCTLR.C bit to prevent further cache allocations +* - Flush the desired level of cache +* - Clear the ACTLR "SMP" bit to disable local coherency +* +* ... and so without any intervening memory access in between those steps, +* not even to the stack. +* +* The clobber list is dictated by the call to v7_flush_dcache_*. +*/ +#define v7_disable_flush_cache (level) \ + asm volatile( \ + "mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" \ + "bic r0, r0, #"__stringify(CR_C)" \n\t" \ + "mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" \ + "isb \n\t" \ + "bl v7_flush_dcache_"__stringify(level)" \n\t" \ + "clrex \n\t" \ + "mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" \ + "bic r0, r0, #(1 << 6) @ disable local coherency \n\t" \ + "mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" \ + "isb \n\t" \Quoted 8 lines
arch/arm/include/asm/cacheflush.h static inline void __sync_cache_range_r(volatile void *p, size_t size) · line 468
Quoted 5 lines
arch/arm/include/asm/cacheflush.h +4
-0+ "dsb " \ + : : : "r0","r1","r2","r3","r4","r5","r6","r7", \ + "r9","r10","r11","lr","memory" ) +#endif That's roughly what I had in mind, though it might belong somewhere more obscure than
cacheflush.h(?)Quoted 2 lines
Any suggestions for that? Maybe
asm/mcpm.hbut that might be used in other circumstances as well.I don't really have a better idea... if nobody objects strongly to putting it in
cacheflush.h, I happy to go with that.Quoted 8 lines
Quoted 7 lines
"
disable_flush_cache" sounds a too general-purpose for my liking."v7" isn't really right because we touch the ACTLR. This only works on certain CPUs and when Linux is running Secure. Maybe saying "a15" instead of "a7" is reasonable, since a7 is supposed to be an a15 workalike in most places.
Quoted 6 lines
Quoted 1 line
Isn't this how this should be done on an A9 too? Lorenzo asked me to do
Quite possibly -- the point is, it's not guaranteed that all v7 CPUs will
work the same way, especially the custom implementations. Third-party v7
implementations like Snapdragon etc. need not be in any way the same as ARM's CPUs with regard to details like the SMP bit.
Well, if they change the SMP bit behaviour from what the TRM describes they certainly know what they are doing, I am not sure we should cater for that, they will just use their own function if their behaviour differs from "standard".
At least all v7 implementations I've run into in the kernel (mainline and platform trees) could have used the sequence above (well, security notwithstanding).
Also, we should point out that after clearing the C bit ldr/str exclusive must not be used anymore (even though this is implementation defined since it depends on a global monitor in DRAM). The macro is also a barrier in terms of coherency when we call it we should know what to expect, basically a CPU with caches that are not coherent anymore.
Quoted 12 lines
Quoted 2 lines
it this way, by fear of seeing people copy the previous implementation, so the same sequence works on A9 as well as A15.
Would it make sense to have things like
#define
a15_something()asm(volatile ... )
#definea7_something()a15_something()
#definea9_something()a15_something()(where the correct one to call for a b.L system would probably be the one corresponding to the big cluster)
Quoted 7 lines
... or just call is something like
cortex_a_something()with a big comment (or alias macros, as above) documenting which CPUs we know it works for, and warning people to stop and think before using it on some other CPU.
It might be, even though a well written comment would do IMHO.
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
I had other names in mind, like "
coherency_exit" or "cache_exit". Those are not very intelligible, but that might at least make people pause and think before blindly using it.Good point. It should still embody the architecture name for which it is valid though.
Sure, I was assuming something would be pasted on the start of the name.
v7 :-) with a comment describing the assumptions (in particular related as Dave mentioned to the SMP bit behaviour) ?
Lorenzo
PATCH 1/4 ARM: vexpress/dcscb: fix cache disabling sequences
Quoted 8 lines · Lorenzo Pieralisi
Quoted 7 lines · Dave Martin
Quoted 6 lines · Nicolas Pitre
Quoted 3 lines · Dave Martin
I had other names in mind, like "
coherency_exit" or "cache_exit". Those are not very intelligible, but that might at least make people pause and think before blindly using it.
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Good point. It should still embody the architecture name for which it is valid though.
Sure, I was assuming something would be pasted on the start of the name.
v7 :-) with a comment describing the assumptions (in particular related as Dave mentioned to the SMP bit behaviour) ?
OK... What about this then:
----- >8
From: Nicolas Pitre <[email protected]>
Date: Thu, 18 Jul 2013 13:12:48 -0400
Subject: [PATCH] ARM: cacheflush: consolidate single-CPU ARMv7 cache disabling
code
This code is becoming duplicated in many places. So let's consolidate it into a handy macro that is known to be right and available for reuse.
arch/arm/include/asm/cacheflush.h +40 -0
@@ -436,4 +436,44 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size)#define sync_cache_w (ptr) __sync_cache_range_w(ptr, sizeof *(ptr))#define sync_cache_r (ptr) __sync_cache_range_r(ptr, sizeof *(ptr)) +/* +* Disabling cache access for one CPU in an ARMv7 SMP system is tricky. +* To do so we must: +* +* - Clear the SCTLR.C bit to prevent further cache allocations +* - Flush the desired level of cache +* - Clear the ACTLR "SMP" bit to disable local coherency +* +* ... and so without any intervening memory access in between those steps, +* not even to the stack. +* +* WARNING -- After this has been called: +* +* - No ldr/str exclusive must be used. +* - The CPU is obviously no longer coherent with the other CPUs. +* +* Further considerations: +* +* - This relies on the presence and behavior of the AUXCR.SMP bit as +* documented in the ARMv7 TRM. Vendor implementations that deviate from +* that will need their own procedure. +* - This is unlikely to work if Linux is running non-secure. +*/ +#define v7_exit_coherency_flush(level) \ + asm volatile( \ + "mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" \ + "bic r0, r0, #"__stringify(CR_C)" \n\t" \ + "mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" \ + "isb \n\t" \ + "bl v7_flush_dcache_"__stringify(level)" \n\t" \ + "clrex \n\t" \ + "mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" \ + "bic r0, r0, #(1 << 6) @ disable local coherency \n\t" \ + "mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" \ + "isb \n\t" \ + "dsb " \ + /* The clobber list is dictated by the call to v7_flush_dcache_* */ \ + : : : "r0","r1","r2","r3","r4","r5","r6","r7", \ + "r9","r10","r11","lr","memory" ) +#endif
arch/arm/mach-vexpress/dcscb.c +4 -44
60 lines not on this page · raw message
arch/arm/mach-vexpress/tc2_pm.c +2 -38
@@ -134,26 +134,7 @@ static void tc2_pm_down(u64 residency) : : "r" (0x400) ); } -/* -* We need to disable and flush the whole (L1 and L2) cache. -* Let's do it in the safest possible way i.e. with -* no memory access within the following sequence -* including the stack. -*/ - asmvolatile ( -"mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" - "bic r0, r0, #"__stringify(CR_C)" \n\t" -"mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" -"isb \n\t" -"bl v7_flush_dcache_all \n\t" -"clrex \n\t" -"mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" -"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" -"mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" -"isb \n\t" -"dsb " - : : : "r0","r1","r2","r3","r4","r5","r6","r7", - "r9","r10","r11","lr","memory"); +v7_exit_coherency_flush (all);cci_disable_port_by_cpu (mpidr);
@@ -169,24 +150,7 @@ static void tc2_pm_down(u64 residency)arch_spin_unlock (&tc2_pm_lock); -/* -* We need to disable and flush only the L1 cache. -* Let's do it in the safest possible way as above. -*/ - asmvolatile ( -"mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" - "bic r0, r0, #"__stringify(CR_C)" \n\t" -"mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" -"isb \n\t" -"bl v7_flush_dcache_louis \n\t" -"clrex \n\t" -"mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" -"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" -"mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" -"isb \n\t" -"dsb " - : : : "r0","r1","r2","r3","r4","r5","r6","r7", - "r9","r10","r11","lr","memory"); +v7_exit_coherency_flush (louis); }__mcpm_cpu_down (cpu, cluster);
PATCH 1/4 ARM: vexpress/dcscb: fix cache disabling sequences
Quoted 43 lines · Nicolas Pitre
Quoted 8 lines · Lorenzo Pieralisi
Quoted 7 lines · Dave Martin
Quoted 6 lines · Nicolas Pitre
Quoted 3 lines · Dave Martin
I had other names in mind, like "
coherency_exit" or "cache_exit". Those are not very intelligible, but that might at least make people pause and think before blindly using it.Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Good point. It should still embody the architecture name for which it is valid though.
Sure, I was assuming something would be pasted on the start of the name.
v7 :-) with a comment describing the assumptions (in particular related as Dave mentioned to the SMP bit behaviour) ?
OK... What about this then:
----- >8
From: Nicolas Pitre <[email protected]>
Date: Thu, 18 Jul 2013 13:12:48 -0400
Subject: [PATCH] ARM: cacheflush: consolidate single-CPU ARMv7 cache disabling
codeThis code is becoming duplicated in many places. So let's consolidate it into a handy macro that is known to be right and available for reuse.
Signed-off-by Nicolas Pitre <[email protected]>arch/arm/include/asm/cacheflush.h +4
-0@@ -436,4 +436,44 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size)#define sync_cache_w (ptr) __sync_cache_range_w(ptr, sizeof *(ptr))#define sync_cache_r (ptr) __sync_cache_range_r(ptr, sizeof *(ptr)) +/* +* Disabling cache access for one CPU in an ARMv7 SMP system is tricky. +* To do so we must: +*
arch/arm/include/asm/cacheflush.h static inline void __sync_cache_range_r(volatile void *p, size_t size) · line 452
Quoted 10 lines
arch/arm/include/asm/cacheflush.h +10
-0+* - Clear the SCTLR.C bit to prevent further cache allocations +* - Flush the desired level of cache +* - Clear the ACTLR "SMP" bit to disable local coherency +* +* ... and so without any intervening memory access in between those steps, +* not even to the stack. +* +* WARNING -- After this has been called: +* +* - No ldr/str exclusive must be used.
Maybe write ldrex/strex (I misread that the first time around as "no ldr/str ... must be used", which seemed a bit drastic)
arch/arm/include/asm/cacheflush.h static inline void __sync_cache_range_r(volatile void *p, size_t size) · line 458
Quoted 6 lines
arch/arm/include/asm/cacheflush.h +6
-0+* - The CPU is obviously no longer coherent with the other CPUs. +* +* Further considerations: +* +* - This relies on the presence and behavior of the AUXCR.SMP bit as +* documented in the ARMv7 TRM. Vendor implementations that deviate from
Sorry to be pedantic here, but there is no "ARMv7 TRM". The SMP bit is not part of ARMv7 at all. Also, it seems that A9 isn't precisely the
same: two ACTLR bits need to be twiddled. R-class CPUs are generally not the same either.
This is why I preferred to treat the whole sequence as specific to a particular CPU implementation. The similarity between A7 and A15 might be viewed as a happy coincidence (it also makes life easier in big.LITTLE land).
(Also, you mix the names "ACTLR" and "AUXCR", but people will generally be able to guess those are the same thing)
arch/arm/include/asm/cacheflush.h static inline void __sync_cache_range_r(volatile void *p, size_t size) · line 462
Quoted 4 lines
arch/arm/include/asm/cacheflush.h +4
-0+* that will need their own procedure. +* - This is unlikely to work if Linux is running non-secure. +*/ +#define v7_exit_coherency_flush (level) \
... hence:
#define cortex_a15_exit_coherency(level) ...
#define cortex_a7_exit_coherency(level) cortex_a15_exit_coherency(level)
What do you think?
Cheers
---Dave
Quoted 146 lines
arch/arm/include/asm/cacheflush.h +16
-0+ asmvolatile ( \ +"mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" \ + "bic r0, r0, #"__stringify(CR_C)" \n\t" \ +"mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" \ +"isb \n\t" \ + "bl v7_flush_dcache_"__stringify(level)" \n\t" \ +"clrex \n\t" \ +"mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" \ +"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" \ +"mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" \ +"isb \n\t" \ +"dsb " \ +/* The clobber list is dictated by the call to v7_flush_dcache_* */ \ + : : : "r0","r1","r2","r3","r4","r5","r6","r7", \ + "r9","r10","r11","lr","memory" ) + #endifarch/arm/mach-vexpress/dcscb.c +4
-44@@ -133,32 +133,8 @@ static void dcscb_power_down(void)if (last_man &&__mcpm_outbound_enter_critical (cpu, cluster)) {arch_spin_unlock (&dcscb_lock); -/* -* Flush all cache levels for this cluster. -* -* To do so we do: -* - Clear the SCTLR.C bit to prevent further cache allocations -* - Flush the whole cache -* - Clear the ACTLR "SMP" bit to disable local coherency -* -* Let's do it in the safest possible way i.e. with -* no memory access within the following sequence -* including to the stack. -*/ - asmvolatile ( -"mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" - "bic r0, r0, #"__stringify(CR_C)" \n\t" -"mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" -"isb \n\t" -"bl v7_flush_dcache_all \n\t" -"clrex \n\t" -"mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" -"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" -"mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" -"isb \n\t" -"dsb " - : : : "r0","r1","r2","r3","r4","r5","r6","r7", - "r9","r10","r11","lr","memory"); +/* Flush all cache levels for this cluster. */ +v7_exit_coherency_flush (all);/* * This is a harmless no-op. On platforms with a real @@ -177,24 +153,8 @@ static void dcscb_power_down(void) }else {arch_spin_unlock (&dcscb_lock); -/* -* Flush the local CPU cache. -* Let's do it in the safest possible way as above. -*/ - asmvolatile ( -"mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" - "bic r0, r0, #"__stringify(CR_C)" \n\t" -"mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" -"isb \n\t" -"bl v7_flush_dcache_louis \n\t" -"clrex \n\t" -"mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" -"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" -"mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" -"isb \n\t" -"dsb " - : : : "r0","r1","r2","r3","r4","r5","r6","r7", - "r9","r10","r11","lr","memory"); +/* Disable and flush the local CPU cache. */ +v7_exit_coherency_flush (louis); }__mcpm_cpu_down (cpu, cluster);arch/arm/mach-vexpress/tc2_pm.c +2
-38@@ -134,26 +134,7 @@ static void tc2_pm_down(u64 residency) : : "r" (0x400) ); } -/* -* We need to disable and flush the whole (L1 and L2) cache. -* Let's do it in the safest possible way i.e. with -* no memory access within the following sequence -* including the stack. -*/ - asmvolatile ( -"mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" - "bic r0, r0, #"__stringify(CR_C)" \n\t" -"mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" -"isb \n\t" -"bl v7_flush_dcache_all \n\t" -"clrex \n\t" -"mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" -"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" -"mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" -"isb \n\t" -"dsb " - : : : "r0","r1","r2","r3","r4","r5","r6","r7", - "r9","r10","r11","lr","memory"); +v7_exit_coherency_flush (all);cci_disable_port_by_cpu (mpidr);@@ -169,24 +150,7 @@ static void tc2_pm_down(u64 residency)arch_spin_unlock (&tc2_pm_lock); -/* -* We need to disable and flush only the L1 cache. -* Let's do it in the safest possible way as above. -*/ - asmvolatile ( -"mrc p15, 0, r0, c1, c0, 0 @ get CR \n\t" - "bic r0, r0, #"__stringify(CR_C)" \n\t" -"mcr p15, 0, r0, c1, c0, 0 @ set CR \n\t" -"isb \n\t" -"bl v7_flush_dcache_louis \n\t" -"clrex \n\t" -"mrc p15, 0, r0, c1, c0, 1 @ get AUXCR \n\t" -"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" -"mcr p15, 0, r0, c1, c0, 1 @ set AUXCR \n\t" -"isb \n\t" -"dsb " - : : : "r0","r1","r2","r3","r4","r5","r6","r7", - "r9","r10","r11","lr","memory"); +v7_exit_coherency_flush (louis); }__mcpm_cpu_down (cpu, cluster);_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
PATCH 1/4 ARM: vexpress/dcscb: fix cache disabling sequences
Quoted 49 lines · Dave Martin
Quoted 48 lines · Nicolas Pitre
Quoted 8 lines · Lorenzo Pieralisi
Quoted 7 lines · Dave Martin
Quoted 6 lines · Nicolas Pitre
Quoted 3 lines · Dave Martin
I had other names in mind, like "
coherency_exit" or "cache_exit". Those are not very intelligible, but that might at least make people pause and think before blindly using it.Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Good point. It should still embody the architecture name for which it is valid though.
Sure, I was assuming something would be pasted on the start of the name.
v7 :-) with a comment describing the assumptions (in particular related as Dave mentioned to the SMP bit behaviour) ?
OK... What about this then:
----- >8
From: Nicolas Pitre <[email protected]>
Date: Thu, 18 Jul 2013 13:12:48 -0400
Subject: [PATCH] ARM: cacheflush: consolidate single-CPU ARMv7 cache disabling
codeThis code is becoming duplicated in many places. So let's consolidate it into a handy macro that is known to be right and available for reuse.
Signed-off-by Nicolas Pitre <[email protected]>arch/arm/include/asm/cacheflush.h +9
-0@@ -436,4 +436,44 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size)#define sync_cache_w (ptr) __sync_cache_range_w(ptr, sizeof *(ptr))#define sync_cache_r (ptr) __sync_cache_range_r(ptr, sizeof *(ptr)) +/* +* Disabling cache access for one CPU in an ARMv7 SMP system is tricky. +* To do so we must: +* +* - Clear the SCTLR.C bit to prevent further cache allocations +* - Flush the desired level of cache +* - Clear the ACTLR "SMP" bit to disable local coherency +* +* ... and so without any intervening memory access in between those steps,
Quoted 8 lines
arch/arm/include/asm/cacheflush.h static inline void __sync_cache_range_r(volatile void *p, size_t size) · line 452
Quoted 5 lines
arch/arm/include/asm/cacheflush.h +5
-0+* not even to the stack. +* +* WARNING -- After this has been called: +* +* - No ldr/str exclusive must be used. Maybe write ldrex/strex (I misread that the first time around as "no ldr/str ... must be used", which seemed a bit drastic)
OK.
Quoted 9 lines
arch/arm/include/asm/cacheflush.h static inline void __sync_cache_range_r(volatile void *p, size_t size) · line 458
Quoted 6 lines
arch/arm/include/asm/cacheflush.h +6
-0+* - The CPU is obviously no longer coherent with the other CPUs. +* +* Further considerations: +* +* - This relies on the presence and behavior of the AUXCR.SMP bit as +* documented in the ARMv7 TRM. Vendor implementations that deviate from Sorry to be pedantic here, but there is no "ARMv7 TRM". The SMP bit is not part of ARMv7 at all.
Well, I just copied Lorenzo's words here, trusting he knew more about it than I do.
Quoted 8 lines
Also, it seems that A9 isn't precisely the
same: two ACTLR bits need to be twiddled. R-class CPUs are generally not the same either.This is why I preferred to treat the whole sequence as specific to a particular CPU implementation. The similarity between A7 and A15 might be viewed as a happy coincidence (it also makes life easier in big.LITTLE land).
Fair enough.
Quoted 2 lines
(Also, you mix the names "ACTLR" and "AUXCR", but people will generally be able to guess those are the same thing)
We apparently use both in the kernel already. Which one is the canonical one?
Quoted 5 lines
arch/arm/include/asm/cacheflush.h static inline void __sync_cache_range_r(volatile void *p, size_t size) · line 462
Quoted 4 lines
arch/arm/include/asm/cacheflush.h +4
-0+* that will need their own procedure. +* - This is unlikely to work if Linux is running non-secure. +*/ +#define v7_exit_coherency_flush (level) \
Quoted 7 lines
... hence:
#define
cortex_a15_exit_coherency(level)...#define
cortex_a7_exit_coherency(level)cortex_a15_exit_coherency(level)What do you think?
To be pedantic again, we don't really exit coherency at some cache level. Hence my usage of "flush" indicating that the level argument applies only to that and not to the coherency status.
Nicolas
PATCH 1/4 ARM: vexpress/dcscb: fix cache disabling sequences
On Tue, Jul 23, 2013 at 01:28:16PM +0100, Nicolas Pitre wrote:
[...]
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
+ * - The CPU is obviously no longer coherent with the other CPUs.
+ *
+ * Further considerations:
+ *
+ * - This relies on the presence and behavior of the AUXCR.SMP bit as
+ * documented in the ARMv7 TRM. Vendor implementations that deviate from
Quoted 9 lines
Quoted 2 lines
Sorry to be pedantic here, but there is no "ARMv7 TRM". The SMP bit is not part of ARMv7 at all.
Well, I just copied Lorenzo's words here, trusting he knew more about it than I do.
Quoted 3 lines
Also, it seems that A9 isn't precisely the
same: two ACTLR bits need to be twiddled. R-class CPUs are generally not the same either.
If you mean the ACTLR.FW bit in A9, A5, and R7, then, IIRC, we do not need to clear it, clearing the SMP bit is enough.
See, Dave has a point, there is no explicit "unified v7 TRM disable clean and exit coherency procedure" even though the designers end goal is to have one and that's the one you wrote. The code you posted is perfectly ok on all v7 implementations in the kernel I am aware of, I stand to be corrected but to the best of my knowledge that's the case.
Quoted 6 lines
Quoted 4 lines
This is why I preferred to treat the whole sequence as specific to a particular CPU implementation. The similarity between A7 and A15 might be viewed as a happy coincidence (it also makes life easier in big.LITTLE land).
Fair enough.
I disagree on the happy coincidence but the point is taken. I am not sure about what we should do, but I reiterate my point, the sequence as it stands is OK on all NS v7 implementations I am aware of. We can add macros to differentiate processors when we need them, but again that's just my opinion, as correct as it can be.
Lorenzo
PATCH 1/4 ARM: vexpress/dcscb: fix cache disabling sequences
Quoted 21 lines · Lorenzo Pieralisi
On Tue, Jul 23, 2013 at 01:28:16PM +0100, Nicolas Pitre wrote:
[...]
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
+ * - The CPU is obviously no longer coherent with the other CPUs.
+ *
+ * Further considerations:
+ *
+ * - This relies on the presence and behavior of the AUXCR.SMP bit as
+ * documented in the ARMv7 TRM. Vendor implementations that deviate fromQuoted 9 lines
Quoted 2 lines
Sorry to be pedantic here, but there is no "ARMv7 TRM". The SMP bit is not part of ARMv7 at all.
Well, I just copied Lorenzo's words here, trusting he knew more about it than I do.
Quoted 3 lines
Also, it seems that A9 isn't precisely the
same: two ACTLR bits need to be twiddled. R-class CPUs are generally not the same either.
Quoted 8 lines
If you mean the ACTLR.FW bit in A9, A5, and R7, then, IIRC, we do not need to clear it, clearing the SMP bit is enough.
See, Dave has a point, there is no explicit "unified v7 TRM disable clean and exit coherency procedure" even though the designers end goal is to have one and that's the one you wrote. The code you posted is perfectly ok on all v7 implementations in the kernel I am aware of, I stand to be corrected but to the best of my knowledge that's the case.
OK, I'm removing allusion to an ARMv7 TRM from the comment.
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
This is why I preferred to treat the whole sequence as specific to a particular CPU implementation. The similarity between A7 and A15 might be viewed as a happy coincidence (it also makes life easier in big.LITTLE land).
Quoted 7 lines
Quoted 1 line
Fair enough.
I disagree on the happy coincidence but the point is taken. I am not sure about what we should do, but I reiterate my point, the sequence as it stands is OK on all NS v7 implementations I am aware of. We can add macros to differentiate processors when we need them, but again that's just my opinion, as correct as it can be.
I tend to prefer that as well.
"In theory, practice and theory are equivalent, but in practice they're not"
So if in _practice_ all the ARMv7 implementations we care about are OK with the above, then I don't see why we couldn't call it v7_*.
Here's the portion of the patch that I just changed. All the rest stayed the same. What do you think?
arch/arm/include/asm/cacheflush.h +34 -0
@@ -436,4 +436,38 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size)#define sync_cache_w (ptr) __sync_cache_range_w(ptr, sizeof *(ptr))#define sync_cache_r (ptr) __sync_cache_range_r(ptr, sizeof *(ptr)) +/* +* Disabling cache access for one CPU in an ARMv7 SMP system is tricky. +* To do so we must: +* +* - Clear the SCTLR.C bit to prevent further cache allocations +* - Flush the desired level of cache +* - Clear the ACTLR "SMP" bit to disable local coherency +* +* ... and so without any intervening memory access in between those steps, +* not even to the stack. +* +* WARNING -- After this has been called: +* +* - No ldrex/strex (and similar) instructions must be used. +* - The CPU is obviously no longer coherent with the other CPUs. +* - This is unlikely to work as expected if Linux is running non-secure. +*/ +#define v7_exit_coherency_flush(level) \ + asm volatile( \ + "mrc p15, 0, r0, c1, c0, 0 @ get SCTLR \n\t" \ + "bic r0, r0, #"__stringify(CR_C)" \n\t" \ + "mcr p15, 0, r0, c1, c0, 0 @ set SCTLR \n\t" \ + "isb \n\t" \ + "bl v7_flush_dcache_"__stringify(level)" \n\t" \ + "clrex \n\t" \ + "mrc p15, 0, r0, c1, c0, 1 @ get ACTLR \n\t" \ + "bic r0, r0, #(1 << 6) @ disable local coherency \n\t" \ + "mcr p15, 0, r0, c1, c0, 1 @ set ACTLR \n\t" \ + "isb \n\t" \ + "dsb " \ + /* The clobber list is dictated by the call to v7_flush_dcache_* */ \ + : : : "r0","r1","r2","r3","r4","r5","r6","r7", \ + "r9","r10","r11","lr","memory" ) +#endif
Nicolas
PATCH 1/4 ARM: vexpress/dcscb: fix cache disabling sequences
In reply to Lorenzo PieralisiQuoted 21 lines · Lorenzo Pieralisi
On Tue, Jul 23, 2013 at 01:28:16PM +0100, Nicolas Pitre wrote:
[...]
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
+ * - The CPU is obviously no longer coherent with the other CPUs.
+ *
+ * Further considerations:
+ *
+ * - This relies on the presence and behavior of the AUXCR.SMP bit as
+ * documented in the ARMv7 TRM. Vendor implementations that deviate fromQuoted 9 lines
Quoted 2 lines
Sorry to be pedantic here, but there is no "ARMv7 TRM". The SMP bit is not part of ARMv7 at all.
Well, I just copied Lorenzo's words here, trusting he knew more about it than I do.
Quoted 3 lines
Also, it seems that A9 isn't precisely the
same: two ACTLR bits need to be twiddled. R-class CPUs are generally not the same either.
Quoted 8 lines
If you mean the ACTLR.FW bit in A9, A5, and R7, then, IIRC, we do not need to clear it, clearing the SMP bit is enough.
See, Dave has a point, there is no explicit "unified v7 TRM disable clean and exit coherency procedure" even though the designers end goal is to have one and that's the one you wrote. The code you posted is perfectly ok on all v7 implementations in the kernel I am aware of, I stand to be corrected but to the best of my knowledge that's the case.
What I'm really concerned about here is not Cortex-*, but the vendors who have their own CPU implementations. I don't think I've ever seen a TRM for one of those.
Quoted 9 lines
Quoted 7 lines
Quoted 5 lines
This is why I preferred to treat the whole sequence as specific to a particular CPU implementation. The similarity between A7 and A15 might be viewed as a happy coincidence (it also makes life easier in big.LITTLE land).
Fair enough.
I disagree on the happy coincidence but the point is taken. I am not
I confess to exaggeration! There was obviously an effort to align A15 and A7, but we know there are differences at the system level, and there is always the possibility of b.L pairings which differ on things like the SMP bit, or b.L pairings of CPUs not originally designed to pair but which are "similar enough" to be pairable.
Quoted 4 lines
sure about what we should do, but I reiterate my point, the sequence as it stands is OK on all NS v7 implementations I am aware of. We can add macros to differentiate processors when we need them, but again that's just my opinion, as correct as it can be.
I still vote for naming them a15_* a7_* or similar.
For big.LITTLE pairings, I think we should assume that the big CPU's macro is usable on the LITTLE CPU too. Assuming sane CPU designs, that will be true, and we know it works for A15+A7.
So we would use the a15 macro on TC2, but the a7 macro on an a7-only platform.
The other way to abstract this stuff would be to add a new per-CPU proc_fn, but that may be overkill, particularly since we know the whole mcpm backend may tend to be platform-specific, not just the CPU coherency exit part.
Cheers
---Dave
PATCH 1/4 ARM: vexpress/dcscb: fix cache disabling sequences
Quoted 31 lines · Dave Martin
Quoted 21 lines · Lorenzo Pieralisi
On Tue, Jul 23, 2013 at 01:28:16PM +0100, Nicolas Pitre wrote:
[...]
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
+ * - The CPU is obviously no longer coherent with the other CPUs.
+ *
+ * Further considerations:
+ *
+ * - This relies on the presence and behavior of the AUXCR.SMP bit as
+ * documented in the ARMv7 TRM. Vendor implementations that deviate fromQuoted 9 lines
Quoted 2 lines
Sorry to be pedantic here, but there is no "ARMv7 TRM". The SMP bit is not part of ARMv7 at all.
Well, I just copied Lorenzo's words here, trusting he knew more about it than I do.
Quoted 3 lines
Also, it seems that A9 isn't precisely the
same: two ACTLR bits need to be twiddled. R-class CPUs are generally not the same either.Quoted 8 lines
If you mean the ACTLR.FW bit in A9, A5, and R7, then, IIRC, we do not need to clear it, clearing the SMP bit is enough.
See, Dave has a point, there is no explicit "unified v7 TRM disable clean and exit coherency procedure" even though the designers end goal is to have one and that's the one you wrote. The code you posted is perfectly ok on all v7 implementations in the kernel I am aware of, I stand to be corrected but to the best of my knowledge that's the case.
Quoted 3 lines
What I'm really concerned about here is not Cortex-*, but the vendors who have their own CPU implementations. I don't think I've ever seen a TRM for one of those.
Could we wait until they materialize before worrying about possible incompatibility issues? After all this is not a user space ABI that cannot be changed afterwards. Remember this is Linux internal code we have the ability to change when needed, hence we should resist the temptation to over-engineer.
Quoted 11 lines
I confess to exaggeration! There was obviously an effort to align A15 and A7, but we know there are differences at the system level, and there is always the possibility of b.L pairings which differ on things like the SMP bit, or b.L pairings of CPUs not originally designed to pair but which are "similar enough" to be pairable.
Quoted 4 lines
sure about what we should do, but I reiterate my point, the sequence as it stands is OK on all NS v7 implementations I am aware of. We can add macros to differentiate processors when we need them, but again that's just my opinion, as correct as it can be.
Quoted 5 lines
I still vote for naming them a15_* a7_* or similar.
For big.LITTLE pairings, I think we should assume that the big CPU's macro is usable on the LITTLE CPU too. Assuming sane CPU designs, that will be true, and we know it works for A15+A7.
The MCPM backend don't have to assume any kind of pairing. The TC2 backend already has to test whether or not it is running on an A15 in order to turn off L2 prefetching which is an A15-only feature. This is done outside of this macro exactly to keep the macro generic to all known (so far) v7 implementations.
Nicolas
PATCH 1/4 ARM: vexpress/dcscb: fix cache disabling sequences
Quoted 37 lines · Nicolas Pitre
Quoted 31 lines · Dave Martin
Quoted 21 lines · Lorenzo Pieralisi
On Tue, Jul 23, 2013 at 01:28:16PM +0100, Nicolas Pitre wrote:
[...]
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
+ * - The CPU is obviously no longer coherent with the other CPUs.
+ *
+ * Further considerations:
+ *
+ * - This relies on the presence and behavior of the AUXCR.SMP bit as
+ * documented in the ARMv7 TRM. Vendor implementations that deviate fromQuoted 9 lines
Quoted 2 lines
Sorry to be pedantic here, but there is no "ARMv7 TRM". The SMP bit is not part of ARMv7 at all.
Well, I just copied Lorenzo's words here, trusting he knew more about it than I do.
Quoted 3 lines
Also, it seems that A9 isn't precisely the
same: two ACTLR bits need to be twiddled. R-class CPUs are generally not the same either.Quoted 8 lines
If you mean the ACTLR.FW bit in A9, A5, and R7, then, IIRC, we do not need to clear it, clearing the SMP bit is enough.
See, Dave has a point, there is no explicit "unified v7 TRM disable clean and exit coherency procedure" even though the designers end goal is to have one and that's the one you wrote. The code you posted is perfectly ok on all v7 implementations in the kernel I am aware of, I stand to be corrected but to the best of my knowledge that's the case.
Quoted 3 lines
What I'm really concerned about here is not Cortex-*, but the vendors who have their own CPU implementations. I don't think I've ever seen a TRM for one of those.
Quoted 5 lines
Could we wait until they materialize before worrying about possible incompatibility issues? After all this is not a user space ABI that cannot be changed afterwards. Remember this is Linux internal code we have the ability to change when needed, hence we should resist the temptation to over-engineer.
If I could think of a better name, I would suggest it ... but unless we call it "cortexa" or something, I don't know what it should be. I'm not sure how much I like that either. Strictly speaking, that's still not correct.
So I guess this comes down to being clear about which CPUs we expect it to work for.
Right now, we know it works for A7 and A15.
It sounds like we believe it might work for A9. Lorenzo might know about A5, A7 etc. But I'm not sure this exact sequence has been tested on any of those CPUs(?)
We shouldn't expect it to work for any non ARM Ltd CPU, but on platforms where firmware does the power control it's not Linux's responsibility anyhow. (Probably the case for most of those vendors).
Quoted 17 lines
Quoted 11 lines
I confess to exaggeration! There was obviously an effort to align A15 and A7, but we know there are differences at the system level, and there is always the possibility of b.L pairings which differ on things like the SMP bit, or b.L pairings of CPUs not originally designed to pair but which are "similar enough" to be pairable.
Quoted 4 lines
sure about what we should do, but I reiterate my point, the sequence as it stands is OK on all NS v7 implementations I am aware of. We can add macros to differentiate processors when we need them, but again that's just my opinion, as correct as it can be.
Quoted 5 lines
I still vote for naming them a15_* a7_* or similar.
For big.LITTLE pairings, I think we should assume that the big CPU's macro is usable on the LITTLE CPU too. Assuming sane CPU designs, that will be true, and we know it works for A15+A7.
Quoted 5 lines
The MCPM backend don't have to assume any kind of pairing. The TC2 backend already has to test whether or not it is running on an A15 in order to turn off L2 prefetching which is an A15-only feature. This is done outside of this macro exactly to keep the macro generic to all known (so far) v7 implementations.
That's true.
Cheers
---Dave
PATCH 1/4 ARM: vexpress/dcscb: fix cache disabling sequences
Quoted 48 lines · Dave Martin
Quoted 37 lines · Nicolas Pitre
Quoted 31 lines · Dave Martin
Quoted 21 lines · Lorenzo Pieralisi
On Tue, Jul 23, 2013 at 01:28:16PM +0100, Nicolas Pitre wrote:
[...]
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
+ * - The CPU is obviously no longer coherent with the other CPUs.
+ *
+ * Further considerations:
+ *
+ * - This relies on the presence and behavior of the AUXCR.SMP bit as
+ * documented in the ARMv7 TRM. Vendor implementations that deviate fromQuoted 9 lines
Quoted 2 lines
Sorry to be pedantic here, but there is no "ARMv7 TRM". The SMP bit is not part of ARMv7 at all.
Well, I just copied Lorenzo's words here, trusting he knew more about it than I do.
Quoted 3 lines
Also, it seems that A9 isn't precisely the
same: two ACTLR bits need to be twiddled. R-class CPUs are generally not the same either.Quoted 8 lines
If you mean the ACTLR.FW bit in A9, A5, and R7, then, IIRC, we do not need to clear it, clearing the SMP bit is enough.
See, Dave has a point, there is no explicit "unified v7 TRM disable clean and exit coherency procedure" even though the designers end goal is to have one and that's the one you wrote. The code you posted is perfectly ok on all v7 implementations in the kernel I am aware of, I stand to be corrected but to the best of my knowledge that's the case.
Quoted 3 lines
What I'm really concerned about here is not Cortex-*, but the vendors who have their own CPU implementations. I don't think I've ever seen a TRM for one of those.
Quoted 5 lines
Could we wait until they materialize before worrying about possible incompatibility issues? After all this is not a user space ABI that cannot be changed afterwards. Remember this is Linux internal code we have the ability to change when needed, hence we should resist the temptation to over-engineer.
If I could think of a better name, I would suggest it ... but unless we call it "cortexa" or something, I don't know what it should be. I'm not sure how much I like that either. Strictly speaking, that's still not correct.
Quoted 8 lines
So I guess this comes down to being clear about which CPUs we expect it to work for.
Right now, we know it works for A7 and A15.
It sounds like we believe it might work for A9. Lorenzo might know about A5, A7 etc. But I'm not sure this exact sequence has been tested on any of those CPUs(?)
I tested this sequence on A9 MP a while ago, even though, obviously was not this same macro. I know for certain it has been tested on A5, again not the same macro but the same sequence.
On R7 honestly I can't certify.
What if we postpone the consolidation till MCPM for some A9 platforms (eg Tegra) is posted (and in the meantime you leave the macro in mach-vexpress to avoid duplication) ?
Thank you,
Lorenzo
PATCH 2/4 drivers/platform: vexpress: add Serial Power Controller (SPC) support
In reply to Nicolas PitreFrom: Lorenzo Pieralisi <[email protected]>
The TC2 versatile express core tile integrates a logic block that provides the interface between the dual cluster test-chip and the M3 microcontroller that carries out power management. The logic block, called Serial Power Controller (SPC), contains several memory mapped registers to control among other things low-power states, wake-up irqs and per-CPU jump addresses registers.
This patch provides a driver that enables run-time control of features implemented by the SPC power management control logic with an API to be used by different subsystem drivers on top.
The SPC control logic is required to be programmed very early in the boot process to reset secondary CPUs on the TC2 testchip, set-up jump addresses and wake-up IRQs for power management. Hence, waiting for core changes to be made in the device core code to enable early registration of platform devices, the driver puts in place an early init scheme that allows kernel drivers to initialize the SPC driver directly from the components requiring it, if their initialization routine is called before this driver init function during the boot process.
Device tree bindings documentation for the SPC component is also provided.
--- .../devicetree/bindings/arm/vexpress-spc.txt | 36 +++ drivers/platform/Kconfig | 4 +- drivers/platform/Makefile | 1 + drivers/platform/vexpress/Kconfig | 9 + drivers/platform/vexpress/Makefile | 1 + drivers/platform/vexpress/spc.c | 253 +++++++++++++++++++++ include/linux/vexpress.h | 17 ++ 7 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/arm/vexpress-spc.txt create mode 100644 drivers/platform/vexpress/Kconfig create mode 100644 drivers/platform/vexpress/Makefile create mode 100644 drivers/platform/vexpress/spc.c
Documentation/devicetree/bindings/arm/vexpress-spc.txt new file +36 -0
@@ -0,0 +1,36 @@ +* ARM Versatile Express Serial Power Controller device tree bindings + +Latest ARM development boards implement a power management interface (serial +power controller - SPC) that is capable of managing power states transitions, +wake-up IRQs and resume addresses for ARM multiprocessor testchips. +The serial controller can be programmed through a memory mapped interface +that enables communication between firmware running on the microcontroller +managing power states and the application processors. + +The SPC DT bindings are defined as follows: + +- spc node + + - compatible: + Usage: required + Value type: <stringlist> + Definition: must be + "arm,vexpress-spc,v2p-ca15_a7", "arm,vexpress-spc" + - reg: + Usage: required + Value type: <prop-encode-array> + Definition: A standard property that specifies the base address + and the size of the SPC address space + - interrupts: + Usage: required + Value type: <prop-encoded-array> + Definition: SPC interrupt configuration. A standard property + that follows ePAPR interrupts specifications + +Example: + +spc: spc at 7fff0000 { + compatible = "arm,vexpress-spc,v2p-ca15_a7", "arm,vexpress-spc"; + reg = <0x7fff0000 0x1000>; + interrupts = <0 95 4>; +};
drivers/platform/Kconfig +3 -1
@@ -4,4 +4,6 @@ endif if GOLDFISH source "drivers/platform/goldfish/Kconfig" endif - +if ARCH_VEXPRESS +source "drivers/platform/vexpress/Kconfig" +endif
drivers/platform/Makefile +1 -0
@@ -5,3 +5,4 @@ obj-$(CONFIG_X86) += x86/ obj-$(CONFIG_OLPC) += olpc/ obj-$(CONFIG_GOLDFISH) += goldfish/ +obj-$(CONFIG_ARCH_VEXPRESS) += vexpress/
drivers/platform/vexpress/Kconfig new file +9 -0
@@ -0,0 +1,9 @@ +config VEXPRESS_SPC + bool "Versatile Express SPC driver support" + help + The Serial Power Controller (SPC) for ARM Ltd. test chips, is + an IP that provides a memory mapped interface to power controller + HW. The driver provides an API abstraction meant to be used by + subsystem drivers allowing to program registers controlling + low-level power management features like power down flags, + global and per-cpu wake-up IRQs.
drivers/platform/vexpress/Makefile new file +1 -0
@@ -0,0 +1 @@ +obj-$(CONFIG_VEXPRESS_SPC) += spc.o
drivers/platform/vexpress/spc.c new file +253 -0
253 lines not on this page · raw message
include/linux/vexpress.h +17 -0
@@ -124,4 +124,21 @@ void vexpress_osc_of_setup(struct device_node *node);void vexpress_clk_init (void __iomem *sp810_base);void vexpress_clk_of_init (void ); +/* SPC */ + +#ifdef CONFIG_VEXPRESS_SPC +int __init ve_spc_init (void ); +void ve_spc_global_wakeup_irq (bool set); +void ve_spc_cpu_wakeup_irq (u32 cluster,u32 cpu,bool set); +void ve_spc_set_resume_addr (u32 cluster,u32 cpu,u32 addr); +u32 ve_spc_get_nr_cpus (u32 cluster); +void ve_spc_powerdown (u32 cluster,bool enable); +#else +static inline int ve_spc_init (void ) {return -ENODEV ; } +static inline void ve_spc_global_wakeup_irq (bool set) { } +static inline void ve_spc_cpu_wakeup_irq (u32 cluster,u32 cpu,bool set) { } +static inline void ve_spc_set_resume_addr (u32 cluster,u32 cpu,u32 addr) { } +static inline u32 ve_spc_get_nr_cpus (u32 cluster) {return 0 ; } +static inline void ve_spc_powerdown (u32 cluster,bool enable) { } +#endif #endif
Signature · 1 line
1.8.1.2
PATCH 3/4 ARM: vexpress/TC2: basic PM support
In reply to Nicolas PitreThis is the MCPM backend for the Virtual Express A15x2 A7x3 CoreTile aka TC2. This provides cluster management for SMP secondary boot and CPU hotplug.
--- arch/arm/mach-vexpress/Kconfig | 9 ++ arch/arm/mach-vexpress/Makefile | 1 + arch/arm/mach-vexpress/tc2_pm.c | 287 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 297 insertions(+) create mode 100644 arch/arm/mach-vexpress/tc2_pm.c
arch/arm/mach-vexpress/Kconfig +9 -0
@@ -66,4 +66,13 @@ config ARCH_VEXPRESS_DCSCB This is needed to provide CPU and cluster power management on RTSM implementing big.LITTLE. +config ARCH_VEXPRESS_TC2_PM + bool "Versatile Express TC2 power management" + depends on MCPM + select VEXPRESS_SPC + select ARM_CCI + help + Support for CPU and cluster power management on Versatile Express + with a TC2 (A15x2 A7x3) big.LITTLE core tile. + endmenu
arch/arm/mach-vexpress/Makefile +1 -0
@@ -7,5 +7,6 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \ obj-y := v2m.o obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o obj-$(CONFIG_ARCH_VEXPRESS_DCSCB) += dcscb.o dcscb_setup.o +obj-$(CONFIG_ARCH_VEXPRESS_TC2_PM) += tc2_pm.o obj-$(CONFIG_SMP) += platsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
arch/arm/mach-vexpress/tc2_pm.c new file +287 -0
287 lines not on this page · raw message
Signature · 1 line
1.8.1.2
PATCH 4/4 ARM: vexpress/TC2: implement PM suspend method
In reply to Nicolas PitreFrom: Nicolas Pitre <[email protected]>
Similar to power_down(), except that for a suspend, the firmware mailbox address has to be set prior entering low power mode.
The residency argument is not used yet, so the last man always shuts down the cluster for now.
--- arch/arm/mach-vexpress/tc2_pm.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-)
arch/arm/mach-vexpress/tc2_pm.c +18 -1
@@ -84,7 +84,7 @@ static int tc2_pm_power_up(unsigned int cpu, unsigned int cluster)return 0 ; } -static void tc2_pm_power_down (void ) +static void tc2_pm_down (u64 residency) {unsigned int mpidr, cpu, cluster;bool last_man = false, skip_wfi = false;
@@ -198,6 +198,22 @@ static void tc2_pm_power_down(void)/* Not dead at this point? Let our caller cope. */ } +static void tc2_pm_power_down (void ) +{ +tc2_pm_down (0 ); +} + +static void tc2_pm_suspend (u64 residency) +{ +unsigned int mpidr, cpu, cluster; + + mpidr =read_cpuid_mpidr (); + cpu =MPIDR_AFFINITY_LEVEL (mpidr,0 ); + cluster =MPIDR_AFFINITY_LEVEL (mpidr,1 ); +ve_spc_set_resume_addr (cluster, cpu,virt_to_phys (mcpm_entry_point)); +tc2_pm_down (residency); +} +static void tc2_pm_powered_up (void ) {unsigned int mpidr, cpu, cluster;
@@ -231,6 +247,7 @@ static void tc2_pm_powered_up(void)static const struct mcpm_platform_ops tc2_pm_power_ops = { .power_up = tc2_pm_power_up, .power_down = tc2_pm_power_down, + .suspend = tc2_pm_suspend, .powered_up = tc2_pm_powered_up, };
Signature · 1 line
1.8.1.2