aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/pci_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/pci_common.c')
-rw-r--r--arch/sparc64/kernel/pci_common.c291
1 files changed, 6 insertions, 285 deletions
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
index b06a2955bf5f..7a59cc72c844 100644
--- a/arch/sparc64/kernel/pci_common.c
+++ b/arch/sparc64/kernel/pci_common.c
@@ -10,12 +10,10 @@
10 10
11#include <asm/pbm.h> 11#include <asm/pbm.h>
12#include <asm/prom.h> 12#include <asm/prom.h>
13#include <asm/of_device.h>
13 14
14#include "pci_impl.h" 15#include "pci_impl.h"
15 16
16/* Pass "pci=irq_verbose" on the kernel command line to enable this. */
17int pci_irq_verbose;
18
19/* Fix self device of BUS and hook it into BUS->self. 17/* Fix self device of BUS and hook it into BUS->self.
20 * The pci_scan_bus does not do this for the host bridge. 18 * The pci_scan_bus does not do this for the host bridge.
21 */ 19 */
@@ -169,6 +167,7 @@ static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm,
169 } 167 }
170 pcp->pbm = pbm; 168 pcp->pbm = pbm;
171 pcp->prom_node = dp; 169 pcp->prom_node = dp;
170 pcp->op = of_find_device_by_node(dp);
172 memcpy(pcp->prom_regs, pregs, 171 memcpy(pcp->prom_regs, pregs,
173 nregs * sizeof(struct linux_prom_pci_registers)); 172 nregs * sizeof(struct linux_prom_pci_registers));
174 pcp->num_prom_regs = nregs; 173 pcp->num_prom_regs = nregs;
@@ -549,296 +548,18 @@ void __init pci_assign_unassigned(struct pci_pbm_info *pbm,
549 pci_assign_unassigned(pbm, bus); 548 pci_assign_unassigned(pbm, bus);
550} 549}
551 550
552static inline unsigned int pci_slot_swivel(struct pci_pbm_info *pbm,
553 struct pci_dev *toplevel_pdev,
554 struct pci_dev *pdev,
555 unsigned int interrupt)
556{
557 unsigned int ret;
558
559 if (unlikely(interrupt < 1 || interrupt > 4)) {
560 printk("%s: Device %s interrupt value of %u is strange.\n",
561 pbm->name, pci_name(pdev), interrupt);
562 return interrupt;
563 }
564
565 ret = ((interrupt - 1 + (PCI_SLOT(pdev->devfn) & 3)) & 3) + 1;
566
567 if (pci_irq_verbose)
568 printk("%s: %s IRQ Swivel %s [%x:%x] -> [%x]\n",
569 pbm->name, pci_name(toplevel_pdev), pci_name(pdev),
570 interrupt, PCI_SLOT(pdev->devfn), ret);
571
572 return ret;
573}
574
575static inline unsigned int pci_apply_intmap(struct pci_pbm_info *pbm,
576 struct pci_dev *toplevel_pdev,
577 struct pci_dev *pbus,
578 struct pci_dev *pdev,
579 unsigned int interrupt,
580 struct device_node **cnode)
581{
582 struct linux_prom_pci_intmap *imap;
583 struct linux_prom_pci_intmask *imask;
584 struct pcidev_cookie *pbus_pcp = pbus->sysdata;
585 struct pcidev_cookie *pdev_pcp = pdev->sysdata;
586 struct linux_prom_pci_registers *pregs = pdev_pcp->prom_regs;
587 struct property *prop;
588 int plen, num_imap, i;
589 unsigned int hi, mid, lo, irq, orig_interrupt;
590
591 *cnode = pbus_pcp->prom_node;
592
593 prop = of_find_property(pbus_pcp->prom_node, "interrupt-map", &plen);
594 if (!prop ||
595 (plen % sizeof(struct linux_prom_pci_intmap)) != 0) {
596 printk("%s: Device %s interrupt-map has bad len %d\n",
597 pbm->name, pci_name(pbus), plen);
598 goto no_intmap;
599 }
600 imap = prop->value;
601 num_imap = plen / sizeof(struct linux_prom_pci_intmap);
602
603 prop = of_find_property(pbus_pcp->prom_node, "interrupt-map-mask", &plen);
604 if (!prop ||
605 (plen % sizeof(struct linux_prom_pci_intmask)) != 0) {
606 printk("%s: Device %s interrupt-map-mask has bad len %d\n",
607 pbm->name, pci_name(pbus), plen);
608 goto no_intmap;
609 }
610 imask = prop->value;
611
612 orig_interrupt = interrupt;
613
614 hi = pregs->phys_hi & imask->phys_hi;
615 mid = pregs->phys_mid & imask->phys_mid;
616 lo = pregs->phys_lo & imask->phys_lo;
617 irq = interrupt & imask->interrupt;
618
619 for (i = 0; i < num_imap; i++) {
620 if (imap[i].phys_hi == hi &&
621 imap[i].phys_mid == mid &&
622 imap[i].phys_lo == lo &&
623 imap[i].interrupt == irq) {
624 *cnode = of_find_node_by_phandle(imap[i].cnode);
625 interrupt = imap[i].cinterrupt;
626 }
627 }
628
629 if (pci_irq_verbose)
630 printk("%s: %s MAP BUS %s DEV %s [%x] -> [%x]\n",
631 pbm->name, pci_name(toplevel_pdev),
632 pci_name(pbus), pci_name(pdev),
633 orig_interrupt, interrupt);
634
635no_intmap:
636 return interrupt;
637}
638
639/* For each PCI bus on the way to the root:
640 * 1) If it has an interrupt-map property, apply it.
641 * 2) Else, swivel the interrupt number based upon the PCI device number.
642 *
643 * Return the "IRQ controller" node. If this is the PBM's device node,
644 * all interrupt translations are complete, else we should use that node's
645 * "reg" property to apply the PBM's "interrupt-{map,mask}" to the interrupt.
646 */
647static struct device_node * __init
648pci_intmap_match_to_root(struct pci_pbm_info *pbm,
649 struct pci_dev *pdev,
650 unsigned int *interrupt)
651{
652 struct pci_dev *toplevel_pdev = pdev;
653 struct pcidev_cookie *toplevel_pcp = toplevel_pdev->sysdata;
654 struct device_node *cnode = toplevel_pcp->prom_node;
655
656 while (pdev->bus->number != pbm->pci_first_busno) {
657 struct pci_dev *pbus = pdev->bus->self;
658 struct pcidev_cookie *pcp = pbus->sysdata;
659 struct property *prop;
660
661 prop = of_find_property(pcp->prom_node, "interrupt-map", NULL);
662 if (!prop) {
663 *interrupt = pci_slot_swivel(pbm, toplevel_pdev,
664 pdev, *interrupt);
665 cnode = pcp->prom_node;
666 } else {
667 *interrupt = pci_apply_intmap(pbm, toplevel_pdev,
668 pbus, pdev,
669 *interrupt, &cnode);
670
671 while (pcp->prom_node != cnode &&
672 pbus->bus->number != pbm->pci_first_busno) {
673 pbus = pbus->bus->self;
674 pcp = pbus->sysdata;
675 }
676 }
677 pdev = pbus;
678
679 if (cnode == pbm->prom_node)
680 break;
681 }
682
683 return cnode;
684}
685
686static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt)
687{
688 struct pcidev_cookie *dev_pcp = pdev->sysdata;
689 struct pci_pbm_info *pbm = dev_pcp->pbm;
690 struct linux_prom_pci_registers *reg;
691 struct device_node *cnode;
692 struct property *prop;
693 unsigned int hi, mid, lo, irq;
694 int i, plen;
695
696 cnode = pci_intmap_match_to_root(pbm, pdev, interrupt);
697 if (cnode == pbm->prom_node)
698 goto success;
699
700 prop = of_find_property(cnode, "reg", &plen);
701 if (!prop ||
702 (plen % sizeof(struct linux_prom_pci_registers)) != 0) {
703 printk("%s: OBP node %s reg property has bad len %d\n",
704 pbm->name, cnode->full_name, plen);
705 goto fail;
706 }
707 reg = prop->value;
708
709 hi = reg[0].phys_hi & pbm->pbm_intmask->phys_hi;
710 mid = reg[0].phys_mid & pbm->pbm_intmask->phys_mid;
711 lo = reg[0].phys_lo & pbm->pbm_intmask->phys_lo;
712 irq = *interrupt & pbm->pbm_intmask->interrupt;
713
714 for (i = 0; i < pbm->num_pbm_intmap; i++) {
715 struct linux_prom_pci_intmap *intmap;
716
717 intmap = &pbm->pbm_intmap[i];
718
719 if (intmap->phys_hi == hi &&
720 intmap->phys_mid == mid &&
721 intmap->phys_lo == lo &&
722 intmap->interrupt == irq) {
723 *interrupt = intmap->cinterrupt;
724 goto success;
725 }
726 }
727
728fail:
729 return 0;
730
731success:
732 if (pci_irq_verbose)
733 printk("%s: Routing bus[%2x] slot[%2x] to INO[%02x]\n",
734 pbm->name,
735 pdev->bus->number, PCI_SLOT(pdev->devfn),
736 *interrupt);
737 return 1;
738}
739
740static void __init pdev_fixup_irq(struct pci_dev *pdev) 551static void __init pdev_fixup_irq(struct pci_dev *pdev)
741{ 552{
742 struct pcidev_cookie *pcp = pdev->sysdata; 553 struct pcidev_cookie *pcp = pdev->sysdata;
743 struct pci_pbm_info *pbm = pcp->pbm; 554 struct of_device *op = pcp->op;
744 struct pci_controller_info *p = pbm->parent;
745 unsigned int portid = pbm->portid;
746 unsigned int prom_irq;
747 struct device_node *dp = pcp->prom_node;
748 struct property *prop;
749
750 /* If this is an empty EBUS device, sometimes OBP fails to
751 * give it a valid fully specified interrupts property.
752 * The EBUS hooked up to SunHME on PCI I/O boards of
753 * Ex000 systems is one such case.
754 *
755 * The interrupt is not important so just ignore it.
756 */
757 if (pdev->vendor == PCI_VENDOR_ID_SUN &&
758 pdev->device == PCI_DEVICE_ID_SUN_EBUS &&
759 !dp->child) {
760 pdev->irq = 0;
761 return;
762 }
763 555
764 prop = of_find_property(dp, "interrupts", NULL); 556 if (op->irqs[0] == 0xffffffff) {
765 if (!prop) { 557 pdev->irq = PCI_IRQ_NONE;
766 pdev->irq = 0;
767 return; 558 return;
768 } 559 }
769 prom_irq = *(unsigned int *) prop->value;
770
771 if (tlb_type != hypervisor) {
772 /* Fully specified already? */
773 if (((prom_irq & PCI_IRQ_IGN) >> 6) == portid) {
774 pdev->irq = p->irq_build(pbm, pdev, prom_irq);
775 goto have_irq;
776 }
777
778 /* An onboard device? (bit 5 set) */
779 if ((prom_irq & PCI_IRQ_INO) & 0x20) {
780 pdev->irq = p->irq_build(pbm, pdev, (portid << 6 | prom_irq));
781 goto have_irq;
782 }
783 }
784
785 /* Can we find a matching entry in the interrupt-map? */
786 if (pci_intmap_match(pdev, &prom_irq)) {
787 pdev->irq = p->irq_build(pbm, pdev, (portid << 6) | prom_irq);
788 goto have_irq;
789 }
790
791 /* Ok, we have to do it the hard way. */
792 {
793 unsigned int bus, slot, line;
794
795 bus = (pbm == &pbm->parent->pbm_B) ? (1 << 4) : 0;
796
797 /* If we have a legal interrupt property, use it as
798 * the IRQ line.
799 */
800 if (prom_irq > 0 && prom_irq < 5) {
801 line = ((prom_irq - 1) & 3);
802 } else {
803 u8 pci_irq_line;
804 560
805 /* Else just directly consult PCI config space. */ 561 pdev->irq = op->irqs[0];
806 pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pci_irq_line);
807 line = ((pci_irq_line - 1) & 3);
808 }
809
810 /* Now figure out the slot.
811 *
812 * Basically, device number zero on the top-level bus is
813 * always the PCI host controller. Slot 0 is then device 1.
814 * PBM A supports two external slots (0 and 1), and PBM B
815 * supports 4 external slots (0, 1, 2, and 3). On-board PCI
816 * devices are wired to device numbers outside of these
817 * ranges. -DaveM
818 */
819 if (pdev->bus->number == pbm->pci_first_busno) {
820 slot = PCI_SLOT(pdev->devfn) - pbm->pci_first_slot;
821 } else {
822 struct pci_dev *bus_dev;
823
824 /* Underneath a bridge, use slot number of parent
825 * bridge which is closest to the PBM.
826 */
827 bus_dev = pdev->bus->self;
828 while (bus_dev->bus &&
829 bus_dev->bus->number != pbm->pci_first_busno)
830 bus_dev = bus_dev->bus->self;
831
832 slot = PCI_SLOT(bus_dev->devfn) - pbm->pci_first_slot;
833 }
834 slot = slot << 2;
835
836 pdev->irq = p->irq_build(pbm, pdev,
837 ((portid << 6) & PCI_IRQ_IGN) |
838 (bus | slot | line));
839 }
840 562
841have_irq:
842 pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 563 pci_write_config_byte(pdev, PCI_INTERRUPT_LINE,
843 pdev->irq & PCI_IRQ_INO); 564 pdev->irq & PCI_IRQ_INO);
844} 565}