[PATCH 1/10] powerpc/4xx: Extended DCR support v2
Josh Boyer
jwboyer at linux.vnet.ibm.com
Fri Dec 19 23:36:11 EST 2008
On Fri, Dec 19, 2008 at 04:13:22PM +1100, Benjamin Herrenschmidt wrote:
>This adds supports to the "extended" DCR addressing via
>the indirect mfdcrx/mtdcrx instructions supported by some
>4xx cores (440H6 and later)
>
>I enabled the feature for now only on AMCC 460 chips
>
>Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
Acked-by: Josh Boyer <jwboyer at linux.vnet.ibm.com>
In general, if you just carry over my previous Acks it'll make life
easier ;)
josh
>---
>
>This variant uses "440x6" instead of "440H6". I made no other
>changes to the code as I think the codegen is the less bad I've
>had so far and I rely on Josh further work on cleaning up the
>type of 440core selection at Kconfig time so the feature are
>properly reflected in the POSSIBLE and ALWAYS masks based on
>the core selection. That way, if only one core type is selected
>the feature test should resolve at compile time.
>
>
> arch/powerpc/include/asm/cputable.h | 7 ++-
> arch/powerpc/include/asm/dcr-native.h | 63 +++++++++++++++++++++++++++-------
> arch/powerpc/kernel/cputable.c | 4 +-
> arch/powerpc/sysdev/dcr-low.S | 8 +++-
> 4 files changed, 65 insertions(+), 17 deletions(-)
>
>--- linux-work.orig/arch/powerpc/include/asm/cputable.h 2008-12-17 12:28:23.000000000 +1100
>+++ linux-work/arch/powerpc/include/asm/cputable.h 2008-12-17 12:30:52.000000000 +1100
>@@ -164,6 +164,7 @@ extern const char *powerpc_base_platform
> #define CPU_FTR_NEED_PAIRED_STWCX ASM_CONST(0x0000000004000000)
> #define CPU_FTR_LWSYNC ASM_CONST(0x0000000008000000)
> #define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000010000000)
>+#define CPU_FTR_INDEXED_DCR ASM_CONST(0x0000000020000000)
>
> /*
> * Add the 64-bit processor unique features in the top half of the word;
>@@ -369,6 +370,8 @@ extern const char *powerpc_base_platform
> #define CPU_FTRS_8XX (CPU_FTR_USE_TB)
> #define CPU_FTRS_40X (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE)
> #define CPU_FTRS_44X (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE)
>+#define CPU_FTRS_440x6 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE | \
>+ CPU_FTR_INDEXED_DCR)
> #define CPU_FTRS_E200 (CPU_FTR_USE_TB | CPU_FTR_SPE_COMP | \
> CPU_FTR_NODSISRALIGN | CPU_FTR_COHERENT_ICACHE | \
> CPU_FTR_UNIFIED_ID_CACHE | CPU_FTR_NOEXECUTE)
>@@ -455,7 +458,7 @@ enum {
> CPU_FTRS_40X |
> #endif
> #ifdef CONFIG_44x
>- CPU_FTRS_44X |
>+ CPU_FTRS_44X | CPU_FTRS_440x6 |
> #endif
> #ifdef CONFIG_E200
> CPU_FTRS_E200 |
>@@ -495,7 +498,7 @@ enum {
> CPU_FTRS_40X &
> #endif
> #ifdef CONFIG_44x
>- CPU_FTRS_44X &
>+ CPU_FTRS_44X & CPU_FTRS_440x6 &
> #endif
> #ifdef CONFIG_E200
> CPU_FTRS_E200 &
>Index: linux-work/arch/powerpc/include/asm/dcr-native.h
>===================================================================
>--- linux-work.orig/arch/powerpc/include/asm/dcr-native.h 2008-09-29 14:21:37.000000000 +1000
>+++ linux-work/arch/powerpc/include/asm/dcr-native.h 2008-12-17 12:30:52.000000000 +1100
>@@ -23,6 +23,7 @@
> #ifndef __ASSEMBLY__
>
> #include <linux/spinlock.h>
>+#include <asm/cputable.h>
>
> typedef struct {
> unsigned int base;
>@@ -39,23 +40,45 @@ static inline bool dcr_map_ok_native(dcr
> #define dcr_read_native(host, dcr_n) mfdcr(dcr_n + host.base)
> #define dcr_write_native(host, dcr_n, value) mtdcr(dcr_n + host.base, value)
>
>-/* Device Control Registers */
>-void __mtdcr(int reg, unsigned int val);
>-unsigned int __mfdcr(int reg);
>+/* Table based DCR accessors */
>+extern void __mtdcr(unsigned int reg, unsigned int val);
>+extern unsigned int __mfdcr(unsigned int reg);
>+
>+/* mfdcrx/mtdcrx instruction based accessors. We hand code
>+ * the opcodes in order not to depend on newer binutils
>+ */
>+static inline unsigned int mfdcrx(unsigned int reg)
>+{
>+ unsigned int ret;
>+ asm volatile(".long 0x7c000206 | (%0 << 21) | (%1 << 16)"
>+ : "=r" (ret) : "r" (reg));
>+ return ret;
>+}
>+
>+static inline void mtdcrx(unsigned int reg, unsigned int val)
>+{
>+ asm volatile(".long 0x7c000306 | (%0 << 21) | (%1 << 16)"
>+ : : "r" (val), "r" (reg));
>+}
>+
> #define mfdcr(rn) \
> ({unsigned int rval; \
>- if (__builtin_constant_p(rn)) \
>+ if (__builtin_constant_p(rn) && rn < 1024) \
> asm volatile("mfdcr %0," __stringify(rn) \
> : "=r" (rval)); \
>+ else if (likely(cpu_has_feature(CPU_FTR_INDEXED_DCR))) \
>+ rval = mfdcrx(rn); \
> else \
> rval = __mfdcr(rn); \
> rval;})
>
> #define mtdcr(rn, v) \
> do { \
>- if (__builtin_constant_p(rn)) \
>+ if (__builtin_constant_p(rn) && rn < 1024) \
> asm volatile("mtdcr " __stringify(rn) ",%0" \
> : : "r" (v)); \
>+ else if (likely(cpu_has_feature(CPU_FTR_INDEXED_DCR))) \
>+ mtdcrx(rn, v); \
> else \
> __mtdcr(rn, v); \
> } while (0)
>@@ -69,8 +92,13 @@ static inline unsigned __mfdcri(int base
> unsigned int val;
>
> spin_lock_irqsave(&dcr_ind_lock, flags);
>- __mtdcr(base_addr, reg);
>- val = __mfdcr(base_data);
>+ if (cpu_has_feature(CPU_FTR_INDEXED_DCR)) {
>+ mtdcrx(base_addr, reg);
>+ val = mfdcrx(base_data);
>+ } else {
>+ __mtdcr(base_addr, reg);
>+ val = __mfdcr(base_data);
>+ }
> spin_unlock_irqrestore(&dcr_ind_lock, flags);
> return val;
> }
>@@ -81,8 +109,13 @@ static inline void __mtdcri(int base_add
> unsigned long flags;
>
> spin_lock_irqsave(&dcr_ind_lock, flags);
>- __mtdcr(base_addr, reg);
>- __mtdcr(base_data, val);
>+ if (cpu_has_feature(CPU_FTR_INDEXED_DCR)) {
>+ mtdcrx(base_addr, reg);
>+ mtdcrx(base_data, val);
>+ } else {
>+ __mtdcr(base_addr, reg);
>+ __mtdcr(base_data, val);
>+ }
> spin_unlock_irqrestore(&dcr_ind_lock, flags);
> }
>
>@@ -93,9 +126,15 @@ static inline void __dcri_clrset(int bas
> unsigned int val;
>
> spin_lock_irqsave(&dcr_ind_lock, flags);
>- __mtdcr(base_addr, reg);
>- val = (__mfdcr(base_data) & ~clr) | set;
>- __mtdcr(base_data, val);
>+ if (cpu_has_feature(CPU_FTR_INDEXED_DCR)) {
>+ mtdcrx(base_addr, reg);
>+ val = (mfdcrx(base_data) & ~clr) | set;
>+ mtdcrx(base_data, val);
>+ } else {
>+ __mtdcr(base_addr, reg);
>+ val = (__mfdcr(base_data) & ~clr) | set;
>+ __mtdcr(base_data, val);
>+ }
> spin_unlock_irqrestore(&dcr_ind_lock, flags);
> }
>
>Index: linux-work/arch/powerpc/sysdev/dcr-low.S
>===================================================================
>--- linux-work.orig/arch/powerpc/sysdev/dcr-low.S 2008-07-07 13:45:04.000000000 +1000
>+++ linux-work/arch/powerpc/sysdev/dcr-low.S 2008-12-17 12:30:52.000000000 +1100
>@@ -11,14 +11,20 @@
>
> #include <asm/ppc_asm.h>
> #include <asm/processor.h>
>+#include <asm/bug.h>
>
> #define DCR_ACCESS_PROLOG(table) \
>+ cmpli cr0,r3,1024; \
> rlwinm r3,r3,4,18,27; \
> lis r5,table at h; \
> ori r5,r5,table at l; \
> add r3,r3,r5; \
>+ bge- 1f; \
> mtctr r3; \
>- bctr
>+ bctr; \
>+1: trap; \
>+ EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0; \
>+ blr
>
> _GLOBAL(__mfdcr)
> DCR_ACCESS_PROLOG(__mfdcr_table)
>Index: linux-work/arch/powerpc/kernel/cputable.c
>===================================================================
>--- linux-work.orig/arch/powerpc/kernel/cputable.c 2008-12-17 12:28:23.000000000 +1100
>+++ linux-work/arch/powerpc/kernel/cputable.c 2008-12-17 12:30:52.000000000 +1100
>@@ -1509,7 +1509,7 @@ static struct cpu_spec __initdata cpu_sp
> .pvr_mask = 0xffff0002,
> .pvr_value = 0x13020002,
> .cpu_name = "460EX",
>- .cpu_features = CPU_FTRS_44X,
>+ .cpu_features = CPU_FTRS_440x6,
> .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
> .icache_bsize = 32,
> .dcache_bsize = 32,
>@@ -1521,7 +1521,7 @@ static struct cpu_spec __initdata cpu_sp
> .pvr_mask = 0xffff0002,
> .pvr_value = 0x13020000,
> .cpu_name = "460GT",
>- .cpu_features = CPU_FTRS_44X,
>+ .cpu_features = CPU_FTRS_440x6,
> .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
> .icache_bsize = 32,
> .dcache_bsize = 32,
More information about the Linuxppc-dev
mailing list