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.c201
1 files changed, 122 insertions, 79 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 8c7e8528e7c4..4e9ccb1015de 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -154,7 +154,7 @@ static inline unsigned int mpic_processor_id(struct mpic *mpic)
154{ 154{
155 unsigned int cpu = 0; 155 unsigned int cpu = 0;
156 156
157 if (mpic->flags & MPIC_PRIMARY) 157 if (!(mpic->flags & MPIC_SECONDARY))
158 cpu = hard_smp_processor_id(); 158 cpu = hard_smp_processor_id();
159 159
160 return cpu; 160 return cpu;
@@ -315,29 +315,25 @@ static void _mpic_map_mmio(struct mpic *mpic, phys_addr_t phys_addr,
315} 315}
316 316
317#ifdef CONFIG_PPC_DCR 317#ifdef CONFIG_PPC_DCR
318static void _mpic_map_dcr(struct mpic *mpic, struct device_node *node, 318static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb,
319 struct mpic_reg_bank *rb,
320 unsigned int offset, unsigned int size) 319 unsigned int offset, unsigned int size)
321{ 320{
322 const u32 *dbasep; 321 phys_addr_t phys_addr = dcr_resource_start(mpic->node, 0);
323 322 rb->dhost = dcr_map(mpic->node, phys_addr + offset, size);
324 dbasep = of_get_property(node, "dcr-reg", NULL);
325
326 rb->dhost = dcr_map(node, *dbasep + offset, size);
327 BUG_ON(!DCR_MAP_OK(rb->dhost)); 323 BUG_ON(!DCR_MAP_OK(rb->dhost));
328} 324}
329 325
330static inline void mpic_map(struct mpic *mpic, struct device_node *node, 326static inline void mpic_map(struct mpic *mpic,
331 phys_addr_t phys_addr, struct mpic_reg_bank *rb, 327 phys_addr_t phys_addr, struct mpic_reg_bank *rb,
332 unsigned int offset, unsigned int size) 328 unsigned int offset, unsigned int size)
333{ 329{
334 if (mpic->flags & MPIC_USES_DCR) 330 if (mpic->flags & MPIC_USES_DCR)
335 _mpic_map_dcr(mpic, node, rb, offset, size); 331 _mpic_map_dcr(mpic, rb, offset, size);
336 else 332 else
337 _mpic_map_mmio(mpic, phys_addr, rb, offset, size); 333 _mpic_map_mmio(mpic, phys_addr, rb, offset, size);
338} 334}
339#else /* CONFIG_PPC_DCR */ 335#else /* CONFIG_PPC_DCR */
340#define mpic_map(m,n,p,b,o,s) _mpic_map_mmio(m,p,b,o,s) 336#define mpic_map(m,p,b,o,s) _mpic_map_mmio(m,p,b,o,s)
341#endif /* !CONFIG_PPC_DCR */ 337#endif /* !CONFIG_PPC_DCR */
342 338
343 339
@@ -901,7 +897,7 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
901 if (vold != vnew) 897 if (vold != vnew)
902 mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vnew); 898 mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vnew);
903 899
904 return IRQ_SET_MASK_OK_NOCOPY;; 900 return IRQ_SET_MASK_OK_NOCOPY;
905} 901}
906 902
907void mpic_set_vector(unsigned int virq, unsigned int vector) 903void mpic_set_vector(unsigned int virq, unsigned int vector)
@@ -990,7 +986,7 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
990 986
991#ifdef CONFIG_SMP 987#ifdef CONFIG_SMP
992 else if (hw >= mpic->ipi_vecs[0]) { 988 else if (hw >= mpic->ipi_vecs[0]) {
993 WARN_ON(!(mpic->flags & MPIC_PRIMARY)); 989 WARN_ON(mpic->flags & MPIC_SECONDARY);
994 990
995 DBG("mpic: mapping as IPI\n"); 991 DBG("mpic: mapping as IPI\n");
996 irq_set_chip_data(virq, mpic); 992 irq_set_chip_data(virq, mpic);
@@ -1001,7 +997,7 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
1001#endif /* CONFIG_SMP */ 997#endif /* CONFIG_SMP */
1002 998
1003 if (hw >= mpic->timer_vecs[0] && hw <= mpic->timer_vecs[7]) { 999 if (hw >= mpic->timer_vecs[0] && hw <= mpic->timer_vecs[7]) {
1004 WARN_ON(!(mpic->flags & MPIC_PRIMARY)); 1000 WARN_ON(mpic->flags & MPIC_SECONDARY);
1005 1001
1006 DBG("mpic: mapping as timer\n"); 1002 DBG("mpic: mapping as timer\n");
1007 irq_set_chip_data(virq, mpic); 1003 irq_set_chip_data(virq, mpic);
@@ -1115,17 +1111,28 @@ static int mpic_host_xlate(struct irq_host *h, struct device_node *ct,
1115 return 0; 1111 return 0;
1116} 1112}
1117 1113
1114/* IRQ handler for a secondary MPIC cascaded from another IRQ controller */
1115static void mpic_cascade(unsigned int irq, struct irq_desc *desc)
1116{
1117 struct irq_chip *chip = irq_desc_get_chip(desc);
1118 struct mpic *mpic = irq_desc_get_handler_data(desc);
1119 unsigned int virq;
1120
1121 BUG_ON(!(mpic->flags & MPIC_SECONDARY));
1122
1123 virq = mpic_get_one_irq(mpic);
1124 if (virq != NO_IRQ)
1125 generic_handle_irq(virq);
1126
1127 chip->irq_eoi(&desc->irq_data);
1128}
1129
1118static struct irq_host_ops mpic_host_ops = { 1130static struct irq_host_ops mpic_host_ops = {
1119 .match = mpic_host_match, 1131 .match = mpic_host_match,
1120 .map = mpic_host_map, 1132 .map = mpic_host_map,
1121 .xlate = mpic_host_xlate, 1133 .xlate = mpic_host_xlate,
1122}; 1134};
1123 1135
1124static int mpic_reset_prohibited(struct device_node *node)
1125{
1126 return node && of_get_property(node, "pic-no-reset", NULL);
1127}
1128
1129/* 1136/*
1130 * Exported functions 1137 * Exported functions
1131 */ 1138 */
@@ -1137,27 +1144,60 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1137 unsigned int irq_count, 1144 unsigned int irq_count,
1138 const char *name) 1145 const char *name)
1139{ 1146{
1140 struct mpic *mpic; 1147 int i, psize, intvec_top;
1141 u32 greg_feature; 1148 struct mpic *mpic;
1142 const char *vers; 1149 u32 greg_feature;
1143 int i; 1150 const char *vers;
1144 int intvec_top; 1151 const u32 *psrc;
1145 u64 paddr = phys_addr; 1152
1153 /* Default MPIC search parameters */
1154 static const struct of_device_id __initconst mpic_device_id[] = {
1155 { .type = "open-pic", },
1156 { .compatible = "open-pic", },
1157 {},
1158 };
1159
1160 /*
1161 * If we were not passed a device-tree node, then perform the default
1162 * search for standardized a standardized OpenPIC.
1163 */
1164 if (node) {
1165 node = of_node_get(node);
1166 } else {
1167 node = of_find_matching_node(NULL, mpic_device_id);
1168 if (!node)
1169 return NULL;
1170 }
1171
1172 /* Pick the physical address from the device tree if unspecified */
1173 if (!phys_addr) {
1174 /* Check if it is DCR-based */
1175 if (of_get_property(node, "dcr-reg", NULL)) {
1176 flags |= MPIC_USES_DCR;
1177 } else {
1178 struct resource r;
1179 if (of_address_to_resource(node, 0, &r))
1180 goto err_of_node_put;
1181 phys_addr = r.start;
1182 }
1183 }
1146 1184
1147 mpic = kzalloc(sizeof(struct mpic), GFP_KERNEL); 1185 mpic = kzalloc(sizeof(struct mpic), GFP_KERNEL);
1148 if (mpic == NULL) 1186 if (mpic == NULL)
1149 return NULL; 1187 goto err_of_node_put;
1150 1188
1151 mpic->name = name; 1189 mpic->name = name;
1190 mpic->node = node;
1191 mpic->paddr = phys_addr;
1152 1192
1153 mpic->hc_irq = mpic_irq_chip; 1193 mpic->hc_irq = mpic_irq_chip;
1154 mpic->hc_irq.name = name; 1194 mpic->hc_irq.name = name;
1155 if (flags & MPIC_PRIMARY) 1195 if (!(flags & MPIC_SECONDARY))
1156 mpic->hc_irq.irq_set_affinity = mpic_set_affinity; 1196 mpic->hc_irq.irq_set_affinity = mpic_set_affinity;
1157#ifdef CONFIG_MPIC_U3_HT_IRQS 1197#ifdef CONFIG_MPIC_U3_HT_IRQS
1158 mpic->hc_ht_irq = mpic_irq_ht_chip; 1198 mpic->hc_ht_irq = mpic_irq_ht_chip;
1159 mpic->hc_ht_irq.name = name; 1199 mpic->hc_ht_irq.name = name;
1160 if (flags & MPIC_PRIMARY) 1200 if (!(flags & MPIC_SECONDARY))
1161 mpic->hc_ht_irq.irq_set_affinity = mpic_set_affinity; 1201 mpic->hc_ht_irq.irq_set_affinity = mpic_set_affinity;
1162#endif /* CONFIG_MPIC_U3_HT_IRQS */ 1202#endif /* CONFIG_MPIC_U3_HT_IRQS */
1163 1203
@@ -1194,28 +1234,22 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1194 mpic->spurious_vec = intvec_top; 1234 mpic->spurious_vec = intvec_top;
1195 1235
1196 /* Check for "big-endian" in device-tree */ 1236 /* Check for "big-endian" in device-tree */
1197 if (node && of_get_property(node, "big-endian", NULL) != NULL) 1237 if (of_get_property(mpic->node, "big-endian", NULL) != NULL)
1198 mpic->flags |= MPIC_BIG_ENDIAN; 1238 mpic->flags |= MPIC_BIG_ENDIAN;
1199 if (node && of_device_is_compatible(node, "fsl,mpic")) 1239 if (of_device_is_compatible(mpic->node, "fsl,mpic"))
1200 mpic->flags |= MPIC_FSL; 1240 mpic->flags |= MPIC_FSL;
1201 1241
1202 /* Look for protected sources */ 1242 /* Look for protected sources */
1203 if (node) { 1243 psrc = of_get_property(mpic->node, "protected-sources", &psize);
1204 int psize; 1244 if (psrc) {
1205 unsigned int bits, mapsize; 1245 /* Allocate a bitmap with one bit per interrupt */
1206 const u32 *psrc = 1246 unsigned int mapsize = BITS_TO_LONGS(intvec_top + 1);
1207 of_get_property(node, "protected-sources", &psize); 1247 mpic->protected = kzalloc(mapsize*sizeof(long), GFP_KERNEL);
1208 if (psrc) { 1248 BUG_ON(mpic->protected == NULL);
1209 psize /= 4; 1249 for (i = 0; i < psize/sizeof(u32); i++) {
1210 bits = intvec_top + 1; 1250 if (psrc[i] > intvec_top)
1211 mapsize = BITS_TO_LONGS(bits) * sizeof(unsigned long); 1251 continue;
1212 mpic->protected = kzalloc(mapsize, GFP_KERNEL); 1252 __set_bit(psrc[i], mpic->protected);
1213 BUG_ON(mpic->protected == NULL);
1214 for (i = 0; i < psize; i++) {
1215 if (psrc[i] > intvec_top)
1216 continue;
1217 __set_bit(psrc[i], mpic->protected);
1218 }
1219 } 1253 }
1220 } 1254 }
1221 1255
@@ -1224,42 +1258,32 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1224#endif 1258#endif
1225 1259
1226 /* default register type */ 1260 /* default register type */
1227 mpic->reg_type = (flags & MPIC_BIG_ENDIAN) ? 1261 if (flags & MPIC_BIG_ENDIAN)
1228 mpic_access_mmio_be : mpic_access_mmio_le; 1262 mpic->reg_type = mpic_access_mmio_be;
1229 1263 else
1230 /* If no physical address is passed in, a device-node is mandatory */ 1264 mpic->reg_type = mpic_access_mmio_le;
1231 BUG_ON(paddr == 0 && node == NULL);
1232 1265
1233 /* If no physical address passed in, check if it's dcr based */ 1266 /*
1234 if (paddr == 0 && of_get_property(node, "dcr-reg", NULL) != NULL) { 1267 * An MPIC with a "dcr-reg" property must be accessed that way, but
1268 * only if the kernel includes DCR support.
1269 */
1235#ifdef CONFIG_PPC_DCR 1270#ifdef CONFIG_PPC_DCR
1236 mpic->flags |= MPIC_USES_DCR; 1271 if (flags & MPIC_USES_DCR)
1237 mpic->reg_type = mpic_access_dcr; 1272 mpic->reg_type = mpic_access_dcr;
1238#else 1273#else
1239 BUG(); 1274 BUG_ON(flags & MPIC_USES_DCR);
1240#endif /* CONFIG_PPC_DCR */ 1275#endif
1241 }
1242
1243 /* If the MPIC is not DCR based, and no physical address was passed
1244 * in, try to obtain one
1245 */
1246 if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) {
1247 const u32 *reg = of_get_property(node, "reg", NULL);
1248 BUG_ON(reg == NULL);
1249 paddr = of_translate_address(node, reg);
1250 BUG_ON(paddr == OF_BAD_ADDR);
1251 }
1252 1276
1253 /* Map the global registers */ 1277 /* Map the global registers */
1254 mpic_map(mpic, node, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); 1278 mpic_map(mpic, mpic->paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000);
1255 mpic_map(mpic, node, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); 1279 mpic_map(mpic, mpic->paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
1256 1280
1257 /* Reset */ 1281 /* Reset */
1258 1282
1259 /* When using a device-node, reset requests are only honored if the MPIC 1283 /* When using a device-node, reset requests are only honored if the MPIC
1260 * is allowed to reset. 1284 * is allowed to reset.
1261 */ 1285 */
1262 if (mpic_reset_prohibited(node)) 1286 if (of_get_property(mpic->node, "pic-no-reset", NULL))
1263 mpic->flags |= MPIC_NO_RESET; 1287 mpic->flags |= MPIC_NO_RESET;
1264 1288
1265 if ((flags & MPIC_WANTS_RESET) && !(mpic->flags & MPIC_NO_RESET)) { 1289 if ((flags & MPIC_WANTS_RESET) && !(mpic->flags & MPIC_NO_RESET)) {
@@ -1307,7 +1331,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1307 for_each_possible_cpu(i) { 1331 for_each_possible_cpu(i) {
1308 unsigned int cpu = get_hard_smp_processor_id(i); 1332 unsigned int cpu = get_hard_smp_processor_id(i);
1309 1333
1310 mpic_map(mpic, node, paddr, &mpic->cpuregs[cpu], 1334 mpic_map(mpic, mpic->paddr, &mpic->cpuregs[cpu],
1311 MPIC_INFO(CPU_BASE) + cpu * MPIC_INFO(CPU_STRIDE), 1335 MPIC_INFO(CPU_BASE) + cpu * MPIC_INFO(CPU_STRIDE),
1312 0x1000); 1336 0x1000);
1313 } 1337 }
@@ -1315,16 +1339,21 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1315 /* Initialize main ISU if none provided */ 1339 /* Initialize main ISU if none provided */
1316 if (mpic->isu_size == 0) { 1340 if (mpic->isu_size == 0) {
1317 mpic->isu_size = mpic->num_sources; 1341 mpic->isu_size = mpic->num_sources;
1318 mpic_map(mpic, node, paddr, &mpic->isus[0], 1342 mpic_map(mpic, mpic->paddr, &mpic->isus[0],
1319 MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); 1343 MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
1320 } 1344 }
1321 mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); 1345 mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
1322 mpic->isu_mask = (1 << mpic->isu_shift) - 1; 1346 mpic->isu_mask = (1 << mpic->isu_shift) - 1;
1323 1347
1324 mpic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR, 1348 mpic->irqhost = irq_alloc_host(mpic->node, IRQ_HOST_MAP_LINEAR,
1325 isu_size ? isu_size : mpic->num_sources, 1349 isu_size ? isu_size : mpic->num_sources,
1326 &mpic_host_ops, 1350 &mpic_host_ops,
1327 flags & MPIC_LARGE_VECTORS ? 2048 : 256); 1351 flags & MPIC_LARGE_VECTORS ? 2048 : 256);
1352
1353 /*
1354 * FIXME: The code leaks the MPIC object and mappings here; this
1355 * is very unlikely to fail but it ought to be fixed anyways.
1356 */
1328 if (mpic->irqhost == NULL) 1357 if (mpic->irqhost == NULL)
1329 return NULL; 1358 return NULL;
1330 1359
@@ -1347,19 +1376,23 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1347 } 1376 }
1348 printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %llx," 1377 printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %llx,"
1349 " max %d CPUs\n", 1378 " max %d CPUs\n",
1350 name, vers, (unsigned long long)paddr, num_possible_cpus()); 1379 name, vers, (unsigned long long)mpic->paddr, num_possible_cpus());
1351 printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", 1380 printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n",
1352 mpic->isu_size, mpic->isu_shift, mpic->isu_mask); 1381 mpic->isu_size, mpic->isu_shift, mpic->isu_mask);
1353 1382
1354 mpic->next = mpics; 1383 mpic->next = mpics;
1355 mpics = mpic; 1384 mpics = mpic;
1356 1385
1357 if (flags & MPIC_PRIMARY) { 1386 if (!(flags & MPIC_SECONDARY)) {
1358 mpic_primary = mpic; 1387 mpic_primary = mpic;
1359 irq_set_default_host(mpic->irqhost); 1388 irq_set_default_host(mpic->irqhost);
1360 } 1389 }
1361 1390
1362 return mpic; 1391 return mpic;
1392
1393err_of_node_put:
1394 of_node_put(node);
1395 return NULL;
1363} 1396}
1364 1397
1365void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, 1398void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
@@ -1369,7 +1402,7 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
1369 1402
1370 BUG_ON(isu_num >= MPIC_MAX_ISU); 1403 BUG_ON(isu_num >= MPIC_MAX_ISU);
1371 1404
1372 mpic_map(mpic, mpic->irqhost->of_node, 1405 mpic_map(mpic,
1373 paddr, &mpic->isus[isu_num], 0, 1406 paddr, &mpic->isus[isu_num], 0,
1374 MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); 1407 MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
1375 1408
@@ -1385,8 +1418,7 @@ void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count)
1385 1418
1386void __init mpic_init(struct mpic *mpic) 1419void __init mpic_init(struct mpic *mpic)
1387{ 1420{
1388 int i; 1421 int i, cpu;
1389 int cpu;
1390 1422
1391 BUG_ON(mpic->num_sources == 0); 1423 BUG_ON(mpic->num_sources == 0);
1392 1424
@@ -1424,7 +1456,7 @@ void __init mpic_init(struct mpic *mpic)
1424 1456
1425 /* Do the HT PIC fixups on U3 broken mpic */ 1457 /* Do the HT PIC fixups on U3 broken mpic */
1426 DBG("MPIC flags: %x\n", mpic->flags); 1458 DBG("MPIC flags: %x\n", mpic->flags);
1427 if ((mpic->flags & MPIC_U3_HT_IRQS) && (mpic->flags & MPIC_PRIMARY)) { 1459 if ((mpic->flags & MPIC_U3_HT_IRQS) && !(mpic->flags & MPIC_SECONDARY)) {
1428 mpic_scan_ht_pics(mpic); 1460 mpic_scan_ht_pics(mpic);
1429 mpic_u3msi_init(mpic); 1461 mpic_u3msi_init(mpic);
1430 } 1462 }
@@ -1471,6 +1503,17 @@ void __init mpic_init(struct mpic *mpic)
1471 GFP_KERNEL); 1503 GFP_KERNEL);
1472 BUG_ON(mpic->save_data == NULL); 1504 BUG_ON(mpic->save_data == NULL);
1473#endif 1505#endif
1506
1507 /* Check if this MPIC is chained from a parent interrupt controller */
1508 if (mpic->flags & MPIC_SECONDARY) {
1509 int virq = irq_of_parse_and_map(mpic->node, 0);
1510 if (virq != NO_IRQ) {
1511 printk(KERN_INFO "%s: hooking up to IRQ %d\n",
1512 mpic->node->full_name, virq);
1513 irq_set_handler_data(virq, mpic);
1514 irq_set_chained_handler(virq, &mpic_cascade);
1515 }
1516 }
1474} 1517}
1475 1518
1476void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio) 1519void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)