diff options
Diffstat (limited to 'arch/powerpc/include/asm/dcr-native.h')
-rw-r--r-- | arch/powerpc/include/asm/dcr-native.h | 63 |
1 files changed, 51 insertions, 12 deletions
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 | ||