aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/pci_schizo.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/pci_schizo.c')
-rw-r--r--arch/sparc64/kernel/pci_schizo.c192
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 235static 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 */
239static 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
288static 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
330static 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
273static 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
280static 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
368static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, 287static 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)
458static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq) 364static 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. */