summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@nuts.ninka.net>2003-07-24 18:41:42 -0700
committerDavid S. Miller <davem@nuts.ninka.net>2003-07-24 18:41:42 -0700
commit52a77587c29b6ba5a7e10eedc7ec9d570076ad1a (patch)
treefc5b20376031db5e7dbc96f5f44f8cbbb258318a
parent63eceba1e3a4fad6a346ba804d1b9be43898abb9 (diff)
[SPARC64]: Sanitize PCI controller handling to support Tomatillo better.
- Move varions controller datums into pbm structure. - Add controller type/version/revision info to pbm structure. - SCHIZO/TOMATILLO fixes: - Treat PBM etc. register bases as PBM local. - Use PBM prom node ranges property to figure out where CFG/MEM/IO space physical bases are.
-rw-r--r--arch/sparc64/kernel/pci.c3
-rw-r--r--arch/sparc64/kernel/pci_common.c2
-rw-r--r--arch/sparc64/kernel/pci_psycho.c98
-rw-r--r--arch/sparc64/kernel/pci_sabre.c82
-rw-r--r--arch/sparc64/kernel/pci_schizo.c674
-rw-r--r--include/asm-sparc64/pbm.h25
6 files changed, 443 insertions, 441 deletions
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index 61974099b185..462d82cf0fa2 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -185,6 +185,7 @@ void pci_config_write32(u32 *addr, u32 val)
extern void sabre_init(int, char *);
extern void psycho_init(int, char *);
extern void schizo_init(int, char *);
+extern void schizo_plus_init(int, char *);
extern void tomatillo_init(int, char *);
static struct {
@@ -198,6 +199,8 @@ static struct {
{ "pci108e,8000", psycho_init },
{ "SUNW,schizo", schizo_init },
{ "pci108e,8001", schizo_init },
+ { "SUNW,schizo+", schizo_plus_init },
+ { "pci108e,8002", schizo_plus_init },
{ "SUNW,tomatillo", tomatillo_init },
{ "pci108e,a801", tomatillo_init },
};
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
index 1f0c350526de..b40478d6b997 100644
--- a/arch/sparc64/kernel/pci_common.c
+++ b/arch/sparc64/kernel/pci_common.c
@@ -686,7 +686,7 @@ static void __init pdev_fixup_irq(struct pci_dev *pdev)
struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm = pcp->pbm;
struct pci_controller_info *p = pbm->parent;
- unsigned int portid = p->portid;
+ unsigned int portid = pbm->portid;
unsigned int prom_irq;
int prom_node = pcp->prom_node;
int err;
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index 8dee5e1e0c08..aacf71cfbd64 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -348,7 +348,6 @@ static unsigned int __init psycho_irq_build(struct pci_pbm_info *pbm,
struct pci_dev *pdev,
unsigned int ino)
{
- struct pci_controller_info *p = pbm->parent;
struct ino_bucket *bucket;
unsigned long imap, iclr;
unsigned long imap_off, iclr_off;
@@ -373,11 +372,11 @@ static unsigned int __init psycho_irq_build(struct pci_pbm_info *pbm,
if (PIL_RESERVED(pil))
BUG();
- imap = p->controller_regs + imap_off;
+ imap = pbm->controller_regs + imap_off;
imap += 4;
iclr_off = psycho_iclr_offset(ino);
- iclr = p->controller_regs + iclr_off;
+ iclr = pbm->controller_regs + iclr_off;
iclr += 4;
if ((ino & 0x20) == 0)
@@ -444,7 +443,7 @@ static void __psycho_check_one_stc(struct pci_controller_info *p,
int is_pbm_a)
{
struct pci_strbuf *strbuf = &pbm->stc;
- unsigned long regbase = p->controller_regs;
+ unsigned long regbase = p->pbm_A.controller_regs;
unsigned long err_base, tag_base, line_base;
u64 control;
int i;
@@ -639,7 +638,7 @@ static void psycho_check_iommu_error(struct pci_controller_info *p,
psycho_write(iommu->iommu_control,
control | PSYCHO_IOMMU_CTRL_DENAB);
for (i = 0; i < 16; i++) {
- unsigned long base = p->controller_regs;
+ unsigned long base = p->pbm_A.controller_regs;
iommu_tag[i] =
psycho_read(base + PSYCHO_IOMMU_TAG + (i * 8UL));
@@ -716,8 +715,8 @@ static void psycho_check_iommu_error(struct pci_controller_info *p,
static irqreturn_t psycho_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 + PSYCHO_UE_AFSR;
- unsigned long afar_reg = p->controller_regs + PSYCHO_UE_AFAR;
+ unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_UE_AFSR;
+ unsigned long afar_reg = p->pbm_A.controller_regs + PSYCHO_UE_AFAR;
unsigned long afsr, afar, error_bits;
int reported;
@@ -793,8 +792,8 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t psycho_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 + PSYCHO_CE_AFSR;
- unsigned long afar_reg = p->controller_regs + PSYCHO_CE_AFAR;
+ unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_CE_AFSR;
+ unsigned long afar_reg = p->pbm_A.controller_regs + PSYCHO_CE_AFAR;
unsigned long afsr, afar, error_bits;
int reported;
@@ -885,11 +884,11 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id, struct pt_regs *reg
is_pbm_a = (pbm == &pbm->parent->pbm_A);
if (is_pbm_a) {
- afsr_reg = p->controller_regs + PSYCHO_PCI_AFSR_A;
- afar_reg = p->controller_regs + PSYCHO_PCI_AFAR_A;
+ afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_A;
+ afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_A;
} else {
- afsr_reg = p->controller_regs + PSYCHO_PCI_AFSR_B;
- afar_reg = p->controller_regs + PSYCHO_PCI_AFAR_B;
+ afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_B;
+ afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_B;
}
/* Latch error status. */
@@ -988,8 +987,8 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id, struct pt_regs *reg
static void __init psycho_register_error_handlers(struct pci_controller_info *p)
{
struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */
- unsigned long base = p->controller_regs;
- unsigned int irq, portid = p->portid;
+ unsigned long base = p->pbm_A.controller_regs;
+ unsigned int irq, portid = pbm->portid;
u64 tmp;
/* Build IRQs and register handlers. */
@@ -1174,26 +1173,26 @@ static void __init psycho_iommu_init(struct pci_controller_info *p)
iommu->iommu_cur_ctx = 0;
/* Register addresses. */
- iommu->iommu_control = p->controller_regs + PSYCHO_IOMMU_CONTROL;
- iommu->iommu_tsbbase = p->controller_regs + PSYCHO_IOMMU_TSBBASE;
- iommu->iommu_flush = p->controller_regs + PSYCHO_IOMMU_FLUSH;
+ iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL;
+ iommu->iommu_tsbbase = p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE;
+ iommu->iommu_flush = p->pbm_A.controller_regs + PSYCHO_IOMMU_FLUSH;
/* PSYCHO's IOMMU lacks ctx flushing. */
iommu->iommu_ctxflush = 0;
/* We use the main control register of PSYCHO as the write
* completion register.
*/
- iommu->write_complete_reg = p->controller_regs + PSYCHO_CONTROL;
+ iommu->write_complete_reg = p->pbm_A.controller_regs + PSYCHO_CONTROL;
/*
* Invalidate TLB Entries.
*/
- control = psycho_read(p->controller_regs + PSYCHO_IOMMU_CONTROL);
+ control = psycho_read(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL);
control |= PSYCHO_IOMMU_CTRL_DENAB;
- psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL, control);
for(i = 0; i < 16; i++) {
- psycho_write(p->controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0);
- psycho_write(p->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0);
}
/* Leave diag mode enabled for full-flushing done
@@ -1224,16 +1223,16 @@ static void __init psycho_iommu_init(struct pci_controller_info *p)
iommu->alloc_info[i].next = 0;
}
- psycho_write(p->controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(tsbbase));
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(tsbbase));
- control = psycho_read(p->controller_regs + PSYCHO_IOMMU_CONTROL);
+ control = psycho_read(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL);
control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ);
control |= (PSYCHO_IOMMU_TSBSZ_128K | PSYCHO_IOMMU_CTRL_ENAB);
- psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL, control);
/* If necessary, hook us up for starfire IRQ translations. */
if(this_is_starfire)
- p->starfire_cookie = starfire_hookup(p->portid);
+ p->starfire_cookie = starfire_hookup(p->pbm_A.portid);
else
p->starfire_cookie = NULL;
}
@@ -1255,28 +1254,28 @@ static void psycho_controller_hwinit(struct pci_controller_info *p)
u64 tmp;
/* PROM sets the IRQ retry value too low, increase it. */
- psycho_write(p->controller_regs + PSYCHO_IRQ_RETRY, 0xff);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_IRQ_RETRY, 0xff);
/* Enable arbiter for all PCI slots. */
- tmp = psycho_read(p->controller_regs + PSYCHO_PCIA_CTRL);
+ tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIA_CTRL);
tmp |= PSYCHO_PCICTRL_AEN;
- psycho_write(p->controller_regs + PSYCHO_PCIA_CTRL, tmp);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIA_CTRL, tmp);
- tmp = psycho_read(p->controller_regs + PSYCHO_PCIB_CTRL);
+ tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIB_CTRL);
tmp |= PSYCHO_PCICTRL_AEN;
- psycho_write(p->controller_regs + PSYCHO_PCIB_CTRL, tmp);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_CTRL, tmp);
/* Disable DMA write / PIO read synchronization on
* both PCI bus segments.
* [ U2P Erratum 1243770, STP2223BGA data sheet ]
*/
- tmp = psycho_read(p->controller_regs + PSYCHO_PCIA_DIAG);
+ tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIA_DIAG);
tmp |= PSYCHO_PCIDIAG_DDWSYNC;
- psycho_write(p->controller_regs + PSYCHO_PCIA_DIAG, tmp);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIA_DIAG, tmp);
- tmp = psycho_read(p->controller_regs + PSYCHO_PCIB_DIAG);
+ tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG);
tmp |= PSYCHO_PCIDIAG_DDWSYNC;
- psycho_write(p->controller_regs + PSYCHO_PCIB_DIAG, tmp);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG, tmp);
}
static void __init pbm_register_toplevel_resources(struct pci_controller_info *p,
@@ -1299,7 +1298,7 @@ static void psycho_pbm_strbuf_init(struct pci_controller_info *p,
struct pci_pbm_info *pbm,
int is_pbm_a)
{
- unsigned long base = p->controller_regs;
+ unsigned long base = pbm->controller_regs;
u64 control;
if (is_pbm_a) {
@@ -1364,14 +1363,21 @@ static void psycho_pbm_init(struct pci_controller_info *p,
if (is_pbm_a) {
pbm = &p->pbm_A;
pbm->pci_first_slot = 1;
- pbm->io_space.start = p->controller_regs + PSYCHO_IOSPACE_A;
- pbm->mem_space.start = p->controller_regs + PSYCHO_MEMSPACE_A;
+ pbm->io_space.start = pbm->controller_regs + PSYCHO_IOSPACE_A;
+ pbm->mem_space.start = pbm->controller_regs + PSYCHO_MEMSPACE_A;
} else {
pbm = &p->pbm_B;
pbm->pci_first_slot = 2;
- pbm->io_space.start = p->controller_regs + PSYCHO_IOSPACE_B;
- pbm->mem_space.start = p->controller_regs + PSYCHO_MEMSPACE_B;
+ pbm->io_space.start = pbm->controller_regs + PSYCHO_IOSPACE_B;
+ pbm->mem_space.start = pbm->controller_regs + PSYCHO_MEMSPACE_B;
}
+
+ pbm->chip_type = PBM_CHIP_TYPE_PSYCHO;
+ pbm->chip_version =
+ prom_getintdefault(prom_node, "version#", 0);
+ pbm->chip_revision =
+ prom_getintdefault(prom_node, "module-revision#", 0);
+
pbm->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE;
pbm->io_space.flags = IORESOURCE_IO;
pbm->mem_space.end = pbm->mem_space.start + PSYCHO_MEMSPACE_SIZE;
@@ -1439,7 +1445,7 @@ void __init psycho_init(int node, char *model_name)
spin_lock_irqsave(&pci_controller_lock, flags);
for(p = pci_controller_root; p; p = p->next) {
- if (p->portid == upa_portid) {
+ if (p->pbm_A.portid == upa_portid) {
spin_unlock_irqrestore(&pci_controller_lock, flags);
is_pbm_a = (p->pbm_A.prom_node == 0);
psycho_pbm_init(p, node, is_pbm_a);
@@ -1467,7 +1473,8 @@ void __init psycho_init(int node, char *model_name)
pci_controller_root = p;
spin_unlock_irqrestore(&pci_controller_lock, flags);
- p->portid = upa_portid;
+ p->pbm_A.portid = upa_portid;
+ p->pbm_B.portid = upa_portid;
p->index = pci_num_controllers++;
p->pbms_same_domain = 0;
p->scan_bus = psycho_scan_bus;
@@ -1484,9 +1491,10 @@ void __init psycho_init(int node, char *model_name)
prom_halt();
}
- p->controller_regs = pr_regs[2].phys_addr;
+ p->pbm_A.controller_regs = pr_regs[2].phys_addr;
+ p->pbm_B.controller_regs = pr_regs[2].phys_addr;
printk("PCI: Found PSYCHO, control regs at %016lx\n",
- p->controller_regs);
+ p->pbm_A.controller_regs);
p->pbm_A.config_space = p->pbm_B.config_space =
(pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE);
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index f79eea735a6b..07e79c66163f 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -591,7 +591,6 @@ static unsigned int __init sabre_irq_build(struct pci_pbm_info *pbm,
struct pci_dev *pdev,
unsigned int ino)
{
- struct pci_controller_info *p = pbm->parent;
struct ino_bucket *bucket;
unsigned long imap, iclr;
unsigned long imap_off, iclr_off;
@@ -616,11 +615,11 @@ static unsigned int __init sabre_irq_build(struct pci_pbm_info *pbm,
if (PIL_RESERVED(pil))
BUG();
- imap = p->controller_regs + imap_off;
+ imap = pbm->controller_regs + imap_off;
imap += 4;
iclr_off = sabre_iclr_offset(ino);
- iclr = p->controller_regs + iclr_off;
+ iclr = pbm->controller_regs + iclr_off;
iclr += 4;
if ((ino & 0x20) == 0)
@@ -698,7 +697,7 @@ static void sabre_check_iommu_error(struct pci_controller_info *p,
sabre_write(iommu->iommu_control,
(control | SABRE_IOMMUCTRL_DENAB));
for (i = 0; i < 16; i++) {
- unsigned long base = p->controller_regs;
+ unsigned long base = p->pbm_A.controller_regs;
iommu_tag[i] =
sabre_read(base + SABRE_IOMMU_TAG + (i * 8UL));
@@ -747,8 +746,8 @@ static void sabre_check_iommu_error(struct pci_controller_info *p,
static irqreturn_t sabre_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 + SABRE_UE_AFSR;
- unsigned long afar_reg = p->controller_regs + SABRE_UECE_AFAR;
+ unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_UE_AFSR;
+ unsigned long afar_reg = p->pbm_A.controller_regs + SABRE_UECE_AFAR;
unsigned long afsr, afar, error_bits;
int reported;
@@ -807,8 +806,8 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t sabre_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 + SABRE_CE_AFSR;
- unsigned long afar_reg = p->controller_regs + SABRE_UECE_AFAR;
+ unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_CE_AFSR;
+ unsigned long afar_reg = p->pbm_A.controller_regs + SABRE_UECE_AFAR;
unsigned long afsr, afar, error_bits;
int reported;
@@ -867,8 +866,8 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs
unsigned long afsr, afar, error_bits;
int reported;
- afsr_reg = p->controller_regs + SABRE_PIOAFSR;
- afar_reg = p->controller_regs + SABRE_PIOAFAR;
+ afsr_reg = p->pbm_A.controller_regs + SABRE_PIOAFSR;
+ afar_reg = p->pbm_A.controller_regs + SABRE_PIOAFAR;
/* Latch error status. */
afar = sabre_read(afar_reg);
@@ -962,8 +961,8 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs
static void __init sabre_register_error_handlers(struct pci_controller_info *p)
{
struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */
- unsigned long base = p->controller_regs;
- unsigned long irq, portid = p->portid;
+ unsigned long base = pbm->controller_regs;
+ unsigned long irq, portid = pbm->portid;
u64 tmp;
/* We clear the error bits in the appropriate AFSR before
@@ -1011,13 +1010,12 @@ static void __init sabre_resource_adjust(struct pci_dev *pdev,
struct resource *root)
{
struct pci_pbm_info *pbm = pdev->bus->sysdata;
- struct pci_controller_info *p = pbm->parent;
unsigned long base;
if (res->flags & IORESOURCE_IO)
- base = p->controller_regs + SABRE_IOSPACE;
+ base = pbm->controller_regs + SABRE_IOSPACE;
else
- base = p->controller_regs + SABRE_MEMSPACE;
+ base = pbm->controller_regs + SABRE_MEMSPACE;
res->start += base;
res->end += base;
@@ -1027,7 +1025,6 @@ static void __init sabre_base_address_update(struct pci_dev *pdev, int resource)
{
struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm = pcp->pbm;
- struct pci_controller_info *p = pbm->parent;
struct resource *res;
unsigned long base;
u32 reg;
@@ -1045,9 +1042,9 @@ static void __init sabre_base_address_update(struct pci_dev *pdev, int resource)
is_64bit = 0;
if (res->flags & IORESOURCE_IO)
- base = p->controller_regs + SABRE_IOSPACE;
+ base = pbm->controller_regs + SABRE_IOSPACE;
else {
- base = p->controller_regs + SABRE_MEMSPACE;
+ base = pbm->controller_regs + SABRE_MEMSPACE;
if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
== PCI_BASE_ADDRESS_MEM_TYPE_64)
is_64bit = 1;
@@ -1229,21 +1226,21 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
iommu->iommu_cur_ctx = 0;
/* Register addresses. */
- iommu->iommu_control = p->controller_regs + SABRE_IOMMU_CONTROL;
- iommu->iommu_tsbbase = p->controller_regs + SABRE_IOMMU_TSBBASE;
- iommu->iommu_flush = p->controller_regs + SABRE_IOMMU_FLUSH;
- iommu->write_complete_reg = p->controller_regs + SABRE_WRSYNC;
+ iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL;
+ iommu->iommu_tsbbase = p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE;
+ iommu->iommu_flush = p->pbm_A.controller_regs + SABRE_IOMMU_FLUSH;
+ iommu->write_complete_reg = p->pbm_A.controller_regs + SABRE_WRSYNC;
/* Sabre's IOMMU lacks ctx flushing. */
iommu->iommu_ctxflush = 0;
/* Invalidate TLB Entries. */
- control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL);
+ control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL);
control |= SABRE_IOMMUCTRL_DENAB;
- sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);
+ sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control);
for(i = 0; i < 16; i++) {
- sabre_write(p->controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0);
- sabre_write(p->controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0);
+ sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0);
+ sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0);
}
/* Leave diag mode enabled for full-flushing done
@@ -1260,9 +1257,9 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
iommu->dma_addr_mask = dma_mask;
memset((char *)tsbbase, 0, PAGE_SIZE << order);
- sabre_write(p->controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase));
+ sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase));
- control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL);
+ control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL);
control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ);
control |= SABRE_IOMMUCTRL_ENAB;
switch(tsbsize) {
@@ -1279,7 +1276,7 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
prom_halt();
break;
}
- sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);
+ sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control);
/* We start with no consistent mappings. */
iommu->lowest_consistent_map =
@@ -1295,8 +1292,8 @@ static void __init pbm_register_toplevel_resources(struct pci_controller_info *p
struct pci_pbm_info *pbm)
{
char *name = pbm->name;
- unsigned long ibase = p->controller_regs + SABRE_IOSPACE;
- unsigned long mbase = p->controller_regs + SABRE_MEMSPACE;
+ unsigned long ibase = p->pbm_A.controller_regs + SABRE_IOSPACE;
+ unsigned long mbase = p->pbm_A.controller_regs + SABRE_MEMSPACE;
unsigned int devfn;
unsigned long first, last, i;
u8 *addr, map;
@@ -1389,6 +1386,7 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node,
pbm = &p->pbm_B;
else
pbm = &p->pbm_A;
+ pbm->chip_type = PBM_CHIP_TYPE_SABRE;
pbm->parent = p;
pbm->prom_node = node;
pbm->pci_first_slot = 1;
@@ -1475,11 +1473,11 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node,
pbm->io_space.name = pbm->mem_space.name = pbm->name;
/* Hack up top-level resources. */
- pbm->io_space.start = p->controller_regs + SABRE_IOSPACE;
+ pbm->io_space.start = p->pbm_A.controller_regs + SABRE_IOSPACE;
pbm->io_space.end = pbm->io_space.start + (1UL << 24) - 1UL;
pbm->io_space.flags = IORESOURCE_IO;
- pbm->mem_space.start = p->controller_regs + SABRE_MEMSPACE;
+ pbm->mem_space.start = p->pbm_A.controller_regs + SABRE_MEMSPACE;
pbm->mem_space.end = pbm->mem_space.start + (unsigned long)dma_begin - 1UL;
pbm->mem_space.flags = IORESOURCE_MEM;
@@ -1554,7 +1552,8 @@ void __init sabre_init(int pnode, char *model_name)
pci_controller_root = p;
spin_unlock_irqrestore(&pci_controller_lock, flags);
- p->portid = upa_portid;
+ p->pbm_A.portid = upa_portid;
+ p->pbm_B.portid = upa_portid;
p->index = pci_num_controllers++;
p->pbms_same_domain = 1;
p->scan_bus = sabre_scan_bus;
@@ -1577,30 +1576,31 @@ void __init sabre_init(int pnode, char *model_name)
/*
* First REG in property is base of entire SABRE register space.
*/
- p->controller_regs = pr_regs[0].phys_addr;
- pci_dma_wsync = p->controller_regs + SABRE_WRSYNC;
+ p->pbm_A.controller_regs = pr_regs[0].phys_addr;
+ p->pbm_B.controller_regs = pr_regs[0].phys_addr;
+ pci_dma_wsync = p->pbm_A.controller_regs + SABRE_WRSYNC;
printk("PCI: Found SABRE, main regs at %016lx, wsync at %016lx\n",
- p->controller_regs, pci_dma_wsync);
+ p->pbm_A.controller_regs, pci_dma_wsync);
/* Clear interrupts */
/* PCI first */
for (clear_irq = SABRE_ICLR_A_SLOT0; clear_irq < SABRE_ICLR_B_SLOT0 + 0x80; clear_irq += 8)
- sabre_write(p->controller_regs + clear_irq, 0x0UL);
+ sabre_write(p->pbm_A.controller_regs + clear_irq, 0x0UL);
/* Then OBIO */
for (clear_irq = SABRE_ICLR_SCSI; clear_irq < SABRE_ICLR_SCSI + 0x80; clear_irq += 8)
- sabre_write(p->controller_regs + clear_irq, 0x0UL);
+ sabre_write(p->pbm_A.controller_regs + clear_irq, 0x0UL);
/* Error interrupts are enabled later after the bus scan. */
- sabre_write(p->controller_regs + SABRE_PCICTRL,
+ sabre_write(p->pbm_A.controller_regs + SABRE_PCICTRL,
(SABRE_PCICTRL_MRLEN | SABRE_PCICTRL_SERR |
SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN));
/* Now map in PCI config space for entire SABRE. */
p->pbm_A.config_space = p->pbm_B.config_space =
- (p->controller_regs + SABRE_CONFIGSPACE);
+ (p->pbm_A.controller_regs + SABRE_CONFIGSPACE);
printk("SABRE: Shared PCI config space at %016lx\n",
p->pbm_A.config_space);
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index 917cdb9f4a2e..68dbc281c588 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -46,13 +46,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 */
@@ -336,17 +330,11 @@ static unsigned int __init schizo_irq_build(struct pci_pbm_info *pbm,
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;
-
ino &= PCI_IRQ_INO;
imap_off = schizo_imap_offset(ino);
@@ -356,11 +344,11 @@ static unsigned int __init schizo_irq_build(struct pci_pbm_info *pbm,
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
@@ -385,6 +373,13 @@ static unsigned long stc_error_buf[128];
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);
@@ -416,18 +411,12 @@ static void schizo_clear_other_err_intr(int irq)
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;
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;
@@ -530,7 +519,6 @@ static void __schizo_check_stc_error_pbm(struct pci_pbm_info *pbm,
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];
@@ -579,11 +567,7 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm,
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] =
@@ -671,8 +655,8 @@ static void schizo_check_iommu_error(struct pci_controller_info *p,
static irqreturn_t 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;
@@ -761,8 +745,8 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t 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;
@@ -860,12 +844,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id, struct pt_regs *reg
unsigned long afsr, afar, error_bits;
int reported;
- base = p->controller_regs;
- if (pbm == &pbm->parent->pbm_A) {
- base += SCHIZO_PBM_A_REGS_OFF;
- } else {
- base += SCHIZO_PBM_B_REGS_OFF;
- }
+ base = pbm->pbm_regs;
afsr_reg = base + SCHIZO_PCI_AFSR;
afar_reg = base + SCHIZO_PCI_AFAR;
@@ -1019,8 +998,8 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *
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 & BUS_ERROR_UNMAP)) {
@@ -1056,8 +1035,7 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *
#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_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 */
@@ -1102,8 +1080,7 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *
static void __init tomatillo_register_error_handlers(struct pci_controller_info *p)
{
struct pci_pbm_info *pbm;
- unsigned long base = p->controller_regs;
- unsigned int irq, portid = p->portid;
+ unsigned int irq;
struct ino_bucket *bucket;
u64 tmp, err_mask;
int is_pbm_a;
@@ -1112,7 +1089,7 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
is_pbm_a = 0;
/* Build IRQs and register handlers. */
- irq = schizo_irq_build(pbm, NULL, (portid << 6) | 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",
@@ -1121,13 +1098,10 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
}
bucket = __bucket(irq);
tmp = readl(bucket->imap);
- upa_writel(tmp, (base +
- (is_pbm_a ?
- SCHIZO_PBM_A_REGS_OFF :
- SCHIZO_PBM_B_REGS_OFF) +
+ upa_writel(tmp, (pbm->pbm_regs +
schizo_imap_offset(SCHIZO_UE_INO) + 4));
- irq = schizo_irq_build(pbm, NULL, (portid << 6) | 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",
@@ -1136,16 +1110,13 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
}
bucket = __bucket(irq);
tmp = upa_readl(bucket->imap);
- upa_writel(tmp, (base +
- (is_pbm_a ?
- SCHIZO_PBM_A_REGS_OFF :
- SCHIZO_PBM_B_REGS_OFF) +
+ upa_writel(tmp, (pbm->pbm_regs +
schizo_imap_offset(SCHIZO_CE_INO) + 4));
pbm = &p->pbm_A;
is_pbm_a = 1;
- irq = schizo_irq_build(pbm, NULL, ((portid << 6) |
+ 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) {
@@ -1155,16 +1126,13 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
}
bucket = __bucket(irq);
tmp = upa_readl(bucket->imap);
- upa_writel(tmp, (base +
- (is_pbm_a ?
- SCHIZO_PBM_A_REGS_OFF :
- SCHIZO_PBM_B_REGS_OFF) +
+ upa_writel(tmp, (pbm->pbm_regs +
schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));
pbm = &p->pbm_B;
is_pbm_a = 0;
- irq = schizo_irq_build(pbm, NULL, ((portid << 6) |
+ 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) {
@@ -1174,13 +1142,10 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
}
bucket = __bucket(irq);
tmp = upa_readl(bucket->imap);
- upa_writel(tmp, (base +
- (is_pbm_a ?
- SCHIZO_PBM_A_REGS_OFF :
- SCHIZO_PBM_B_REGS_OFF) +
+ upa_writel(tmp, (pbm->pbm_regs +
schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4));
- irq = schizo_irq_build(pbm, NULL, (portid << 6) | 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",
@@ -1189,14 +1154,16 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
}
bucket = __bucket(irq);
tmp = upa_readl(bucket->imap);
- upa_writel(tmp, (base +
- (is_pbm_a ?
- SCHIZO_PBM_A_REGS_OFF :
- SCHIZO_PBM_B_REGS_OFF) +
+ 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));
+
+ schizo_write(p->pbm_B.controller_regs + SCHIZO_ECC_CTRL,
(SCHIZO_ECCCTRL_EE |
SCHIZO_ECCCTRL_UE |
SCHIZO_ECCCTRL_CE));
@@ -1211,27 +1178,23 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
SCHIZO_PCICTRL_SERR |
SCHIZO_PCICTRL_EEN);
- tmp = schizo_read(base +
- (is_pbm_a ?
- SCHIZO_PCIA_CTRL :
- SCHIZO_PCIB_CTRL));
+ tmp = schizo_read(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL);
tmp |= err_mask;
- schizo_write(base +
- (is_pbm_a ?
- SCHIZO_PCIA_CTRL :
- SCHIZO_PCIB_CTRL), tmp);
-
- schizo_write(base +
- (is_pbm_a ?
- SCHIZO_PBM_A_REGS_OFF :
- SCHIZO_PBM_B_REGS_OFF) +
- SCHIZO_PCI_AFSR,
- (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_CTRL, tmp);
+
+ tmp = schizo_read(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL);
+ tmp |= err_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 |
@@ -1243,10 +1206,14 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
BUS_ERROR_APERR | BUS_ERROR_UNMAP |
BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT);
- schizo_write(base + SCHIZO_SAFARI_ERRCTRL,
+ 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(base + SCHIZO_SAFARI_IRQCTRL,
+ 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)));
}
@@ -1254,13 +1221,12 @@ 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;
+ unsigned int irq;
struct ino_bucket *bucket;
u64 tmp, err_mask;
/* Build IRQs and register handlers. */
- irq = schizo_irq_build(pbm_b, NULL, (portid << 6) | SCHIZO_UE_INO);
+ irq = schizo_irq_build(pbm_b, NULL, (pbm_b->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",
@@ -1269,9 +1235,9 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
}
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_b->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4));
- irq = schizo_irq_build(pbm_b, NULL, (portid << 6) | SCHIZO_CE_INO);
+ irq = schizo_irq_build(pbm_b, NULL, (pbm_b->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",
@@ -1280,9 +1246,9 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
}
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_b->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4));
- irq = schizo_irq_build(pbm_a, NULL, (portid << 6) | SCHIZO_PCIERR_A_INO);
+ irq = schizo_irq_build(pbm_a, NULL, (pbm_a->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",
@@ -1291,9 +1257,9 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
}
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_a->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));
- irq = schizo_irq_build(pbm_b, NULL, (portid << 6) | SCHIZO_PCIERR_B_INO);
+ irq = schizo_irq_build(pbm_b, NULL, (pbm_b->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",
@@ -1302,9 +1268,9 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
}
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_b->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4));
- irq = schizo_irq_build(pbm_b, NULL, (portid << 6) | SCHIZO_SERR_INO);
+ irq = schizo_irq_build(pbm_b, NULL, (pbm_b->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",
@@ -1313,10 +1279,10 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
}
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_b->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4));
/* Enable UE and CE interrupts for controller. */
- schizo_write(base + SCHIZO_ECC_CTRL,
+ schizo_write(pbm_a->controller_regs + SCHIZO_ECC_CTRL,
(SCHIZO_ECCCTRL_EE |
SCHIZO_ECCCTRL_UE |
SCHIZO_ECCCTRL_CE));
@@ -1334,11 +1300,11 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
/* Enable PCI Error interrupts and clear error
* bits for each PBM.
*/
- tmp = schizo_read(base + SCHIZO_PCIA_CTRL);
+ tmp = schizo_read(pbm_a->pbm_regs + SCHIZO_PCI_CTRL);
tmp |= err_mask;
- schizo_write(base + SCHIZO_PCIA_CTRL, tmp);
+ schizo_write(pbm_a->pbm_regs + SCHIZO_PCI_CTRL, tmp);
- schizo_write(base + SCHIZO_PBM_A_REGS_OFF + SCHIZO_PCI_AFSR,
+ schizo_write(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 |
@@ -1346,11 +1312,11 @@ 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(base + SCHIZO_PCIB_CTRL);
+ tmp = schizo_read(pbm_b->pbm_regs + SCHIZO_PCI_CTRL);
tmp |= err_mask;
- schizo_write(base + SCHIZO_PCIB_CTRL, tmp);
+ schizo_write(pbm_b->pbm_regs + SCHIZO_PCI_CTRL, tmp);
- schizo_write(base + SCHIZO_PBM_B_REGS_OFF + SCHIZO_PCI_AFSR,
+ schizo_write(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 |
@@ -1383,10 +1349,10 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB);
#endif
- schizo_write(base + SCHIZO_SAFARI_ERRCTRL,
+ schizo_write(pbm_a->controller_regs + SCHIZO_SAFARI_ERRCTRL,
(SCHIZO_SAFERRCTRL_EN | err_mask));
- schizo_write(base + SCHIZO_SAFARI_IRQCTRL,
+ schizo_write(pbm_a->controller_regs + SCHIZO_SAFARI_IRQCTRL,
(SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));
}
@@ -1436,10 +1402,10 @@ static void __init pbm_scan_bus(struct pci_controller_info *p,
}
static void __init __schizo_scan_bus(struct pci_controller_info *p,
- int is_tomatillo)
+ int chip_type)
{
if (!p->pbm_B.prom_node || !p->pbm_A.prom_node) {
- printk("PCI: One PCI bus module of controller found.\n");
+ printk("PCI: Only one PCI bus module of controller found.\n");
printk("PCI: Ignoring entire controller.\n");
return;
}
@@ -1456,7 +1422,7 @@ static void __init __schizo_scan_bus(struct pci_controller_info *p,
/* After the PCI bus scan is complete, we can register
* the error interrupt handlers.
*/
- if (is_tomatillo)
+ if (chip_type == PBM_CHIP_TYPE_TOMATILLO)
tomatillo_register_error_handlers(p);
else
schizo_register_error_handlers(p);
@@ -1464,12 +1430,12 @@ static void __init __schizo_scan_bus(struct pci_controller_info *p,
static void __init schizo_scan_bus(struct pci_controller_info *p)
{
- __schizo_scan_bus(p, 0);
+ __schizo_scan_bus(p, PBM_CHIP_TYPE_SCHIZO);
}
static void __init tomatillo_scan_bus(struct pci_controller_info *p)
{
- __schizo_scan_bus(p, 1);
+ __schizo_scan_bus(p, PBM_CHIP_TYPE_TOMATILLO);
}
static void __init schizo_base_address_update(struct pci_dev *pdev, int resource)
@@ -1525,73 +1491,70 @@ static void __init schizo_resource_adjust(struct pci_dev *pdev,
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.
*/
-
-#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,
- int is_tomatillo)
+static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm)
{
- u64 mem_match;
- u64 io_match;
- u64 a;
+ int i, saw_cfg, saw_mem, saw_io;
- 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;
- }
+ 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));
- if (is_tomatillo) {
- a += ((0x3UL << 41UL) |
- ((u64)pbm->parent->portid << 36UL));
- }
-
- /* 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;
+ 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;
- if (is_tomatillo) {
- a += ((0x3UL << 41UL) |
- ((u64)pbm->parent->portid << 36UL));
+ default:
+ break;
+ };
}
- pbm->config_space = a;
- printk("%s: Local PCI config space at %016lx\n",
- pbm->name, pbm->config_space);
+ 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();
+ }
- a += (16UL * 1024UL * 1024UL);
- pbm->io_space.start = a;
- pbm->io_space.end = a + ((16UL * 1024UL * 1024UL) - 1UL);
- pbm->io_space.flags = IORESOURCE_IO;
+ 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,
- int is_tomatillo)
+ struct pci_pbm_info *pbm)
{
pbm->io_space.name = pbm->mem_space.name = pbm->name;
@@ -1601,45 +1564,28 @@ static void __init pbm_register_toplevel_resources(struct pci_controller_info *p
&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,
- int is_tomatillo)
+#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;
- if (is_tomatillo) {
+ if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {
/* TOMATILLO lacks streaming cache. */
return;
}
/* 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;
- }
+ 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])
@@ -1662,23 +1608,12 @@ static void schizo_pbm_strbuf_init(struct pci_controller_info *p,
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,
- int is_tomatillo)
+#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;
@@ -1689,22 +1624,15 @@ static void schizo_pbm_iommu_init(struct pci_controller_info *p,
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.
@@ -1713,13 +1641,11 @@ static void schizo_pbm_iommu_init(struct pci_controller_info *p,
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
@@ -1758,12 +1684,10 @@ static void schizo_pbm_iommu_init(struct pci_controller_info *p,
schizo_write(iommu->iommu_control, control);
}
-#define SCHIZO_PCIA_IRQ_RETRY (SCHIZO_PBM_A_REGS_OFF + 0x1a00UL)
-#define SCHIZO_PCIB_IRQ_RETRY (SCHIZO_PBM_B_REGS_OFF + 0x1a00UL)
+#define SCHIZO_PCI_IRQ_RETRY (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_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) */
@@ -1774,94 +1698,164 @@ static void schizo_pbm_iommu_init(struct pci_controller_info *p,
#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) */
-static void __init schizo_pbm_hw_init(struct pci_controller_info *p,
- int is_pbm_a, int is_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(p->controller_regs +
- (is_pbm_a ?
- SCHIZO_PCIA_IRQ_RETRY :
- SCHIZO_PCIB_IRQ_RETRY),
+ 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(p->controller_regs +
- (is_pbm_a ?
- SCHIZO_PCIA_CTRL :
- SCHIZO_PCIB_CTRL));
- if (is_tomatillo)
- tmp |= SCHIZO_PCICTRL_ARB_T;
+ 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 |= SCHIZO_PCICTRL_ARB_S;
- if (is_tomatillo) {
-#if 0
- /* This is the recommended setting, but we'll just
- * leave the value alone for now.
- */
- tmp &= ~SCHIZO_PCICTRL_PTO;
- tmp |= 0x1UL << SCHIZO_PCICTRL_PTO_SHIFT;
-#endif
- /* XXX Prefetch settings? */
- } else {
+ tmp |= 0xff;
+
+ if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO &&
+ pbm->chip_version == 0x2) {
tmp &= ~SCHIZO_PCICTRL_PTO;
+ tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT;
}
- schizo_write(p->controller_regs +
- (is_pbm_a ?
- SCHIZO_PCIA_CTRL :
- SCHIZO_PCIB_CTRL), tmp);
-
- /* Leave this at OBP initialized value on Tomatillo. */
- if (!is_tomatillo) {
- /* 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).
+
+ 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 = schizo_read(p->controller_regs +
- (is_pbm_a ?
- SCHIZO_PCIA_DIAG :
- SCHIZO_PCIB_DIAG));
- tmp |= (SCHIZO_PCIDIAG_D_TTO | SCHIZO_PCIDIAG_D_RTRYARB);
- schizo_write(p->controller_regs +
- (is_pbm_a ?
- SCHIZO_PCIA_DIAG :
- SCHIZO_PCIB_DIAG), tmp);
+ 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, int is_pbm_a,
- int is_tomatillo)
+ 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;
+ int is_pbm_a;
int err;
- schizo_pbm_hw_init(p, is_pbm_a, is_tomatillo);
+ 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;
+ 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,
- (is_tomatillo ?
+ (chip_type == PBM_CHIP_TYPE_TOMATILLO ?
"TOMATILLO%d PBM%c" :
"SCHIZO%d PBM%c"),
p->index,
(pbm == &p->pbm_A ? 'A' : 'B'));
- schizo_determine_mem_io_space(pbm, is_pbm_a,
- p->controller_regs, is_tomatillo);
- pbm_register_toplevel_resources(p, pbm, is_tomatillo);
+ 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,
@@ -1870,11 +1864,17 @@ static void __init schizo_pbm_init(struct pci_controller_info *p,
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,
@@ -1904,13 +1904,13 @@ static void __init schizo_pbm_init(struct pci_controller_info *p,
pbm->pci_first_busno = busrange[0];
pbm->pci_last_busno = busrange[1];
- schizo_pbm_iommu_init(p, pbm, is_pbm_a, is_tomatillo);
- schizo_pbm_strbuf_init(p, pbm, is_pbm_a, is_tomatillo);
+ schizo_pbm_iommu_init(pbm);
+ schizo_pbm_strbuf_init(pbm);
}
-static inline int portid_compare(u32 x, u32 y, int is_tomatillo)
+static inline int portid_compare(u32 x, u32 y, int chip_type)
{
- if (is_tomatillo) {
+ if (chip_type == PBM_CHIP_TYPE_TOMATILLO) {
if (x == (y ^ 1))
return 1;
return 0;
@@ -1918,29 +1918,31 @@ static inline int portid_compare(u32 x, u32 y, int is_tomatillo)
return (x == y);
}
-static void __init __schizo_init(int node, char *model_name, int is_tomatillo)
+static void __init __schizo_init(int node, char *model_name, int chip_type)
{
- struct linux_prom64_registers pr_regs[4];
struct pci_controller_info *p;
struct pci_iommu *iommu;
unsigned long flags;
+ int is_pbm_a;
u32 portid;
- int is_pbm_a, err;
- const char *chipset_name;
-
- if (is_tomatillo)
- chipset_name = "TOMATILLO";
- else
- chipset_name = "SCHIZO";
portid = prom_getintdefault(node, "portid", 0xff);
spin_lock_irqsave(&pci_controller_lock, flags);
for(p = pci_controller_root; p; p = p->next) {
- if (portid_compare(p->portid, portid, is_tomatillo)) {
+ 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, is_tomatillo);
+ schizo_pbm_init(p, node, portid, chip_type);
return;
}
}
@@ -1948,16 +1950,14 @@ static void __init __schizo_init(int node, char *model_name, int is_tomatillo)
p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
if (!p) {
- prom_printf("%s: Fatal memory allocation error.\n",
- chipset_name);
+ prom_printf("SCHIZO: Fatal memory allocation error.\n");
prom_halt();
}
memset(p, 0, sizeof(*p));
iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
if (!iommu) {
- prom_printf("%s: Fatal memory allocation error.\n",
- chipset_name);
+ prom_printf("SCHIZO: Fatal memory allocation error.\n");
prom_halt();
}
memset(iommu, 0, sizeof(*iommu));
@@ -1965,8 +1965,7 @@ static void __init __schizo_init(int node, char *model_name, int is_tomatillo)
iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
if (!iommu) {
- prom_printf("%s: Fatal memory allocation error.\n",
- chipset_name);
+ prom_printf("SCHIZO: Fatal memory allocation error.\n");
prom_halt();
}
memset(iommu, 0, sizeof(*iommu));
@@ -1977,54 +1976,33 @@ static void __init __schizo_init(int node, char *model_name, int is_tomatillo)
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 = (is_tomatillo ? tomatillo_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;
- /* 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 (same for both PBMs)
- * 3) PBM PCI config space
- * 4) Ichip regs
- */
- err = prom_getproperty(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();
- }
-
- p->controller_regs = pr_regs[1].phys_addr - 0x10000UL;
- printk("PCI: Found %s, Port ID %x, control regs at %016lx\n",
- chipset_name,
- p->portid,
- p->controller_regs);
-
/* Like PSYCHO we have a 2GB aligned area for memory space. */
pci_memspace_mask = 0x7fffffffUL;
- is_pbm_a = ((pr_regs[0].phys_addr & 0x00700000) == 0x00600000);
- schizo_pbm_init(p, node, is_pbm_a, is_tomatillo);
+ schizo_pbm_init(p, node, portid, chip_type);
}
void __init schizo_init(int node, char *model_name)
{
- __schizo_init(node, model_name, 0);
+ __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, 1);
+ __schizo_init(node, model_name, PBM_CHIP_TYPE_TOMATILLO);
}
diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h
index f3dc10516fdf..14e302f236e1 100644
--- a/include/asm-sparc64/pbm.h
+++ b/include/asm-sparc64/pbm.h
@@ -128,6 +128,25 @@ struct pci_pbm_info {
/* PCI controller we sit under. */
struct pci_controller_info *parent;
+ /* Physical address base of controller registers. */
+ unsigned long controller_regs;
+
+ /* Physical address base of PBM registers. */
+ unsigned long pbm_regs;
+
+ /* Opaque 32-bit system bus Port ID. */
+ u32 portid;
+
+ /* Chipset version information. */
+ int chip_type;
+#define PBM_CHIP_TYPE_SABRE 1
+#define PBM_CHIP_TYPE_PSYCHO 2
+#define PBM_CHIP_TYPE_SCHIZO 3
+#define PBM_CHIP_TYPE_SCHIZO_PLUS 4
+#define PBM_CHIP_TYPE_TOMATILLO 5
+ int chip_version;
+ int chip_revision;
+
/* Name used for top-level resources. */
char name[64];
@@ -170,12 +189,6 @@ struct pci_controller_info {
/* List of all PCI controllers. */
struct pci_controller_info *next;
- /* Physical address base of controller registers. */
- unsigned long controller_regs;
-
- /* Opaque 32-bit system bus Port ID. */
- u32 portid;
-
/* Each controller gets a unique index, used mostly for
* error logging purposes.
*/