diff options
Diffstat (limited to 'arch/sparc64/kernel/sbus.c')
-rw-r--r-- | arch/sparc64/kernel/sbus.c | 122 |
1 files changed, 67 insertions, 55 deletions
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 0b3e7bc96f61..60605eaf49bb 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c | |||
@@ -201,10 +201,9 @@ static unsigned long sysio_imap_to_iclr(unsigned long imap) | |||
201 | return imap + diff; | 201 | return imap + diff; |
202 | } | 202 | } |
203 | 203 | ||
204 | unsigned int sbus_build_irq(void *buscookie, unsigned int ino) | 204 | static unsigned int sbus_build_irq(struct of_device *op, unsigned int ino) |
205 | { | 205 | { |
206 | struct sbus_bus *sbus = (struct sbus_bus *)buscookie; | 206 | struct iommu *iommu = op->dev.archdata.iommu; |
207 | struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; | ||
208 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; | 207 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; |
209 | unsigned long imap, iclr; | 208 | unsigned long imap, iclr; |
210 | int sbus_level = 0; | 209 | int sbus_level = 0; |
@@ -265,12 +264,12 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino) | |||
265 | #define SYSIO_UEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ | 264 | #define SYSIO_UEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ |
266 | static irqreturn_t sysio_ue_handler(int irq, void *dev_id) | 265 | static irqreturn_t sysio_ue_handler(int irq, void *dev_id) |
267 | { | 266 | { |
268 | struct sbus_bus *sbus = dev_id; | 267 | struct of_device *op = dev_id; |
269 | struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; | 268 | struct iommu *iommu = op->dev.archdata.iommu; |
270 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; | 269 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; |
271 | unsigned long afsr_reg, afar_reg; | 270 | unsigned long afsr_reg, afar_reg; |
272 | unsigned long afsr, afar, error_bits; | 271 | unsigned long afsr, afar, error_bits; |
273 | int reported; | 272 | int reported, portid; |
274 | 273 | ||
275 | afsr_reg = reg_base + SYSIO_UE_AFSR; | 274 | afsr_reg = reg_base + SYSIO_UE_AFSR; |
276 | afar_reg = reg_base + SYSIO_UE_AFAR; | 275 | afar_reg = reg_base + SYSIO_UE_AFAR; |
@@ -285,9 +284,11 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) | |||
285 | SYSIO_UEAFSR_SPIO | SYSIO_UEAFSR_SDRD | SYSIO_UEAFSR_SDWR); | 284 | SYSIO_UEAFSR_SPIO | SYSIO_UEAFSR_SDRD | SYSIO_UEAFSR_SDWR); |
286 | upa_writeq(error_bits, afsr_reg); | 285 | upa_writeq(error_bits, afsr_reg); |
287 | 286 | ||
287 | portid = of_getintprop_default(op->node, "portid", -1); | ||
288 | |||
288 | /* Log the error. */ | 289 | /* Log the error. */ |
289 | printk("SYSIO[%x]: Uncorrectable ECC Error, primary error type[%s]\n", | 290 | printk("SYSIO[%x]: Uncorrectable ECC Error, primary error type[%s]\n", |
290 | sbus->portid, | 291 | portid, |
291 | (((error_bits & SYSIO_UEAFSR_PPIO) ? | 292 | (((error_bits & SYSIO_UEAFSR_PPIO) ? |
292 | "PIO" : | 293 | "PIO" : |
293 | ((error_bits & SYSIO_UEAFSR_PDRD) ? | 294 | ((error_bits & SYSIO_UEAFSR_PDRD) ? |
@@ -295,12 +296,12 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) | |||
295 | ((error_bits & SYSIO_UEAFSR_PDWR) ? | 296 | ((error_bits & SYSIO_UEAFSR_PDWR) ? |
296 | "DVMA Write" : "???"))))); | 297 | "DVMA Write" : "???"))))); |
297 | printk("SYSIO[%x]: DOFF[%lx] SIZE[%lx] MID[%lx]\n", | 298 | printk("SYSIO[%x]: DOFF[%lx] SIZE[%lx] MID[%lx]\n", |
298 | sbus->portid, | 299 | portid, |
299 | (afsr & SYSIO_UEAFSR_DOFF) >> 45UL, | 300 | (afsr & SYSIO_UEAFSR_DOFF) >> 45UL, |
300 | (afsr & SYSIO_UEAFSR_SIZE) >> 42UL, | 301 | (afsr & SYSIO_UEAFSR_SIZE) >> 42UL, |
301 | (afsr & SYSIO_UEAFSR_MID) >> 37UL); | 302 | (afsr & SYSIO_UEAFSR_MID) >> 37UL); |
302 | printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); | 303 | printk("SYSIO[%x]: AFAR[%016lx]\n", portid, afar); |
303 | printk("SYSIO[%x]: Secondary UE errors [", sbus->portid); | 304 | printk("SYSIO[%x]: Secondary UE errors [", portid); |
304 | reported = 0; | 305 | reported = 0; |
305 | if (afsr & SYSIO_UEAFSR_SPIO) { | 306 | if (afsr & SYSIO_UEAFSR_SPIO) { |
306 | reported++; | 307 | reported++; |
@@ -337,12 +338,12 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) | |||
337 | #define SYSIO_CEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ | 338 | #define SYSIO_CEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ |
338 | static irqreturn_t sysio_ce_handler(int irq, void *dev_id) | 339 | static irqreturn_t sysio_ce_handler(int irq, void *dev_id) |
339 | { | 340 | { |
340 | struct sbus_bus *sbus = dev_id; | 341 | struct of_device *op = dev_id; |
341 | struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; | 342 | struct iommu *iommu = op->dev.archdata.iommu; |
342 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; | 343 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; |
343 | unsigned long afsr_reg, afar_reg; | 344 | unsigned long afsr_reg, afar_reg; |
344 | unsigned long afsr, afar, error_bits; | 345 | unsigned long afsr, afar, error_bits; |
345 | int reported; | 346 | int reported, portid; |
346 | 347 | ||
347 | afsr_reg = reg_base + SYSIO_CE_AFSR; | 348 | afsr_reg = reg_base + SYSIO_CE_AFSR; |
348 | afar_reg = reg_base + SYSIO_CE_AFAR; | 349 | afar_reg = reg_base + SYSIO_CE_AFAR; |
@@ -357,8 +358,10 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) | |||
357 | SYSIO_CEAFSR_SPIO | SYSIO_CEAFSR_SDRD | SYSIO_CEAFSR_SDWR); | 358 | SYSIO_CEAFSR_SPIO | SYSIO_CEAFSR_SDRD | SYSIO_CEAFSR_SDWR); |
358 | upa_writeq(error_bits, afsr_reg); | 359 | upa_writeq(error_bits, afsr_reg); |
359 | 360 | ||
361 | portid = of_getintprop_default(op->node, "portid", -1); | ||
362 | |||
360 | printk("SYSIO[%x]: Correctable ECC Error, primary error type[%s]\n", | 363 | printk("SYSIO[%x]: Correctable ECC Error, primary error type[%s]\n", |
361 | sbus->portid, | 364 | portid, |
362 | (((error_bits & SYSIO_CEAFSR_PPIO) ? | 365 | (((error_bits & SYSIO_CEAFSR_PPIO) ? |
363 | "PIO" : | 366 | "PIO" : |
364 | ((error_bits & SYSIO_CEAFSR_PDRD) ? | 367 | ((error_bits & SYSIO_CEAFSR_PDRD) ? |
@@ -370,14 +373,14 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) | |||
370 | * XXX UDB CE trap handler does... -DaveM | 373 | * XXX UDB CE trap handler does... -DaveM |
371 | */ | 374 | */ |
372 | printk("SYSIO[%x]: DOFF[%lx] ECC Syndrome[%lx] Size[%lx] MID[%lx]\n", | 375 | printk("SYSIO[%x]: DOFF[%lx] ECC Syndrome[%lx] Size[%lx] MID[%lx]\n", |
373 | sbus->portid, | 376 | portid, |
374 | (afsr & SYSIO_CEAFSR_DOFF) >> 45UL, | 377 | (afsr & SYSIO_CEAFSR_DOFF) >> 45UL, |
375 | (afsr & SYSIO_CEAFSR_ESYND) >> 48UL, | 378 | (afsr & SYSIO_CEAFSR_ESYND) >> 48UL, |
376 | (afsr & SYSIO_CEAFSR_SIZE) >> 42UL, | 379 | (afsr & SYSIO_CEAFSR_SIZE) >> 42UL, |
377 | (afsr & SYSIO_CEAFSR_MID) >> 37UL); | 380 | (afsr & SYSIO_CEAFSR_MID) >> 37UL); |
378 | printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); | 381 | printk("SYSIO[%x]: AFAR[%016lx]\n", portid, afar); |
379 | 382 | ||
380 | printk("SYSIO[%x]: Secondary CE errors [", sbus->portid); | 383 | printk("SYSIO[%x]: Secondary CE errors [", portid); |
381 | reported = 0; | 384 | reported = 0; |
382 | if (afsr & SYSIO_CEAFSR_SPIO) { | 385 | if (afsr & SYSIO_CEAFSR_SPIO) { |
383 | reported++; | 386 | reported++; |
@@ -414,11 +417,11 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) | |||
414 | #define SYSIO_SBAFSR_RESV3 0x0000001fffffffffUL /* Reserved */ | 417 | #define SYSIO_SBAFSR_RESV3 0x0000001fffffffffUL /* Reserved */ |
415 | static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) | 418 | static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) |
416 | { | 419 | { |
417 | struct sbus_bus *sbus = dev_id; | 420 | struct of_device *op = dev_id; |
418 | struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; | 421 | struct iommu *iommu = op->dev.archdata.iommu; |
419 | unsigned long afsr_reg, afar_reg, reg_base; | 422 | unsigned long afsr_reg, afar_reg, reg_base; |
420 | unsigned long afsr, afar, error_bits; | 423 | unsigned long afsr, afar, error_bits; |
421 | int reported; | 424 | int reported, portid; |
422 | 425 | ||
423 | reg_base = iommu->write_complete_reg - 0x2000UL; | 426 | reg_base = iommu->write_complete_reg - 0x2000UL; |
424 | afsr_reg = reg_base + SYSIO_SBUS_AFSR; | 427 | afsr_reg = reg_base + SYSIO_SBUS_AFSR; |
@@ -433,9 +436,11 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) | |||
433 | SYSIO_SBAFSR_SLE | SYSIO_SBAFSR_STO | SYSIO_SBAFSR_SBERR); | 436 | SYSIO_SBAFSR_SLE | SYSIO_SBAFSR_STO | SYSIO_SBAFSR_SBERR); |
434 | upa_writeq(error_bits, afsr_reg); | 437 | upa_writeq(error_bits, afsr_reg); |
435 | 438 | ||
439 | portid = of_getintprop_default(op->node, "portid", -1); | ||
440 | |||
436 | /* Log the error. */ | 441 | /* Log the error. */ |
437 | printk("SYSIO[%x]: SBUS Error, primary error type[%s] read(%d)\n", | 442 | printk("SYSIO[%x]: SBUS Error, primary error type[%s] read(%d)\n", |
438 | sbus->portid, | 443 | portid, |
439 | (((error_bits & SYSIO_SBAFSR_PLE) ? | 444 | (((error_bits & SYSIO_SBAFSR_PLE) ? |
440 | "Late PIO Error" : | 445 | "Late PIO Error" : |
441 | ((error_bits & SYSIO_SBAFSR_PTO) ? | 446 | ((error_bits & SYSIO_SBAFSR_PTO) ? |
@@ -444,11 +449,11 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) | |||
444 | "Error Ack" : "???")))), | 449 | "Error Ack" : "???")))), |
445 | (afsr & SYSIO_SBAFSR_RD) ? 1 : 0); | 450 | (afsr & SYSIO_SBAFSR_RD) ? 1 : 0); |
446 | printk("SYSIO[%x]: size[%lx] MID[%lx]\n", | 451 | printk("SYSIO[%x]: size[%lx] MID[%lx]\n", |
447 | sbus->portid, | 452 | portid, |
448 | (afsr & SYSIO_SBAFSR_SIZE) >> 42UL, | 453 | (afsr & SYSIO_SBAFSR_SIZE) >> 42UL, |
449 | (afsr & SYSIO_SBAFSR_MID) >> 37UL); | 454 | (afsr & SYSIO_SBAFSR_MID) >> 37UL); |
450 | printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); | 455 | printk("SYSIO[%x]: AFAR[%016lx]\n", portid, afar); |
451 | printk("SYSIO[%x]: Secondary SBUS errors [", sbus->portid); | 456 | printk("SYSIO[%x]: Secondary SBUS errors [", portid); |
452 | reported = 0; | 457 | reported = 0; |
453 | if (afsr & SYSIO_SBAFSR_SLE) { | 458 | if (afsr & SYSIO_SBAFSR_SLE) { |
454 | reported++; | 459 | reported++; |
@@ -480,34 +485,37 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) | |||
480 | #define SYSIO_CE_INO 0x35 | 485 | #define SYSIO_CE_INO 0x35 |
481 | #define SYSIO_SBUSERR_INO 0x36 | 486 | #define SYSIO_SBUSERR_INO 0x36 |
482 | 487 | ||
483 | static void __init sysio_register_error_handlers(struct sbus_bus *sbus) | 488 | static void __init sysio_register_error_handlers(struct of_device *op) |
484 | { | 489 | { |
485 | struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; | 490 | struct iommu *iommu = op->dev.archdata.iommu; |
486 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; | 491 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; |
487 | unsigned int irq; | 492 | unsigned int irq; |
488 | u64 control; | 493 | u64 control; |
494 | int portid; | ||
495 | |||
496 | portid = of_getintprop_default(op->node, "portid", -1); | ||
489 | 497 | ||
490 | irq = sbus_build_irq(sbus, SYSIO_UE_INO); | 498 | irq = sbus_build_irq(op, SYSIO_UE_INO); |
491 | if (request_irq(irq, sysio_ue_handler, 0, | 499 | if (request_irq(irq, sysio_ue_handler, 0, |
492 | "SYSIO_UE", sbus) < 0) { | 500 | "SYSIO_UE", op) < 0) { |
493 | prom_printf("SYSIO[%x]: Cannot register UE interrupt.\n", | 501 | prom_printf("SYSIO[%x]: Cannot register UE interrupt.\n", |
494 | sbus->portid); | 502 | portid); |
495 | prom_halt(); | 503 | prom_halt(); |
496 | } | 504 | } |
497 | 505 | ||
498 | irq = sbus_build_irq(sbus, SYSIO_CE_INO); | 506 | irq = sbus_build_irq(op, SYSIO_CE_INO); |
499 | if (request_irq(irq, sysio_ce_handler, 0, | 507 | if (request_irq(irq, sysio_ce_handler, 0, |
500 | "SYSIO_CE", sbus) < 0) { | 508 | "SYSIO_CE", op) < 0) { |
501 | prom_printf("SYSIO[%x]: Cannot register CE interrupt.\n", | 509 | prom_printf("SYSIO[%x]: Cannot register CE interrupt.\n", |
502 | sbus->portid); | 510 | portid); |
503 | prom_halt(); | 511 | prom_halt(); |
504 | } | 512 | } |
505 | 513 | ||
506 | irq = sbus_build_irq(sbus, SYSIO_SBUSERR_INO); | 514 | irq = sbus_build_irq(op, SYSIO_SBUSERR_INO); |
507 | if (request_irq(irq, sysio_sbus_error_handler, 0, | 515 | if (request_irq(irq, sysio_sbus_error_handler, 0, |
508 | "SYSIO_SBERR", sbus) < 0) { | 516 | "SYSIO_SBERR", op) < 0) { |
509 | prom_printf("SYSIO[%x]: Cannot register SBUS Error interrupt.\n", | 517 | prom_printf("SYSIO[%x]: Cannot register SBUS Error interrupt.\n", |
510 | sbus->portid); | 518 | portid); |
511 | prom_halt(); | 519 | prom_halt(); |
512 | } | 520 | } |
513 | 521 | ||
@@ -523,19 +531,15 @@ static void __init sysio_register_error_handlers(struct sbus_bus *sbus) | |||
523 | } | 531 | } |
524 | 532 | ||
525 | /* Boot time initialization. */ | 533 | /* Boot time initialization. */ |
526 | static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | 534 | static void __init sbus_iommu_init(struct of_device *op) |
527 | { | 535 | { |
528 | const struct linux_prom64_registers *pr; | 536 | const struct linux_prom64_registers *pr; |
529 | struct device_node *dp; | 537 | struct device_node *dp = op->node; |
530 | struct iommu *iommu; | 538 | struct iommu *iommu; |
531 | struct strbuf *strbuf; | 539 | struct strbuf *strbuf; |
532 | unsigned long regs, reg_base; | 540 | unsigned long regs, reg_base; |
541 | int i, portid; | ||
533 | u64 control; | 542 | u64 control; |
534 | int i; | ||
535 | |||
536 | dp = of_find_node_by_phandle(__node); | ||
537 | |||
538 | sbus->portid = of_getintprop_default(dp, "upa-portid", -1); | ||
539 | 543 | ||
540 | pr = of_get_property(dp, "reg", NULL); | 544 | pr = of_get_property(dp, "reg", NULL); |
541 | if (!pr) { | 545 | if (!pr) { |
@@ -552,9 +556,9 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | |||
552 | if (!strbuf) | 556 | if (!strbuf) |
553 | goto fatal_memory_error; | 557 | goto fatal_memory_error; |
554 | 558 | ||
555 | sbus->ofdev.dev.archdata.iommu = iommu; | 559 | op->dev.archdata.iommu = iommu; |
556 | sbus->ofdev.dev.archdata.stc = strbuf; | 560 | op->dev.archdata.stc = strbuf; |
557 | sbus->ofdev.dev.archdata.numa_node = -1; | 561 | op->dev.archdata.numa_node = -1; |
558 | 562 | ||
559 | reg_base = regs + SYSIO_IOMMUREG_BASE; | 563 | reg_base = regs + SYSIO_IOMMUREG_BASE; |
560 | iommu->iommu_control = reg_base + IOMMU_CONTROL; | 564 | iommu->iommu_control = reg_base + IOMMU_CONTROL; |
@@ -582,8 +586,9 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | |||
582 | */ | 586 | */ |
583 | iommu->write_complete_reg = regs + 0x2000UL; | 587 | iommu->write_complete_reg = regs + 0x2000UL; |
584 | 588 | ||
585 | printk("SYSIO: UPA portID %x, at %016lx\n", | 589 | portid = of_getintprop_default(op->node, "portid", -1); |
586 | sbus->portid, regs); | 590 | printk(KERN_INFO "SYSIO: UPA portID %x, at %016lx\n", |
591 | portid, regs); | ||
587 | 592 | ||
588 | /* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */ | 593 | /* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */ |
589 | if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff, -1)) | 594 | if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff, -1)) |
@@ -641,23 +646,30 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | |||
641 | 646 | ||
642 | /* Now some Xfire specific grot... */ | 647 | /* Now some Xfire specific grot... */ |
643 | if (this_is_starfire) | 648 | if (this_is_starfire) |
644 | starfire_hookup(sbus->portid); | 649 | starfire_hookup(portid); |
645 | 650 | ||
646 | sysio_register_error_handlers(sbus); | 651 | sysio_register_error_handlers(op); |
647 | return; | 652 | return; |
648 | 653 | ||
649 | fatal_memory_error: | 654 | fatal_memory_error: |
650 | prom_printf("sbus_iommu_init: Fatal memory allocation error.\n"); | 655 | prom_printf("sbus_iommu_init: Fatal memory allocation error.\n"); |
651 | } | 656 | } |
652 | 657 | ||
653 | void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) | 658 | static int __init sbus_init(void) |
654 | { | ||
655 | sbus_iommu_init(dp->node, sbus); | ||
656 | } | ||
657 | |||
658 | void __init sbus_arch_postinit(void) | ||
659 | { | 659 | { |
660 | extern void firetruck_init(void); | 660 | extern void firetruck_init(void); |
661 | struct device_node *dp; | ||
662 | |||
663 | for_each_node_by_name(dp, "sbus") { | ||
664 | struct of_device *op = of_find_device_by_node(dp); | ||
665 | |||
666 | sbus_iommu_init(op); | ||
667 | of_propagate_archdata(op); | ||
668 | } | ||
661 | 669 | ||
662 | firetruck_init(); | 670 | firetruck_init(); |
671 | |||
672 | return 0; | ||
663 | } | 673 | } |
674 | |||
675 | subsys_initcall(sbus_init); | ||