Commit 0bcd7365 authored by David S. Miller's avatar David S. Miller

[SPARC64]: More tomatillo PCI controller fixes.

- Use ino-bitmap property to figure out which PCI bus
  module each interrupt gets routed through.
- Fix timeout setting in PCI control register
- Do not enable DTO interrupts.
- Use the correct IGN in INOs on Tomatillo.
parent b86422d7
......@@ -333,7 +333,7 @@ static unsigned int __init schizo_irq_build(struct pci_pbm_info *pbm,
struct ino_bucket *bucket;
unsigned long imap, iclr;
unsigned long imap_off, iclr_off;
int pil;
int pil, ign_fixup;
ino &= PCI_IRQ_INO;
imap_off = schizo_imap_offset(ino);
......@@ -356,8 +356,17 @@ static unsigned int __init schizo_irq_build(struct pci_pbm_info *pbm,
* there is only one IMAP register for each PCI slot even
* though four different INOs can be generated by each
* PCI slot.
*
* But, for JBUS variants (essentially, Tomatillo), we have
* to fixup the lowest bit of the interrupt group number.
*/
bucket = __bucket(build_irq(pil, 0, iclr, imap));
ign_fixup = 0;
if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {
if (pbm->portid & 1)
ign_fixup = (1 << 6);
}
bucket = __bucket(build_irq(pil, ign_fixup, iclr, imap));
bucket->flags |= IBF_PCI;
return __irq(bucket);
......@@ -1063,6 +1072,20 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *
#define SCHIZO_PCICTRL_ARB_S (0x3fUL << 0UL) /* Safari */
#define SCHIZO_PCICTRL_ARB_T (0xffUL << 0UL) /* Tomatillo */
struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino)
{
ino &= IMAP_INO;
if (p->pbm_A.ino_bitmap & (1UL << ino))
return &p->pbm_A;
if (p->pbm_B.ino_bitmap & (1UL << ino))
return &p->pbm_B;
prom_printf("TOMATILLO%d: No entry in ino bitmap for %d\n",
p->index, ino);
prom_halt();
/* NOTREACHED */
return NULL;
}
/* How the Tomatillo IRQs are routed around is pure guesswork here.
*
* All the Tomatillo devices I see in prtconf dumps seem to have only
......@@ -1082,18 +1105,15 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
struct pci_pbm_info *pbm;
unsigned int irq;
struct ino_bucket *bucket;
u64 tmp, err_mask;
int is_pbm_a;
pbm = &p->pbm_B;
is_pbm_a = 0;
u64 tmp, err_mask, err_no_mask;
/* Build IRQs and register handlers. */
pbm = pbm_for_ino(p, SCHIZO_UE_INO);
irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_UE_INO);
if (request_irq(irq, schizo_ue_intr,
SA_SHIRQ, "TOMATILLO UE", p) < 0) {
prom_printf("TOMATILLO%d: Cannot register UE interrupt.\n",
p->index);
prom_printf("%s: Cannot register UE interrupt.\n",
pbm->name);
prom_halt();
}
bucket = __bucket(irq);
......@@ -1101,11 +1121,12 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
upa_writel(tmp, (pbm->pbm_regs +
schizo_imap_offset(SCHIZO_UE_INO) + 4));
pbm = pbm_for_ino(p, SCHIZO_CE_INO);
irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_CE_INO);
if (request_irq(irq, schizo_ce_intr,
SA_SHIRQ, "TOMATILLO CE", p) < 0) {
prom_printf("TOMATILLO%d: Cannot register CE interrupt.\n",
p->index);
prom_printf("%s: Cannot register CE interrupt.\n",
pbm->name);
prom_halt();
}
bucket = __bucket(irq);
......@@ -1113,14 +1134,12 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
upa_writel(tmp, (pbm->pbm_regs +
schizo_imap_offset(SCHIZO_CE_INO) + 4));
pbm = &p->pbm_A;
is_pbm_a = 1;
pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO);
irq = schizo_irq_build(pbm, NULL, ((pbm->portid << 6) |
SCHIZO_PCIERR_A_INO));
if (request_irq(irq, schizo_pcierr_intr,
SA_SHIRQ, "TOMATILLO PCIERR", pbm) < 0) {
prom_printf("%s: Cannot register PciERR interrupt.\n",
prom_printf("%s: Cannot register PBM A PciERR interrupt.\n",
pbm->name);
prom_halt();
}
......@@ -1129,14 +1148,12 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
upa_writel(tmp, (pbm->pbm_regs +
schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));
pbm = &p->pbm_B;
is_pbm_a = 0;
pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO);
irq = schizo_irq_build(pbm, NULL, ((pbm->portid << 6) |
SCHIZO_PCIERR_B_INO));
if (request_irq(irq, schizo_pcierr_intr,
SA_SHIRQ, "TOMATILLO PCIERR", pbm) < 0) {
prom_printf("%s: Cannot register PciERR interrupt.\n",
prom_printf("%s: Cannot register PBM B PciERR interrupt.\n",
pbm->name);
prom_halt();
}
......@@ -1145,6 +1162,7 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
upa_writel(tmp, (pbm->pbm_regs +
schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4));
pbm = pbm_for_ino(p, SCHIZO_SERR_INO);
irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_SERR_INO);
if (request_irq(irq, schizo_safarierr_intr,
SA_SHIRQ, "TOMATILLO SERR", p) < 0) {
......@@ -1174,16 +1192,19 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
err_mask = (SCHIZO_PCICTRL_BUS_UNUS |
SCHIZO_PCICTRL_TTO_ERR |
SCHIZO_PCICTRL_RTRY_ERR |
SCHIZO_PCICTRL_DTO_ERR |
SCHIZO_PCICTRL_SERR |
SCHIZO_PCICTRL_EEN);
err_no_mask = SCHIZO_PCICTRL_DTO_ERR;
tmp = schizo_read(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL);
tmp |= err_mask;
tmp &= ~err_no_mask;
schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL, tmp);
tmp = schizo_read(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL);
tmp |= err_mask;
tmp &= ~err_no_mask;
schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL, tmp);
err_mask = (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA |
......@@ -1219,70 +1240,74 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
static void __init schizo_register_error_handlers(struct pci_controller_info *p)
{
struct pci_pbm_info *pbm_a = &p->pbm_A;
struct pci_pbm_info *pbm_b = &p->pbm_B;
struct pci_pbm_info *pbm;
unsigned int irq;
struct ino_bucket *bucket;
u64 tmp, err_mask;
u64 tmp, err_mask, err_no_mask;
/* Build IRQs and register handlers. */
irq = schizo_irq_build(pbm_b, NULL, (pbm_b->portid << 6) | SCHIZO_UE_INO);
pbm = pbm_for_ino(p, SCHIZO_UE_INO);
irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_UE_INO);
if (request_irq(irq, schizo_ue_intr,
SA_SHIRQ, "SCHIZO UE", p) < 0) {
prom_printf("SCHIZO%d: Cannot register UE interrupt.\n",
p->index);
prom_printf("%s: Cannot register UE interrupt.\n",
pbm->name);
prom_halt();
}
bucket = __bucket(irq);
tmp = readl(bucket->imap);
upa_writel(tmp, (pbm_b->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4));
upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4));
irq = schizo_irq_build(pbm_b, NULL, (pbm_b->portid << 6) | SCHIZO_CE_INO);
pbm = pbm_for_ino(p, SCHIZO_CE_INO);
irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_CE_INO);
if (request_irq(irq, schizo_ce_intr,
SA_SHIRQ, "SCHIZO CE", p) < 0) {
prom_printf("SCHIZO%d: Cannot register CE interrupt.\n",
p->index);
prom_printf("%s: Cannot register CE interrupt.\n",
pbm->name);
prom_halt();
}
bucket = __bucket(irq);
tmp = upa_readl(bucket->imap);
upa_writel(tmp, (pbm_b->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4));
upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4));
irq = schizo_irq_build(pbm_a, NULL, (pbm_a->portid << 6) | SCHIZO_PCIERR_A_INO);
pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO);
irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_PCIERR_A_INO);
if (request_irq(irq, schizo_pcierr_intr,
SA_SHIRQ, "SCHIZO PCIERR", pbm_a) < 0) {
prom_printf("SCHIZO%d(PBMA): Cannot register PciERR interrupt.\n",
p->index);
SA_SHIRQ, "SCHIZO PCIERR", pbm) < 0) {
prom_printf("%s: Cannot register PBM A PciERR interrupt.\n",
pbm->name);
prom_halt();
}
bucket = __bucket(irq);
tmp = upa_readl(bucket->imap);
upa_writel(tmp, (pbm_a->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));
upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));
irq = schizo_irq_build(pbm_b, NULL, (pbm_b->portid << 6) | SCHIZO_PCIERR_B_INO);
pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO);
irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_PCIERR_B_INO);
if (request_irq(irq, schizo_pcierr_intr,
SA_SHIRQ, "SCHIZO PCIERR", pbm_b) < 0) {
prom_printf("SCHIZO%d(PBMB): Cannot register PciERR interrupt.\n",
p->index);
SA_SHIRQ, "SCHIZO PCIERR", &p->pbm_B) < 0) {
prom_printf("%s: Cannot register PBM B PciERR interrupt.\n",
pbm->name);
prom_halt();
}
bucket = __bucket(irq);
tmp = upa_readl(bucket->imap);
upa_writel(tmp, (pbm_b->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4));
upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4));
irq = schizo_irq_build(pbm_b, NULL, (pbm_b->portid << 6) | SCHIZO_SERR_INO);
pbm = pbm_for_ino(p, SCHIZO_SERR_INO);
irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_SERR_INO);
if (request_irq(irq, schizo_safarierr_intr,
SA_SHIRQ, "SCHIZO SERR", p) < 0) {
prom_printf("SCHIZO%d(PBMB): Cannot register SafariERR interrupt.\n",
p->index);
prom_printf("%s: Cannot register SafariERR interrupt.\n",
pbm->name);
prom_halt();
}
bucket = __bucket(irq);
tmp = upa_readl(bucket->imap);
upa_writel(tmp, (pbm_b->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4));
upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4));
/* Enable UE and CE interrupts for controller. */
schizo_write(pbm_a->controller_regs + SCHIZO_ECC_CTRL,
schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL,
(SCHIZO_ECCCTRL_EE |
SCHIZO_ECCCTRL_UE |
SCHIZO_ECCCTRL_CE));
......@@ -1291,20 +1316,22 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
SCHIZO_PCICTRL_ESLCK |
SCHIZO_PCICTRL_TTO_ERR |
SCHIZO_PCICTRL_RTRY_ERR |
SCHIZO_PCICTRL_DTO_ERR |
SCHIZO_PCICTRL_SBH_ERR |
SCHIZO_PCICTRL_SERR |
SCHIZO_PCICTRL_SBH_INT |
SCHIZO_PCICTRL_EEN);
err_no_mask = SCHIZO_PCICTRL_DTO_ERR;
/* Enable PCI Error interrupts and clear error
* bits for each PBM.
*/
tmp = schizo_read(pbm_a->pbm_regs + SCHIZO_PCI_CTRL);
tmp = schizo_read(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL);
tmp |= err_mask;
schizo_write(pbm_a->pbm_regs + SCHIZO_PCI_CTRL, tmp);
tmp &= ~err_no_mask;
schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL, tmp);
schizo_write(pbm_a->pbm_regs + SCHIZO_PCI_AFSR,
schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_AFSR,
(SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA |
SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR |
SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS |
......@@ -1312,11 +1339,12 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR |
SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS));
tmp = schizo_read(pbm_b->pbm_regs + SCHIZO_PCI_CTRL);
tmp = schizo_read(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL);
tmp |= err_mask;
schizo_write(pbm_b->pbm_regs + SCHIZO_PCI_CTRL, tmp);
tmp &= ~err_no_mask;
schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL, tmp);
schizo_write(pbm_b->pbm_regs + SCHIZO_PCI_AFSR,
schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_AFSR,
(SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA |
SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR |
SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS |
......@@ -1349,10 +1377,10 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB);
#endif
schizo_write(pbm_a->controller_regs + SCHIZO_SAFARI_ERRCTRL,
schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_ERRCTRL,
(SCHIZO_SAFERRCTRL_EN | err_mask));
schizo_write(pbm_a->controller_regs + SCHIZO_SAFARI_IRQCTRL,
schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_IRQCTRL,
(SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));
}
......@@ -1795,11 +1823,12 @@ static void __init schizo_pbm_hw_init(struct pci_pbm_info *pbm)
else
tmp |= 0xff;
tmp &= ~SCHIZO_PCICTRL_PTO;
if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO &&
pbm->chip_version == 0x2) {
tmp &= ~SCHIZO_PCICTRL_PTO;
pbm->chip_version == 0x2)
tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT;
}
else
tmp |= 0x1UL << SCHIZO_PCICTRL_PTO_SHIFT;
if (!prom_getbool(pbm->prom_node, "no-bus-parking"))
tmp |= SCHIZO_PCICTRL_PARK;
......@@ -1838,6 +1867,7 @@ static void __init schizo_pbm_init(struct pci_controller_info *p,
unsigned int busrange[2];
struct pci_pbm_info *pbm;
const char *chipset_name;
u32 ino_bitmap[2];
int is_pbm_a;
int err;
......@@ -1951,6 +1981,16 @@ static void __init schizo_pbm_init(struct pci_controller_info *p,
memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
}
err = prom_getproperty(prom_node, "ino-bitmap",
(char *) &ino_bitmap[0],
sizeof(ino_bitmap));
if (err == 0 || err == -1) {
prom_printf("%s: Fatal error, no ino-bitmap.\n", pbm->name);
prom_halt();
}
pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) |
((u64)ino_bitmap[0] << 0UL));
err = prom_getproperty(prom_node, "bus-range",
(char *)&busrange[0],
sizeof(busrange));
......
......@@ -158,6 +158,7 @@ struct pci_pbm_info {
struct linux_prom_pci_intmap pbm_intmap[PROM_PCIIMAP_MAX];
int num_pbm_intmap;
struct linux_prom_pci_intmask pbm_intmask;
u64 ino_bitmap;
/* PBM I/O and Memory space resources. */
struct resource io_space;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment