aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/pci_schizo.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/pci_schizo.c')
-rw-r--r--arch/sparc64/kernel/pci_schizo.c311
1 files changed, 60 insertions, 251 deletions
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index f16449ccd7bc..5c6e2a9b91f8 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -217,116 +217,6 @@ static struct pci_ops schizo_ops = {
217 .write = schizo_write_pci_cfg, 217 .write = schizo_write_pci_cfg,
218}; 218};
219 219
220/* SCHIZO interrupt mapping support. Unlike Psycho, for this controller the
221 * imap/iclr registers are per-PBM.
222 */
223#define SCHIZO_IMAP_BASE 0x1000UL
224#define SCHIZO_ICLR_BASE 0x1400UL
225
226static unsigned long schizo_imap_offset(unsigned long ino)
227{
228 return SCHIZO_IMAP_BASE + (ino * 8UL);
229}
230
231static unsigned long schizo_iclr_offset(unsigned long ino)
232{
233 return SCHIZO_ICLR_BASE + (ino * 8UL);
234}
235
236static void tomatillo_wsync_handler(unsigned int ino, void *_arg1, void *_arg2)
237{
238 unsigned long sync_reg = (unsigned long) _arg2;
239 u64 mask = 1UL << (ino & IMAP_INO);
240 u64 val;
241 int limit;
242
243 schizo_write(sync_reg, mask);
244
245 limit = 100000;
246 val = 0;
247 while (--limit) {
248 val = schizo_read(sync_reg);
249 if (!(val & mask))
250 break;
251 }
252 if (limit <= 0) {
253 printk("tomatillo_wsync_handler: DMA won't sync [%lx:%lx]\n",
254 val, mask);
255 }
256
257 if (_arg1) {
258 static unsigned char cacheline[64]
259 __attribute__ ((aligned (64)));
260
261 __asm__ __volatile__("rd %%fprs, %0\n\t"
262 "or %0, %4, %1\n\t"
263 "wr %1, 0x0, %%fprs\n\t"
264 "stda %%f0, [%5] %6\n\t"
265 "wr %0, 0x0, %%fprs\n\t"
266 "membar #Sync"
267 : "=&r" (mask), "=&r" (val)
268 : "0" (mask), "1" (val),
269 "i" (FPRS_FEF), "r" (&cacheline[0]),
270 "i" (ASI_BLK_COMMIT_P));
271 }
272}
273
274static unsigned long schizo_ino_to_iclr(struct pci_pbm_info *pbm,
275 unsigned int ino)
276{
277 ino &= PCI_IRQ_INO;
278 return pbm->pbm_regs + schizo_iclr_offset(ino) + 4;
279}
280
281static unsigned long schizo_ino_to_imap(struct pci_pbm_info *pbm,
282 unsigned int ino)
283{
284 ino &= PCI_IRQ_INO;
285 return pbm->pbm_regs + schizo_imap_offset(ino) + 4;
286}
287
288static unsigned int schizo_irq_build(struct pci_pbm_info *pbm,
289 struct pci_dev *pdev,
290 unsigned int ino)
291{
292 unsigned long imap, iclr;
293 int ign_fixup;
294 int virt_irq;
295
296 ino &= PCI_IRQ_INO;
297
298 /* Now build the IRQ bucket. */
299 imap = schizo_ino_to_imap(pbm, ino);
300 iclr = schizo_ino_to_iclr(pbm, ino);
301
302 /* On Schizo, no inofixup occurs. This is because each
303 * INO has it's own IMAP register. On Psycho and Sabre
304 * there is only one IMAP register for each PCI slot even
305 * though four different INOs can be generated by each
306 * PCI slot.
307 *
308 * But, for JBUS variants (essentially, Tomatillo), we have
309 * to fixup the lowest bit of the interrupt group number.
310 */
311 ign_fixup = 0;
312 if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {
313 if (pbm->portid & 1)
314 ign_fixup = (1 << 6);
315 }
316
317 virt_irq = build_irq(ign_fixup, iclr, imap);
318
319 if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {
320 irq_install_pre_handler(virt_irq,
321 tomatillo_wsync_handler,
322 ((pbm->chip_version <= 4) ?
323 (void *) 1 : (void *) 0),
324 (void *) pbm->sync_reg);
325 }
326
327 return virt_irq;
328}
329
330/* SCHIZO error handling support. */ 220/* SCHIZO error handling support. */
331enum schizo_error_type { 221enum schizo_error_type {
332 UE_ERR, CE_ERR, PCI_ERR, SAFARI_ERR 222 UE_ERR, CE_ERR, PCI_ERR, SAFARI_ERR
@@ -362,34 +252,6 @@ struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino)
362 return &p->pbm_A; 252 return &p->pbm_A;
363} 253}
364 254
365static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq)
366{
367 struct pci_pbm_info *pbm;
368 unsigned long iclr;
369
370 /* Do not clear the interrupt for the other PCI bus.
371 *
372 * This "ACK both PBM IRQs" only needs to be performed
373 * for chip-wide error interrupts.
374 */
375 if ((irq & IMAP_INO) == SCHIZO_PCIERR_A_INO ||
376 (irq & IMAP_INO) == SCHIZO_PCIERR_B_INO)
377 return;
378
379 pbm = pbm_for_ino(p, irq);
380 if (pbm == &p->pbm_A)
381 pbm = &p->pbm_B;
382 else
383 pbm = &p->pbm_A;
384
385 schizo_irq_build(pbm, NULL,
386 (pbm->portid << 6) | (irq & IMAP_INO));
387
388 iclr = schizo_ino_to_iclr(pbm,
389 (pbm->portid << 6) | (irq & IMAP_INO));
390 upa_writel(ICLR_IDLE, iclr);
391}
392
393#define SCHIZO_STC_ERR 0xb800UL /* --> 0xba00 */ 255#define SCHIZO_STC_ERR 0xb800UL /* --> 0xba00 */
394#define SCHIZO_STC_TAG 0xba00UL /* --> 0xba80 */ 256#define SCHIZO_STC_TAG 0xba00UL /* --> 0xba80 */
395#define SCHIZO_STC_LINE 0xbb00UL /* --> 0xbb80 */ 257#define SCHIZO_STC_LINE 0xbb00UL /* --> 0xbb80 */
@@ -720,8 +582,6 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
720 /* Interrogate IOMMU for error status. */ 582 /* Interrogate IOMMU for error status. */
721 schizo_check_iommu_error(p, UE_ERR); 583 schizo_check_iommu_error(p, UE_ERR);
722 584
723 schizo_clear_other_err_intr(p, irq);
724
725 return IRQ_HANDLED; 585 return IRQ_HANDLED;
726} 586}
727 587
@@ -811,8 +671,6 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
811 printk("(none)"); 671 printk("(none)");
812 printk("]\n"); 672 printk("]\n");
813 673
814 schizo_clear_other_err_intr(p, irq);
815
816 return IRQ_HANDLED; 674 return IRQ_HANDLED;
817} 675}
818 676
@@ -1033,8 +891,6 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id, struct pt_regs *reg
1033 if (error_bits & (SCHIZO_PCIAFSR_PPERR | SCHIZO_PCIAFSR_SPERR)) 891 if (error_bits & (SCHIZO_PCIAFSR_PPERR | SCHIZO_PCIAFSR_SPERR))
1034 pci_scan_for_parity_error(p, pbm, pbm->pci_bus); 892 pci_scan_for_parity_error(p, pbm, pbm->pci_bus);
1035 893
1036 schizo_clear_other_err_intr(p, irq);
1037
1038 return IRQ_HANDLED; 894 return IRQ_HANDLED;
1039} 895}
1040 896
@@ -1090,7 +946,6 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *
1090 printk("PCI%d: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n", 946 printk("PCI%d: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n",
1091 p->index, errlog); 947 p->index, errlog);
1092 948
1093 schizo_clear_other_err_intr(p, irq);
1094 return IRQ_HANDLED; 949 return IRQ_HANDLED;
1095 } 950 }
1096 951
@@ -1098,7 +953,6 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *
1098 p->index); 953 p->index);
1099 schizo_check_iommu_error(p, SAFARI_ERR); 954 schizo_check_iommu_error(p, SAFARI_ERR);
1100 955
1101 schizo_clear_other_err_intr(p, irq);
1102 return IRQ_HANDLED; 956 return IRQ_HANDLED;
1103} 957}
1104 958
@@ -1130,74 +984,47 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *
1130static void tomatillo_register_error_handlers(struct pci_controller_info *p) 984static void tomatillo_register_error_handlers(struct pci_controller_info *p)
1131{ 985{
1132 struct pci_pbm_info *pbm; 986 struct pci_pbm_info *pbm;
1133 unsigned int irq; 987 struct of_device *op;
1134 u64 tmp, err_mask, err_no_mask; 988 u64 tmp, err_mask, err_no_mask;
1135 989
1136 /* Build IRQs and register handlers. */ 990 /* Tomatillo IRQ property layout is:
991 * 0: PCIERR
992 * 1: UE ERR
993 * 2: CE ERR
994 * 3: SERR
995 * 4: POWER FAIL?
996 */
997
1137 pbm = pbm_for_ino(p, SCHIZO_UE_INO); 998 pbm = pbm_for_ino(p, SCHIZO_UE_INO);
1138 irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_UE_INO); 999 op = of_find_device_by_node(pbm->prom_node);
1139 if (request_irq(irq, schizo_ue_intr, 1000 if (op)
1140 SA_SHIRQ, "TOMATILLO UE", p) < 0) { 1001 request_irq(op->irqs[1], schizo_ue_intr, SA_SHIRQ,
1141 prom_printf("%s: Cannot register UE interrupt.\n", 1002 "TOMATILLO_UE", p);
1142 pbm->name);
1143 prom_halt();
1144 }
1145 tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO));
1146 upa_writel(tmp, (pbm->pbm_regs +
1147 schizo_imap_offset(SCHIZO_UE_INO) + 4));
1148 1003
1149 pbm = pbm_for_ino(p, SCHIZO_CE_INO); 1004 pbm = pbm_for_ino(p, SCHIZO_CE_INO);
1150 irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_CE_INO); 1005 op = of_find_device_by_node(pbm->prom_node);
1151 if (request_irq(irq, schizo_ce_intr, 1006 if (op)
1152 SA_SHIRQ, "TOMATILLO CE", p) < 0) { 1007 request_irq(op->irqs[2], schizo_ce_intr, SA_SHIRQ,
1153 prom_printf("%s: Cannot register CE interrupt.\n", 1008 "TOMATILLO CE", p);
1154 pbm->name);
1155 prom_halt();
1156 }
1157 tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO));
1158 upa_writel(tmp, (pbm->pbm_regs +
1159 schizo_imap_offset(SCHIZO_CE_INO) + 4));
1160 1009
1161 pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); 1010 pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO);
1162 irq = schizo_irq_build(pbm, NULL, ((pbm->portid << 6) | 1011 op = of_find_device_by_node(pbm->prom_node);
1163 SCHIZO_PCIERR_A_INO)); 1012 if (op)
1164 if (request_irq(irq, schizo_pcierr_intr, 1013 request_irq(op->irqs[0], schizo_pcierr_intr, SA_SHIRQ,
1165 SA_SHIRQ, "TOMATILLO PCIERR", pbm) < 0) { 1014 "TOMATILLO PCIERR-A", pbm);
1166 prom_printf("%s: Cannot register PBM A PciERR interrupt.\n", 1015
1167 pbm->name);
1168 prom_halt();
1169 }
1170 tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) |
1171 SCHIZO_PCIERR_A_INO)));
1172 upa_writel(tmp, (pbm->pbm_regs +
1173 schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));
1174 1016
1175 pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); 1017 pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO);
1176 irq = schizo_irq_build(pbm, NULL, ((pbm->portid << 6) | 1018 op = of_find_device_by_node(pbm->prom_node);
1177 SCHIZO_PCIERR_B_INO)); 1019 if (op)
1178 if (request_irq(irq, schizo_pcierr_intr, 1020 request_irq(op->irqs[0], schizo_pcierr_intr, SA_SHIRQ,
1179 SA_SHIRQ, "TOMATILLO PCIERR", pbm) < 0) { 1021 "TOMATILLO PCIERR-B", pbm);
1180 prom_printf("%s: Cannot register PBM B PciERR interrupt.\n",
1181 pbm->name);
1182 prom_halt();
1183 }
1184 tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) |
1185 SCHIZO_PCIERR_B_INO)));
1186 upa_writel(tmp, (pbm->pbm_regs +
1187 schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4));
1188 1022
1189 pbm = pbm_for_ino(p, SCHIZO_SERR_INO); 1023 pbm = pbm_for_ino(p, SCHIZO_SERR_INO);
1190 irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_SERR_INO); 1024 op = of_find_device_by_node(pbm->prom_node);
1191 if (request_irq(irq, schizo_safarierr_intr, 1025 if (op)
1192 SA_SHIRQ, "TOMATILLO SERR", p) < 0) { 1026 request_irq(op->irqs[3], schizo_safarierr_intr, SA_SHIRQ,
1193 prom_printf("%s: Cannot register SafariERR interrupt.\n", 1027 "TOMATILLO SERR", p);
1194 pbm->name);
1195 prom_halt();
1196 }
1197 tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) |
1198 SCHIZO_SERR_INO)));
1199 upa_writel(tmp, (pbm->pbm_regs +
1200 schizo_imap_offset(SCHIZO_SERR_INO) + 4));
1201 1028
1202 /* Enable UE and CE interrupts for controller. */ 1029 /* Enable UE and CE interrupts for controller. */
1203 schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL, 1030 schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL,
@@ -1265,64 +1092,47 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p)
1265static void schizo_register_error_handlers(struct pci_controller_info *p) 1092static void schizo_register_error_handlers(struct pci_controller_info *p)
1266{ 1093{
1267 struct pci_pbm_info *pbm; 1094 struct pci_pbm_info *pbm;
1268 unsigned int irq; 1095 struct of_device *op;
1269 u64 tmp, err_mask, err_no_mask; 1096 u64 tmp, err_mask, err_no_mask;
1270 1097
1271 /* Build IRQs and register handlers. */ 1098 /* Schizo IRQ property layout is:
1099 * 0: PCIERR
1100 * 1: UE ERR
1101 * 2: CE ERR
1102 * 3: SERR
1103 * 4: POWER FAIL?
1104 */
1105
1272 pbm = pbm_for_ino(p, SCHIZO_UE_INO); 1106 pbm = pbm_for_ino(p, SCHIZO_UE_INO);
1273 irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_UE_INO); 1107 op = of_find_device_by_node(pbm->prom_node);
1274 if (request_irq(irq, schizo_ue_intr, 1108 if (op)
1275 SA_SHIRQ, "SCHIZO UE", p) < 0) { 1109 request_irq(op->irqs[1], schizo_ue_intr, SA_SHIRQ,
1276 prom_printf("%s: Cannot register UE interrupt.\n", 1110 "SCHIZO_UE", p);
1277 pbm->name);
1278 prom_halt();
1279 }
1280 tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO));
1281 upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4));
1282 1111
1283 pbm = pbm_for_ino(p, SCHIZO_CE_INO); 1112 pbm = pbm_for_ino(p, SCHIZO_CE_INO);
1284 irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_CE_INO); 1113 op = of_find_device_by_node(pbm->prom_node);
1285 if (request_irq(irq, schizo_ce_intr, 1114 if (op)
1286 SA_SHIRQ, "SCHIZO CE", p) < 0) { 1115 request_irq(op->irqs[2], schizo_ce_intr, SA_SHIRQ,
1287 prom_printf("%s: Cannot register CE interrupt.\n", 1116 "SCHIZO CE", p);
1288 pbm->name);
1289 prom_halt();
1290 }
1291 tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO));
1292 upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4));
1293 1117
1294 pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); 1118 pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO);
1295 irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_PCIERR_A_INO); 1119 op = of_find_device_by_node(pbm->prom_node);
1296 if (request_irq(irq, schizo_pcierr_intr, 1120 if (op)
1297 SA_SHIRQ, "SCHIZO PCIERR", pbm) < 0) { 1121 request_irq(op->irqs[0], schizo_pcierr_intr, SA_SHIRQ,
1298 prom_printf("%s: Cannot register PBM A PciERR interrupt.\n", 1122 "SCHIZO PCIERR-A", pbm);
1299 pbm->name); 1123
1300 prom_halt();
1301 }
1302 tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_A_INO));
1303 upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));
1304 1124
1305 pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); 1125 pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO);
1306 irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_PCIERR_B_INO); 1126 op = of_find_device_by_node(pbm->prom_node);
1307 if (request_irq(irq, schizo_pcierr_intr, 1127 if (op)
1308 SA_SHIRQ, "SCHIZO PCIERR", &p->pbm_B) < 0) { 1128 request_irq(op->irqs[0], schizo_pcierr_intr, SA_SHIRQ,
1309 prom_printf("%s: Cannot register PBM B PciERR interrupt.\n", 1129 "SCHIZO PCIERR-B", pbm);
1310 pbm->name);
1311 prom_halt();
1312 }
1313 tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_B_INO));
1314 upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4));
1315 1130
1316 pbm = pbm_for_ino(p, SCHIZO_SERR_INO); 1131 pbm = pbm_for_ino(p, SCHIZO_SERR_INO);
1317 irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_SERR_INO); 1132 op = of_find_device_by_node(pbm->prom_node);
1318 if (request_irq(irq, schizo_safarierr_intr, 1133 if (op)
1319 SA_SHIRQ, "SCHIZO SERR", p) < 0) { 1134 request_irq(op->irqs[3], schizo_safarierr_intr, SA_SHIRQ,
1320 prom_printf("%s: Cannot register SafariERR interrupt.\n", 1135 "SCHIZO SERR", p);
1321 pbm->name);
1322 prom_halt();
1323 }
1324 tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_SERR_INO));
1325 upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4));
1326 1136
1327 /* Enable UE and CE interrupts for controller. */ 1137 /* Enable UE and CE interrupts for controller. */
1328 schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL, 1138 schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL,
@@ -2022,7 +1832,6 @@ static void __schizo_init(struct device_node *dp, char *model_name, int chip_typ
2022 p->scan_bus = (chip_type == PBM_CHIP_TYPE_TOMATILLO ? 1832 p->scan_bus = (chip_type == PBM_CHIP_TYPE_TOMATILLO ?
2023 tomatillo_scan_bus : 1833 tomatillo_scan_bus :
2024 schizo_scan_bus); 1834 schizo_scan_bus);
2025 p->irq_build = schizo_irq_build;
2026 p->base_address_update = schizo_base_address_update; 1835 p->base_address_update = schizo_base_address_update;
2027 p->resource_adjust = schizo_resource_adjust; 1836 p->resource_adjust = schizo_resource_adjust;
2028 p->pci_ops = &schizo_ops; 1837 p->pci_ops = &schizo_ops;