diff options
Diffstat (limited to 'arch/sparc64/kernel/pci_sun4v.c')
-rw-r--r-- | arch/sparc64/kernel/pci_sun4v.c | 294 |
1 files changed, 128 insertions, 166 deletions
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 1ccf4c9a9a43..0c76a8891a96 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/irq.h> | 13 | #include <linux/irq.h> |
14 | #include <linux/msi.h> | 14 | #include <linux/msi.h> |
15 | 15 | ||
16 | #include <asm/pbm.h> | ||
17 | #include <asm/iommu.h> | 16 | #include <asm/iommu.h> |
18 | #include <asm/irq.h> | 17 | #include <asm/irq.h> |
19 | #include <asm/upa.h> | 18 | #include <asm/upa.h> |
@@ -677,29 +676,15 @@ static struct pci_ops pci_sun4v_ops = { | |||
677 | }; | 676 | }; |
678 | 677 | ||
679 | 678 | ||
680 | static void pbm_scan_bus(struct pci_controller_info *p, | 679 | static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm) |
681 | struct pci_pbm_info *pbm) | ||
682 | { | ||
683 | pbm->pci_bus = pci_scan_one_pbm(pbm); | ||
684 | } | ||
685 | |||
686 | static void pci_sun4v_scan_bus(struct pci_controller_info *p) | ||
687 | { | 680 | { |
688 | struct property *prop; | 681 | struct property *prop; |
689 | struct device_node *dp; | 682 | struct device_node *dp; |
690 | 683 | ||
691 | if ((dp = p->pbm_A.prom_node) != NULL) { | 684 | dp = pbm->prom_node; |
692 | prop = of_find_property(dp, "66mhz-capable", NULL); | 685 | prop = of_find_property(dp, "66mhz-capable", NULL); |
693 | p->pbm_A.is_66mhz_capable = (prop != NULL); | 686 | pbm->is_66mhz_capable = (prop != NULL); |
694 | 687 | pbm->pci_bus = pci_scan_one_pbm(pbm); | |
695 | pbm_scan_bus(p, &p->pbm_A); | ||
696 | } | ||
697 | if ((dp = p->pbm_B.prom_node) != NULL) { | ||
698 | prop = of_find_property(dp, "66mhz-capable", NULL); | ||
699 | p->pbm_B.is_66mhz_capable = (prop != NULL); | ||
700 | |||
701 | pbm_scan_bus(p, &p->pbm_B); | ||
702 | } | ||
703 | 688 | ||
704 | /* XXX register error interrupt handlers XXX */ | 689 | /* XXX register error interrupt handlers XXX */ |
705 | } | 690 | } |
@@ -802,20 +787,6 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) | |||
802 | pbm->name, sz); | 787 | pbm->name, sz); |
803 | } | 788 | } |
804 | 789 | ||
805 | static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm) | ||
806 | { | ||
807 | struct property *prop; | ||
808 | unsigned int *busrange; | ||
809 | |||
810 | prop = of_find_property(pbm->prom_node, "bus-range", NULL); | ||
811 | |||
812 | busrange = prop->value; | ||
813 | |||
814 | pbm->pci_first_busno = busrange[0]; | ||
815 | pbm->pci_last_busno = busrange[1]; | ||
816 | |||
817 | } | ||
818 | |||
819 | #ifdef CONFIG_PCI_MSI | 790 | #ifdef CONFIG_PCI_MSI |
820 | struct pci_sun4v_msiq_entry { | 791 | struct pci_sun4v_msiq_entry { |
821 | u64 version_type; | 792 | u64 version_type; |
@@ -1019,114 +990,6 @@ h_error: | |||
1019 | return -EINVAL; | 990 | return -EINVAL; |
1020 | } | 991 | } |
1021 | 992 | ||
1022 | static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) | ||
1023 | { | ||
1024 | const u32 *val; | ||
1025 | int len; | ||
1026 | |||
1027 | val = of_get_property(pbm->prom_node, "#msi-eqs", &len); | ||
1028 | if (!val || len != 4) | ||
1029 | goto no_msi; | ||
1030 | pbm->msiq_num = *val; | ||
1031 | if (pbm->msiq_num) { | ||
1032 | const struct msiq_prop { | ||
1033 | u32 first_msiq; | ||
1034 | u32 num_msiq; | ||
1035 | u32 first_devino; | ||
1036 | } *mqp; | ||
1037 | const struct msi_range_prop { | ||
1038 | u32 first_msi; | ||
1039 | u32 num_msi; | ||
1040 | } *mrng; | ||
1041 | const struct addr_range_prop { | ||
1042 | u32 msi32_high; | ||
1043 | u32 msi32_low; | ||
1044 | u32 msi32_len; | ||
1045 | u32 msi64_high; | ||
1046 | u32 msi64_low; | ||
1047 | u32 msi64_len; | ||
1048 | } *arng; | ||
1049 | |||
1050 | val = of_get_property(pbm->prom_node, "msi-eq-size", &len); | ||
1051 | if (!val || len != 4) | ||
1052 | goto no_msi; | ||
1053 | |||
1054 | pbm->msiq_ent_count = *val; | ||
1055 | |||
1056 | mqp = of_get_property(pbm->prom_node, | ||
1057 | "msi-eq-to-devino", &len); | ||
1058 | if (!mqp || len != sizeof(struct msiq_prop)) | ||
1059 | goto no_msi; | ||
1060 | |||
1061 | pbm->msiq_first = mqp->first_msiq; | ||
1062 | pbm->msiq_first_devino = mqp->first_devino; | ||
1063 | |||
1064 | val = of_get_property(pbm->prom_node, "#msi", &len); | ||
1065 | if (!val || len != 4) | ||
1066 | goto no_msi; | ||
1067 | pbm->msi_num = *val; | ||
1068 | |||
1069 | mrng = of_get_property(pbm->prom_node, "msi-ranges", &len); | ||
1070 | if (!mrng || len != sizeof(struct msi_range_prop)) | ||
1071 | goto no_msi; | ||
1072 | pbm->msi_first = mrng->first_msi; | ||
1073 | |||
1074 | val = of_get_property(pbm->prom_node, "msi-data-mask", &len); | ||
1075 | if (!val || len != 4) | ||
1076 | goto no_msi; | ||
1077 | pbm->msi_data_mask = *val; | ||
1078 | |||
1079 | val = of_get_property(pbm->prom_node, "msix-data-width", &len); | ||
1080 | if (!val || len != 4) | ||
1081 | goto no_msi; | ||
1082 | pbm->msix_data_width = *val; | ||
1083 | |||
1084 | arng = of_get_property(pbm->prom_node, "msi-address-ranges", | ||
1085 | &len); | ||
1086 | if (!arng || len != sizeof(struct addr_range_prop)) | ||
1087 | goto no_msi; | ||
1088 | pbm->msi32_start = ((u64)arng->msi32_high << 32) | | ||
1089 | (u64) arng->msi32_low; | ||
1090 | pbm->msi64_start = ((u64)arng->msi64_high << 32) | | ||
1091 | (u64) arng->msi64_low; | ||
1092 | pbm->msi32_len = arng->msi32_len; | ||
1093 | pbm->msi64_len = arng->msi64_len; | ||
1094 | |||
1095 | if (msi_bitmap_alloc(pbm)) | ||
1096 | goto no_msi; | ||
1097 | |||
1098 | if (msi_queue_alloc(pbm)) { | ||
1099 | msi_bitmap_free(pbm); | ||
1100 | goto no_msi; | ||
1101 | } | ||
1102 | |||
1103 | printk(KERN_INFO "%s: MSI Queue first[%u] num[%u] count[%u] " | ||
1104 | "devino[0x%x]\n", | ||
1105 | pbm->name, | ||
1106 | pbm->msiq_first, pbm->msiq_num, | ||
1107 | pbm->msiq_ent_count, | ||
1108 | pbm->msiq_first_devino); | ||
1109 | printk(KERN_INFO "%s: MSI first[%u] num[%u] mask[0x%x] " | ||
1110 | "width[%u]\n", | ||
1111 | pbm->name, | ||
1112 | pbm->msi_first, pbm->msi_num, pbm->msi_data_mask, | ||
1113 | pbm->msix_data_width); | ||
1114 | printk(KERN_INFO "%s: MSI addr32[0x%lx:0x%x] " | ||
1115 | "addr64[0x%lx:0x%x]\n", | ||
1116 | pbm->name, | ||
1117 | pbm->msi32_start, pbm->msi32_len, | ||
1118 | pbm->msi64_start, pbm->msi64_len); | ||
1119 | printk(KERN_INFO "%s: MSI queues at RA [%p]\n", | ||
1120 | pbm->name, | ||
1121 | pbm->msi_queues); | ||
1122 | } | ||
1123 | |||
1124 | return; | ||
1125 | |||
1126 | no_msi: | ||
1127 | pbm->msiq_num = 0; | ||
1128 | printk(KERN_INFO "%s: No MSI support.\n", pbm->name); | ||
1129 | } | ||
1130 | 993 | ||
1131 | static int alloc_msi(struct pci_pbm_info *pbm) | 994 | static int alloc_msi(struct pci_pbm_info *pbm) |
1132 | { | 995 | { |
@@ -1245,6 +1108,117 @@ static void pci_sun4v_teardown_msi_irq(unsigned int virt_irq, | |||
1245 | */ | 1108 | */ |
1246 | sun4v_destroy_msi(virt_irq); | 1109 | sun4v_destroy_msi(virt_irq); |
1247 | } | 1110 | } |
1111 | |||
1112 | static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) | ||
1113 | { | ||
1114 | const u32 *val; | ||
1115 | int len; | ||
1116 | |||
1117 | val = of_get_property(pbm->prom_node, "#msi-eqs", &len); | ||
1118 | if (!val || len != 4) | ||
1119 | goto no_msi; | ||
1120 | pbm->msiq_num = *val; | ||
1121 | if (pbm->msiq_num) { | ||
1122 | const struct msiq_prop { | ||
1123 | u32 first_msiq; | ||
1124 | u32 num_msiq; | ||
1125 | u32 first_devino; | ||
1126 | } *mqp; | ||
1127 | const struct msi_range_prop { | ||
1128 | u32 first_msi; | ||
1129 | u32 num_msi; | ||
1130 | } *mrng; | ||
1131 | const struct addr_range_prop { | ||
1132 | u32 msi32_high; | ||
1133 | u32 msi32_low; | ||
1134 | u32 msi32_len; | ||
1135 | u32 msi64_high; | ||
1136 | u32 msi64_low; | ||
1137 | u32 msi64_len; | ||
1138 | } *arng; | ||
1139 | |||
1140 | val = of_get_property(pbm->prom_node, "msi-eq-size", &len); | ||
1141 | if (!val || len != 4) | ||
1142 | goto no_msi; | ||
1143 | |||
1144 | pbm->msiq_ent_count = *val; | ||
1145 | |||
1146 | mqp = of_get_property(pbm->prom_node, | ||
1147 | "msi-eq-to-devino", &len); | ||
1148 | if (!mqp || len != sizeof(struct msiq_prop)) | ||
1149 | goto no_msi; | ||
1150 | |||
1151 | pbm->msiq_first = mqp->first_msiq; | ||
1152 | pbm->msiq_first_devino = mqp->first_devino; | ||
1153 | |||
1154 | val = of_get_property(pbm->prom_node, "#msi", &len); | ||
1155 | if (!val || len != 4) | ||
1156 | goto no_msi; | ||
1157 | pbm->msi_num = *val; | ||
1158 | |||
1159 | mrng = of_get_property(pbm->prom_node, "msi-ranges", &len); | ||
1160 | if (!mrng || len != sizeof(struct msi_range_prop)) | ||
1161 | goto no_msi; | ||
1162 | pbm->msi_first = mrng->first_msi; | ||
1163 | |||
1164 | val = of_get_property(pbm->prom_node, "msi-data-mask", &len); | ||
1165 | if (!val || len != 4) | ||
1166 | goto no_msi; | ||
1167 | pbm->msi_data_mask = *val; | ||
1168 | |||
1169 | val = of_get_property(pbm->prom_node, "msix-data-width", &len); | ||
1170 | if (!val || len != 4) | ||
1171 | goto no_msi; | ||
1172 | pbm->msix_data_width = *val; | ||
1173 | |||
1174 | arng = of_get_property(pbm->prom_node, "msi-address-ranges", | ||
1175 | &len); | ||
1176 | if (!arng || len != sizeof(struct addr_range_prop)) | ||
1177 | goto no_msi; | ||
1178 | pbm->msi32_start = ((u64)arng->msi32_high << 32) | | ||
1179 | (u64) arng->msi32_low; | ||
1180 | pbm->msi64_start = ((u64)arng->msi64_high << 32) | | ||
1181 | (u64) arng->msi64_low; | ||
1182 | pbm->msi32_len = arng->msi32_len; | ||
1183 | pbm->msi64_len = arng->msi64_len; | ||
1184 | |||
1185 | if (msi_bitmap_alloc(pbm)) | ||
1186 | goto no_msi; | ||
1187 | |||
1188 | if (msi_queue_alloc(pbm)) { | ||
1189 | msi_bitmap_free(pbm); | ||
1190 | goto no_msi; | ||
1191 | } | ||
1192 | |||
1193 | printk(KERN_INFO "%s: MSI Queue first[%u] num[%u] count[%u] " | ||
1194 | "devino[0x%x]\n", | ||
1195 | pbm->name, | ||
1196 | pbm->msiq_first, pbm->msiq_num, | ||
1197 | pbm->msiq_ent_count, | ||
1198 | pbm->msiq_first_devino); | ||
1199 | printk(KERN_INFO "%s: MSI first[%u] num[%u] mask[0x%x] " | ||
1200 | "width[%u]\n", | ||
1201 | pbm->name, | ||
1202 | pbm->msi_first, pbm->msi_num, pbm->msi_data_mask, | ||
1203 | pbm->msix_data_width); | ||
1204 | printk(KERN_INFO "%s: MSI addr32[0x%lx:0x%x] " | ||
1205 | "addr64[0x%lx:0x%x]\n", | ||
1206 | pbm->name, | ||
1207 | pbm->msi32_start, pbm->msi32_len, | ||
1208 | pbm->msi64_start, pbm->msi64_len); | ||
1209 | printk(KERN_INFO "%s: MSI queues at RA [%p]\n", | ||
1210 | pbm->name, | ||
1211 | pbm->msi_queues); | ||
1212 | } | ||
1213 | pbm->setup_msi_irq = pci_sun4v_setup_msi_irq; | ||
1214 | pbm->teardown_msi_irq = pci_sun4v_teardown_msi_irq; | ||
1215 | |||
1216 | return; | ||
1217 | |||
1218 | no_msi: | ||
1219 | pbm->msiq_num = 0; | ||
1220 | printk(KERN_INFO "%s: No MSI support.\n", pbm->name); | ||
1221 | } | ||
1248 | #else /* CONFIG_PCI_MSI */ | 1222 | #else /* CONFIG_PCI_MSI */ |
1249 | static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) | 1223 | static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) |
1250 | { | 1224 | { |
@@ -1260,6 +1234,14 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node | |||
1260 | else | 1234 | else |
1261 | pbm = &p->pbm_A; | 1235 | pbm = &p->pbm_A; |
1262 | 1236 | ||
1237 | pbm->next = pci_pbm_root; | ||
1238 | pci_pbm_root = pbm; | ||
1239 | |||
1240 | pbm->scan_bus = pci_sun4v_scan_bus; | ||
1241 | pbm->pci_ops = &pci_sun4v_ops; | ||
1242 | |||
1243 | pbm->index = pci_num_pbms++; | ||
1244 | |||
1263 | pbm->parent = p; | 1245 | pbm->parent = p; |
1264 | pbm->prom_node = dp; | 1246 | pbm->prom_node = dp; |
1265 | 1247 | ||
@@ -1271,7 +1253,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node | |||
1271 | 1253 | ||
1272 | pci_determine_mem_io_space(pbm); | 1254 | pci_determine_mem_io_space(pbm); |
1273 | 1255 | ||
1274 | pci_sun4v_get_bus_range(pbm); | 1256 | pci_get_pbm_props(pbm); |
1275 | pci_sun4v_iommu_init(pbm); | 1257 | pci_sun4v_iommu_init(pbm); |
1276 | pci_sun4v_msi_init(pbm); | 1258 | pci_sun4v_msi_init(pbm); |
1277 | } | 1259 | } |
@@ -1279,6 +1261,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node | |||
1279 | void sun4v_pci_init(struct device_node *dp, char *model_name) | 1261 | void sun4v_pci_init(struct device_node *dp, char *model_name) |
1280 | { | 1262 | { |
1281 | struct pci_controller_info *p; | 1263 | struct pci_controller_info *p; |
1264 | struct pci_pbm_info *pbm; | ||
1282 | struct iommu *iommu; | 1265 | struct iommu *iommu; |
1283 | struct property *prop; | 1266 | struct property *prop; |
1284 | struct linux_prom64_registers *regs; | 1267 | struct linux_prom64_registers *regs; |
@@ -1290,18 +1273,9 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) | |||
1290 | 1273 | ||
1291 | devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; | 1274 | devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; |
1292 | 1275 | ||
1293 | for (p = pci_controller_root; p; p = p->next) { | 1276 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { |
1294 | struct pci_pbm_info *pbm; | ||
1295 | |||
1296 | if (p->pbm_A.prom_node && p->pbm_B.prom_node) | ||
1297 | continue; | ||
1298 | |||
1299 | pbm = (p->pbm_A.prom_node ? | ||
1300 | &p->pbm_A : | ||
1301 | &p->pbm_B); | ||
1302 | |||
1303 | if (pbm->devhandle == (devhandle ^ 0x40)) { | 1277 | if (pbm->devhandle == (devhandle ^ 0x40)) { |
1304 | pci_sun4v_pbm_init(p, dp, devhandle); | 1278 | pci_sun4v_pbm_init(pbm->parent, dp, devhandle); |
1305 | return; | 1279 | return; |
1306 | } | 1280 | } |
1307 | } | 1281 | } |
@@ -1331,18 +1305,6 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) | |||
1331 | 1305 | ||
1332 | p->pbm_B.iommu = iommu; | 1306 | p->pbm_B.iommu = iommu; |
1333 | 1307 | ||
1334 | p->next = pci_controller_root; | ||
1335 | pci_controller_root = p; | ||
1336 | |||
1337 | p->index = pci_num_controllers++; | ||
1338 | |||
1339 | p->scan_bus = pci_sun4v_scan_bus; | ||
1340 | #ifdef CONFIG_PCI_MSI | ||
1341 | p->setup_msi_irq = pci_sun4v_setup_msi_irq; | ||
1342 | p->teardown_msi_irq = pci_sun4v_teardown_msi_irq; | ||
1343 | #endif | ||
1344 | p->pci_ops = &pci_sun4v_ops; | ||
1345 | |||
1346 | /* Like PSYCHO and SCHIZO we have a 2GB aligned area | 1308 | /* Like PSYCHO and SCHIZO we have a 2GB aligned area |
1347 | * for memory space. | 1309 | * for memory space. |
1348 | */ | 1310 | */ |