aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64')
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c116
1 files changed, 102 insertions, 14 deletions
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index dc79b748feaf..5174346ce35d 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -538,6 +538,12 @@ static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
538 ret = pci_sun4v_config_get(devhandle, 538 ret = pci_sun4v_config_get(devhandle,
539 HV_PCI_DEVICE_BUILD(bus, device, func), 539 HV_PCI_DEVICE_BUILD(bus, device, func),
540 where, size); 540 where, size);
541#if 0
542 printk("read_pci_cfg: devh[%x] device[%08x] where[%x] sz[%d] "
543 "== [%016lx]\n",
544 devhandle, HV_PCI_DEVICE_BUILD(bus, device, func),
545 where, size, ret);
546#endif
541 } 547 }
542 switch (size) { 548 switch (size) {
543 case 1: 549 case 1:
@@ -571,6 +577,12 @@ static int pci_sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
571 ret = pci_sun4v_config_put(devhandle, 577 ret = pci_sun4v_config_put(devhandle,
572 HV_PCI_DEVICE_BUILD(bus, device, func), 578 HV_PCI_DEVICE_BUILD(bus, device, func),
573 where, size, value); 579 where, size, value);
580#if 0
581 printk("write_pci_cfg: devh[%x] device[%08x] where[%x] sz[%d] "
582 "val[%08x] == [%016lx]\n",
583 devhandle, HV_PCI_DEVICE_BUILD(bus, device, func),
584 where, size, value, ret);
585#endif
574 } 586 }
575 return PCIBIOS_SUCCESSFUL; 587 return PCIBIOS_SUCCESSFUL;
576} 588}
@@ -598,10 +610,13 @@ static void pbm_scan_bus(struct pci_controller_info *p,
598 pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, 610 pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno,
599 p->pci_ops, 611 p->pci_ops,
600 pbm); 612 pbm);
613#if 0
601 pci_fixup_host_bridge_self(pbm->pci_bus); 614 pci_fixup_host_bridge_self(pbm->pci_bus);
602 pbm->pci_bus->self->sysdata = cookie; 615 pbm->pci_bus->self->sysdata = cookie;
616#endif
603 617
604 pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); 618 pci_fill_in_pbm_cookies(pbm->pci_bus, pbm,
619 prom_getchild(pbm->prom_node));
605 pci_record_assignments(pbm, pbm->pci_bus); 620 pci_record_assignments(pbm, pbm->pci_bus);
606 pci_assign_unassigned(pbm, pbm->pci_bus); 621 pci_assign_unassigned(pbm, pbm->pci_bus);
607 pci_fixup_irq(pbm, pbm->pci_bus); 622 pci_fixup_irq(pbm, pbm->pci_bus);
@@ -631,8 +646,65 @@ static unsigned int pci_sun4v_irq_build(struct pci_pbm_info *pbm,
631 struct pci_dev *pdev, 646 struct pci_dev *pdev,
632 unsigned int ino) 647 unsigned int ino)
633{ 648{
634 /* XXX Implement me! XXX */ 649 struct ino_bucket *bucket;
635 return 0; 650 unsigned long sysino;
651 u32 devhandle = pbm->devhandle;
652 int pil;
653
654 sysino = sun4v_devino_to_sysino(devhandle, ino);
655
656 printk(KERN_INFO "pci_irq_buld: Mapping ( devh[%08x] ino[%08x] ) "
657 "--> sysino[%016lx]\n", devhandle, ino, sysino);
658
659 pil = 4;
660 if (pdev) {
661 switch ((pdev->class >> 16) & 0xff) {
662 case PCI_BASE_CLASS_STORAGE:
663 pil = 4;
664 break;
665
666 case PCI_BASE_CLASS_NETWORK:
667 pil = 6;
668 break;
669
670 case PCI_BASE_CLASS_DISPLAY:
671 pil = 9;
672 break;
673
674 case PCI_BASE_CLASS_MULTIMEDIA:
675 case PCI_BASE_CLASS_MEMORY:
676 case PCI_BASE_CLASS_BRIDGE:
677 case PCI_BASE_CLASS_SERIAL:
678 pil = 10;
679 break;
680
681 default:
682 pil = 4;
683 break;
684 };
685 }
686 BUG_ON(PIL_RESERVED(pil));
687
688 bucket = &ivector_table[sysino];
689
690 /* Catch accidental accesses to these things. IMAP/ICLR handling
691 * is done by hypervisor calls on sun4v platforms, not by direct
692 * register accesses.
693 */
694 bucket->imap = ~0UL;
695 bucket->iclr = ~0UL;
696
697 bucket->pil = pil;
698 bucket->flags = IBF_PCI;
699
700 bucket->irq_info = kmalloc(sizeof(struct irq_desc), GFP_ATOMIC);
701 if (!bucket->irq_info) {
702 prom_printf("IRQ: Error, kmalloc(irq_desc) failed.\n");
703 prom_halt();
704 }
705 memset(bucket->irq_info, 0, sizeof(struct irq_desc));
706
707 return __irq(bucket);
636} 708}
637 709
638static void pci_sun4v_base_address_update(struct pci_dev *pdev, int resource) 710static void pci_sun4v_base_address_update(struct pci_dev *pdev, int resource)
@@ -834,10 +906,35 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
834 probe_existing_entries(pbm, iommu); 906 probe_existing_entries(pbm, iommu);
835} 907}
836 908
909/* Don't get this from the root nexus, get it from the "pci@0" node below. */
910static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm)
911{
912 unsigned int busrange[2];
913 int prom_node = pbm->prom_node;
914 int err;
915
916 prom_node = prom_getchild(prom_node);
917 if (prom_node == 0) {
918 prom_printf("%s: Fatal error, no child OBP node.\n", pbm->name);
919 prom_halt();
920 }
921
922 err = prom_getproperty(prom_node, "bus-range",
923 (char *)&busrange[0],
924 sizeof(busrange));
925 if (err == 0 || err == -1) {
926 prom_printf("%s: Fatal error, no bus-range.\n", pbm->name);
927 prom_halt();
928 }
929
930 pbm->pci_first_busno = busrange[0];
931 pbm->pci_last_busno = busrange[1];
932
933}
934
837static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, unsigned int devhandle) 935static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, unsigned int devhandle)
838{ 936{
839 struct pci_pbm_info *pbm; 937 struct pci_pbm_info *pbm;
840 unsigned int busrange[2];
841 int err, i; 938 int err, i;
842 939
843 if (devhandle & 0x40) 940 if (devhandle & 0x40)
@@ -898,16 +995,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, uns
898 memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask)); 995 memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
899 } 996 }
900 997
901 err = prom_getproperty(prom_node, "bus-range", 998 pci_sun4v_get_bus_range(pbm);
902 (char *)&busrange[0],
903 sizeof(busrange));
904 if (err == 0 || err == -1) {
905 prom_printf("%s: Fatal error, no bus-range.\n", pbm->name);
906 prom_halt();
907 }
908 pbm->pci_first_busno = busrange[0];
909 pbm->pci_last_busno = busrange[1];
910
911 pci_sun4v_iommu_init(pbm); 999 pci_sun4v_iommu_init(pbm);
912} 1000}
913 1001