aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/mpic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
-rw-r--r--arch/powerpc/sysdev/mpic.c172
1 files changed, 130 insertions, 42 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index ba4833f57d47..411480d5c626 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
150static inline u32 _mpic_read(unsigned int be, volatile u32 __iomem *base, 150static 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
159static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base, 168static 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
168static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi) 186static 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
179static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value) 197static 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
187static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg) 205static 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
197static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value) 214static 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
207static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigned int reg) 224static 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
258static 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
267static 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
276static 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
@@ -845,7 +894,7 @@ static struct irq_host_ops mpic_host_ops = {
845 */ 894 */
846 895
847struct mpic * __init mpic_alloc(struct device_node *node, 896struct mpic * __init mpic_alloc(struct device_node *node,
848 unsigned long phys_addr, 897 phys_addr_t phys_addr,
849 unsigned int flags, 898 unsigned int flags,
850 unsigned int isu_size, 899 unsigned int isu_size,
851 unsigned int irq_count, 900 unsigned int irq_count,
@@ -855,6 +904,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
855 u32 reg; 904 u32 reg;
856 const char *vers; 905 const char *vers;
857 int i; 906 int i;
907 u64 paddr = phys_addr;
858 908
859 mpic = alloc_bootmem(sizeof(struct mpic)); 909 mpic = alloc_bootmem(sizeof(struct mpic));
860 if (mpic == NULL) 910 if (mpic == NULL)
@@ -883,6 +933,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
883 if (flags & MPIC_PRIMARY) 933 if (flags & MPIC_PRIMARY)
884 mpic->hc_ht_irq.set_affinity = mpic_set_affinity; 934 mpic->hc_ht_irq.set_affinity = mpic_set_affinity;
885#endif /* CONFIG_MPIC_BROKEN_U3 */ 935#endif /* CONFIG_MPIC_BROKEN_U3 */
936
886#ifdef CONFIG_SMP 937#ifdef CONFIG_SMP
887 mpic->hc_ipi = mpic_ipi_chip; 938 mpic->hc_ipi = mpic_ipi_chip;
888 mpic->hc_ipi.typename = name; 939 mpic->hc_ipi.typename = name;
@@ -893,15 +944,52 @@ struct mpic * __init mpic_alloc(struct device_node *node,
893 mpic->irq_count = irq_count; 944 mpic->irq_count = irq_count;
894 mpic->num_sources = 0; /* so far */ 945 mpic->num_sources = 0; /* so far */
895 946
947 /* Check for "big-endian" in device-tree */
948 if (node && get_property(node, "big-endian", NULL) != NULL)
949 mpic->flags |= MPIC_BIG_ENDIAN;
950
951
896#ifdef CONFIG_MPIC_WEIRD 952#ifdef CONFIG_MPIC_WEIRD
897 mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; 953 mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)];
898#endif 954#endif
899 955
956 /* default register type */
957 mpic->reg_type = (flags & MPIC_BIG_ENDIAN) ?
958 mpic_access_mmio_be : mpic_access_mmio_le;
959
960 /* If no physical address is passed in, a device-node is mandatory */
961 BUG_ON(paddr == 0 && node == NULL);
962
963 /* If no physical address passed in, check if it's dcr based */
964 if (paddr == 0 && get_property(node, "dcr-reg", NULL) != NULL)
965 mpic->flags |= MPIC_USES_DCR;
966
967#ifdef CONFIG_PPC_DCR
968 if (mpic->flags & MPIC_USES_DCR) {
969 const u32 *dbasep;
970 dbasep = get_property(node, "dcr-reg", NULL);
971 BUG_ON(dbasep == NULL);
972 mpic->dcr_base = *dbasep;
973 mpic->reg_type = mpic_access_dcr;
974 }
975#else
976 BUG_ON (mpic->flags & MPIC_USES_DCR);
977#endif /* CONFIG_PPC_DCR */
978
979 /* If the MPIC is not DCR based, and no physical address was passed
980 * in, try to obtain one
981 */
982 if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) {
983 const u32 *reg;
984 reg = get_property(node, "reg", NULL);
985 BUG_ON(reg == NULL);
986 paddr = of_translate_address(node, reg);
987 BUG_ON(paddr == OF_BAD_ADDR);
988 }
989
900 /* Map the global registers */ 990 /* Map the global registers */
901 mpic->gregs = ioremap(phys_addr + MPIC_INFO(GREG_BASE), 0x1000); 991 mpic_map(mpic, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000);
902 mpic->tmregs = mpic->gregs + 992 mpic_map(mpic, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
903 ((MPIC_INFO(TIMER_BASE) - MPIC_INFO(GREG_BASE)) >> 2);
904 BUG_ON(mpic->gregs == NULL);
905 993
906 /* Reset */ 994 /* Reset */
907 if (flags & MPIC_WANTS_RESET) { 995 if (flags & MPIC_WANTS_RESET) {
@@ -926,17 +1014,16 @@ struct mpic * __init mpic_alloc(struct device_node *node,
926 1014
927 /* Map the per-CPU registers */ 1015 /* Map the per-CPU registers */
928 for (i = 0; i < mpic->num_cpus; i++) { 1016 for (i = 0; i < mpic->num_cpus; i++) {
929 mpic->cpuregs[i] = ioremap(phys_addr + MPIC_INFO(CPU_BASE) + 1017 mpic_map(mpic, paddr, &mpic->cpuregs[i],
930 i * MPIC_INFO(CPU_STRIDE), 0x1000); 1018 MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE),
931 BUG_ON(mpic->cpuregs[i] == NULL); 1019 0x1000);
932 } 1020 }
933 1021
934 /* Initialize main ISU if none provided */ 1022 /* Initialize main ISU if none provided */
935 if (mpic->isu_size == 0) { 1023 if (mpic->isu_size == 0) {
936 mpic->isu_size = mpic->num_sources; 1024 mpic->isu_size = mpic->num_sources;
937 mpic->isus[0] = ioremap(phys_addr + MPIC_INFO(IRQ_BASE), 1025 mpic_map(mpic, paddr, &mpic->isus[0],
938 MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); 1026 MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
939 BUG_ON(mpic->isus[0] == NULL);
940 } 1027 }
941 mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); 1028 mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
942 mpic->isu_mask = (1 << mpic->isu_shift) - 1; 1029 mpic->isu_mask = (1 << mpic->isu_shift) - 1;
@@ -956,10 +1043,11 @@ struct mpic * __init mpic_alloc(struct device_node *node,
956 vers = "<unknown>"; 1043 vers = "<unknown>";
957 break; 1044 break;
958 } 1045 }
959 printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %lx, max %d CPUs\n", 1046 printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %llx,"
960 name, vers, phys_addr, mpic->num_cpus); 1047 " max %d CPUs\n",
961 printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", mpic->isu_size, 1048 name, vers, (unsigned long long)paddr, mpic->num_cpus);
962 mpic->isu_shift, mpic->isu_mask); 1049 printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n",
1050 mpic->isu_size, mpic->isu_shift, mpic->isu_mask);
963 1051
964 mpic->next = mpics; 1052 mpic->next = mpics;
965 mpics = mpic; 1053 mpics = mpic;
@@ -973,14 +1061,14 @@ struct mpic * __init mpic_alloc(struct device_node *node,
973} 1061}
974 1062
975void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, 1063void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
976 unsigned long phys_addr) 1064 phys_addr_t paddr)
977{ 1065{
978 unsigned int isu_first = isu_num * mpic->isu_size; 1066 unsigned int isu_first = isu_num * mpic->isu_size;
979 1067
980 BUG_ON(isu_num >= MPIC_MAX_ISU); 1068 BUG_ON(isu_num >= MPIC_MAX_ISU);
981 1069
982 mpic->isus[isu_num] = ioremap(phys_addr, 1070 mpic_map(mpic, paddr, &mpic->isus[isu_num], 0,
983 MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); 1071 MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
984 if ((isu_first + mpic->isu_size) > mpic->num_sources) 1072 if ((isu_first + mpic->isu_size) > mpic->num_sources)
985 mpic->num_sources = isu_first + mpic->isu_size; 1073 mpic->num_sources = isu_first + mpic->isu_size;
986} 1074}