aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/pci_sun4v.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/pci_sun4v.c')
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c160
1 files changed, 75 insertions, 85 deletions
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 5419480edf41..b69e2270a721 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)
@@ -811,8 +814,7 @@ static void pbm_scan_bus(struct pci_controller_info *p,
811 pci_fixup_host_bridge_self(pbm->pci_bus); 814 pci_fixup_host_bridge_self(pbm->pci_bus);
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, pbm->prom_node);
815 pbm->prom_node);
816 pci_record_assignments(pbm, pbm->pci_bus); 818 pci_record_assignments(pbm, pbm->pci_bus);
817 pci_assign_unassigned(pbm, pbm->pci_bus); 819 pci_assign_unassigned(pbm, pbm->pci_bus);
818 pci_fixup_irq(pbm, pbm->pci_bus); 820 pci_fixup_irq(pbm, pbm->pci_bus);
@@ -822,15 +824,18 @@ static void pbm_scan_bus(struct pci_controller_info *p,
822 824
823static void pci_sun4v_scan_bus(struct pci_controller_info *p) 825static void pci_sun4v_scan_bus(struct pci_controller_info *p)
824{ 826{
825 if (p->pbm_A.prom_node) { 827 struct property *prop;
826 p->pbm_A.is_66mhz_capable = 828 struct device_node *dp;
827 prom_getbool(p->pbm_A.prom_node, "66mhz-capable"); 829
830 if ((dp = p->pbm_A.prom_node) != NULL) {
831 prop = of_find_property(dp, "66mhz-capable", NULL);
832 p->pbm_A.is_66mhz_capable = (prop != NULL);
828 833
829 pbm_scan_bus(p, &p->pbm_A); 834 pbm_scan_bus(p, &p->pbm_A);
830 } 835 }
831 if (p->pbm_B.prom_node) { 836 if ((dp = p->pbm_B.prom_node) != NULL) {
832 p->pbm_B.is_66mhz_capable = 837 prop = of_find_property(dp, "66mhz-capable", NULL);
833 prom_getbool(p->pbm_B.prom_node, "66mhz-capable"); 838 p->pbm_B.is_66mhz_capable = (prop != NULL);
834 839
835 pbm_scan_bus(p, &p->pbm_B); 840 pbm_scan_bus(p, &p->pbm_B);
836 } 841 }
@@ -982,8 +987,13 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
982 HV_PCI_TSBID(0, i), 987 HV_PCI_TSBID(0, i),
983 &io_attrs, &ra); 988 &io_attrs, &ra);
984 if (ret == HV_EOK) { 989 if (ret == HV_EOK) {
985 cnt++; 990 if (page_in_phys_avail(ra)) {
986 __set_bit(i, arena->map); 991 pci_sun4v_iommu_demap(devhandle,
992 HV_PCI_TSBID(0, i), 1);
993 } else {
994 cnt++;
995 __set_bit(i, arena->map);
996 }
987 } 997 }
988 } 998 }
989 999
@@ -993,13 +1003,18 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
993static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) 1003static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
994{ 1004{
995 struct pci_iommu *iommu = pbm->iommu; 1005 struct pci_iommu *iommu = pbm->iommu;
1006 struct property *prop;
996 unsigned long num_tsb_entries, sz; 1007 unsigned long num_tsb_entries, sz;
997 u32 vdma[2], dma_mask, dma_offset; 1008 u32 vdma[2], dma_mask, dma_offset;
998 int err, tsbsize; 1009 int tsbsize;
1010
1011 prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
1012 if (prop) {
1013 u32 *val = prop->value;
999 1014
1000 err = prom_getproperty(pbm->prom_node, "virtual-dma", 1015 vdma[0] = val[0];
1001 (char *)&vdma[0], sizeof(vdma)); 1016 vdma[1] = val[1];
1002 if (err == 0 || err == -1) { 1017 } else {
1003 /* No property, use default values. */ 1018 /* No property, use default values. */
1004 vdma[0] = 0x80000000; 1019 vdma[0] = 0x80000000;
1005 vdma[1] = 0x80000000; 1020 vdma[1] = 0x80000000;
@@ -1051,34 +1066,30 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
1051 iommu->arena.limit = num_tsb_entries; 1066 iommu->arena.limit = num_tsb_entries;
1052 1067
1053 sz = probe_existing_entries(pbm, iommu); 1068 sz = probe_existing_entries(pbm, iommu);
1054 1069 if (sz)
1055 printk("%s: TSB entries [%lu], existing mapings [%lu]\n", 1070 printk("%s: Imported %lu TSB entries from OBP\n",
1056 pbm->name, num_tsb_entries, sz); 1071 pbm->name, sz);
1057} 1072}
1058 1073
1059static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm) 1074static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm)
1060{ 1075{
1061 unsigned int busrange[2]; 1076 struct property *prop;
1062 int prom_node = pbm->prom_node; 1077 unsigned int *busrange;
1063 int err; 1078
1064 1079 prop = of_find_property(pbm->prom_node, "bus-range", NULL);
1065 err = prom_getproperty(prom_node, "bus-range", 1080
1066 (char *)&busrange[0], 1081 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 1082
1073 pbm->pci_first_busno = busrange[0]; 1083 pbm->pci_first_busno = busrange[0];
1074 pbm->pci_last_busno = busrange[1]; 1084 pbm->pci_last_busno = busrange[1];
1075 1085
1076} 1086}
1077 1087
1078static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32 devhandle) 1088static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle)
1079{ 1089{
1080 struct pci_pbm_info *pbm; 1090 struct pci_pbm_info *pbm;
1081 int err, i; 1091 struct property *prop;
1092 int len, i;
1082 1093
1083 if (devhandle & 0x40) 1094 if (devhandle & 0x40)
1084 pbm = &p->pbm_B; 1095 pbm = &p->pbm_B;
@@ -1086,32 +1097,19 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
1086 pbm = &p->pbm_A; 1097 pbm = &p->pbm_A;
1087 1098
1088 pbm->parent = p; 1099 pbm->parent = p;
1089 pbm->prom_node = prom_node; 1100 pbm->prom_node = dp;
1090 pbm->pci_first_slot = 1; 1101 pbm->pci_first_slot = 1;
1091 1102
1092 pbm->devhandle = devhandle; 1103 pbm->devhandle = devhandle;
1093 1104
1094 sprintf(pbm->name, "SUN4V-PCI%d PBM%c", 1105 pbm->name = dp->full_name;
1095 p->index, (pbm == &p->pbm_A ? 'A' : 'B'));
1096 1106
1097 printk("%s: devhandle[%x] prom_node[%x:%x]\n", 1107 printk("%s: SUN4V PCI Bus Module\n", pbm->name);
1098 pbm->name, pbm->devhandle,
1099 pbm->prom_node, prom_getchild(pbm->prom_node));
1100
1101 prom_getstring(prom_node, "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 1108
1109 prop = of_find_property(dp, "ranges", &len);
1110 pbm->pbm_ranges = prop->value;
1113 pbm->num_pbm_ranges = 1111 pbm->num_pbm_ranges =
1114 (err / sizeof(struct linux_prom_pci_ranges)); 1112 (len / sizeof(struct linux_prom_pci_ranges));
1115 1113
1116 /* Mask out the top 8 bits of the ranges, leaving the real 1114 /* Mask out the top 8 bits of the ranges, leaving the real
1117 * physical address. 1115 * physical address.
@@ -1122,24 +1120,13 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
1122 pci_sun4v_determine_mem_io_space(pbm); 1120 pci_sun4v_determine_mem_io_space(pbm);
1123 pbm_register_toplevel_resources(p, pbm); 1121 pbm_register_toplevel_resources(p, pbm);
1124 1122
1125 err = prom_getproperty(prom_node, "interrupt-map", 1123 prop = of_find_property(dp, "interrupt-map", &len);
1126 (char *)pbm->pbm_intmap, 1124 pbm->pbm_intmap = prop->value;
1127 sizeof(pbm->pbm_intmap)); 1125 pbm->num_pbm_intmap =
1128 if (err == 0 || err == -1) { 1126 (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 1127
1134 pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); 1128 prop = of_find_property(dp, "interrupt-map-mask", NULL);
1135 err = prom_getproperty(prom_node, "interrupt-map-mask", 1129 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 1130
1144 pci_sun4v_get_bus_range(pbm); 1131 pci_sun4v_get_bus_range(pbm);
1145 pci_sun4v_iommu_init(pbm); 1132 pci_sun4v_iommu_init(pbm);
@@ -1147,16 +1134,19 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
1147 pdev_htab_populate(pbm); 1134 pdev_htab_populate(pbm);
1148} 1135}
1149 1136
1150void sun4v_pci_init(int node, char *model_name) 1137void sun4v_pci_init(struct device_node *dp, char *model_name)
1151{ 1138{
1152 struct pci_controller_info *p; 1139 struct pci_controller_info *p;
1153 struct pci_iommu *iommu; 1140 struct pci_iommu *iommu;
1154 struct linux_prom64_registers regs; 1141 struct property *prop;
1142 struct linux_prom64_registers *regs;
1155 u32 devhandle; 1143 u32 devhandle;
1156 int i; 1144 int i;
1157 1145
1158 prom_getproperty(node, "reg", (char *)&regs, sizeof(regs)); 1146 prop = of_find_property(dp, "reg", NULL);
1159 devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff; 1147 regs = prop->value;
1148
1149 devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff;
1160 1150
1161 for (p = pci_controller_root; p; p = p->next) { 1151 for (p = pci_controller_root; p; p = p->next) {
1162 struct pci_pbm_info *pbm; 1152 struct pci_pbm_info *pbm;
@@ -1169,7 +1159,7 @@ void sun4v_pci_init(int node, char *model_name)
1169 &p->pbm_B); 1159 &p->pbm_B);
1170 1160
1171 if (pbm->devhandle == (devhandle ^ 0x40)) { 1161 if (pbm->devhandle == (devhandle ^ 0x40)) {
1172 pci_sun4v_pbm_init(p, node, devhandle); 1162 pci_sun4v_pbm_init(p, dp, devhandle);
1173 return; 1163 return;
1174 } 1164 }
1175 } 1165 }
@@ -1220,7 +1210,7 @@ void sun4v_pci_init(int node, char *model_name)
1220 */ 1210 */
1221 pci_memspace_mask = 0x7fffffffUL; 1211 pci_memspace_mask = 0x7fffffffUL;
1222 1212
1223 pci_sun4v_pbm_init(p, node, devhandle); 1213 pci_sun4v_pbm_init(p, dp, devhandle);
1224 return; 1214 return;
1225 1215
1226fatal_memory_error: 1216fatal_memory_error: