aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/pci_sun4v.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-06-21 21:18:47 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-06-24 02:15:07 -0400
commite87dc35020bc555969810452f44bceaf8394eafa (patch)
treeb58f14d41f8e147f6ddc2d9657a88813fdb73bdf /arch/sparc64/kernel/pci_sun4v.c
parentaaf7cec2769942035985716452107fc5ba0b11f6 (diff)
[SPARC64]: Use in-kernel OBP device tree for PCI controller probing.
It can be pushed even further down, but this is a first step. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/pci_sun4v.c')
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c144
1 files changed, 65 insertions, 79 deletions
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 5419480edf41..b63b2834133f 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -18,6 +18,7 @@
18#include <asm/pstate.h> 18#include <asm/pstate.h>
19#include <asm/oplib.h> 19#include <asm/oplib.h>
20#include <asm/hypervisor.h> 20#include <asm/hypervisor.h>
21#include <asm/prom.h>
21 22
22#include "pci_impl.h" 23#include "pci_impl.h"
23#include "iommu_common.h" 24#include "iommu_common.h"
@@ -646,35 +647,37 @@ static int pdev_htab_add(u32 devhandle, unsigned int bus, unsigned int device, u
646/* Recursively descend into the OBP device tree, rooted at toplevel_node, 647/* Recursively descend into the OBP device tree, rooted at toplevel_node,
647 * looking for a PCI device matching bus and devfn. 648 * looking for a PCI device matching bus and devfn.
648 */ 649 */
649static int obp_find(struct linux_prom_pci_registers *pregs, int toplevel_node, unsigned int bus, unsigned int devfn) 650static int obp_find(struct device_node *toplevel_node, unsigned int bus, unsigned int devfn)
650{ 651{
651 toplevel_node = prom_getchild(toplevel_node); 652 toplevel_node = toplevel_node->child;
652 653
653 while (toplevel_node != 0) { 654 while (toplevel_node != NULL) {
654 int ret = obp_find(pregs, toplevel_node, bus, devfn); 655 struct linux_prom_pci_registers *regs;
656 struct property *prop;
657 int ret;
655 658
659 ret = obp_find(toplevel_node, bus, devfn);
656 if (ret != 0) 660 if (ret != 0)
657 return ret; 661 return ret;
658 662
659 ret = prom_getproperty(toplevel_node, "reg", (char *) pregs, 663 prop = of_find_property(toplevel_node, "reg", NULL);
660 sizeof(*pregs) * PROMREG_MAX); 664 if (!prop)
661 if (ret == 0 || ret == -1)
662 goto next_sibling; 665 goto next_sibling;
663 666
664 if (((pregs[0].phys_hi >> 16) & 0xff) == bus && 667 regs = prop->value;
665 ((pregs[0].phys_hi >> 8) & 0xff) == devfn) 668 if (((regs->phys_hi >> 16) & 0xff) == bus &&
669 ((regs->phys_hi >> 8) & 0xff) == devfn)
666 break; 670 break;
667 671
668 next_sibling: 672 next_sibling:
669 toplevel_node = prom_getsibling(toplevel_node); 673 toplevel_node = toplevel_node->sibling;
670 } 674 }
671 675
672 return toplevel_node; 676 return toplevel_node != NULL;
673} 677}
674 678
675static int pdev_htab_populate(struct pci_pbm_info *pbm) 679static int pdev_htab_populate(struct pci_pbm_info *pbm)
676{ 680{
677 struct linux_prom_pci_registers pr[PROMREG_MAX];
678 u32 devhandle = pbm->devhandle; 681 u32 devhandle = pbm->devhandle;
679 unsigned int bus; 682 unsigned int bus;
680 683
@@ -685,7 +688,7 @@ static int pdev_htab_populate(struct pci_pbm_info *pbm)
685 unsigned int device = PCI_SLOT(devfn); 688 unsigned int device = PCI_SLOT(devfn);
686 unsigned int func = PCI_FUNC(devfn); 689 unsigned int func = PCI_FUNC(devfn);
687 690
688 if (obp_find(pr, pbm->prom_node, bus, devfn)) { 691 if (obp_find(pbm->prom_node, bus, devfn)) {
689 int err = pdev_htab_add(devhandle, bus, 692 int err = pdev_htab_add(devhandle, bus,
690 device, func); 693 device, func);
691 if (err) 694 if (err)
@@ -812,7 +815,7 @@ static void pbm_scan_bus(struct pci_controller_info *p,
812 pbm->pci_bus->self->sysdata = cookie; 815 pbm->pci_bus->self->sysdata = cookie;
813#endif 816#endif
814 pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, 817 pci_fill_in_pbm_cookies(pbm->pci_bus, pbm,
815 pbm->prom_node); 818 pbm->prom_node->node);
816 pci_record_assignments(pbm, pbm->pci_bus); 819 pci_record_assignments(pbm, pbm->pci_bus);
817 pci_assign_unassigned(pbm, pbm->pci_bus); 820 pci_assign_unassigned(pbm, pbm->pci_bus);
818 pci_fixup_irq(pbm, pbm->pci_bus); 821 pci_fixup_irq(pbm, pbm->pci_bus);
@@ -822,15 +825,18 @@ static void pbm_scan_bus(struct pci_controller_info *p,
822 825
823static void pci_sun4v_scan_bus(struct pci_controller_info *p) 826static void pci_sun4v_scan_bus(struct pci_controller_info *p)
824{ 827{
825 if (p->pbm_A.prom_node) { 828 struct property *prop;
826 p->pbm_A.is_66mhz_capable = 829 struct device_node *dp;
827 prom_getbool(p->pbm_A.prom_node, "66mhz-capable"); 830
831 if ((dp = p->pbm_A.prom_node) != NULL) {
832 prop = of_find_property(dp, "66mhz-capable", NULL);
833 p->pbm_A.is_66mhz_capable = (prop != NULL);
828 834
829 pbm_scan_bus(p, &p->pbm_A); 835 pbm_scan_bus(p, &p->pbm_A);
830 } 836 }
831 if (p->pbm_B.prom_node) { 837 if ((dp = p->pbm_B.prom_node) != NULL) {
832 p->pbm_B.is_66mhz_capable = 838 prop = of_find_property(dp, "66mhz-capable", NULL);
833 prom_getbool(p->pbm_B.prom_node, "66mhz-capable"); 839 p->pbm_B.is_66mhz_capable = (prop != NULL);
834 840
835 pbm_scan_bus(p, &p->pbm_B); 841 pbm_scan_bus(p, &p->pbm_B);
836 } 842 }
@@ -993,13 +999,18 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
993static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) 999static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
994{ 1000{
995 struct pci_iommu *iommu = pbm->iommu; 1001 struct pci_iommu *iommu = pbm->iommu;
1002 struct property *prop;
996 unsigned long num_tsb_entries, sz; 1003 unsigned long num_tsb_entries, sz;
997 u32 vdma[2], dma_mask, dma_offset; 1004 u32 vdma[2], dma_mask, dma_offset;
998 int err, tsbsize; 1005 int tsbsize;
1006
1007 prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
1008 if (prop) {
1009 u32 *val = prop->value;
999 1010
1000 err = prom_getproperty(pbm->prom_node, "virtual-dma", 1011 vdma[0] = val[0];
1001 (char *)&vdma[0], sizeof(vdma)); 1012 vdma[1] = val[1];
1002 if (err == 0 || err == -1) { 1013 } else {
1003 /* No property, use default values. */ 1014 /* No property, use default values. */
1004 vdma[0] = 0x80000000; 1015 vdma[0] = 0x80000000;
1005 vdma[1] = 0x80000000; 1016 vdma[1] = 0x80000000;
@@ -1058,27 +1069,23 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
1058 1069
1059static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm) 1070static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm)
1060{ 1071{
1061 unsigned int busrange[2]; 1072 struct property *prop;
1062 int prom_node = pbm->prom_node; 1073 unsigned int *busrange;
1063 int err; 1074
1064 1075 prop = of_find_property(pbm->prom_node, "bus-range", NULL);
1065 err = prom_getproperty(prom_node, "bus-range", 1076
1066 (char *)&busrange[0], 1077 busrange = prop->value;
1067 sizeof(busrange));
1068 if (err == 0 || err == -1) {
1069 prom_printf("%s: Fatal error, no bus-range.\n", pbm->name);
1070 prom_halt();
1071 }
1072 1078
1073 pbm->pci_first_busno = busrange[0]; 1079 pbm->pci_first_busno = busrange[0];
1074 pbm->pci_last_busno = busrange[1]; 1080 pbm->pci_last_busno = busrange[1];
1075 1081
1076} 1082}
1077 1083
1078static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32 devhandle) 1084static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle)
1079{ 1085{
1080 struct pci_pbm_info *pbm; 1086 struct pci_pbm_info *pbm;
1081 int err, i; 1087 struct property *prop;
1088 int len, i;
1082 1089
1083 if (devhandle & 0x40) 1090 if (devhandle & 0x40)
1084 pbm = &p->pbm_B; 1091 pbm = &p->pbm_B;
@@ -1086,32 +1093,19 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
1086 pbm = &p->pbm_A; 1093 pbm = &p->pbm_A;
1087 1094
1088 pbm->parent = p; 1095 pbm->parent = p;
1089 pbm->prom_node = prom_node; 1096 pbm->prom_node = dp;
1090 pbm->pci_first_slot = 1; 1097 pbm->pci_first_slot = 1;
1091 1098
1092 pbm->devhandle = devhandle; 1099 pbm->devhandle = devhandle;
1093 1100
1094 sprintf(pbm->name, "SUN4V-PCI%d PBM%c", 1101 pbm->name = dp->full_name;
1095 p->index, (pbm == &p->pbm_A ? 'A' : 'B'));
1096
1097 printk("%s: devhandle[%x] prom_node[%x:%x]\n",
1098 pbm->name, pbm->devhandle,
1099 pbm->prom_node, prom_getchild(pbm->prom_node));
1100 1102
1101 prom_getstring(prom_node, "name", 1103 printk("%s: SUN4V PCI Bus Module\n", pbm->name);
1102 pbm->prom_name, sizeof(pbm->prom_name));
1103
1104 err = prom_getproperty(prom_node, "ranges",
1105 (char *) pbm->pbm_ranges,
1106 sizeof(pbm->pbm_ranges));
1107 if (err == 0 || err == -1) {
1108 prom_printf("%s: Fatal error, no ranges property.\n",
1109 pbm->name);
1110 prom_halt();
1111 }
1112 1104
1105 prop = of_find_property(dp, "ranges", &len);
1106 pbm->pbm_ranges = prop->value;
1113 pbm->num_pbm_ranges = 1107 pbm->num_pbm_ranges =
1114 (err / sizeof(struct linux_prom_pci_ranges)); 1108 (len / sizeof(struct linux_prom_pci_ranges));
1115 1109
1116 /* Mask out the top 8 bits of the ranges, leaving the real 1110 /* Mask out the top 8 bits of the ranges, leaving the real
1117 * physical address. 1111 * physical address.
@@ -1122,24 +1116,13 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
1122 pci_sun4v_determine_mem_io_space(pbm); 1116 pci_sun4v_determine_mem_io_space(pbm);
1123 pbm_register_toplevel_resources(p, pbm); 1117 pbm_register_toplevel_resources(p, pbm);
1124 1118
1125 err = prom_getproperty(prom_node, "interrupt-map", 1119 prop = of_find_property(dp, "interrupt-map", &len);
1126 (char *)pbm->pbm_intmap, 1120 pbm->pbm_intmap = prop->value;
1127 sizeof(pbm->pbm_intmap)); 1121 pbm->num_pbm_intmap =
1128 if (err == 0 || err == -1) { 1122 (len / sizeof(struct linux_prom_pci_intmap));
1129 prom_printf("%s: Fatal error, no interrupt-map property.\n",
1130 pbm->name);
1131 prom_halt();
1132 }
1133 1123
1134 pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); 1124 prop = of_find_property(dp, "interrupt-map-mask", NULL);
1135 err = prom_getproperty(prom_node, "interrupt-map-mask", 1125 pbm->pbm_intmask = prop->value;
1136 (char *)&pbm->pbm_intmask,
1137 sizeof(pbm->pbm_intmask));
1138 if (err == 0 || err == -1) {
1139 prom_printf("%s: Fatal error, no interrupt-map-mask.\n",
1140 pbm->name);
1141 prom_halt();
1142 }
1143 1126
1144 pci_sun4v_get_bus_range(pbm); 1127 pci_sun4v_get_bus_range(pbm);
1145 pci_sun4v_iommu_init(pbm); 1128 pci_sun4v_iommu_init(pbm);
@@ -1147,16 +1130,19 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
1147 pdev_htab_populate(pbm); 1130 pdev_htab_populate(pbm);
1148} 1131}
1149 1132
1150void sun4v_pci_init(int node, char *model_name) 1133void sun4v_pci_init(struct device_node *dp, char *model_name)
1151{ 1134{
1152 struct pci_controller_info *p; 1135 struct pci_controller_info *p;
1153 struct pci_iommu *iommu; 1136 struct pci_iommu *iommu;
1154 struct linux_prom64_registers regs; 1137 struct property *prop;
1138 struct linux_prom64_registers *regs;
1155 u32 devhandle; 1139 u32 devhandle;
1156 int i; 1140 int i;
1157 1141
1158 prom_getproperty(node, "reg", (char *)&regs, sizeof(regs)); 1142 prop = of_find_property(dp, "reg", NULL);
1159 devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff; 1143 regs = prop->value;
1144
1145 devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff;
1160 1146
1161 for (p = pci_controller_root; p; p = p->next) { 1147 for (p = pci_controller_root; p; p = p->next) {
1162 struct pci_pbm_info *pbm; 1148 struct pci_pbm_info *pbm;
@@ -1169,7 +1155,7 @@ void sun4v_pci_init(int node, char *model_name)
1169 &p->pbm_B); 1155 &p->pbm_B);
1170 1156
1171 if (pbm->devhandle == (devhandle ^ 0x40)) { 1157 if (pbm->devhandle == (devhandle ^ 0x40)) {
1172 pci_sun4v_pbm_init(p, node, devhandle); 1158 pci_sun4v_pbm_init(p, dp, devhandle);
1173 return; 1159 return;
1174 } 1160 }
1175 } 1161 }
@@ -1220,7 +1206,7 @@ void sun4v_pci_init(int node, char *model_name)
1220 */ 1206 */
1221 pci_memspace_mask = 0x7fffffffUL; 1207 pci_memspace_mask = 0x7fffffffUL;
1222 1208
1223 pci_sun4v_pbm_init(p, node, devhandle); 1209 pci_sun4v_pbm_init(p, dp, devhandle);
1224 return; 1210 return;
1225 1211
1226fatal_memory_error: 1212fatal_memory_error: