patch-2.4.23 linux-2.4.23/arch/sparc64/kernel/pci_schizo.c
Next file: linux-2.4.23/arch/sparc64/kernel/setup.c
Previous file: linux-2.4.23/arch/sparc64/kernel/pci_sabre.c
Back to the patch index
Back to the overall index
- Lines: 1983
- Date:
2003-11-28 10:26:19.000000000 -0800
- Orig file:
linux-2.4.22/arch/sparc64/kernel/pci_schizo.c
- Orig date:
2002-11-28 15:53:12.000000000 -0800
diff -urN linux-2.4.22/arch/sparc64/kernel/pci_schizo.c linux-2.4.23/arch/sparc64/kernel/pci_schizo.c
@@ -1,7 +1,7 @@
/* $Id: pci_schizo.c,v 1.23.2.2 2002/03/11 07:55:24 davem Exp $
- * pci_schizo.c: SCHIZO specific PCI controller support.
+ * pci_schizo.c: SCHIZO/TOMATILLO specific PCI controller support.
*
- * Copyright (C) 2001 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2001, 2002, 2003 David S. Miller (davem@redhat.com)
*/
#include <linux/kernel.h>
@@ -45,13 +45,7 @@
* block requires more space in Schizo's address space than
* they predicted, thus requiring an address space reorg when
* the newer Schizo is taped out.
- *
- * These offsets look weird because I keep in p->controller_regs
- * the second PROM register property minus 0x10000 which is the
- * base of the Safari and UPA64S registers of SCHIZO.
*/
-#define SCHIZO_PBM_A_REGS_OFF (0x600000UL - 0x400000UL)
-#define SCHIZO_PBM_B_REGS_OFF (0x700000UL - 0x400000UL)
/* Streaming buffer control register. */
#define SCHIZO_STRBUF_CTRL_LPTR 0x00000000000000f0UL /* LRU Lock Pointer */
@@ -101,25 +95,21 @@
{
if (!pbm)
return NULL;
+ bus -= pbm->pci_first_busno;
return (void *)
(SCHIZO_CONFIG_BASE(pbm) |
SCHIZO_CONFIG_ENCODE(bus, devfn, where));
}
-/* 4 slots on pbm A, and 6 slots on pbm B. In both cases
- * slot 0 is the SCHIZO host bridge itself.
- */
+/* Just make sure the bus number is in range. */
static int schizo_out_of_range(struct pci_pbm_info *pbm,
unsigned char bus,
unsigned char devfn)
{
- return ((pbm->parent == 0) ||
- ((pbm == &pbm->parent->pbm_B) &&
- (bus == pbm->pci_first_busno) &&
- PCI_SLOT(devfn) > 6) ||
- ((pbm == &pbm->parent->pbm_A) &&
- (bus == pbm->pci_first_busno) &&
- PCI_SLOT(devfn) > 4));
+ if (bus < pbm->pci_first_busno ||
+ bus > pbm->pci_last_busno)
+ return 1;
+ return 0;
}
/* SCHIZO PCI configuration space accessors. */
@@ -188,6 +178,15 @@
}
pci_config_read32(addr, value);
+ if (where == PCI_PRIMARY_BUS &&
+ dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
+ *value != 0xffffffff) {
+ u8 *busp = ((u8 *) value) + 1;
+ int i;
+
+ for (i = 0; i < 3; i++)
+ busp[i] += pbm->pci_first_busno;
+ }
return PCIBIOS_SUCCESSFUL;
}
@@ -251,6 +250,20 @@
where);
return PCIBIOS_SUCCESSFUL;
}
+
+ if (where == PCI_PRIMARY_BUS &&
+ dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ u8 *busp = ((u8 *) &value) + 1;
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ if (busp[i] >= pbm->pci_first_busno)
+ busp[i] += pbm->pci_first_busno;
+ else
+ busp[i] = 0;
+ }
+ }
+
pci_config_write32(addr, value);
return PCIBIOS_SUCCESSFUL;
}
@@ -379,16 +392,10 @@
struct pci_dev *pdev,
unsigned int ino)
{
- struct pci_controller_info *p = pbm->parent;
struct ino_bucket *bucket;
- unsigned long imap, iclr, pbm_off;
+ unsigned long imap, iclr;
unsigned long imap_off, iclr_off;
- int pil;
-
- if (pbm == &p->pbm_A)
- pbm_off = SCHIZO_PBM_A_REGS_OFF;
- else
- pbm_off = SCHIZO_PBM_B_REGS_OFF;
+ int pil, ign_fixup;
ino &= PCI_IRQ_INO;
imap_off = schizo_imap_offset(ino);
@@ -399,11 +406,11 @@
if (PIL_RESERVED(pil))
BUG();
- imap = p->controller_regs + pbm_off + imap_off;
+ imap = pbm->pbm_regs + imap_off;
imap += 4;
iclr_off = schizo_iclr_offset(ino);
- iclr = p->controller_regs + pbm_off + iclr_off;
+ iclr = pbm->pbm_regs + iclr_off;
iclr += 4;
/* On Schizo, no inofixup occurs. This is because each
@@ -411,8 +418,17 @@
* 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);
@@ -428,6 +444,13 @@
static unsigned long stc_tag_buf[16];
static unsigned long stc_line_buf[16];
+/* These offsets look weird because I keep in pbm->controller_regs
+ * the second PROM register property minus 0x10000 which is the
+ * base of the Safari and UPA64S registers of SCHIZO.
+ */
+#define SCHIZO_PBM_A_REGS_OFF (0x600000UL - 0x400000UL)
+#define SCHIZO_PBM_B_REGS_OFF (0x700000UL - 0x400000UL)
+
static void schizo_clear_other_err_intr(int irq)
{
struct ino_bucket *bucket = __bucket(irq);
@@ -459,19 +482,12 @@
static void __schizo_check_stc_error_pbm(struct pci_pbm_info *pbm,
enum schizo_error_type type)
{
- struct pci_controller_info *p = pbm->parent;
struct pci_strbuf *strbuf = &pbm->stc;
- unsigned long regbase = p->controller_regs;
+ unsigned long regbase = pbm->pbm_regs;
unsigned long err_base, tag_base, line_base;
u64 control;
- char pbm_name = (pbm == &p->pbm_A ? 'A' : 'B');
int i;
- if (pbm == &p->pbm_A)
- regbase += SCHIZO_PBM_A_REGS_OFF;
- else
- regbase += SCHIZO_PBM_B_REGS_OFF;
-
err_base = regbase + SCHIZO_STC_ERR;
tag_base = regbase + SCHIZO_STC_TAG;
line_base = regbase + SCHIZO_STC_LINE;
@@ -517,8 +533,8 @@
unsigned long errval = stc_error_buf[j];
if (errval != 0) {
saw_error++;
- printk("SCHIZO%d: PBM-%c STC_ERR(%d)[wr(%d)rd(%d)]\n",
- p->index, pbm_name,
+ printk("%s: STC_ERR(%d)[wr(%d)rd(%d)]\n",
+ pbm->name,
j,
(errval & SCHIZO_STCERR_WRITE) ? 1 : 0,
(errval & SCHIZO_STCERR_READ) ? 1 : 0);
@@ -527,8 +543,8 @@
if (saw_error != 0) {
unsigned long tagval = stc_tag_buf[i];
unsigned long lineval = stc_line_buf[i];
- printk("SCHIZO%d: PBM-%c STC_TAG(%d)[PA(%016lx)VA(%08lx)V(%d)R(%d)]\n",
- p->index, pbm_name,
+ printk("%s: STC_TAG(%d)[PA(%016lx)VA(%08lx)V(%d)R(%d)]\n",
+ pbm->name,
i,
((tagval & SCHIZO_STCTAG_PPN) >> 19UL),
(tagval & SCHIZO_STCTAG_VPN),
@@ -536,9 +552,9 @@
((tagval & SCHIZO_STCTAG_READ) ? 1 : 0));
/* XXX Should spit out per-bank error information... -DaveM */
- printk("SCHIZO%d: PBM-%c STC_LINE(%d)[LIDX(%lx)SP(%lx)LADDR(%lx)EP(%lx)"
+ printk("%s: STC_LINE(%d)[LIDX(%lx)SP(%lx)LADDR(%lx)EP(%lx)"
"V(%d)FOFN(%d)]\n",
- p->index, pbm_name,
+ pbm->name,
i,
((lineval & SCHIZO_STCLINE_LINDX) >> 23UL),
((lineval & SCHIZO_STCLINE_SPTR) >> 13UL),
@@ -574,13 +590,11 @@
static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm,
enum schizo_error_type type)
{
- struct pci_controller_info *p = pbm->parent;
struct pci_iommu *iommu = pbm->iommu;
unsigned long iommu_tag[16];
unsigned long iommu_data[16];
unsigned long flags;
u64 control;
- char pbm_name = (pbm == &p->pbm_A ? 'A' : 'B');
int i;
spin_lock_irqsave(&iommu->lock, flags);
@@ -608,8 +622,8 @@
type_string = "ECC Error";
break;
};
- printk("SCHIZO%d: PBM-%c IOMMU Error, type[%s]\n",
- p->index, pbm_name, type_string);
+ printk("%s: IOMMU Error, type[%s]\n",
+ pbm->name, type_string);
/* Put the IOMMU into diagnostic mode and probe
* it's TLB for entries with error status.
@@ -624,11 +638,7 @@
schizo_write(iommu->iommu_control,
control | SCHIZO_IOMMU_CTRL_DENAB);
- base = p->controller_regs;
- if (pbm == &p->pbm_A)
- base += SCHIZO_PBM_A_REGS_OFF;
- else
- base += SCHIZO_PBM_B_REGS_OFF;
+ base = pbm->pbm_regs;
for (i = 0; i < 16; i++) {
iommu_tag[i] =
@@ -667,22 +677,23 @@
type_string = "ECC Error";
break;
};
- printk("SCHIZO%d: PBM-%c IOMMU TAG(%d)[error(%s) ctx(%x) wr(%d) str(%d) "
+ printk("%s: IOMMU TAG(%d)[error(%s) ctx(%x) wr(%d) str(%d) "
"sz(%dK) vpg(%08lx)]\n",
- p->index, pbm_name, i, type_string,
+ pbm->name, i, type_string,
(int)((tag & SCHIZO_IOMMU_TAG_CTXT) >> 25UL),
((tag & SCHIZO_IOMMU_TAG_WRITE) ? 1 : 0),
((tag & SCHIZO_IOMMU_TAG_STREAM) ? 1 : 0),
((tag & SCHIZO_IOMMU_TAG_SIZE) ? 64 : 8),
(tag & SCHIZO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT);
- printk("SCHIZO%d: PBM-%c IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n",
- p->index, pbm_name, i,
+ printk("%s: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n",
+ pbm->name, i,
((data & SCHIZO_IOMMU_DATA_VALID) ? 1 : 0),
((data & SCHIZO_IOMMU_DATA_CACHE) ? 1 : 0),
(data & SCHIZO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT);
}
}
- __schizo_check_stc_error_pbm(pbm, type);
+ if (pbm->stc.strbuf_enabled)
+ __schizo_check_stc_error_pbm(pbm, type);
spin_unlock_irqrestore(&iommu->lock, flags);
}
@@ -697,26 +708,26 @@
#define SCHIZO_UE_AFSR 0x10030UL
#define SCHIZO_UE_AFAR 0x10038UL
-#define SCHIZO_UEAFSR_PPIO 0x8000000000000000UL
-#define SCHIZO_UEAFSR_PDRD 0x4000000000000000UL
-#define SCHIZO_UEAFSR_PDWR 0x2000000000000000UL
-#define SCHIZO_UEAFSR_SPIO 0x1000000000000000UL
-#define SCHIZO_UEAFSR_SDMA 0x0800000000000000UL
-#define SCHIZO_UEAFSR_ERRPNDG 0x0300000000000000UL
-#define SCHIZO_UEAFSR_BMSK 0x000003ff00000000UL
-#define SCHIZO_UEAFSR_QOFF 0x00000000c0000000UL
-#define SCHIZO_UEAFSR_AID 0x000000001f000000UL
-#define SCHIZO_UEAFSR_PARTIAL 0x0000000000800000UL
-#define SCHIZO_UEAFSR_OWNEDIN 0x0000000000400000UL
-#define SCHIZO_UEAFSR_MTAGSYND 0x00000000000f0000UL
-#define SCHIZO_UEAFSR_MTAG 0x000000000000e000UL
-#define SCHIZO_UEAFSR_ECCSYND 0x00000000000001ffUL
+#define SCHIZO_UEAFSR_PPIO 0x8000000000000000UL /* Safari */
+#define SCHIZO_UEAFSR_PDRD 0x4000000000000000UL /* Safari/Tomatillo */
+#define SCHIZO_UEAFSR_PDWR 0x2000000000000000UL /* Safari */
+#define SCHIZO_UEAFSR_SPIO 0x1000000000000000UL /* Safari */
+#define SCHIZO_UEAFSR_SDMA 0x0800000000000000UL /* Safari/Tomatillo */
+#define SCHIZO_UEAFSR_ERRPNDG 0x0300000000000000UL /* Safari */
+#define SCHIZO_UEAFSR_BMSK 0x000003ff00000000UL /* Safari */
+#define SCHIZO_UEAFSR_QOFF 0x00000000c0000000UL /* Safari/Tomatillo */
+#define SCHIZO_UEAFSR_AID 0x000000001f000000UL /* Safari/Tomatillo */
+#define SCHIZO_UEAFSR_PARTIAL 0x0000000000800000UL /* Safari */
+#define SCHIZO_UEAFSR_OWNEDIN 0x0000000000400000UL /* Safari */
+#define SCHIZO_UEAFSR_MTAGSYND 0x00000000000f0000UL /* Safari */
+#define SCHIZO_UEAFSR_MTAG 0x000000000000e000UL /* Safari */
+#define SCHIZO_UEAFSR_ECCSYND 0x00000000000001ffUL /* Safari */
static void schizo_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct pci_controller_info *p = dev_id;
- unsigned long afsr_reg = p->controller_regs + SCHIZO_UE_AFSR;
- unsigned long afar_reg = p->controller_regs + SCHIZO_UE_AFAR;
+ unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFSR;
+ unsigned long afar_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFAR;
unsigned long afsr, afar, error_bits;
int reported, limit;
@@ -741,7 +752,7 @@
schizo_write(afsr_reg, error_bits);
/* Log the error. */
- printk("SCHIZO%d: Uncorrectable Error, primary error type[%s]\n",
+ printk("PCI%d: Uncorrectable Error, primary error type[%s]\n",
p->index,
(((error_bits & SCHIZO_UEAFSR_PPIO) ?
"PIO" :
@@ -749,20 +760,20 @@
"DMA Read" :
((error_bits & SCHIZO_UEAFSR_PDWR) ?
"DMA Write" : "???")))));
- printk("SCHIZO%d: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n",
+ printk("PCI%d: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n",
p->index,
(afsr & SCHIZO_UEAFSR_BMSK) >> 32UL,
(afsr & SCHIZO_UEAFSR_QOFF) >> 30UL,
(afsr & SCHIZO_UEAFSR_AID) >> 24UL);
- printk("SCHIZO%d: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n",
+ printk("PCI%d: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n",
p->index,
(afsr & SCHIZO_UEAFSR_PARTIAL) ? 1 : 0,
(afsr & SCHIZO_UEAFSR_OWNEDIN) ? 1 : 0,
(afsr & SCHIZO_UEAFSR_MTAG) >> 13UL,
(afsr & SCHIZO_UEAFSR_MTAGSYND) >> 16UL,
(afsr & SCHIZO_UEAFSR_ECCSYND) >> 0UL);
- printk("SCHIZO%d: UE AFAR [%016lx]\n", p->index, afar);
- printk("SCHIZO%d: UE Secondary errors [", p->index);
+ printk("PCI%d: UE AFAR [%016lx]\n", p->index, afar);
+ printk("PCI%d: UE Secondary errors [", p->index);
reported = 0;
if (afsr & SCHIZO_UEAFSR_SPIO) {
reported++;
@@ -803,8 +814,8 @@
static void schizo_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct pci_controller_info *p = dev_id;
- unsigned long afsr_reg = p->controller_regs + SCHIZO_CE_AFSR;
- unsigned long afar_reg = p->controller_regs + SCHIZO_CE_AFAR;
+ unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFSR;
+ unsigned long afar_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFAR;
unsigned long afsr, afar, error_bits;
int reported, limit;
@@ -829,7 +840,7 @@
schizo_write(afsr_reg, error_bits);
/* Log the error. */
- printk("SCHIZO%d: Correctable Error, primary error type[%s]\n",
+ printk("PCI%d: Correctable Error, primary error type[%s]\n",
p->index,
(((error_bits & SCHIZO_CEAFSR_PPIO) ?
"PIO" :
@@ -841,20 +852,20 @@
/* XXX Use syndrome and afar to print out module string just like
* XXX UDB CE trap handler does... -DaveM
*/
- printk("SCHIZO%d: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n",
+ printk("PCI%d: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n",
p->index,
(afsr & SCHIZO_UEAFSR_BMSK) >> 32UL,
(afsr & SCHIZO_UEAFSR_QOFF) >> 30UL,
(afsr & SCHIZO_UEAFSR_AID) >> 24UL);
- printk("SCHIZO%d: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n",
+ printk("PCI%d: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n",
p->index,
(afsr & SCHIZO_UEAFSR_PARTIAL) ? 1 : 0,
(afsr & SCHIZO_UEAFSR_OWNEDIN) ? 1 : 0,
(afsr & SCHIZO_UEAFSR_MTAG) >> 13UL,
(afsr & SCHIZO_UEAFSR_MTAGSYND) >> 16UL,
(afsr & SCHIZO_UEAFSR_ECCSYND) >> 0UL);
- printk("SCHIZO%d: CE AFAR [%016lx]\n", p->index, afar);
- printk("SCHIZO%d: CE Secondary errors [", p->index);
+ printk("PCI%d: CE AFAR [%016lx]\n", p->index, afar);
+ printk("PCI%d: CE Secondary errors [", p->index);
reported = 0;
if (afsr & SCHIZO_CEAFSR_SPIO) {
reported++;
@@ -874,23 +885,101 @@
#define SCHIZO_PCI_AFSR 0x2010UL
#define SCHIZO_PCI_AFAR 0x2018UL
-#define SCHIZO_PCIAFSR_PMA 0x8000000000000000UL
-#define SCHIZO_PCIAFSR_PTA 0x4000000000000000UL
-#define SCHIZO_PCIAFSR_PRTRY 0x2000000000000000UL
-#define SCHIZO_PCIAFSR_PPERR 0x1000000000000000UL
-#define SCHIZO_PCIAFSR_PTTO 0x0800000000000000UL
-#define SCHIZO_PCIAFSR_PUNUS 0x0400000000000000UL
-#define SCHIZO_PCIAFSR_SMA 0x0200000000000000UL
-#define SCHIZO_PCIAFSR_STA 0x0100000000000000UL
-#define SCHIZO_PCIAFSR_SRTRY 0x0080000000000000UL
-#define SCHIZO_PCIAFSR_SPERR 0x0040000000000000UL
-#define SCHIZO_PCIAFSR_STTO 0x0020000000000000UL
-#define SCHIZO_PCIAFSR_SUNUS 0x0010000000000000UL
-#define SCHIZO_PCIAFSR_BMSK 0x000003ff00000000UL
-#define SCHIZO_PCIAFSR_BLK 0x0000000080000000UL
-#define SCHIZO_PCIAFSR_CFG 0x0000000040000000UL
-#define SCHIZO_PCIAFSR_MEM 0x0000000020000000UL
-#define SCHIZO_PCIAFSR_IO 0x0000000010000000UL
+#define SCHIZO_PCIAFSR_PMA 0x8000000000000000UL /* Schizo/Tomatillo */
+#define SCHIZO_PCIAFSR_PTA 0x4000000000000000UL /* Schizo/Tomatillo */
+#define SCHIZO_PCIAFSR_PRTRY 0x2000000000000000UL /* Schizo/Tomatillo */
+#define SCHIZO_PCIAFSR_PPERR 0x1000000000000000UL /* Schizo/Tomatillo */
+#define SCHIZO_PCIAFSR_PTTO 0x0800000000000000UL /* Schizo/Tomatillo */
+#define SCHIZO_PCIAFSR_PUNUS 0x0400000000000000UL /* Schizo */
+#define SCHIZO_PCIAFSR_SMA 0x0200000000000000UL /* Schizo/Tomatillo */
+#define SCHIZO_PCIAFSR_STA 0x0100000000000000UL /* Schizo/Tomatillo */
+#define SCHIZO_PCIAFSR_SRTRY 0x0080000000000000UL /* Schizo/Tomatillo */
+#define SCHIZO_PCIAFSR_SPERR 0x0040000000000000UL /* Schizo/Tomatillo */
+#define SCHIZO_PCIAFSR_STTO 0x0020000000000000UL /* Schizo/Tomatillo */
+#define SCHIZO_PCIAFSR_SUNUS 0x0010000000000000UL /* Schizo */
+#define SCHIZO_PCIAFSR_BMSK 0x000003ff00000000UL /* Schizo/Tomatillo */
+#define SCHIZO_PCIAFSR_BLK 0x0000000080000000UL /* Schizo/Tomatillo */
+#define SCHIZO_PCIAFSR_CFG 0x0000000040000000UL /* Schizo/Tomatillo */
+#define SCHIZO_PCIAFSR_MEM 0x0000000020000000UL /* Schizo/Tomatillo */
+#define SCHIZO_PCIAFSR_IO 0x0000000010000000UL /* Schizo/Tomatillo */
+
+#define SCHIZO_PCI_CTRL (0x2000UL)
+#define SCHIZO_PCICTRL_BUS_UNUS (1UL << 63UL) /* Safari */
+#define SCHIZO_PCICTRL_ARB_PRIO (0x1ff << 52UL) /* Tomatillo */
+#define SCHIZO_PCICTRL_ESLCK (1UL << 51UL) /* Safari */
+#define SCHIZO_PCICTRL_ERRSLOT (7UL << 48UL) /* Safari */
+#define SCHIZO_PCICTRL_TTO_ERR (1UL << 38UL) /* Safari/Tomatillo */
+#define SCHIZO_PCICTRL_RTRY_ERR (1UL << 37UL) /* Safari/Tomatillo */
+#define SCHIZO_PCICTRL_DTO_ERR (1UL << 36UL) /* Safari/Tomatillo */
+#define SCHIZO_PCICTRL_SBH_ERR (1UL << 35UL) /* Safari */
+#define SCHIZO_PCICTRL_SERR (1UL << 34UL) /* Safari/Tomatillo */
+#define SCHIZO_PCICTRL_PCISPD (1UL << 33UL) /* Safari */
+#define SCHIZO_PCICTRL_MRM_PREF (1UL << 28UL) /* Tomatillo */
+#define SCHIZO_PCICTRL_RDO_PREF (1UL << 27UL) /* Tomatillo */
+#define SCHIZO_PCICTRL_RDL_PREF (1UL << 26UL) /* Tomatillo */
+#define SCHIZO_PCICTRL_PTO (3UL << 24UL) /* Safari/Tomatillo */
+#define SCHIZO_PCICTRL_PTO_SHIFT 24UL
+#define SCHIZO_PCICTRL_TRWSW (7UL << 21UL) /* Tomatillo */
+#define SCHIZO_PCICTRL_F_TGT_A (1UL << 20UL) /* Tomatillo */
+#define SCHIZO_PCICTRL_S_DTO_INT (1UL << 19UL) /* Safari */
+#define SCHIZO_PCICTRL_F_TGT_RT (1UL << 19UL) /* Tomatillo */
+#define SCHIZO_PCICTRL_SBH_INT (1UL << 18UL) /* Safari */
+#define SCHIZO_PCICTRL_T_DTO_INT (1UL << 18UL) /* Tomatillo */
+#define SCHIZO_PCICTRL_EEN (1UL << 17UL) /* Safari/Tomatillo */
+#define SCHIZO_PCICTRL_PARK (1UL << 16UL) /* Safari/Tomatillo */
+#define SCHIZO_PCICTRL_PCIRST (1UL << 8UL) /* Safari */
+#define SCHIZO_PCICTRL_ARB_S (0x3fUL << 0UL) /* Safari */
+#define SCHIZO_PCICTRL_ARB_T (0xffUL << 0UL) /* Tomatillo */
+
+static void schizo_pcierr_intr_other(struct pci_pbm_info *pbm)
+{
+ unsigned long csr_reg, csr, csr_error_bits;
+ u16 stat;
+
+ csr_reg = pbm->pbm_regs + SCHIZO_PCI_CTRL;
+ csr = schizo_read(csr_reg);
+ csr_error_bits =
+ csr & (SCHIZO_PCICTRL_BUS_UNUS |
+ SCHIZO_PCICTRL_TTO_ERR |
+ SCHIZO_PCICTRL_RTRY_ERR |
+ SCHIZO_PCICTRL_DTO_ERR |
+ SCHIZO_PCICTRL_SBH_ERR |
+ SCHIZO_PCICTRL_SERR);
+ if (csr_error_bits) {
+ /* Clear the errors. */
+ schizo_write(csr_reg, csr);
+
+ /* Log 'em. */
+ if (csr_error_bits & SCHIZO_PCICTRL_BUS_UNUS)
+ printk("%s: Bus unusable error asserted.\n",
+ pbm->name);
+ if (csr_error_bits & SCHIZO_PCICTRL_TTO_ERR)
+ printk("%s: PCI TRDY# timeout error asserted.\n",
+ pbm->name);
+ if (csr_error_bits & SCHIZO_PCICTRL_RTRY_ERR)
+ printk("%s: PCI excessive retry error asserted.\n",
+ pbm->name);
+ if (csr_error_bits & SCHIZO_PCICTRL_DTO_ERR)
+ printk("%s: PCI discard timeout error asserted.\n",
+ pbm->name);
+ if (csr_error_bits & SCHIZO_PCICTRL_SBH_ERR)
+ printk("%s: PCI streaming byte hole error asserted.\n",
+ pbm->name);
+ if (csr_error_bits & SCHIZO_PCICTRL_SERR)
+ printk("%s: PCI SERR signal asserted.\n",
+ pbm->name);
+ }
+ pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat);
+ if (stat & (PCI_STATUS_PARITY |
+ PCI_STATUS_SIG_TARGET_ABORT |
+ PCI_STATUS_REC_TARGET_ABORT |
+ PCI_STATUS_REC_MASTER_ABORT |
+ PCI_STATUS_SIG_SYSTEM_ERROR)) {
+ printk("%s: PCI bus error, PCI_STATUS[%04x]\n",
+ pbm->name, stat);
+ pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff);
+ }
+}
static void schizo_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -899,16 +988,8 @@
unsigned long afsr_reg, afar_reg, base;
unsigned long afsr, afar, error_bits;
int reported;
- char pbm_name;
- base = p->controller_regs;
- if (pbm == &pbm->parent->pbm_A) {
- base += SCHIZO_PBM_A_REGS_OFF;
- pbm_name = 'A';
- } else {
- base += SCHIZO_PBM_B_REGS_OFF;
- pbm_name = 'B';
- }
+ base = pbm->pbm_regs;
afsr_reg = base + SCHIZO_PCI_AFSR;
afar_reg = base + SCHIZO_PCI_AFAR;
@@ -926,12 +1007,12 @@
SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR |
SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS);
if (!error_bits)
- return;
+ return schizo_pcierr_intr_other(pbm);
schizo_write(afsr_reg, error_bits);
/* Log the error. */
- printk("SCHIZO%d: PBM-%c PCI Error, primary error type[%s]\n",
- p->index, pbm_name,
+ printk("%s: PCI Error, primary error type[%s]\n",
+ pbm->name,
(((error_bits & SCHIZO_PCIAFSR_PMA) ?
"Master Abort" :
((error_bits & SCHIZO_PCIAFSR_PTA) ?
@@ -944,8 +1025,8 @@
"Timeout" :
((error_bits & SCHIZO_PCIAFSR_PUNUS) ?
"Bus Unusable" : "???"))))))));
- printk("SCHIZO%d: PBM-%c bytemask[%04lx] was_block(%d) space(%s)\n",
- p->index, pbm_name,
+ printk("%s: bytemask[%04lx] was_block(%d) space(%s)\n",
+ pbm->name,
(afsr & SCHIZO_PCIAFSR_BMSK) >> 32UL,
(afsr & SCHIZO_PCIAFSR_BLK) ? 1 : 0,
((afsr & SCHIZO_PCIAFSR_CFG) ?
@@ -954,10 +1035,10 @@
"Memory" :
((afsr & SCHIZO_PCIAFSR_IO) ?
"I/O" : "???"))));
- printk("SCHIZO%d: PBM-%c PCI AFAR [%016lx]\n",
- p->index, pbm_name, afar);
- printk("SCHIZO%d: PBM-%c PCI Secondary errors [",
- p->index, pbm_name);
+ printk("%s: PCI AFAR [%016lx]\n",
+ pbm->name, afar);
+ printk("%s: PCI Secondary errors [",
+ pbm->name);
reported = 0;
if (afsr & SCHIZO_PCIAFSR_SMA) {
reported++;
@@ -1020,24 +1101,37 @@
#define SAFARI_ERRLOG_ERROUT 0x8000000000000000UL
-#define SAFARI_ERROR_BADCMD 0x4000000000000000UL
-#define SAFARI_ERROR_SSMDIS 0x2000000000000000UL
-#define SAFARI_ERROR_BADMA 0x1000000000000000UL
-#define SAFARI_ERROR_BADMB 0x0800000000000000UL
-#define SAFARI_ERROR_BADMC 0x0400000000000000UL
-#define SAFARI_ERROR_CPU1PS 0x0000000000002000UL
-#define SAFARI_ERROR_CPU1PB 0x0000000000001000UL
-#define SAFARI_ERROR_CPU0PS 0x0000000000000800UL
-#define SAFARI_ERROR_CPU0PB 0x0000000000000400UL
-#define SAFARI_ERROR_CIQTO 0x0000000000000200UL
-#define SAFARI_ERROR_LPQTO 0x0000000000000100UL
-#define SAFARI_ERROR_SFPQTO 0x0000000000000080UL
-#define SAFARI_ERROR_UFPQTO 0x0000000000000040UL
-#define SAFARI_ERROR_APERR 0x0000000000000020UL
-#define SAFARI_ERROR_UNMAP 0x0000000000000010UL
-#define SAFARI_ERROR_BUSERR 0x0000000000000004UL
-#define SAFARI_ERROR_TIMEOUT 0x0000000000000002UL
-#define SAFARI_ERROR_ILL 0x0000000000000001UL
+#define BUS_ERROR_BADCMD 0x4000000000000000UL /* Schizo/Tomatillo */
+#define BUS_ERROR_SSMDIS 0x2000000000000000UL /* Safari */
+#define BUS_ERROR_BADMA 0x1000000000000000UL /* Safari */
+#define BUS_ERROR_BADMB 0x0800000000000000UL /* Safari */
+#define BUS_ERROR_BADMC 0x0400000000000000UL /* Safari */
+#define BUS_ERROR_SNOOP_GR 0x0000000000200000UL /* Tomatillo */
+#define BUS_ERROR_SNOOP_PCI 0x0000000000100000UL /* Tomatillo */
+#define BUS_ERROR_SNOOP_RD 0x0000000000080000UL /* Tomatillo */
+#define BUS_ERROR_SNOOP_RDS 0x0000000000020000UL /* Tomatillo */
+#define BUS_ERROR_SNOOP_RDSA 0x0000000000010000UL /* Tomatillo */
+#define BUS_ERROR_SNOOP_OWN 0x0000000000008000UL /* Tomatillo */
+#define BUS_ERROR_SNOOP_RDO 0x0000000000004000UL /* Tomatillo */
+#define BUS_ERROR_CPU1PS 0x0000000000002000UL /* Safari */
+#define BUS_ERROR_WDATA_PERR 0x0000000000002000UL /* Tomatillo */
+#define BUS_ERROR_CPU1PB 0x0000000000001000UL /* Safari */
+#define BUS_ERROR_CTRL_PERR 0x0000000000001000UL /* Tomatillo */
+#define BUS_ERROR_CPU0PS 0x0000000000000800UL /* Safari */
+#define BUS_ERROR_SNOOP_ERR 0x0000000000000800UL /* Tomatillo */
+#define BUS_ERROR_CPU0PB 0x0000000000000400UL /* Safari */
+#define BUS_ERROR_JBUS_ILL_B 0x0000000000000400UL /* Tomatillo */
+#define BUS_ERROR_CIQTO 0x0000000000000200UL /* Safari */
+#define BUS_ERROR_LPQTO 0x0000000000000100UL /* Safari */
+#define BUS_ERROR_JBUS_ILL_C 0x0000000000000100UL /* Tomatillo */
+#define BUS_ERROR_SFPQTO 0x0000000000000080UL /* Safari */
+#define BUS_ERROR_UFPQTO 0x0000000000000040UL /* Safari */
+#define BUS_ERROR_RD_PERR 0x0000000000000040UL /* Tomatillo */
+#define BUS_ERROR_APERR 0x0000000000000020UL /* Safari/Tomatillo */
+#define BUS_ERROR_UNMAP 0x0000000000000010UL /* Safari/Tomatillo */
+#define BUS_ERROR_BUSERR 0x0000000000000004UL /* Safari/Tomatillo */
+#define BUS_ERROR_TIMEOUT 0x0000000000000002UL /* Safari/Tomatillo */
+#define BUS_ERROR_ILL 0x0000000000000001UL /* Safari */
/* We only expect UNMAP errors here. The rest of the Safari errors
* are marked fatal and thus cause a system reset.
@@ -1047,19 +1141,19 @@
struct pci_controller_info *p = dev_id;
u64 errlog;
- errlog = schizo_read(p->controller_regs + SCHIZO_SAFARI_ERRLOG);
- schizo_write(p->controller_regs + SCHIZO_SAFARI_ERRLOG,
+ errlog = schizo_read(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRLOG);
+ schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRLOG,
errlog & ~(SAFARI_ERRLOG_ERROUT));
- if (!(errlog & SAFARI_ERROR_UNMAP)) {
- printk("SCHIZO%d: Unexpected Safari error interrupt, errlog[%016lx]\n",
+ if (!(errlog & BUS_ERROR_UNMAP)) {
+ printk("PCI%d: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n",
p->index, errlog);
schizo_clear_other_err_intr(irq);
return;
}
- printk("SCHIZO%d: Safari interrupt, UNMAPPED error, interrogating IOMMUs.\n",
+ printk("PCI%d: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n",
p->index);
schizo_check_iommu_error(p, SAFARI_ERR);
@@ -1083,131 +1177,279 @@
#define SCHIZO_PCIERR_B_INO 0x33 /* PBM B PCI bus error */
#define SCHIZO_SERR_INO 0x34 /* Safari interface error */
-#define SCHIZO_PCIA_CTRL (SCHIZO_PBM_A_REGS_OFF + 0x2000UL)
-#define SCHIZO_PCIB_CTRL (SCHIZO_PBM_B_REGS_OFF + 0x2000UL)
-#define SCHIZO_PCICTRL_BUS_UNUS (1UL << 63UL)
-#define SCHIZO_PCICTRL_ESLCK (1UL << 51UL)
-#define SCHIZO_PCICTRL_ERRSLOT (7UL << 48UL)
-#define SCHIZO_PCICTRL_TTO_ERR (1UL << 38UL)
-#define SCHIZO_PCICTRL_RTRY_ERR (1UL << 37UL)
-#define SCHIZO_PCICTRL_DTO_ERR (1UL << 36UL)
-#define SCHIZO_PCICTRL_SBH_ERR (1UL << 35UL)
-#define SCHIZO_PCICTRL_SERR (1UL << 34UL)
-#define SCHIZO_PCICTRL_PCISPD (1UL << 33UL)
-#define SCHIZO_PCICTRL_PTO (3UL << 24UL)
-#define SCHIZO_PCICTRL_DTO_INT (1UL << 19UL)
-#define SCHIZO_PCICTRL_SBH_INT (1UL << 18UL)
-#define SCHIZO_PCICTRL_EEN (1UL << 17UL)
-#define SCHIZO_PCICTRL_PARK (1UL << 16UL)
-#define SCHIZO_PCICTRL_PCIRST (1UL << 8UL)
-#define SCHIZO_PCICTRL_ARB (0x3fUL << 0UL)
+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
+ * a single PCI bus unit attached to it. It would seem they are seperate
+ * devices because their PortID (ie. JBUS ID) values are all different
+ * and thus the registers are mapped to totally different locations.
+ *
+ * However, two Tomatillo's look "similar" in that the only difference
+ * in their PortID is the lowest bit.
+ *
+ * So if we were to ignore this lower bit, it certainly looks like two
+ * PCI bus units of the same Tomatillo. I still have not really
+ * figured this out...
+ */
+static void __init tomatillo_register_error_handlers(struct pci_controller_info *p)
+{
+ struct pci_pbm_info *pbm;
+ unsigned int irq;
+ struct ino_bucket *bucket;
+ 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("%s: Cannot register UE interrupt.\n",
+ pbm->name);
+ prom_halt();
+ }
+ bucket = __bucket(irq);
+ tmp = readl(bucket->imap);
+ 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("%s: Cannot register CE interrupt.\n",
+ pbm->name);
+ prom_halt();
+ }
+ bucket = __bucket(irq);
+ tmp = upa_readl(bucket->imap);
+ upa_writel(tmp, (pbm->pbm_regs +
+ schizo_imap_offset(SCHIZO_CE_INO) + 4));
+
+ 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 PBM A PciERR interrupt.\n",
+ pbm->name);
+ prom_halt();
+ }
+ bucket = __bucket(irq);
+ tmp = upa_readl(bucket->imap);
+ upa_writel(tmp, (pbm->pbm_regs +
+ schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));
+
+ 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 PBM B PciERR interrupt.\n",
+ pbm->name);
+ prom_halt();
+ }
+ bucket = __bucket(irq);
+ tmp = upa_readl(bucket->imap);
+ 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) {
+ prom_printf("%s: Cannot register SafariERR interrupt.\n",
+ pbm->name);
+ prom_halt();
+ }
+ bucket = __bucket(irq);
+ tmp = upa_readl(bucket->imap);
+ upa_writel(tmp, (pbm->pbm_regs +
+ schizo_imap_offset(SCHIZO_SERR_INO) + 4));
+
+ /* Enable UE and CE interrupts for controller. */
+ schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL,
+ (SCHIZO_ECCCTRL_EE |
+ SCHIZO_ECCCTRL_UE |
+ SCHIZO_ECCCTRL_CE));
+
+ schizo_write(p->pbm_B.controller_regs + SCHIZO_ECC_CTRL,
+ (SCHIZO_ECCCTRL_EE |
+ SCHIZO_ECCCTRL_UE |
+ SCHIZO_ECCCTRL_CE));
+
+ /* Enable PCI Error interrupts and clear error
+ * bits.
+ */
+ err_mask = (SCHIZO_PCICTRL_BUS_UNUS |
+ SCHIZO_PCICTRL_TTO_ERR |
+ SCHIZO_PCICTRL_RTRY_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 |
+ SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR |
+ SCHIZO_PCIAFSR_PTTO |
+ SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA |
+ SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR |
+ SCHIZO_PCIAFSR_STTO);
+
+ schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_AFSR, err_mask);
+ schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_AFSR, err_mask);
+
+ err_mask = (BUS_ERROR_BADCMD | BUS_ERROR_SNOOP_GR |
+ BUS_ERROR_SNOOP_PCI | BUS_ERROR_SNOOP_RD |
+ BUS_ERROR_SNOOP_RDS | BUS_ERROR_SNOOP_RDSA |
+ BUS_ERROR_SNOOP_OWN | BUS_ERROR_SNOOP_RDO |
+ BUS_ERROR_WDATA_PERR | BUS_ERROR_CTRL_PERR |
+ BUS_ERROR_SNOOP_ERR | BUS_ERROR_JBUS_ILL_B |
+ BUS_ERROR_JBUS_ILL_C | BUS_ERROR_RD_PERR |
+ BUS_ERROR_APERR | BUS_ERROR_UNMAP |
+ BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT);
+
+ schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_ERRCTRL,
+ (SCHIZO_SAFERRCTRL_EN | err_mask));
+ schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRCTRL,
+ (SCHIZO_SAFERRCTRL_EN | err_mask));
+
+ schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_IRQCTRL,
+ (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));
+ schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_IRQCTRL,
+ (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));
+}
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;
- unsigned long base = p->controller_regs;
- unsigned int irq, portid = p->portid;
+ struct pci_pbm_info *pbm;
+ unsigned int irq;
struct ino_bucket *bucket;
- u64 tmp;
+ u64 tmp, err_mask, err_no_mask;
/* Build IRQs and register handlers. */
- irq = schizo_irq_build(pbm_b, NULL, (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, (base + SCHIZO_PBM_B_REGS_OFF + 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, (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, (base + SCHIZO_PBM_B_REGS_OFF + 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, (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, (base + SCHIZO_PBM_A_REGS_OFF + 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, (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, (base + SCHIZO_PBM_B_REGS_OFF + 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, (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, (base + SCHIZO_PBM_B_REGS_OFF + 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(base + SCHIZO_ECC_CTRL,
+ schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL,
(SCHIZO_ECCCTRL_EE |
SCHIZO_ECCCTRL_UE |
SCHIZO_ECCCTRL_CE));
+ err_mask = (SCHIZO_PCICTRL_BUS_UNUS |
+ SCHIZO_PCICTRL_ESLCK |
+ SCHIZO_PCICTRL_TTO_ERR |
+ SCHIZO_PCICTRL_RTRY_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(base + SCHIZO_PCIA_CTRL);
- tmp |= (SCHIZO_PCICTRL_BUS_UNUS |
- 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);
- schizo_write(base + SCHIZO_PCIA_CTRL, tmp);
-
- tmp = schizo_read(base + SCHIZO_PCIB_CTRL);
- tmp |= (SCHIZO_PCICTRL_BUS_UNUS |
- 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);
- schizo_write(base + SCHIZO_PCIB_CTRL, tmp);
+ 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);
- schizo_write(base + SCHIZO_PBM_A_REGS_OFF + 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 |
SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA |
SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR |
SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS));
- schizo_write(base + SCHIZO_PBM_B_REGS_OFF + SCHIZO_PCI_AFSR,
+
+ 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);
+
+ 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 |
@@ -1215,9 +1457,19 @@
SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR |
SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS));
- /* Make all Safari error conditions fatal except unmapped errors
- * which we make generate interrupts.
+ /* Make all Safari error conditions fatal except unmapped
+ * errors which we make generate interrupts.
*/
+ err_mask = (BUS_ERROR_BADCMD | BUS_ERROR_SSMDIS |
+ BUS_ERROR_BADMA | BUS_ERROR_BADMB |
+ BUS_ERROR_BADMC |
+ BUS_ERROR_CPU1PS | BUS_ERROR_CPU1PB |
+ BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB |
+ BUS_ERROR_CIQTO |
+ BUS_ERROR_LPQTO | BUS_ERROR_SFPQTO |
+ BUS_ERROR_UFPQTO | BUS_ERROR_APERR |
+ BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT |
+ BUS_ERROR_ILL);
#if 1
/* XXX Something wrong with some Excalibur systems
* XXX Sun is shipping. The behavior on a 2-cpu
@@ -1226,53 +1478,26 @@
* XXX their error status bits are cleared. Just
* XXX ignore them for now. -DaveM
*/
- schizo_write(base + SCHIZO_SAFARI_ERRCTRL,
- (SCHIZO_SAFERRCTRL_EN |
- (SAFARI_ERROR_BADCMD | SAFARI_ERROR_SSMDIS |
- SAFARI_ERROR_BADMA | SAFARI_ERROR_BADMB |
- SAFARI_ERROR_BADMC |
- SAFARI_ERROR_CIQTO |
- SAFARI_ERROR_LPQTO | SAFARI_ERROR_SFPQTO |
- SAFARI_ERROR_UFPQTO | SAFARI_ERROR_APERR |
- SAFARI_ERROR_BUSERR | SAFARI_ERROR_TIMEOUT |
- SAFARI_ERROR_ILL)));
-#else
- schizo_write(base + SCHIZO_SAFARI_ERRCTRL,
- (SCHIZO_SAFERRCTRL_EN |
- (SAFARI_ERROR_BADCMD | SAFARI_ERROR_SSMDIS |
- SAFARI_ERROR_BADMA | SAFARI_ERROR_BADMB |
- SAFARI_ERROR_BADMC |
- SAFARI_ERROR_CPU1PS | SAFARI_ERROR_CPU1PB |
- SAFARI_ERROR_CPU0PS | SAFARI_ERROR_CPU0PB |
- SAFARI_ERROR_CIQTO |
- SAFARI_ERROR_LPQTO | SAFARI_ERROR_SFPQTO |
- SAFARI_ERROR_UFPQTO | SAFARI_ERROR_APERR |
- SAFARI_ERROR_BUSERR | SAFARI_ERROR_TIMEOUT |
- SAFARI_ERROR_ILL)));
+ err_mask &= ~(BUS_ERROR_CPU1PS | BUS_ERROR_CPU1PB |
+ BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB);
#endif
- schizo_write(base + SCHIZO_SAFARI_IRQCTRL,
- (SCHIZO_SAFIRQCTRL_EN | (SAFARI_ERROR_UNMAP)));
+ schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_ERRCTRL,
+ (SCHIZO_SAFERRCTRL_EN | err_mask));
+
+ schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_IRQCTRL,
+ (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));
}
/* We have to do the config space accesses by hand, thus... */
-#define PBM_BRIDGE_BUS 0x40
-#define PBM_BRIDGE_SUBORDINATE 0x41
static void __init pbm_renumber(struct pci_pbm_info *pbm, u8 orig_busno)
{
- u8 *addr, busno;
+ u8 busno;
int nbus;
busno = pci_highest_busnum;
nbus = pbm->pci_last_busno - pbm->pci_first_busno;
- addr = schizo_pci_config_mkaddr(pbm, orig_busno,
- 0, PBM_BRIDGE_BUS);
- pci_config_write8(addr, busno);
- addr = schizo_pci_config_mkaddr(pbm, busno,
- 0, PBM_BRIDGE_SUBORDINATE);
- pci_config_write8(addr, busno + nbus);
-
pbm->pci_first_busno = busno;
pbm->pci_last_busno = busno + nbus;
pci_highest_busnum = busno + nbus + 1;
@@ -1282,75 +1507,8 @@
} while (nbus--);
}
-/* We have to do the config space accesses by hand here since
- * the pci_bus2pbm array is not ready yet.
- */
-static void __init pbm_pci_bridge_renumber(struct pci_pbm_info *pbm,
- u8 busno)
-{
- u32 devfn, l, class;
- u8 hdr_type;
- int is_multi = 0;
-
- for(devfn = 0; devfn < 0xff; ++devfn) {
- u32 *dwaddr;
- u8 *baddr;
-
- if (PCI_FUNC(devfn) != 0 && is_multi == 0)
- continue;
-
- /* Anything there? */
- dwaddr = schizo_pci_config_mkaddr(pbm, busno, devfn, PCI_VENDOR_ID);
- l = 0xffffffff;
- pci_config_read32(dwaddr, &l);
- if (l == 0xffffffff || l == 0x00000000 ||
- l == 0x0000ffff || l == 0xffff0000) {
- is_multi = 0;
- continue;
- }
-
- baddr = schizo_pci_config_mkaddr(pbm, busno, devfn, PCI_HEADER_TYPE);
- pci_config_read8(baddr, &hdr_type);
- if (PCI_FUNC(devfn) == 0)
- is_multi = hdr_type & 0x80;
-
- dwaddr = schizo_pci_config_mkaddr(pbm, busno, devfn, PCI_CLASS_REVISION);
- class = 0xffffffff;
- pci_config_read32(dwaddr, &class);
- if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) {
- u32 buses = 0xffffffff;
-
- dwaddr = schizo_pci_config_mkaddr(pbm, busno, devfn,
- PCI_PRIMARY_BUS);
- pci_config_read32(dwaddr, &buses);
- pbm_pci_bridge_renumber(pbm, (buses >> 8) & 0xff);
- buses &= 0xff000000;
- pci_config_write32(dwaddr, buses);
- }
- }
-}
-
static void __init pbm_bridge_reconfigure(struct pci_controller_info *p)
{
- struct pci_pbm_info *pbm;
- u8 *addr;
-
- /* Clear out primary/secondary/subordinate bus numbers on
- * all PCI-to-PCI bridges under each PBM. The generic bus
- * probing will fix them up.
- */
- pbm_pci_bridge_renumber(&p->pbm_B, p->pbm_B.pci_first_busno);
- pbm_pci_bridge_renumber(&p->pbm_A, p->pbm_A.pci_first_busno);
-
- /* Move PBM A out of the way. */
- pbm = &p->pbm_A;
- addr = schizo_pci_config_mkaddr(pbm, pbm->pci_first_busno,
- 0, PBM_BRIDGE_BUS);
- pci_config_write8(addr, 0xff);
- addr = schizo_pci_config_mkaddr(pbm, 0xff,
- 0, PBM_BRIDGE_SUBORDINATE);
- pci_config_write8(addr, 0xff);
-
/* Now we can safely renumber both PBMs. */
pbm_renumber(&p->pbm_B, p->pbm_B.pci_first_busno);
pbm_renumber(&p->pbm_A, 0xff);
@@ -1379,7 +1537,7 @@
struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL);
if (!cookie) {
- prom_printf("SCHIZO: Critical allocation failure.\n");
+ prom_printf("%s: Critical allocation failure.\n", pbm->name);
prom_halt();
}
@@ -1401,20 +1559,42 @@
pci_setup_busmastering(pbm, pbm->pci_bus);
}
-static void __init schizo_scan_bus(struct pci_controller_info *p)
+static void __init __schizo_scan_bus(struct pci_controller_info *p,
+ int chip_type)
{
+ if (!p->pbm_B.prom_node || !p->pbm_A.prom_node) {
+ printk("PCI: Only one PCI bus module of controller found.\n");
+ printk("PCI: Ignoring entire controller.\n");
+ return;
+ }
+
pbm_bridge_reconfigure(p);
pbm_config_busmastering(&p->pbm_B);
- p->pbm_B.is_66mhz_capable = 0;
+ p->pbm_B.is_66mhz_capable =
+ prom_getbool(p->pbm_B.prom_node, "66mhz-capable");
pbm_config_busmastering(&p->pbm_A);
- p->pbm_A.is_66mhz_capable = 1;
+ p->pbm_A.is_66mhz_capable =
+ prom_getbool(p->pbm_A.prom_node, "66mhz-capable");
pbm_scan_bus(p, &p->pbm_B);
pbm_scan_bus(p, &p->pbm_A);
/* After the PCI bus scan is complete, we can register
* the error interrupt handlers.
*/
- schizo_register_error_handlers(p);
+ if (chip_type == PBM_CHIP_TYPE_TOMATILLO)
+ tomatillo_register_error_handlers(p);
+ else
+ schizo_register_error_handlers(p);
+}
+
+static void __init schizo_scan_bus(struct pci_controller_info *p)
+{
+ __schizo_scan_bus(p, PBM_CHIP_TYPE_SCHIZO);
+}
+
+static void __init tomatillo_scan_bus(struct pci_controller_info *p)
+{
+ __schizo_scan_bus(p, PBM_CHIP_TYPE_TOMATILLO);
}
static void __init schizo_base_address_update(struct pci_dev *pdev, int resource)
@@ -1470,68 +1650,72 @@
res->end += root->start;
}
-/* Interrogate Safari match/mask registers to figure out where
- * PCI MEM, I/O, and Config space are for this PCI bus module.
+/* Use ranges property to determine where PCI MEM, I/O, and Config
+ * space are for this PCI bus module.
*/
+static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm)
+{
+ int i, saw_cfg, saw_mem, saw_io;
-#define SCHIZO_PCI_A_MEM_MATCH 0x00040UL
-#define SCHIZO_PCI_A_MEM_MASK 0x00048UL
-#define SCHIZO_PCI_A_IO_MATCH 0x00050UL
-#define SCHIZO_PCI_A_IO_MASK 0x00058UL
-#define SCHIZO_PCI_B_MEM_MATCH 0x00060UL
-#define SCHIZO_PCI_B_MEM_MASK 0x00068UL
-#define SCHIZO_PCI_B_IO_MATCH 0x00070UL
-#define SCHIZO_PCI_B_IO_MASK 0x00078UL
-
-static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm,
- int is_pbm_a, unsigned long reg_base)
-{
- u64 mem_match, mem_mask;
- u64 io_match;
- u64 a;
-
- if (is_pbm_a) {
- mem_match = reg_base + SCHIZO_PCI_A_MEM_MATCH;
- io_match = reg_base + SCHIZO_PCI_A_IO_MATCH;
- } else {
- mem_match = reg_base + SCHIZO_PCI_B_MEM_MATCH;
- io_match = reg_base + SCHIZO_PCI_B_IO_MATCH;
- }
- mem_mask = mem_match + 0x8UL;
+ saw_cfg = saw_mem = saw_io = 0;
+ for (i = 0; i < pbm->num_pbm_ranges; i++) {
+ struct linux_prom_pci_ranges *pr = &pbm->pbm_ranges[i];
+ unsigned long a;
+ int type;
- a = schizo_read(mem_match) & ~0x8000000000000000UL;
+ type = (pr->child_phys_hi >> 24) & 0x3;
+ a = (((unsigned long)pr->parent_phys_hi << 32UL) |
+ ((unsigned long)pr->parent_phys_lo << 0UL));
- /* It should be 2GB in size but the decode is set for the full
- * 4GB so we have to add the 2G by hand.
- */
- pbm->mem_space.start = a;
- pbm->mem_space.end = a + 0x80000000;
- pbm->mem_space.flags = IORESOURCE_MEM;
+ switch (type) {
+ case 0:
+ /* PCI config space, 16MB */
+ pbm->config_space = a;
+ saw_cfg = 1;
+ break;
- /* This 32MB area is divided into two pieces. The first
- * 16MB is Config space, the next 16MB is I/O space.
- */
+ case 1:
+ /* 16-bit IO space, 16MB */
+ pbm->io_space.start = a;
+ pbm->io_space.end = a + ((16UL*1024UL*1024UL) - 1UL);
+ pbm->io_space.flags = IORESOURCE_IO;
+ saw_io = 1;
+ break;
- a = schizo_read(io_match) & ~0x8000000000000000UL;
- pbm->config_space = a;
- printk("SCHIZO PBM%c: Local PCI config space at %016lx\n",
- (is_pbm_a ? 'A' : 'B'), pbm->config_space);
+ case 2:
+ /* 32-bit MEM space, 2GB */
+ pbm->mem_space.start = a;
+ pbm->mem_space.end = a + (0x80000000UL - 1UL);
+ pbm->mem_space.flags = IORESOURCE_MEM;
+ saw_mem = 1;
+ break;
+
+ default:
+ break;
+ };
+ }
- a += (16UL * 1024UL * 1024UL);
- pbm->io_space.start = a;
- pbm->io_space.end = a + ((16UL * 1024UL * 1024UL) - 1UL);
- pbm->io_space.flags = IORESOURCE_IO;
+ if (!saw_cfg || !saw_io || !saw_mem) {
+ prom_printf("%s: Fatal error, missing %s PBM range.\n",
+ pbm->name,
+ ((!saw_cfg ?
+ "CFG" :
+ (!saw_io ?
+ "IO" : "MEM"))));
+ prom_halt();
+ }
+
+ printk("%s: PCI CFG[%lx] IO[%lx] MEM[%lx]\n",
+ pbm->name,
+ pbm->config_space,
+ pbm->io_space.start,
+ pbm->mem_space.start);
}
static void __init pbm_register_toplevel_resources(struct pci_controller_info *p,
struct pci_pbm_info *pbm)
{
- char *name = pbm->name;
-
- sprintf(name, "SCHIZO%d PBM%c",
- p->index,
- (pbm == &p->pbm_A ? 'A' : 'B'));
- pbm->io_space.name = pbm->mem_space.name = name;
+ pbm->io_space.name = pbm->mem_space.name = pbm->name;
request_resource(&ioport_resource, &pbm->io_space);
request_resource(&iomem_resource, &pbm->mem_space);
@@ -1539,40 +1723,29 @@
&pbm->mem_space);
}
-#define SCHIZO_STRBUF_CONTROL_A (SCHIZO_PBM_A_REGS_OFF + 0x02800UL)
-#define SCHIZO_STRBUF_FLUSH_A (SCHIZO_PBM_A_REGS_OFF + 0x02808UL)
-#define SCHIZO_STRBUF_FSYNC_A (SCHIZO_PBM_A_REGS_OFF + 0x02810UL)
-#define SCHIZO_STRBUF_CTXFLUSH_A (SCHIZO_PBM_A_REGS_OFF + 0x02818UL)
-#define SCHIZO_STRBUF_CTXMATCH_A (SCHIZO_PBM_A_REGS_OFF + 0x10000UL)
-
-#define SCHIZO_STRBUF_CONTROL_B (SCHIZO_PBM_B_REGS_OFF + 0x02800UL)
-#define SCHIZO_STRBUF_FLUSH_B (SCHIZO_PBM_B_REGS_OFF + 0x02808UL)
-#define SCHIZO_STRBUF_FSYNC_B (SCHIZO_PBM_B_REGS_OFF + 0x02810UL)
-#define SCHIZO_STRBUF_CTXFLUSH_B (SCHIZO_PBM_B_REGS_OFF + 0x02818UL)
-#define SCHIZO_STRBUF_CTXMATCH_B (SCHIZO_PBM_B_REGS_OFF + 0x10000UL)
-
-static void schizo_pbm_strbuf_init(struct pci_controller_info *p,
- struct pci_pbm_info *pbm,
- int is_pbm_a)
+#define SCHIZO_STRBUF_CONTROL (0x02800UL)
+#define SCHIZO_STRBUF_FLUSH (0x02808UL)
+#define SCHIZO_STRBUF_FSYNC (0x02810UL)
+#define SCHIZO_STRBUF_CTXFLUSH (0x02818UL)
+#define SCHIZO_STRBUF_CTXMATCH (0x10000UL)
+
+static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm)
{
- unsigned long base = p->controller_regs;
+ unsigned long base = pbm->pbm_regs;
u64 control;
- /* SCHIZO has context flushing. */
- if (is_pbm_a) {
- pbm->stc.strbuf_control = base + SCHIZO_STRBUF_CONTROL_A;
- pbm->stc.strbuf_pflush = base + SCHIZO_STRBUF_FLUSH_A;
- pbm->stc.strbuf_fsync = base + SCHIZO_STRBUF_FSYNC_A;
- pbm->stc.strbuf_ctxflush = base + SCHIZO_STRBUF_CTXFLUSH_A;
- pbm->stc.strbuf_ctxmatch_base = base + SCHIZO_STRBUF_CTXMATCH_A;
- } else {
- pbm->stc.strbuf_control = base + SCHIZO_STRBUF_CONTROL_B;
- pbm->stc.strbuf_pflush = base + SCHIZO_STRBUF_FLUSH_B;
- pbm->stc.strbuf_fsync = base + SCHIZO_STRBUF_FSYNC_B;
- pbm->stc.strbuf_ctxflush = base + SCHIZO_STRBUF_CTXFLUSH_B;
- pbm->stc.strbuf_ctxmatch_base = base + SCHIZO_STRBUF_CTXMATCH_B;
+ if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {
+ /* TOMATILLO lacks streaming cache. */
+ return;
}
+ /* SCHIZO has context flushing. */
+ pbm->stc.strbuf_control = base + SCHIZO_STRBUF_CONTROL;
+ pbm->stc.strbuf_pflush = base + SCHIZO_STRBUF_FLUSH;
+ pbm->stc.strbuf_fsync = base + SCHIZO_STRBUF_FSYNC;
+ pbm->stc.strbuf_ctxflush = base + SCHIZO_STRBUF_CTXFLUSH;
+ pbm->stc.strbuf_ctxmatch_base = base + SCHIZO_STRBUF_CTXMATCH;
+
pbm->stc.strbuf_flushflag = (volatile unsigned long *)
((((unsigned long)&pbm->stc.__flushflag_buf[0])
+ 63UL)
@@ -1594,48 +1767,63 @@
pbm->stc.strbuf_enabled = 1;
}
-#define SCHIZO_IOMMU_CONTROL_A (SCHIZO_PBM_A_REGS_OFF + 0x00200UL)
-#define SCHIZO_IOMMU_TSBBASE_A (SCHIZO_PBM_A_REGS_OFF + 0x00208UL)
-#define SCHIZO_IOMMU_FLUSH_A (SCHIZO_PBM_A_REGS_OFF + 0x00210UL)
-#define SCHIZO_IOMMU_CTXFLUSH_A (SCHIZO_PBM_A_REGS_OFF + 0x00218UL)
-#define SCHIZO_IOMMU_TAG_A (SCHIZO_PBM_A_REGS_OFF + 0x0a580UL)
-#define SCHIZO_IOMMU_DATA_A (SCHIZO_PBM_A_REGS_OFF + 0x0a600UL)
-#define SCHIZO_IOMMU_CONTROL_B (SCHIZO_PBM_B_REGS_OFF + 0x00200UL)
-#define SCHIZO_IOMMU_TSBBASE_B (SCHIZO_PBM_B_REGS_OFF + 0x00208UL)
-#define SCHIZO_IOMMU_FLUSH_B (SCHIZO_PBM_B_REGS_OFF + 0x00210UL)
-#define SCHIZO_IOMMU_CTXFLUSH_B (SCHIZO_PBM_B_REGS_OFF + 0x00218UL)
-#define SCHIZO_IOMMU_TAG_B (SCHIZO_PBM_B_REGS_OFF + 0x0a580UL)
-#define SCHIZO_IOMMU_DATA_B (SCHIZO_PBM_B_REGS_OFF + 0x0a600UL)
-
-static void schizo_pbm_iommu_init(struct pci_controller_info *p,
- struct pci_pbm_info *pbm,
- int is_pbm_a)
+#define SCHIZO_IOMMU_CONTROL (0x00200UL)
+#define SCHIZO_IOMMU_TSBBASE (0x00208UL)
+#define SCHIZO_IOMMU_FLUSH (0x00210UL)
+#define SCHIZO_IOMMU_CTXFLUSH (0x00218UL)
+
+static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
{
struct pci_iommu *iommu = pbm->iommu;
- unsigned long tsbbase, i, tagbase, database;
+ unsigned long tsbbase, i, tagbase, database, order;
+ u32 vdma[2], dma_mask;
u64 control;
+ int err, tsbsize;
+
+ err = prom_getproperty(pbm->prom_node, "virtual-dma",
+ (char *)&vdma[0], sizeof(vdma));
+ if (err == 0 || err == -1) {
+ /* No property, use default values. */
+ vdma[0] = 0xc0000000;
+ vdma[1] = 0x40000000;
+ }
+
+ dma_mask = vdma[0];
+ switch (vdma[1]) {
+ case 0x20000000:
+ dma_mask |= 0x1fffffff;
+ tsbsize = 64;
+ break;
+
+ case 0x40000000:
+ dma_mask |= 0x3fffffff;
+ tsbsize = 128;
+ break;
+
+ case 0x80000000:
+ dma_mask |= 0x7fffffff;
+ tsbsize = 128;
+ break;
+
+ default:
+ prom_printf("SCHIZO: strange virtual-dma size.\n");
+ prom_halt();
+ };
/* Setup initial software IOMMU state. */
spin_lock_init(&iommu->lock);
iommu->iommu_cur_ctx = 0;
/* Register addresses, SCHIZO has iommu ctx flushing. */
- if (is_pbm_a) {
- iommu->iommu_control = p->controller_regs + SCHIZO_IOMMU_CONTROL_A;
- iommu->iommu_tsbbase = p->controller_regs + SCHIZO_IOMMU_TSBBASE_A;
- iommu->iommu_flush = p->controller_regs + SCHIZO_IOMMU_FLUSH_A;
- iommu->iommu_ctxflush = p->controller_regs + SCHIZO_IOMMU_CTXFLUSH_A;
- } else {
- iommu->iommu_control = p->controller_regs + SCHIZO_IOMMU_CONTROL_B;
- iommu->iommu_tsbbase = p->controller_regs + SCHIZO_IOMMU_TSBBASE_B;
- iommu->iommu_flush = p->controller_regs + SCHIZO_IOMMU_FLUSH_B;
- iommu->iommu_ctxflush = p->controller_regs + SCHIZO_IOMMU_CTXFLUSH_B;
- }
+ iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL;
+ iommu->iommu_tsbbase = pbm->pbm_regs + SCHIZO_IOMMU_TSBBASE;
+ iommu->iommu_flush = pbm->pbm_regs + SCHIZO_IOMMU_FLUSH;
+ iommu->iommu_ctxflush = pbm->pbm_regs + SCHIZO_IOMMU_CTXFLUSH;
/* We use the main control/status register of SCHIZO as the write
* completion register.
*/
- iommu->write_complete_reg = p->controller_regs + 0x10000UL;
+ iommu->write_complete_reg = pbm->controller_regs + 0x10000UL;
/*
* Invalidate TLB Entries.
@@ -1644,13 +1832,11 @@
control |= SCHIZO_IOMMU_CTRL_DENAB;
schizo_write(iommu->iommu_control, control);
- if (is_pbm_a)
- tagbase = SCHIZO_IOMMU_TAG_A, database = SCHIZO_IOMMU_DATA_A;
- else
- tagbase = SCHIZO_IOMMU_TAG_B, database = SCHIZO_IOMMU_DATA_B;
+ tagbase = SCHIZO_IOMMU_TAG, database = SCHIZO_IOMMU_DATA;
+
for(i = 0; i < 16; i++) {
- schizo_write(p->controller_regs + tagbase + (i * 8UL), 0);
- schizo_write(p->controller_regs + database + (i * 8UL), 0);
+ schizo_write(pbm->pbm_regs + tagbase + (i * 8UL), 0);
+ schizo_write(pbm->pbm_regs + database + (i * 8UL), 0);
}
/* Leave diag mode enabled for full-flushing done
@@ -1661,16 +1847,32 @@
* table (128K ioptes * 8 bytes per iopte). This is
* page order 7 on UltraSparc.
*/
- tsbbase = __get_free_pages(GFP_KERNEL, get_order(IO_TSB_SIZE));
+ order = get_order(tsbsize * 8 * 1024);
+ tsbbase = __get_free_pages(GFP_KERNEL, order);
if (!tsbbase) {
- prom_printf("SCHIZO_IOMMU: Error, gfp(tsb) failed.\n");
+ prom_printf("%s: Error, gfp(tsb) failed.\n", pbm->name);
prom_halt();
}
+
iommu->page_table = (iopte_t *)tsbbase;
- iommu->page_table_sz_bits = 17;
- iommu->page_table_map_base = 0xc0000000;
- iommu->dma_addr_mask = 0xffffffff;
- memset((char *)tsbbase, 0, IO_TSB_SIZE);
+ iommu->page_table_map_base = vdma[0];
+ iommu->dma_addr_mask = dma_mask;
+ memset((char *)tsbbase, 0, PAGE_SIZE << order);
+
+ switch (tsbsize) {
+ case 64:
+ iommu->page_table_sz_bits = 16;
+ break;
+
+ case 128:
+ iommu->page_table_sz_bits = 17;
+ break;
+
+ default:
+ prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize);
+ prom_halt();
+ break;
+ };
/* We start with no consistent mappings. */
iommu->lowest_consistent_map =
@@ -1685,28 +1887,194 @@
control = schizo_read(iommu->iommu_control);
control &= ~(SCHIZO_IOMMU_CTRL_TSBSZ | SCHIZO_IOMMU_CTRL_TBWSZ);
- control |= (SCHIZO_IOMMU_TSBSZ_128K | SCHIZO_IOMMU_CTRL_ENAB);
+ switch (tsbsize) {
+ case 64:
+ control |= SCHIZO_IOMMU_TSBSZ_64K;
+ break;
+ case 128:
+ control |= SCHIZO_IOMMU_TSBSZ_128K;
+ break;
+ };
+
+ control |= SCHIZO_IOMMU_CTRL_ENAB;
schizo_write(iommu->iommu_control, control);
}
-static void schizo_pbm_init(struct pci_controller_info *p,
- int prom_node, int is_pbm_a)
+#define SCHIZO_PCI_IRQ_RETRY (0x1a00UL)
+#define SCHIZO_IRQ_RETRY_INF 0xffUL
+
+#define SCHIZO_PCI_DIAG (0x2020UL)
+#define SCHIZO_PCIDIAG_D_BADECC (1UL << 10UL) /* Disable BAD ECC errors (Schizo) */
+#define SCHIZO_PCIDIAG_D_BYPASS (1UL << 9UL) /* Disable MMU bypass mode (Schizo/Tomatillo) */
+#define SCHIZO_PCIDIAG_D_TTO (1UL << 8UL) /* Disable TTO errors (Schizo/Tomatillo) */
+#define SCHIZO_PCIDIAG_D_RTRYARB (1UL << 7UL) /* Disable retry arbitration (Schizo) */
+#define SCHIZO_PCIDIAG_D_RETRY (1UL << 6UL) /* Disable retry limit (Schizo/Tomatillo) */
+#define SCHIZO_PCIDIAG_D_INTSYNC (1UL << 5UL) /* Disable interrupt/DMA synch (Schizo/Tomatillo) */
+#define SCHIZO_PCIDIAG_I_DMA_PARITY (1UL << 3UL) /* Invert DMA parity (Schizo/Tomatillo) */
+#define SCHIZO_PCIDIAG_I_PIOD_PARITY (1UL << 2UL) /* Invert PIO data parity (Schizo/Tomatillo) */
+#define SCHIZO_PCIDIAG_I_PIOA_PARITY (1UL << 1UL) /* Invert PIO address parity (Schizo/Tomatillo) */
+
+#define TOMATILLO_PCI_IOC_CSR (0x2248UL)
+#define TOMATILLO_IOC_PART_WPENAB 0x0000000000080000UL
+#define TOMATILLO_IOC_RDMULT_PENAB 0x0000000000040000UL
+#define TOMATILLO_IOC_RDONE_PENAB 0x0000000000020000UL
+#define TOMATILLO_IOC_RDLINE_PENAB 0x0000000000010000UL
+#define TOMATILLO_IOC_RDMULT_PLEN 0x000000000000c000UL
+#define TOMATILLO_IOC_RDMULT_PLEN_SHIFT 14UL
+#define TOMATILLO_IOC_RDONE_PLEN 0x0000000000003000UL
+#define TOMATILLO_IOC_RDONE_PLEN_SHIFT 12UL
+#define TOMATILLO_IOC_RDLINE_PLEN 0x0000000000000c00UL
+#define TOMATILLO_IOC_RDLINE_PLEN_SHIFT 10UL
+#define TOMATILLO_IOC_PREF_OFF 0x00000000000003f8UL
+#define TOMATILLO_IOC_PREF_OFF_SHIFT 3UL
+#define TOMATILLO_IOC_RDMULT_CPENAB 0x0000000000000004UL
+#define TOMATILLO_IOC_RDONE_CPENAB 0x0000000000000002UL
+#define TOMATILLO_IOC_RDLINE_CPENAB 0x0000000000000001UL
+
+#define TOMATILLO_PCI_IOC_TDIAG (0x2250UL)
+#define TOMATILLO_PCI_IOC_DDIAG (0x2290UL)
+
+static void __init schizo_pbm_hw_init(struct pci_pbm_info *pbm)
{
+ u64 tmp;
+
+ /* Set IRQ retry to infinity. */
+ schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY,
+ SCHIZO_IRQ_RETRY_INF);
+
+ /* Enable arbiter for all PCI slots. Also, disable PCI interval
+ * timer so that DTO (Discard TimeOuts) are not reported because
+ * some Schizo revisions report them erroneously.
+ */
+ tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL);
+ if (pbm->chip_type == PBM_CHIP_TYPE_SCHIZO_PLUS &&
+ pbm->chip_version == 0x5 &&
+ pbm->chip_revision == 0x1)
+ tmp |= 0x0f;
+ else
+ tmp |= 0xff;
+
+ tmp &= ~SCHIZO_PCICTRL_PTO;
+ if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO &&
+ 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;
+
+ if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO)
+ tmp |= SCHIZO_PCICTRL_MRM_PREF;
+
+ schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp);
+
+ tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_DIAG);
+ tmp &= ~(SCHIZO_PCIDIAG_D_RTRYARB |
+ SCHIZO_PCIDIAG_D_RETRY |
+ SCHIZO_PCIDIAG_D_INTSYNC);
+ schizo_write(pbm->pbm_regs + SCHIZO_PCI_DIAG, tmp);
+
+ if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {
+ /* Clear prefetch lengths to workaround a bug in
+ * Jalapeno...
+ */
+ tmp = (TOMATILLO_IOC_PART_WPENAB |
+ (1 << TOMATILLO_IOC_PREF_OFF_SHIFT) |
+ TOMATILLO_IOC_RDMULT_CPENAB |
+ TOMATILLO_IOC_RDONE_CPENAB |
+ TOMATILLO_IOC_RDLINE_CPENAB);
+
+ schizo_write(pbm->pbm_regs + TOMATILLO_PCI_IOC_CSR,
+ tmp);
+ }
+}
+
+static void __init schizo_pbm_init(struct pci_controller_info *p,
+ int prom_node, u32 portid,
+ int chip_type)
+{
+ struct linux_prom64_registers pr_regs[4];
unsigned int busrange[2];
struct pci_pbm_info *pbm;
+ const char *chipset_name;
+ u32 ino_bitmap[2];
+ int is_pbm_a;
int err;
+ switch (chip_type) {
+ case PBM_CHIP_TYPE_TOMATILLO:
+ chipset_name = "TOMATILLO";
+ break;
+
+ case PBM_CHIP_TYPE_SCHIZO_PLUS:
+ chipset_name = "SCHIZO+";
+ break;
+
+ case PBM_CHIP_TYPE_SCHIZO:
+ default:
+ chipset_name = "SCHIZO";
+ break;
+ };
+
+ /* For SCHIZO, three OBP regs:
+ * 1) PBM controller regs
+ * 2) Schizo front-end controller regs (same for both PBMs)
+ * 3) PBM PCI config space
+ *
+ * For TOMATILLO, four OBP regs:
+ * 1) PBM controller regs
+ * 2) Tomatillo front-end controller regs
+ * 3) PBM PCI config space
+ * 4) Ichip regs
+ */
+ err = prom_getproperty(prom_node, "reg",
+ (char *)&pr_regs[0],
+ sizeof(pr_regs));
+ if (err == 0 || err == -1) {
+ prom_printf("%s: Fatal error, no reg property.\n",
+ chipset_name);
+ prom_halt();
+ }
+
+ is_pbm_a = ((pr_regs[0].phys_addr & 0x00700000) == 0x00600000);
+
if (is_pbm_a)
pbm = &p->pbm_A;
else
pbm = &p->pbm_B;
- schizo_determine_mem_io_space(pbm, is_pbm_a, p->controller_regs);
- pbm_register_toplevel_resources(p, pbm);
-
+ pbm->portid = portid;
pbm->parent = p;
pbm->prom_node = prom_node;
pbm->pci_first_slot = 1;
+
+ pbm->chip_type = chip_type;
+ pbm->chip_version =
+ prom_getintdefault(prom_node, "version#", 0);
+ pbm->chip_revision =
+ prom_getintdefault(prom_node, "module-revision#", 0);
+
+ pbm->pbm_regs = pr_regs[0].phys_addr;
+ pbm->controller_regs = pr_regs[1].phys_addr - 0x10000UL;
+
+ sprintf(pbm->name,
+ (chip_type == PBM_CHIP_TYPE_TOMATILLO ?
+ "TOMATILLO%d PBM%c" :
+ "SCHIZO%d PBM%c"),
+ p->index,
+ (pbm == &p->pbm_A ? 'A' : 'B'));
+
+ printk("%s: ver[%x:%x], portid %x, "
+ "cregs[%lx] pregs[%lx]\n",
+ pbm->name,
+ pbm->chip_version, pbm->chip_revision,
+ pbm->portid,
+ pbm->controller_regs,
+ pbm->pbm_regs);
+
+ schizo_pbm_hw_init(pbm);
+
prom_getstring(prom_node, "name",
pbm->prom_name,
sizeof(pbm->prom_name));
@@ -1714,11 +2082,17 @@
err = prom_getproperty(prom_node, "ranges",
(char *) pbm->pbm_ranges,
sizeof(pbm->pbm_ranges));
- if (err != -1)
- pbm->num_pbm_ranges =
- (err / sizeof(struct linux_prom_pci_ranges));
- else
- pbm->num_pbm_ranges = 0;
+ if (err == 0 || err == -1) {
+ prom_printf("%s: Fatal error, no ranges property.\n",
+ pbm->name);
+ prom_halt();
+ }
+
+ pbm->num_pbm_ranges =
+ (err / sizeof(struct linux_prom_pci_ranges));
+
+ schizo_determine_mem_io_space(pbm);
+ pbm_register_toplevel_resources(p, pbm);
err = prom_getproperty(prom_node, "interrupt-map",
(char *)pbm->pbm_intmap,
@@ -1729,8 +2103,8 @@
(char *)&pbm->pbm_intmask,
sizeof(pbm->pbm_intmask));
if (err == -1) {
- prom_printf("SCHIZO-PBM: Fatal error, no "
- "interrupt-map-mask.\n");
+ prom_printf("%s: Fatal error, no "
+ "interrupt-map-mask.\n", pbm->name);
prom_halt();
}
} else {
@@ -1738,95 +2112,65 @@
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));
if (err == 0 || err == -1) {
- prom_printf("SCHIZO-PBM: Fatal error, no bus-range.\n");
+ prom_printf("%s: Fatal error, no bus-range.\n", pbm->name);
prom_halt();
}
pbm->pci_first_busno = busrange[0];
pbm->pci_last_busno = busrange[1];
- schizo_pbm_iommu_init(p, pbm, is_pbm_a);
- schizo_pbm_strbuf_init(p, pbm, is_pbm_a);
+ schizo_pbm_iommu_init(pbm);
+ schizo_pbm_strbuf_init(pbm);
}
-#define SCHIZO_PCIA_IRQ_RETRY (SCHIZO_PBM_A_REGS_OFF + 0x1a00UL)
-#define SCHIZO_PCIB_IRQ_RETRY (SCHIZO_PBM_B_REGS_OFF + 0x1a00UL)
-#define SCHIZO_IRQ_RETRY_INF 0xffUL
-
-#define SCHIZO_PCIA_DIAG (SCHIZO_PBM_A_REGS_OFF + 0x2020UL)
-#define SCHIZO_PCIB_DIAG (SCHIZO_PBM_B_REGS_OFF + 0x2020UL)
-#define SCHIZO_PCIDIAG_D_BADECC (1UL << 10UL) /* Disable BAD ECC errors */
-#define SCHIZO_PCIDIAG_D_BYPASS (1UL << 9UL) /* Disable MMU bypass mode */
-#define SCHIZO_PCIDIAG_D_TTO (1UL << 8UL) /* Disable TTO errors */
-#define SCHIZO_PCIDIAG_D_RTRYARB (1UL << 7UL) /* Disable retry arbitration */
-#define SCHIZO_PCIDIAG_D_RETRY (1UL << 6UL) /* Disable retry limit */
-#define SCHIZO_PCIDIAG_D_INTSYNC (1UL << 5UL) /* Disable interrupt/DMA synch */
-#define SCHIZO_PCIDIAG_I_DMA_PARITY (1UL << 3UL) /* Invert DMA parity */
-#define SCHIZO_PCIDIAG_I_PIOD_PARITY (1UL << 2UL) /* Invert PIO data parity */
-#define SCHIZO_PCIDIAG_I_PIOA_PARITY (1UL << 1U)L /* Invert PIO address parity */
-
-static void schizo_controller_hwinit(struct pci_controller_info *p)
+static inline int portid_compare(u32 x, u32 y, int chip_type)
{
- unsigned long pbm_a_base, pbm_b_base;
- u64 tmp;
-
- pbm_a_base = p->controller_regs + SCHIZO_PBM_A_REGS_OFF;
- pbm_b_base = p->controller_regs + SCHIZO_PBM_B_REGS_OFF;
-
- /* Set IRQ retry to infinity. */
- schizo_write(p->controller_regs + SCHIZO_PCIA_IRQ_RETRY,
- SCHIZO_IRQ_RETRY_INF);
- schizo_write(p->controller_regs + SCHIZO_PCIB_IRQ_RETRY,
- SCHIZO_IRQ_RETRY_INF);
-
- /* Enable arbiter for all PCI slots. Also, disable PCI interval
- * timer so that DTO (Discard TimeOuts) are not reported because
- * some Schizo revisions report them erroneously.
- */
-
- tmp = schizo_read(p->controller_regs + SCHIZO_PCIA_CTRL);
- tmp |= SCHIZO_PCICTRL_ARB;
- tmp &= ~SCHIZO_PCICTRL_PTO;
- schizo_write(p->controller_regs + SCHIZO_PCIA_CTRL, tmp);
-
- tmp = schizo_read(p->controller_regs + SCHIZO_PCIB_CTRL);
- tmp |= SCHIZO_PCICTRL_ARB;
- tmp &= ~SCHIZO_PCICTRL_PTO;
- schizo_write(p->controller_regs + SCHIZO_PCIB_CTRL, tmp);
-
- /* Disable TTO error reporting (won't happen anyway since we
- * disabled the PCI interval timer above) and retry arbitration
- * (can cause hangs in some Schizo revisions).
- */
- tmp = schizo_read(p->controller_regs + SCHIZO_PCIA_DIAG);
- tmp |= (SCHIZO_PCIDIAG_D_TTO | SCHIZO_PCIDIAG_D_RTRYARB);
- schizo_write(p->controller_regs + SCHIZO_PCIA_DIAG, tmp);
-
- tmp = schizo_read(p->controller_regs + SCHIZO_PCIB_DIAG);
- tmp |= (SCHIZO_PCIDIAG_D_TTO | SCHIZO_PCIDIAG_D_RTRYARB);
- schizo_write(p->controller_regs + SCHIZO_PCIB_DIAG, tmp);
+ if (chip_type == PBM_CHIP_TYPE_TOMATILLO) {
+ if (x == (y ^ 1))
+ return 1;
+ return 0;
+ }
+ return (x == y);
}
-void __init schizo_init(int node, char *model_name)
+static void __init __schizo_init(int node, char *model_name, int chip_type)
{
- struct linux_prom64_registers pr_regs[3];
struct pci_controller_info *p;
struct pci_iommu *iommu;
unsigned long flags;
+ int is_pbm_a;
u32 portid;
- int is_pbm_a, err;
portid = prom_getintdefault(node, "portid", 0xff);
spin_lock_irqsave(&pci_controller_lock, flags);
for(p = pci_controller_root; p; p = p->next) {
- if (p->portid == portid) {
+ struct pci_pbm_info *pbm;
+
+ if (p->pbm_A.prom_node && p->pbm_B.prom_node)
+ continue;
+
+ pbm = (p->pbm_A.prom_node ?
+ &p->pbm_A :
+ &p->pbm_B);
+
+ if (portid_compare(pbm->portid, portid, chip_type)) {
spin_unlock_irqrestore(&pci_controller_lock, flags);
is_pbm_a = (p->pbm_A.prom_node == 0);
- schizo_pbm_init(p, node, is_pbm_a);
+ schizo_pbm_init(p, node, portid, chip_type);
return;
}
}
@@ -1860,38 +2204,33 @@
pci_controller_root = p;
spin_unlock_irqrestore(&pci_controller_lock, flags);
- p->portid = portid;
p->index = pci_num_controllers++;
p->pbms_same_domain = 0;
- p->scan_bus = schizo_scan_bus;
+ p->scan_bus = (chip_type == PBM_CHIP_TYPE_TOMATILLO ?
+ tomatillo_scan_bus :
+ schizo_scan_bus);
p->irq_build = schizo_irq_build;
p->base_address_update = schizo_base_address_update;
p->resource_adjust = schizo_resource_adjust;
p->pci_ops = &schizo_ops;
- /* Three OBP regs:
- * 1) PBM controller regs
- * 2) Schizo front-end controller regs (same for both PBMs)
- * 3) PBM PCI config space
- */
- err = prom_getproperty(node, "reg",
- (char *)&pr_regs[0],
- sizeof(pr_regs));
- if (err == 0 || err == -1) {
- prom_printf("SCHIZO: Fatal error, no reg property.\n");
- prom_halt();
- }
-
- p->controller_regs = pr_regs[1].phys_addr - 0x10000UL;
- printk("PCI: Found SCHIZO, control regs at %016lx\n",
- p->controller_regs);
-
/* Like PSYCHO we have a 2GB aligned area for memory space. */
pci_memspace_mask = 0x7fffffffUL;
- /* Init core controller. */
- schizo_controller_hwinit(p);
+ schizo_pbm_init(p, node, portid, chip_type);
+}
- is_pbm_a = ((pr_regs[0].phys_addr & 0x00700000) == 0x00600000);
- schizo_pbm_init(p, node, is_pbm_a);
+void __init schizo_init(int node, char *model_name)
+{
+ __schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO);
+}
+
+void __init schizo_plus_init(int node, char *model_name)
+{
+ __schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS);
+}
+
+void __init tomatillo_init(int node, char *model_name)
+{
+ __schizo_init(node, model_name, PBM_CHIP_TYPE_TOMATILLO);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)