diff options
Diffstat (limited to 'arch/sparc64/kernel/pci_schizo.c')
-rw-r--r-- | arch/sparc64/kernel/pci_schizo.c | 192 |
1 files changed, 44 insertions, 148 deletions
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 7fe4de03ac2e..cc662e915d32 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c | |||
@@ -232,105 +232,10 @@ static unsigned long schizo_iclr_offset(unsigned long ino) | |||
232 | return SCHIZO_ICLR_BASE + (ino * 8UL); | 232 | return SCHIZO_ICLR_BASE + (ino * 8UL); |
233 | } | 233 | } |
234 | 234 | ||
235 | /* PCI SCHIZO INO number to Sparc PIL level. This table only matters for | 235 | static void tomatillo_wsync_handler(unsigned int ino, void *_arg1, void *_arg2) |
236 | * INOs which will not have an associated PCI device struct, ie. onboard | ||
237 | * EBUS devices and PCI controller internal error interrupts. | ||
238 | */ | ||
239 | static unsigned char schizo_pil_table[] = { | ||
240 | /*0x00*/0, 0, 0, 0, /* PCI slot 0 Int A, B, C, D */ | ||
241 | /*0x04*/0, 0, 0, 0, /* PCI slot 1 Int A, B, C, D */ | ||
242 | /*0x08*/0, 0, 0, 0, /* PCI slot 2 Int A, B, C, D */ | ||
243 | /*0x0c*/0, 0, 0, 0, /* PCI slot 3 Int A, B, C, D */ | ||
244 | /*0x10*/0, 0, 0, 0, /* PCI slot 4 Int A, B, C, D */ | ||
245 | /*0x14*/0, 0, 0, 0, /* PCI slot 5 Int A, B, C, D */ | ||
246 | /*0x18*/5, /* SCSI */ | ||
247 | /*0x19*/5, /* second SCSI */ | ||
248 | /*0x1a*/0, /* UNKNOWN */ | ||
249 | /*0x1b*/0, /* UNKNOWN */ | ||
250 | /*0x1c*/8, /* Parallel */ | ||
251 | /*0x1d*/5, /* Ethernet */ | ||
252 | /*0x1e*/8, /* Firewire-1394 */ | ||
253 | /*0x1f*/9, /* USB */ | ||
254 | /*0x20*/13, /* Audio Record */ | ||
255 | /*0x21*/14, /* Audio Playback */ | ||
256 | /*0x22*/12, /* Serial */ | ||
257 | /*0x23*/5, /* EBUS I2C */ | ||
258 | /*0x24*/10, /* RTC Clock */ | ||
259 | /*0x25*/11, /* Floppy */ | ||
260 | /*0x26*/0, /* UNKNOWN */ | ||
261 | /*0x27*/0, /* UNKNOWN */ | ||
262 | /*0x28*/0, /* UNKNOWN */ | ||
263 | /*0x29*/0, /* UNKNOWN */ | ||
264 | /*0x2a*/10, /* UPA 1 */ | ||
265 | /*0x2b*/10, /* UPA 2 */ | ||
266 | /*0x2c*/0, /* UNKNOWN */ | ||
267 | /*0x2d*/0, /* UNKNOWN */ | ||
268 | /*0x2e*/0, /* UNKNOWN */ | ||
269 | /*0x2f*/0, /* UNKNOWN */ | ||
270 | /*0x30*/15, /* Uncorrectable ECC */ | ||
271 | /*0x31*/15, /* Correctable ECC */ | ||
272 | /*0x32*/15, /* PCI Bus A Error */ | ||
273 | /*0x33*/15, /* PCI Bus B Error */ | ||
274 | /*0x34*/15, /* Safari Bus Error */ | ||
275 | /*0x35*/0, /* Reserved */ | ||
276 | /*0x36*/0, /* Reserved */ | ||
277 | /*0x37*/0, /* Reserved */ | ||
278 | /*0x38*/0, /* Reserved for NewLink */ | ||
279 | /*0x39*/0, /* Reserved for NewLink */ | ||
280 | /*0x3a*/0, /* Reserved for NewLink */ | ||
281 | /*0x3b*/0, /* Reserved for NewLink */ | ||
282 | /*0x3c*/0, /* Reserved for NewLink */ | ||
283 | /*0x3d*/0, /* Reserved for NewLink */ | ||
284 | /*0x3e*/0, /* Reserved for NewLink */ | ||
285 | /*0x3f*/0, /* Reserved for NewLink */ | ||
286 | }; | ||
287 | |||
288 | static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino) | ||
289 | { | ||
290 | int ret; | ||
291 | |||
292 | if (pdev && | ||
293 | pdev->vendor == PCI_VENDOR_ID_SUN && | ||
294 | pdev->device == PCI_DEVICE_ID_SUN_RIO_USB) | ||
295 | return 9; | ||
296 | |||
297 | ret = schizo_pil_table[ino]; | ||
298 | if (ret == 0 && pdev == NULL) { | ||
299 | ret = 5; | ||
300 | } else if (ret == 0) { | ||
301 | switch ((pdev->class >> 16) & 0xff) { | ||
302 | case PCI_BASE_CLASS_STORAGE: | ||
303 | ret = 5; | ||
304 | break; | ||
305 | |||
306 | case PCI_BASE_CLASS_NETWORK: | ||
307 | ret = 6; | ||
308 | break; | ||
309 | |||
310 | case PCI_BASE_CLASS_DISPLAY: | ||
311 | ret = 9; | ||
312 | break; | ||
313 | |||
314 | case PCI_BASE_CLASS_MULTIMEDIA: | ||
315 | case PCI_BASE_CLASS_MEMORY: | ||
316 | case PCI_BASE_CLASS_BRIDGE: | ||
317 | case PCI_BASE_CLASS_SERIAL: | ||
318 | ret = 10; | ||
319 | break; | ||
320 | |||
321 | default: | ||
322 | ret = 5; | ||
323 | break; | ||
324 | }; | ||
325 | } | ||
326 | |||
327 | return ret; | ||
328 | } | ||
329 | |||
330 | static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2) | ||
331 | { | 236 | { |
332 | unsigned long sync_reg = (unsigned long) _arg2; | 237 | unsigned long sync_reg = (unsigned long) _arg2; |
333 | u64 mask = 1UL << (__irq_ino(__irq(bucket)) & IMAP_INO); | 238 | u64 mask = 1UL << (ino & IMAP_INO); |
334 | u64 val; | 239 | u64 val; |
335 | int limit; | 240 | int limit; |
336 | 241 | ||
@@ -365,30 +270,33 @@ static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void | |||
365 | } | 270 | } |
366 | } | 271 | } |
367 | 272 | ||
273 | static unsigned long schizo_ino_to_iclr(struct pci_pbm_info *pbm, | ||
274 | unsigned int ino) | ||
275 | { | ||
276 | ino &= PCI_IRQ_INO; | ||
277 | return pbm->pbm_regs + schizo_iclr_offset(ino) + 4; | ||
278 | } | ||
279 | |||
280 | static unsigned long schizo_ino_to_imap(struct pci_pbm_info *pbm, | ||
281 | unsigned int ino) | ||
282 | { | ||
283 | ino &= PCI_IRQ_INO; | ||
284 | return pbm->pbm_regs + schizo_imap_offset(ino) + 4; | ||
285 | } | ||
286 | |||
368 | static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, | 287 | static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, |
369 | struct pci_dev *pdev, | 288 | struct pci_dev *pdev, |
370 | unsigned int ino) | 289 | unsigned int ino) |
371 | { | 290 | { |
372 | struct ino_bucket *bucket; | ||
373 | unsigned long imap, iclr; | 291 | unsigned long imap, iclr; |
374 | unsigned long imap_off, iclr_off; | 292 | int ign_fixup; |
375 | int pil, ign_fixup; | 293 | int virt_irq; |
376 | 294 | ||
377 | ino &= PCI_IRQ_INO; | 295 | ino &= PCI_IRQ_INO; |
378 | imap_off = schizo_imap_offset(ino); | ||
379 | 296 | ||
380 | /* Now build the IRQ bucket. */ | 297 | /* Now build the IRQ bucket. */ |
381 | pil = schizo_ino_to_pil(pdev, ino); | 298 | imap = schizo_ino_to_imap(pbm, ino); |
382 | 299 | iclr = schizo_ino_to_iclr(pbm, ino); | |
383 | if (PIL_RESERVED(pil)) | ||
384 | BUG(); | ||
385 | |||
386 | imap = pbm->pbm_regs + imap_off; | ||
387 | imap += 4; | ||
388 | |||
389 | iclr_off = schizo_iclr_offset(ino); | ||
390 | iclr = pbm->pbm_regs + iclr_off; | ||
391 | iclr += 4; | ||
392 | 300 | ||
393 | /* On Schizo, no inofixup occurs. This is because each | 301 | /* On Schizo, no inofixup occurs. This is because each |
394 | * INO has it's own IMAP register. On Psycho and Sabre | 302 | * INO has it's own IMAP register. On Psycho and Sabre |
@@ -405,19 +313,17 @@ static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, | |||
405 | ign_fixup = (1 << 6); | 313 | ign_fixup = (1 << 6); |
406 | } | 314 | } |
407 | 315 | ||
408 | bucket = __bucket(build_irq(pil, ign_fixup, iclr, imap)); | 316 | virt_irq = build_irq(ign_fixup, iclr, imap); |
409 | bucket->flags |= IBF_PCI; | ||
410 | 317 | ||
411 | if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { | 318 | if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { |
412 | struct irq_desc *p = bucket->irq_info; | 319 | irq_install_pre_handler(virt_irq, |
413 | 320 | tomatillo_wsync_handler, | |
414 | p->pre_handler = tomatillo_wsync_handler; | 321 | ((pbm->chip_version <= 4) ? |
415 | p->pre_handler_arg1 = ((pbm->chip_version <= 4) ? | 322 | (void *) 1 : (void *) 0), |
416 | (void *) 1 : (void *) 0); | 323 | (void *) pbm->sync_reg); |
417 | p->pre_handler_arg2 = (void *) pbm->sync_reg; | ||
418 | } | 324 | } |
419 | 325 | ||
420 | return __irq(bucket); | 326 | return virt_irq; |
421 | } | 327 | } |
422 | 328 | ||
423 | /* SCHIZO error handling support. */ | 329 | /* SCHIZO error handling support. */ |
@@ -458,7 +364,6 @@ struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino) | |||
458 | static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq) | 364 | static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq) |
459 | { | 365 | { |
460 | struct pci_pbm_info *pbm; | 366 | struct pci_pbm_info *pbm; |
461 | struct ino_bucket *bucket; | ||
462 | unsigned long iclr; | 367 | unsigned long iclr; |
463 | 368 | ||
464 | /* Do not clear the interrupt for the other PCI bus. | 369 | /* Do not clear the interrupt for the other PCI bus. |
@@ -476,11 +381,11 @@ static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq) | |||
476 | else | 381 | else |
477 | pbm = &p->pbm_A; | 382 | pbm = &p->pbm_A; |
478 | 383 | ||
479 | irq = schizo_irq_build(pbm, NULL, | 384 | schizo_irq_build(pbm, NULL, |
480 | (pbm->portid << 6) | (irq & IMAP_INO)); | 385 | (pbm->portid << 6) | (irq & IMAP_INO)); |
481 | bucket = __bucket(irq); | ||
482 | iclr = bucket->iclr; | ||
483 | 386 | ||
387 | iclr = schizo_ino_to_iclr(pbm, | ||
388 | (pbm->portid << 6) | (irq & IMAP_INO)); | ||
484 | upa_writel(ICLR_IDLE, iclr); | 389 | upa_writel(ICLR_IDLE, iclr); |
485 | } | 390 | } |
486 | 391 | ||
@@ -1225,7 +1130,6 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) | |||
1225 | { | 1130 | { |
1226 | struct pci_pbm_info *pbm; | 1131 | struct pci_pbm_info *pbm; |
1227 | unsigned int irq; | 1132 | unsigned int irq; |
1228 | struct ino_bucket *bucket; | ||
1229 | u64 tmp, err_mask, err_no_mask; | 1133 | u64 tmp, err_mask, err_no_mask; |
1230 | 1134 | ||
1231 | /* Build IRQs and register handlers. */ | 1135 | /* Build IRQs and register handlers. */ |
@@ -1237,8 +1141,7 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) | |||
1237 | pbm->name); | 1141 | pbm->name); |
1238 | prom_halt(); | 1142 | prom_halt(); |
1239 | } | 1143 | } |
1240 | bucket = __bucket(irq); | 1144 | tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO)); |
1241 | tmp = upa_readl(bucket->imap); | ||
1242 | upa_writel(tmp, (pbm->pbm_regs + | 1145 | upa_writel(tmp, (pbm->pbm_regs + |
1243 | schizo_imap_offset(SCHIZO_UE_INO) + 4)); | 1146 | schizo_imap_offset(SCHIZO_UE_INO) + 4)); |
1244 | 1147 | ||
@@ -1250,8 +1153,7 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) | |||
1250 | pbm->name); | 1153 | pbm->name); |
1251 | prom_halt(); | 1154 | prom_halt(); |
1252 | } | 1155 | } |
1253 | bucket = __bucket(irq); | 1156 | tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO)); |
1254 | tmp = upa_readl(bucket->imap); | ||
1255 | upa_writel(tmp, (pbm->pbm_regs + | 1157 | upa_writel(tmp, (pbm->pbm_regs + |
1256 | schizo_imap_offset(SCHIZO_CE_INO) + 4)); | 1158 | schizo_imap_offset(SCHIZO_CE_INO) + 4)); |
1257 | 1159 | ||
@@ -1264,8 +1166,8 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) | |||
1264 | pbm->name); | 1166 | pbm->name); |
1265 | prom_halt(); | 1167 | prom_halt(); |
1266 | } | 1168 | } |
1267 | bucket = __bucket(irq); | 1169 | tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | |
1268 | tmp = upa_readl(bucket->imap); | 1170 | SCHIZO_PCIERR_A_INO))); |
1269 | upa_writel(tmp, (pbm->pbm_regs + | 1171 | upa_writel(tmp, (pbm->pbm_regs + |
1270 | schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); | 1172 | schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); |
1271 | 1173 | ||
@@ -1278,8 +1180,8 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) | |||
1278 | pbm->name); | 1180 | pbm->name); |
1279 | prom_halt(); | 1181 | prom_halt(); |
1280 | } | 1182 | } |
1281 | bucket = __bucket(irq); | 1183 | tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | |
1282 | tmp = upa_readl(bucket->imap); | 1184 | SCHIZO_PCIERR_B_INO))); |
1283 | upa_writel(tmp, (pbm->pbm_regs + | 1185 | upa_writel(tmp, (pbm->pbm_regs + |
1284 | schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); | 1186 | schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); |
1285 | 1187 | ||
@@ -1291,8 +1193,8 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) | |||
1291 | pbm->name); | 1193 | pbm->name); |
1292 | prom_halt(); | 1194 | prom_halt(); |
1293 | } | 1195 | } |
1294 | bucket = __bucket(irq); | 1196 | tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | |
1295 | tmp = upa_readl(bucket->imap); | 1197 | SCHIZO_SERR_INO))); |
1296 | upa_writel(tmp, (pbm->pbm_regs + | 1198 | upa_writel(tmp, (pbm->pbm_regs + |
1297 | schizo_imap_offset(SCHIZO_SERR_INO) + 4)); | 1199 | schizo_imap_offset(SCHIZO_SERR_INO) + 4)); |
1298 | 1200 | ||
@@ -1363,7 +1265,6 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) | |||
1363 | { | 1265 | { |
1364 | struct pci_pbm_info *pbm; | 1266 | struct pci_pbm_info *pbm; |
1365 | unsigned int irq; | 1267 | unsigned int irq; |
1366 | struct ino_bucket *bucket; | ||
1367 | u64 tmp, err_mask, err_no_mask; | 1268 | u64 tmp, err_mask, err_no_mask; |
1368 | 1269 | ||
1369 | /* Build IRQs and register handlers. */ | 1270 | /* Build IRQs and register handlers. */ |
@@ -1375,8 +1276,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) | |||
1375 | pbm->name); | 1276 | pbm->name); |
1376 | prom_halt(); | 1277 | prom_halt(); |
1377 | } | 1278 | } |
1378 | bucket = __bucket(irq); | 1279 | tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO)); |
1379 | tmp = upa_readl(bucket->imap); | ||
1380 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4)); | 1280 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4)); |
1381 | 1281 | ||
1382 | pbm = pbm_for_ino(p, SCHIZO_CE_INO); | 1282 | pbm = pbm_for_ino(p, SCHIZO_CE_INO); |
@@ -1387,8 +1287,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) | |||
1387 | pbm->name); | 1287 | pbm->name); |
1388 | prom_halt(); | 1288 | prom_halt(); |
1389 | } | 1289 | } |
1390 | bucket = __bucket(irq); | 1290 | tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO)); |
1391 | tmp = upa_readl(bucket->imap); | ||
1392 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4)); | 1291 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4)); |
1393 | 1292 | ||
1394 | pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); | 1293 | pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); |
@@ -1399,8 +1298,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) | |||
1399 | pbm->name); | 1298 | pbm->name); |
1400 | prom_halt(); | 1299 | prom_halt(); |
1401 | } | 1300 | } |
1402 | bucket = __bucket(irq); | 1301 | tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_A_INO)); |
1403 | tmp = upa_readl(bucket->imap); | ||
1404 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); | 1302 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); |
1405 | 1303 | ||
1406 | pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); | 1304 | pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); |
@@ -1411,8 +1309,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) | |||
1411 | pbm->name); | 1309 | pbm->name); |
1412 | prom_halt(); | 1310 | prom_halt(); |
1413 | } | 1311 | } |
1414 | bucket = __bucket(irq); | 1312 | tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_B_INO)); |
1415 | tmp = upa_readl(bucket->imap); | ||
1416 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); | 1313 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); |
1417 | 1314 | ||
1418 | pbm = pbm_for_ino(p, SCHIZO_SERR_INO); | 1315 | pbm = pbm_for_ino(p, SCHIZO_SERR_INO); |
@@ -1423,8 +1320,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) | |||
1423 | pbm->name); | 1320 | pbm->name); |
1424 | prom_halt(); | 1321 | prom_halt(); |
1425 | } | 1322 | } |
1426 | bucket = __bucket(irq); | 1323 | tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_SERR_INO)); |
1427 | tmp = upa_readl(bucket->imap); | ||
1428 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4)); | 1324 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4)); |
1429 | 1325 | ||
1430 | /* Enable UE and CE interrupts for controller. */ | 1326 | /* Enable UE and CE interrupts for controller. */ |