diff options
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
| -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 | } |
