diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-12-18 14:13:22 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-12-20 22:21:15 -0500 |
commit | 6d2170be4561293a6aa821c773687bd3f18e8206 (patch) | |
tree | b267fb2405c6029dcc7958c5786699741064e43f /arch/powerpc | |
parent | fecba96268fc48ab9b4a016356a8f2371df25e64 (diff) |
powerpc/4xx: Extended DCR support v2
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@kernel.crashing.org>
Acked-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Acked-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/include/asm/cputable.h | 7 | ||||
-rw-r--r-- | arch/powerpc/include/asm/dcr-native.h | 63 | ||||
-rw-r--r-- | arch/powerpc/kernel/cputable.c | 4 | ||||
-rw-r--r-- | arch/powerpc/sysdev/dcr-low.S | 8 |
4 files changed, 65 insertions, 17 deletions
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index f3d9d7417166..31888322d76a 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h | |||
@@ -164,6 +164,7 @@ extern const char *powerpc_base_platform; | |||
164 | #define CPU_FTR_NEED_PAIRED_STWCX ASM_CONST(0x0000000004000000) | 164 | #define CPU_FTR_NEED_PAIRED_STWCX ASM_CONST(0x0000000004000000) |
165 | #define CPU_FTR_LWSYNC ASM_CONST(0x0000000008000000) | 165 | #define CPU_FTR_LWSYNC ASM_CONST(0x0000000008000000) |
166 | #define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000010000000) | 166 | #define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000010000000) |
167 | #define CPU_FTR_INDEXED_DCR ASM_CONST(0x0000000020000000) | ||
167 | 168 | ||
168 | /* | 169 | /* |
169 | * Add the 64-bit processor unique features in the top half of the word; | 170 | * Add the 64-bit processor unique features in the top half of the word; |
@@ -369,6 +370,8 @@ extern const char *powerpc_base_platform; | |||
369 | #define CPU_FTRS_8XX (CPU_FTR_USE_TB) | 370 | #define CPU_FTRS_8XX (CPU_FTR_USE_TB) |
370 | #define CPU_FTRS_40X (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE) | 371 | #define CPU_FTRS_40X (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE) |
371 | #define CPU_FTRS_44X (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE) | 372 | #define CPU_FTRS_44X (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE) |
373 | #define CPU_FTRS_440x6 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE | \ | ||
374 | CPU_FTR_INDEXED_DCR) | ||
372 | #define CPU_FTRS_E200 (CPU_FTR_USE_TB | CPU_FTR_SPE_COMP | \ | 375 | #define CPU_FTRS_E200 (CPU_FTR_USE_TB | CPU_FTR_SPE_COMP | \ |
373 | CPU_FTR_NODSISRALIGN | CPU_FTR_COHERENT_ICACHE | \ | 376 | CPU_FTR_NODSISRALIGN | CPU_FTR_COHERENT_ICACHE | \ |
374 | CPU_FTR_UNIFIED_ID_CACHE | CPU_FTR_NOEXECUTE) | 377 | CPU_FTR_UNIFIED_ID_CACHE | CPU_FTR_NOEXECUTE) |
@@ -455,7 +458,7 @@ enum { | |||
455 | CPU_FTRS_40X | | 458 | CPU_FTRS_40X | |
456 | #endif | 459 | #endif |
457 | #ifdef CONFIG_44x | 460 | #ifdef CONFIG_44x |
458 | CPU_FTRS_44X | | 461 | CPU_FTRS_44X | CPU_FTRS_440x6 | |
459 | #endif | 462 | #endif |
460 | #ifdef CONFIG_E200 | 463 | #ifdef CONFIG_E200 |
461 | CPU_FTRS_E200 | | 464 | CPU_FTRS_E200 | |
@@ -495,7 +498,7 @@ enum { | |||
495 | CPU_FTRS_40X & | 498 | CPU_FTRS_40X & |
496 | #endif | 499 | #endif |
497 | #ifdef CONFIG_44x | 500 | #ifdef CONFIG_44x |
498 | CPU_FTRS_44X & | 501 | CPU_FTRS_44X & CPU_FTRS_440x6 & |
499 | #endif | 502 | #endif |
500 | #ifdef CONFIG_E200 | 503 | #ifdef CONFIG_E200 |
501 | CPU_FTRS_E200 & | 504 | CPU_FTRS_E200 & |
diff --git a/arch/powerpc/include/asm/dcr-native.h b/arch/powerpc/include/asm/dcr-native.h index 72d2b72c7390..7d2e6235726d 100644 --- a/arch/powerpc/include/asm/dcr-native.h +++ b/arch/powerpc/include/asm/dcr-native.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #ifndef __ASSEMBLY__ | 23 | #ifndef __ASSEMBLY__ |
24 | 24 | ||
25 | #include <linux/spinlock.h> | 25 | #include <linux/spinlock.h> |
26 | #include <asm/cputable.h> | ||
26 | 27 | ||
27 | typedef struct { | 28 | typedef struct { |
28 | unsigned int base; | 29 | unsigned int base; |
@@ -39,23 +40,45 @@ static inline bool dcr_map_ok_native(dcr_host_native_t host) | |||
39 | #define dcr_read_native(host, dcr_n) mfdcr(dcr_n + host.base) | 40 | #define dcr_read_native(host, dcr_n) mfdcr(dcr_n + host.base) |
40 | #define dcr_write_native(host, dcr_n, value) mtdcr(dcr_n + host.base, value) | 41 | #define dcr_write_native(host, dcr_n, value) mtdcr(dcr_n + host.base, value) |
41 | 42 | ||
42 | /* Device Control Registers */ | 43 | /* Table based DCR accessors */ |
43 | void __mtdcr(int reg, unsigned int val); | 44 | extern void __mtdcr(unsigned int reg, unsigned int val); |
44 | unsigned int __mfdcr(int reg); | 45 | extern unsigned int __mfdcr(unsigned int reg); |
46 | |||
47 | /* mfdcrx/mtdcrx instruction based accessors. We hand code | ||
48 | * the opcodes in order not to depend on newer binutils | ||
49 | */ | ||
50 | static inline unsigned int mfdcrx(unsigned int reg) | ||
51 | { | ||
52 | unsigned int ret; | ||
53 | asm volatile(".long 0x7c000206 | (%0 << 21) | (%1 << 16)" | ||
54 | : "=r" (ret) : "r" (reg)); | ||
55 | return ret; | ||
56 | } | ||
57 | |||
58 | static inline void mtdcrx(unsigned int reg, unsigned int val) | ||
59 | { | ||
60 | asm volatile(".long 0x7c000306 | (%0 << 21) | (%1 << 16)" | ||
61 | : : "r" (val), "r" (reg)); | ||
62 | } | ||
63 | |||
45 | #define mfdcr(rn) \ | 64 | #define mfdcr(rn) \ |
46 | ({unsigned int rval; \ | 65 | ({unsigned int rval; \ |
47 | if (__builtin_constant_p(rn)) \ | 66 | if (__builtin_constant_p(rn) && rn < 1024) \ |
48 | asm volatile("mfdcr %0," __stringify(rn) \ | 67 | asm volatile("mfdcr %0," __stringify(rn) \ |
49 | : "=r" (rval)); \ | 68 | : "=r" (rval)); \ |
69 | else if (likely(cpu_has_feature(CPU_FTR_INDEXED_DCR))) \ | ||
70 | rval = mfdcrx(rn); \ | ||
50 | else \ | 71 | else \ |
51 | rval = __mfdcr(rn); \ | 72 | rval = __mfdcr(rn); \ |
52 | rval;}) | 73 | rval;}) |
53 | 74 | ||
54 | #define mtdcr(rn, v) \ | 75 | #define mtdcr(rn, v) \ |
55 | do { \ | 76 | do { \ |
56 | if (__builtin_constant_p(rn)) \ | 77 | if (__builtin_constant_p(rn) && rn < 1024) \ |
57 | asm volatile("mtdcr " __stringify(rn) ",%0" \ | 78 | asm volatile("mtdcr " __stringify(rn) ",%0" \ |
58 | : : "r" (v)); \ | 79 | : : "r" (v)); \ |
80 | else if (likely(cpu_has_feature(CPU_FTR_INDEXED_DCR))) \ | ||
81 | mtdcrx(rn, v); \ | ||
59 | else \ | 82 | else \ |
60 | __mtdcr(rn, v); \ | 83 | __mtdcr(rn, v); \ |
61 | } while (0) | 84 | } while (0) |
@@ -69,8 +92,13 @@ static inline unsigned __mfdcri(int base_addr, int base_data, int reg) | |||
69 | unsigned int val; | 92 | unsigned int val; |
70 | 93 | ||
71 | spin_lock_irqsave(&dcr_ind_lock, flags); | 94 | spin_lock_irqsave(&dcr_ind_lock, flags); |
72 | __mtdcr(base_addr, reg); | 95 | if (cpu_has_feature(CPU_FTR_INDEXED_DCR)) { |
73 | val = __mfdcr(base_data); | 96 | mtdcrx(base_addr, reg); |
97 | val = mfdcrx(base_data); | ||
98 | } else { | ||
99 | __mtdcr(base_addr, reg); | ||
100 | val = __mfdcr(base_data); | ||
101 | } | ||
74 | spin_unlock_irqrestore(&dcr_ind_lock, flags); | 102 | spin_unlock_irqrestore(&dcr_ind_lock, flags); |
75 | return val; | 103 | return val; |
76 | } | 104 | } |
@@ -81,8 +109,13 @@ static inline void __mtdcri(int base_addr, int base_data, int reg, | |||
81 | unsigned long flags; | 109 | unsigned long flags; |
82 | 110 | ||
83 | spin_lock_irqsave(&dcr_ind_lock, flags); | 111 | spin_lock_irqsave(&dcr_ind_lock, flags); |
84 | __mtdcr(base_addr, reg); | 112 | if (cpu_has_feature(CPU_FTR_INDEXED_DCR)) { |
85 | __mtdcr(base_data, val); | 113 | mtdcrx(base_addr, reg); |
114 | mtdcrx(base_data, val); | ||
115 | } else { | ||
116 | __mtdcr(base_addr, reg); | ||
117 | __mtdcr(base_data, val); | ||
118 | } | ||
86 | spin_unlock_irqrestore(&dcr_ind_lock, flags); | 119 | spin_unlock_irqrestore(&dcr_ind_lock, flags); |
87 | } | 120 | } |
88 | 121 | ||
@@ -93,9 +126,15 @@ static inline void __dcri_clrset(int base_addr, int base_data, int reg, | |||
93 | unsigned int val; | 126 | unsigned int val; |
94 | 127 | ||
95 | spin_lock_irqsave(&dcr_ind_lock, flags); | 128 | spin_lock_irqsave(&dcr_ind_lock, flags); |
96 | __mtdcr(base_addr, reg); | 129 | if (cpu_has_feature(CPU_FTR_INDEXED_DCR)) { |
97 | val = (__mfdcr(base_data) & ~clr) | set; | 130 | mtdcrx(base_addr, reg); |
98 | __mtdcr(base_data, val); | 131 | val = (mfdcrx(base_data) & ~clr) | set; |
132 | mtdcrx(base_data, val); | ||
133 | } else { | ||
134 | __mtdcr(base_addr, reg); | ||
135 | val = (__mfdcr(base_data) & ~clr) | set; | ||
136 | __mtdcr(base_data, val); | ||
137 | } | ||
99 | spin_unlock_irqrestore(&dcr_ind_lock, flags); | 138 | spin_unlock_irqrestore(&dcr_ind_lock, flags); |
100 | } | 139 | } |
101 | 140 | ||
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 7e8719504f39..921a2298d8e3 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -1509,7 +1509,7 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1509 | .pvr_mask = 0xffff0002, | 1509 | .pvr_mask = 0xffff0002, |
1510 | .pvr_value = 0x13020002, | 1510 | .pvr_value = 0x13020002, |
1511 | .cpu_name = "460EX", | 1511 | .cpu_name = "460EX", |
1512 | .cpu_features = CPU_FTRS_44X, | 1512 | .cpu_features = CPU_FTRS_440x6, |
1513 | .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, | 1513 | .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, |
1514 | .icache_bsize = 32, | 1514 | .icache_bsize = 32, |
1515 | .dcache_bsize = 32, | 1515 | .dcache_bsize = 32, |
@@ -1521,7 +1521,7 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1521 | .pvr_mask = 0xffff0002, | 1521 | .pvr_mask = 0xffff0002, |
1522 | .pvr_value = 0x13020000, | 1522 | .pvr_value = 0x13020000, |
1523 | .cpu_name = "460GT", | 1523 | .cpu_name = "460GT", |
1524 | .cpu_features = CPU_FTRS_44X, | 1524 | .cpu_features = CPU_FTRS_440x6, |
1525 | .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, | 1525 | .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, |
1526 | .icache_bsize = 32, | 1526 | .icache_bsize = 32, |
1527 | .dcache_bsize = 32, | 1527 | .dcache_bsize = 32, |
diff --git a/arch/powerpc/sysdev/dcr-low.S b/arch/powerpc/sysdev/dcr-low.S index 2078f39e2f17..d3098ef1404a 100644 --- a/arch/powerpc/sysdev/dcr-low.S +++ b/arch/powerpc/sysdev/dcr-low.S | |||
@@ -11,14 +11,20 @@ | |||
11 | 11 | ||
12 | #include <asm/ppc_asm.h> | 12 | #include <asm/ppc_asm.h> |
13 | #include <asm/processor.h> | 13 | #include <asm/processor.h> |
14 | #include <asm/bug.h> | ||
14 | 15 | ||
15 | #define DCR_ACCESS_PROLOG(table) \ | 16 | #define DCR_ACCESS_PROLOG(table) \ |
17 | cmpli cr0,r3,1024; \ | ||
16 | rlwinm r3,r3,4,18,27; \ | 18 | rlwinm r3,r3,4,18,27; \ |
17 | lis r5,table@h; \ | 19 | lis r5,table@h; \ |
18 | ori r5,r5,table@l; \ | 20 | ori r5,r5,table@l; \ |
19 | add r3,r3,r5; \ | 21 | add r3,r3,r5; \ |
22 | bge- 1f; \ | ||
20 | mtctr r3; \ | 23 | mtctr r3; \ |
21 | bctr | 24 | bctr; \ |
25 | 1: trap; \ | ||
26 | EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0; \ | ||
27 | blr | ||
22 | 28 | ||
23 | _GLOBAL(__mfdcr) | 29 | _GLOBAL(__mfdcr) |
24 | DCR_ACCESS_PROLOG(__mfdcr_table) | 30 | DCR_ACCESS_PROLOG(__mfdcr_table) |