diff options
| author | David S. Miller <davem@nuts.ninka.net> | 2003-07-24 18:41:42 -0700 |
|---|---|---|
| committer | David S. Miller <davem@nuts.ninka.net> | 2003-07-24 18:41:42 -0700 |
| commit | 52a77587c29b6ba5a7e10eedc7ec9d570076ad1a (patch) | |
| tree | fc5b20376031db5e7dbc96f5f44f8cbbb258318a | |
| parent | 63eceba1e3a4fad6a346ba804d1b9be43898abb9 (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.c | 3 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_common.c | 2 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_psycho.c | 98 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_sabre.c | 82 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_schizo.c | 674 | ||||
| -rw-r--r-- | include/asm-sparc64/pbm.h | 25 |
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. */ |
