aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-12-18 14:13:22 -0500
committerPaul Mackerras <paulus@samba.org>2008-12-20 22:21:15 -0500
commit6d2170be4561293a6aa821c773687bd3f18e8206 (patch)
treeb267fb2405c6029dcc7958c5786699741064e43f /arch
parentfecba96268fc48ab9b4a016356a8f2371df25e64 (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')
-rw-r--r--arch/powerpc/include/asm/cputable.h7
-rw-r--r--arch/powerpc/include/asm/dcr-native.h63
-rw-r--r--arch/powerpc/kernel/cputable.c4
-rw-r--r--arch/powerpc/sysdev/dcr-low.S8
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
27typedef struct { 28typedef 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 */
43void __mtdcr(int reg, unsigned int val); 44extern void __mtdcr(unsigned int reg, unsigned int val);
44unsigned int __mfdcr(int reg); 45extern 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 */
50static 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
58static 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) \
55do { \ 76do { \
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; \
251: 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)