diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2006-11-11 01:24:55 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-12-04 00:08:35 -0500 |
commit | fbf0274e43b7e17ee740fee2d693932be093d56d (patch) | |
tree | ce4719d4c89cdcb8eb4b57f5cf20fecb106a62e2 /arch | |
parent | 1be3770aa9220324e54851d1be7c879942f79620 (diff) |
[POWERPC] Support for DCR based MPIC
This patch implements support for DCR based MPIC implementations. Such
implementations have the MPIC_USES_DCR flag set and don't use the phys_addr
argument of mpic_alloc (they require a valid dcr mapping in the device node)
This version of the patch can use a little bif of cleanup still (I can
probably consolidate rb->dbase/doff, at least once I'm sure on how the
hardware is actually supposed to work vs. possible simulator issues) and
it should be possible to build a DCR-only version of the driver. I need
to cleanup a bit the CONFIG_* handling for that and probably introduce
CONFIG_MPIC_MMIO and CONFIG_MPIC_DCR.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 136 |
1 files changed, 100 insertions, 36 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index ba4833f57d47..909306ca04f4 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
@@ -147,33 +147,51 @@ static u32 mpic_infos[][MPIC_IDX_END] = { | |||
147 | */ | 147 | */ |
148 | 148 | ||
149 | 149 | ||
150 | static inline u32 _mpic_read(unsigned int be, volatile u32 __iomem *base, | 150 | static inline u32 _mpic_read(enum mpic_reg_type type, |
151 | unsigned int reg) | 151 | struct mpic_reg_bank *rb, |
152 | unsigned int reg) | ||
152 | { | 153 | { |
153 | if (be) | 154 | switch(type) { |
154 | return in_be32(base + (reg >> 2)); | 155 | #ifdef CONFIG_PPC_DCR |
155 | else | 156 | case mpic_access_dcr: |
156 | return in_le32(base + (reg >> 2)); | 157 | return dcr_read(rb->dhost, |
158 | rb->dbase + reg + rb->doff); | ||
159 | #endif | ||
160 | case mpic_access_mmio_be: | ||
161 | return in_be32(rb->base + (reg >> 2)); | ||
162 | case mpic_access_mmio_le: | ||
163 | default: | ||
164 | return in_le32(rb->base + (reg >> 2)); | ||
165 | } | ||
157 | } | 166 | } |
158 | 167 | ||
159 | static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base, | 168 | static inline void _mpic_write(enum mpic_reg_type type, |
160 | unsigned int reg, u32 value) | 169 | struct mpic_reg_bank *rb, |
170 | unsigned int reg, u32 value) | ||
161 | { | 171 | { |
162 | if (be) | 172 | switch(type) { |
163 | out_be32(base + (reg >> 2), value); | 173 | #ifdef CONFIG_PPC_DCR |
164 | else | 174 | case mpic_access_dcr: |
165 | out_le32(base + (reg >> 2), value); | 175 | return dcr_write(rb->dhost, |
176 | rb->dbase + reg + rb->doff, value); | ||
177 | #endif | ||
178 | case mpic_access_mmio_be: | ||
179 | return out_be32(rb->base + (reg >> 2), value); | ||
180 | case mpic_access_mmio_le: | ||
181 | default: | ||
182 | return out_le32(rb->base + (reg >> 2), value); | ||
183 | } | ||
166 | } | 184 | } |
167 | 185 | ||
168 | static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi) | 186 | static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi) |
169 | { | 187 | { |
170 | unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0; | 188 | enum mpic_reg_type type = mpic->reg_type; |
171 | unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + | 189 | unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + |
172 | (ipi * MPIC_INFO(GREG_IPI_STRIDE)); | 190 | (ipi * MPIC_INFO(GREG_IPI_STRIDE)); |
173 | 191 | ||
174 | if (mpic->flags & MPIC_BROKEN_IPI) | 192 | if ((mpic->flags & MPIC_BROKEN_IPI) && type == mpic_access_mmio_le) |
175 | be = !be; | 193 | type = mpic_access_mmio_be; |
176 | return _mpic_read(be, mpic->gregs, offset); | 194 | return _mpic_read(type, &mpic->gregs, offset); |
177 | } | 195 | } |
178 | 196 | ||
179 | static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value) | 197 | static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value) |
@@ -181,7 +199,7 @@ static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 valu | |||
181 | unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + | 199 | unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + |
182 | (ipi * MPIC_INFO(GREG_IPI_STRIDE)); | 200 | (ipi * MPIC_INFO(GREG_IPI_STRIDE)); |
183 | 201 | ||
184 | _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value); | 202 | _mpic_write(mpic->reg_type, &mpic->gregs, offset, value); |
185 | } | 203 | } |
186 | 204 | ||
187 | static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg) | 205 | static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg) |
@@ -190,8 +208,7 @@ static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg) | |||
190 | 208 | ||
191 | if (mpic->flags & MPIC_PRIMARY) | 209 | if (mpic->flags & MPIC_PRIMARY) |
192 | cpu = hard_smp_processor_id(); | 210 | cpu = hard_smp_processor_id(); |
193 | return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, | 211 | return _mpic_read(mpic->reg_type, &mpic->cpuregs[cpu], reg); |
194 | mpic->cpuregs[cpu], reg); | ||
195 | } | 212 | } |
196 | 213 | ||
197 | static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value) | 214 | static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value) |
@@ -201,7 +218,7 @@ static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 valu | |||
201 | if (mpic->flags & MPIC_PRIMARY) | 218 | if (mpic->flags & MPIC_PRIMARY) |
202 | cpu = hard_smp_processor_id(); | 219 | cpu = hard_smp_processor_id(); |
203 | 220 | ||
204 | _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg, value); | 221 | _mpic_write(mpic->reg_type, &mpic->cpuregs[cpu], reg, value); |
205 | } | 222 | } |
206 | 223 | ||
207 | static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigned int reg) | 224 | static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigned int reg) |
@@ -209,7 +226,7 @@ static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigne | |||
209 | unsigned int isu = src_no >> mpic->isu_shift; | 226 | unsigned int isu = src_no >> mpic->isu_shift; |
210 | unsigned int idx = src_no & mpic->isu_mask; | 227 | unsigned int idx = src_no & mpic->isu_mask; |
211 | 228 | ||
212 | return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], | 229 | return _mpic_read(mpic->reg_type, &mpic->isus[isu], |
213 | reg + (idx * MPIC_INFO(IRQ_STRIDE))); | 230 | reg + (idx * MPIC_INFO(IRQ_STRIDE))); |
214 | } | 231 | } |
215 | 232 | ||
@@ -219,12 +236,12 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, | |||
219 | unsigned int isu = src_no >> mpic->isu_shift; | 236 | unsigned int isu = src_no >> mpic->isu_shift; |
220 | unsigned int idx = src_no & mpic->isu_mask; | 237 | unsigned int idx = src_no & mpic->isu_mask; |
221 | 238 | ||
222 | _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], | 239 | _mpic_write(mpic->reg_type, &mpic->isus[isu], |
223 | reg + (idx * MPIC_INFO(IRQ_STRIDE)), value); | 240 | reg + (idx * MPIC_INFO(IRQ_STRIDE)), value); |
224 | } | 241 | } |
225 | 242 | ||
226 | #define mpic_read(b,r) _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r)) | 243 | #define mpic_read(b,r) _mpic_read(mpic->reg_type,&(b),(r)) |
227 | #define mpic_write(b,r,v) _mpic_write(mpic->flags & MPIC_BIG_ENDIAN,(b),(r),(v)) | 244 | #define mpic_write(b,r,v) _mpic_write(mpic->reg_type,&(b),(r),(v)) |
228 | #define mpic_ipi_read(i) _mpic_ipi_read(mpic,(i)) | 245 | #define mpic_ipi_read(i) _mpic_ipi_read(mpic,(i)) |
229 | #define mpic_ipi_write(i,v) _mpic_ipi_write(mpic,(i),(v)) | 246 | #define mpic_ipi_write(i,v) _mpic_ipi_write(mpic,(i),(v)) |
230 | #define mpic_cpu_read(i) _mpic_cpu_read(mpic,(i)) | 247 | #define mpic_cpu_read(i) _mpic_cpu_read(mpic,(i)) |
@@ -238,6 +255,38 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, | |||
238 | */ | 255 | */ |
239 | 256 | ||
240 | 257 | ||
258 | static void _mpic_map_mmio(struct mpic *mpic, unsigned long phys_addr, | ||
259 | struct mpic_reg_bank *rb, unsigned int offset, | ||
260 | unsigned int size) | ||
261 | { | ||
262 | rb->base = ioremap(phys_addr + offset, size); | ||
263 | BUG_ON(rb->base == NULL); | ||
264 | } | ||
265 | |||
266 | #ifdef CONFIG_PPC_DCR | ||
267 | static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb, | ||
268 | unsigned int offset, unsigned int size) | ||
269 | { | ||
270 | rb->dbase = mpic->dcr_base; | ||
271 | rb->doff = offset; | ||
272 | rb->dhost = dcr_map(mpic->of_node, rb->dbase + rb->doff, size); | ||
273 | BUG_ON(!DCR_MAP_OK(rb->dhost)); | ||
274 | } | ||
275 | |||
276 | static inline void mpic_map(struct mpic *mpic, unsigned long phys_addr, | ||
277 | struct mpic_reg_bank *rb, unsigned int offset, | ||
278 | unsigned int size) | ||
279 | { | ||
280 | if (mpic->flags & MPIC_USES_DCR) | ||
281 | _mpic_map_dcr(mpic, rb, offset, size); | ||
282 | else | ||
283 | _mpic_map_mmio(mpic, phys_addr, rb, offset, size); | ||
284 | } | ||
285 | #else /* CONFIG_PPC_DCR */ | ||
286 | #define mpic_map(m,p,b,o,s) _mpic_map_mmio(m,p,b,o,s) | ||
287 | #endif /* !CONFIG_PPC_DCR */ | ||
288 | |||
289 | |||
241 | 290 | ||
242 | /* Check if we have one of those nice broken MPICs with a flipped endian on | 291 | /* Check if we have one of those nice broken MPICs with a flipped endian on |
243 | * reads from IPI registers | 292 | * reads from IPI registers |
@@ -883,6 +932,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
883 | if (flags & MPIC_PRIMARY) | 932 | if (flags & MPIC_PRIMARY) |
884 | mpic->hc_ht_irq.set_affinity = mpic_set_affinity; | 933 | mpic->hc_ht_irq.set_affinity = mpic_set_affinity; |
885 | #endif /* CONFIG_MPIC_BROKEN_U3 */ | 934 | #endif /* CONFIG_MPIC_BROKEN_U3 */ |
935 | |||
886 | #ifdef CONFIG_SMP | 936 | #ifdef CONFIG_SMP |
887 | mpic->hc_ipi = mpic_ipi_chip; | 937 | mpic->hc_ipi = mpic_ipi_chip; |
888 | mpic->hc_ipi.typename = name; | 938 | mpic->hc_ipi.typename = name; |
@@ -897,11 +947,26 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
897 | mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; | 947 | mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; |
898 | #endif | 948 | #endif |
899 | 949 | ||
950 | /* default register type */ | ||
951 | mpic->reg_type = (flags & MPIC_BIG_ENDIAN) ? | ||
952 | mpic_access_mmio_be : mpic_access_mmio_le; | ||
953 | |||
954 | #ifdef CONFIG_PPC_DCR | ||
955 | if (mpic->flags & MPIC_USES_DCR) { | ||
956 | const u32 *dbasep; | ||
957 | BUG_ON(mpic->of_node == NULL); | ||
958 | dbasep = get_property(mpic->of_node, "dcr-reg", NULL); | ||
959 | BUG_ON(dbasep == NULL); | ||
960 | mpic->dcr_base = *dbasep; | ||
961 | mpic->reg_type = mpic_access_dcr; | ||
962 | } | ||
963 | #else | ||
964 | BUG_ON (mpic->flags & MPIC_USES_DCR); | ||
965 | #endif /* CONFIG_PPC_DCR */ | ||
966 | |||
900 | /* Map the global registers */ | 967 | /* Map the global registers */ |
901 | mpic->gregs = ioremap(phys_addr + MPIC_INFO(GREG_BASE), 0x1000); | 968 | mpic_map(mpic, phys_addr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); |
902 | mpic->tmregs = mpic->gregs + | 969 | mpic_map(mpic, phys_addr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); |
903 | ((MPIC_INFO(TIMER_BASE) - MPIC_INFO(GREG_BASE)) >> 2); | ||
904 | BUG_ON(mpic->gregs == NULL); | ||
905 | 970 | ||
906 | /* Reset */ | 971 | /* Reset */ |
907 | if (flags & MPIC_WANTS_RESET) { | 972 | if (flags & MPIC_WANTS_RESET) { |
@@ -926,17 +991,16 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
926 | 991 | ||
927 | /* Map the per-CPU registers */ | 992 | /* Map the per-CPU registers */ |
928 | for (i = 0; i < mpic->num_cpus; i++) { | 993 | for (i = 0; i < mpic->num_cpus; i++) { |
929 | mpic->cpuregs[i] = ioremap(phys_addr + MPIC_INFO(CPU_BASE) + | 994 | mpic_map(mpic, phys_addr, &mpic->cpuregs[i], |
930 | i * MPIC_INFO(CPU_STRIDE), 0x1000); | 995 | MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE), |
931 | BUG_ON(mpic->cpuregs[i] == NULL); | 996 | 0x1000); |
932 | } | 997 | } |
933 | 998 | ||
934 | /* Initialize main ISU if none provided */ | 999 | /* Initialize main ISU if none provided */ |
935 | if (mpic->isu_size == 0) { | 1000 | if (mpic->isu_size == 0) { |
936 | mpic->isu_size = mpic->num_sources; | 1001 | mpic->isu_size = mpic->num_sources; |
937 | mpic->isus[0] = ioremap(phys_addr + MPIC_INFO(IRQ_BASE), | 1002 | mpic_map(mpic, phys_addr, &mpic->isus[0], |
938 | MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); | 1003 | MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); |
939 | BUG_ON(mpic->isus[0] == NULL); | ||
940 | } | 1004 | } |
941 | mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); | 1005 | mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); |
942 | mpic->isu_mask = (1 << mpic->isu_shift) - 1; | 1006 | mpic->isu_mask = (1 << mpic->isu_shift) - 1; |
@@ -979,8 +1043,8 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, | |||
979 | 1043 | ||
980 | BUG_ON(isu_num >= MPIC_MAX_ISU); | 1044 | BUG_ON(isu_num >= MPIC_MAX_ISU); |
981 | 1045 | ||
982 | mpic->isus[isu_num] = ioremap(phys_addr, | 1046 | mpic_map(mpic, phys_addr, &mpic->isus[isu_num], 0, |
983 | MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); | 1047 | MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); |
984 | if ((isu_first + mpic->isu_size) > mpic->num_sources) | 1048 | if ((isu_first + mpic->isu_size) > mpic->num_sources) |
985 | mpic->num_sources = isu_first + mpic->isu_size; | 1049 | mpic->num_sources = isu_first + mpic->isu_size; |
986 | } | 1050 | } |