aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-02-13 21:09:44 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-03-20 04:12:39 -0500
commit10804828fd06a43ce964e9d9852332e7ff1507b1 (patch)
treea932ff7ed2722f640dfbcfe1a84e94338cbcad0a /arch
parentbf941d6cd62aa2022f0887e25e3d02c389b0bf9b (diff)
[SPARC64]: More SUN4V PCI work.
Get bus range from child of PCI controller root nexus. This is actually a hack, but the PCI-E bridge sitting at the top of the PCI tree responds to PCI config cycles for every device number, so best to just ignore it for now. Preliminary PCI irq routing, needs lots of work. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-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