Commit 52a77587 authored by David S. Miller's avatar David S. Miller

[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.
parent 63eceba1
...@@ -185,6 +185,7 @@ void pci_config_write32(u32 *addr, u32 val) ...@@ -185,6 +185,7 @@ void pci_config_write32(u32 *addr, u32 val)
extern void sabre_init(int, char *); extern void sabre_init(int, char *);
extern void psycho_init(int, char *); extern void psycho_init(int, char *);
extern void schizo_init(int, char *); extern void schizo_init(int, char *);
extern void schizo_plus_init(int, char *);
extern void tomatillo_init(int, char *); extern void tomatillo_init(int, char *);
static struct { static struct {
...@@ -198,6 +199,8 @@ static struct { ...@@ -198,6 +199,8 @@ static struct {
{ "pci108e,8000", psycho_init }, { "pci108e,8000", psycho_init },
{ "SUNW,schizo", schizo_init }, { "SUNW,schizo", schizo_init },
{ "pci108e,8001", schizo_init }, { "pci108e,8001", schizo_init },
{ "SUNW,schizo+", schizo_plus_init },
{ "pci108e,8002", schizo_plus_init },
{ "SUNW,tomatillo", tomatillo_init }, { "SUNW,tomatillo", tomatillo_init },
{ "pci108e,a801", tomatillo_init }, { "pci108e,a801", tomatillo_init },
}; };
......
...@@ -686,7 +686,7 @@ static void __init pdev_fixup_irq(struct pci_dev *pdev) ...@@ -686,7 +686,7 @@ static void __init pdev_fixup_irq(struct pci_dev *pdev)
struct pcidev_cookie *pcp = pdev->sysdata; struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm = pcp->pbm; struct pci_pbm_info *pbm = pcp->pbm;
struct pci_controller_info *p = pbm->parent; struct pci_controller_info *p = pbm->parent;
unsigned int portid = p->portid; unsigned int portid = pbm->portid;
unsigned int prom_irq; unsigned int prom_irq;
int prom_node = pcp->prom_node; int prom_node = pcp->prom_node;
int err; int err;
......
...@@ -348,7 +348,6 @@ static unsigned int __init psycho_irq_build(struct pci_pbm_info *pbm, ...@@ -348,7 +348,6 @@ static unsigned int __init psycho_irq_build(struct pci_pbm_info *pbm,
struct pci_dev *pdev, struct pci_dev *pdev,
unsigned int ino) unsigned int ino)
{ {
struct pci_controller_info *p = pbm->parent;
struct ino_bucket *bucket; struct ino_bucket *bucket;
unsigned long imap, iclr; unsigned long imap, iclr;
unsigned long imap_off, iclr_off; unsigned long imap_off, iclr_off;
...@@ -373,11 +372,11 @@ static unsigned int __init psycho_irq_build(struct pci_pbm_info *pbm, ...@@ -373,11 +372,11 @@ static unsigned int __init psycho_irq_build(struct pci_pbm_info *pbm,
if (PIL_RESERVED(pil)) if (PIL_RESERVED(pil))
BUG(); BUG();
imap = p->controller_regs + imap_off; imap = pbm->controller_regs + imap_off;
imap += 4; imap += 4;
iclr_off = psycho_iclr_offset(ino); iclr_off = psycho_iclr_offset(ino);
iclr = p->controller_regs + iclr_off; iclr = pbm->controller_regs + iclr_off;
iclr += 4; iclr += 4;
if ((ino & 0x20) == 0) if ((ino & 0x20) == 0)
...@@ -444,7 +443,7 @@ static void __psycho_check_one_stc(struct pci_controller_info *p, ...@@ -444,7 +443,7 @@ static void __psycho_check_one_stc(struct pci_controller_info *p,
int is_pbm_a) int is_pbm_a)
{ {
struct pci_strbuf *strbuf = &pbm->stc; 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; unsigned long err_base, tag_base, line_base;
u64 control; u64 control;
int i; int i;
...@@ -639,7 +638,7 @@ static void psycho_check_iommu_error(struct pci_controller_info *p, ...@@ -639,7 +638,7 @@ static void psycho_check_iommu_error(struct pci_controller_info *p,
psycho_write(iommu->iommu_control, psycho_write(iommu->iommu_control,
control | PSYCHO_IOMMU_CTRL_DENAB); control | PSYCHO_IOMMU_CTRL_DENAB);
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
unsigned long base = p->controller_regs; unsigned long base = p->pbm_A.controller_regs;
iommu_tag[i] = iommu_tag[i] =
psycho_read(base + PSYCHO_IOMMU_TAG + (i * 8UL)); psycho_read(base + PSYCHO_IOMMU_TAG + (i * 8UL));
...@@ -716,8 +715,8 @@ static void psycho_check_iommu_error(struct pci_controller_info *p, ...@@ -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) static irqreturn_t psycho_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct pci_controller_info *p = dev_id; struct pci_controller_info *p = dev_id;
unsigned long afsr_reg = p->controller_regs + PSYCHO_UE_AFSR; unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_UE_AFSR;
unsigned long afar_reg = p->controller_regs + PSYCHO_UE_AFAR; unsigned long afar_reg = p->pbm_A.controller_regs + PSYCHO_UE_AFAR;
unsigned long afsr, afar, error_bits; unsigned long afsr, afar, error_bits;
int reported; int reported;
...@@ -793,8 +792,8 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -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) static irqreturn_t psycho_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct pci_controller_info *p = dev_id; struct pci_controller_info *p = dev_id;
unsigned long afsr_reg = p->controller_regs + PSYCHO_CE_AFSR; unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_CE_AFSR;
unsigned long afar_reg = p->controller_regs + PSYCHO_CE_AFAR; unsigned long afar_reg = p->pbm_A.controller_regs + PSYCHO_CE_AFAR;
unsigned long afsr, afar, error_bits; unsigned long afsr, afar, error_bits;
int reported; int reported;
...@@ -885,11 +884,11 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id, struct pt_regs *reg ...@@ -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); is_pbm_a = (pbm == &pbm->parent->pbm_A);
if (is_pbm_a) { if (is_pbm_a) {
afsr_reg = p->controller_regs + PSYCHO_PCI_AFSR_A; afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_A;
afar_reg = p->controller_regs + PSYCHO_PCI_AFAR_A; afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_A;
} else { } else {
afsr_reg = p->controller_regs + PSYCHO_PCI_AFSR_B; afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_B;
afar_reg = p->controller_regs + PSYCHO_PCI_AFAR_B; afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_B;
} }
/* Latch error status. */ /* Latch error status. */
...@@ -988,8 +987,8 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id, struct pt_regs *reg ...@@ -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) static void __init psycho_register_error_handlers(struct pci_controller_info *p)
{ {
struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */ struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */
unsigned long base = p->controller_regs; unsigned long base = p->pbm_A.controller_regs;
unsigned int irq, portid = p->portid; unsigned int irq, portid = pbm->portid;
u64 tmp; u64 tmp;
/* Build IRQs and register handlers. */ /* Build IRQs and register handlers. */
...@@ -1174,26 +1173,26 @@ static void __init psycho_iommu_init(struct pci_controller_info *p) ...@@ -1174,26 +1173,26 @@ static void __init psycho_iommu_init(struct pci_controller_info *p)
iommu->iommu_cur_ctx = 0; iommu->iommu_cur_ctx = 0;
/* Register addresses. */ /* Register addresses. */
iommu->iommu_control = p->controller_regs + PSYCHO_IOMMU_CONTROL; iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL;
iommu->iommu_tsbbase = p->controller_regs + PSYCHO_IOMMU_TSBBASE; iommu->iommu_tsbbase = p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE;
iommu->iommu_flush = p->controller_regs + PSYCHO_IOMMU_FLUSH; iommu->iommu_flush = p->pbm_A.controller_regs + PSYCHO_IOMMU_FLUSH;
/* PSYCHO's IOMMU lacks ctx flushing. */ /* PSYCHO's IOMMU lacks ctx flushing. */
iommu->iommu_ctxflush = 0; iommu->iommu_ctxflush = 0;
/* We use the main control register of PSYCHO as the write /* We use the main control register of PSYCHO as the write
* completion register. * 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. * 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; 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++) { for(i = 0; i < 16; i++) {
psycho_write(p->controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0); psycho_write(p->pbm_A.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_DATA + (i * 8UL), 0);
} }
/* Leave diag mode enabled for full-flushing done /* Leave diag mode enabled for full-flushing done
...@@ -1224,16 +1223,16 @@ static void __init psycho_iommu_init(struct pci_controller_info *p) ...@@ -1224,16 +1223,16 @@ static void __init psycho_iommu_init(struct pci_controller_info *p)
iommu->alloc_info[i].next = 0; 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_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ);
control |= (PSYCHO_IOMMU_TSBSZ_128K | PSYCHO_IOMMU_CTRL_ENAB); 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 necessary, hook us up for starfire IRQ translations. */
if(this_is_starfire) if(this_is_starfire)
p->starfire_cookie = starfire_hookup(p->portid); p->starfire_cookie = starfire_hookup(p->pbm_A.portid);
else else
p->starfire_cookie = NULL; p->starfire_cookie = NULL;
} }
...@@ -1255,28 +1254,28 @@ static void psycho_controller_hwinit(struct pci_controller_info *p) ...@@ -1255,28 +1254,28 @@ static void psycho_controller_hwinit(struct pci_controller_info *p)
u64 tmp; u64 tmp;
/* PROM sets the IRQ retry value too low, increase it. */ /* 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. */ /* 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; 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; 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 /* Disable DMA write / PIO read synchronization on
* both PCI bus segments. * both PCI bus segments.
* [ U2P Erratum 1243770, STP2223BGA data sheet ] * [ 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; 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; 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, 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, ...@@ -1299,7 +1298,7 @@ static void psycho_pbm_strbuf_init(struct pci_controller_info *p,
struct pci_pbm_info *pbm, struct pci_pbm_info *pbm,
int is_pbm_a) int is_pbm_a)
{ {
unsigned long base = p->controller_regs; unsigned long base = pbm->controller_regs;
u64 control; u64 control;
if (is_pbm_a) { if (is_pbm_a) {
...@@ -1364,14 +1363,21 @@ static void psycho_pbm_init(struct pci_controller_info *p, ...@@ -1364,14 +1363,21 @@ static void psycho_pbm_init(struct pci_controller_info *p,
if (is_pbm_a) { if (is_pbm_a) {
pbm = &p->pbm_A; pbm = &p->pbm_A;
pbm->pci_first_slot = 1; pbm->pci_first_slot = 1;
pbm->io_space.start = p->controller_regs + PSYCHO_IOSPACE_A; pbm->io_space.start = pbm->controller_regs + PSYCHO_IOSPACE_A;
pbm->mem_space.start = p->controller_regs + PSYCHO_MEMSPACE_A; pbm->mem_space.start = pbm->controller_regs + PSYCHO_MEMSPACE_A;
} else { } else {
pbm = &p->pbm_B; pbm = &p->pbm_B;
pbm->pci_first_slot = 2; pbm->pci_first_slot = 2;
pbm->io_space.start = p->controller_regs + PSYCHO_IOSPACE_B; pbm->io_space.start = pbm->controller_regs + PSYCHO_IOSPACE_B;
pbm->mem_space.start = p->controller_regs + PSYCHO_MEMSPACE_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.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE;
pbm->io_space.flags = IORESOURCE_IO; pbm->io_space.flags = IORESOURCE_IO;
pbm->mem_space.end = pbm->mem_space.start + PSYCHO_MEMSPACE_SIZE; pbm->mem_space.end = pbm->mem_space.start + PSYCHO_MEMSPACE_SIZE;
...@@ -1439,7 +1445,7 @@ void __init psycho_init(int node, char *model_name) ...@@ -1439,7 +1445,7 @@ void __init psycho_init(int node, char *model_name)
spin_lock_irqsave(&pci_controller_lock, flags); spin_lock_irqsave(&pci_controller_lock, flags);
for(p = pci_controller_root; p; p = p->next) { 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); spin_unlock_irqrestore(&pci_controller_lock, flags);
is_pbm_a = (p->pbm_A.prom_node == 0); is_pbm_a = (p->pbm_A.prom_node == 0);
psycho_pbm_init(p, node, is_pbm_a); psycho_pbm_init(p, node, is_pbm_a);
...@@ -1467,7 +1473,8 @@ void __init psycho_init(int node, char *model_name) ...@@ -1467,7 +1473,8 @@ void __init psycho_init(int node, char *model_name)
pci_controller_root = p; pci_controller_root = p;
spin_unlock_irqrestore(&pci_controller_lock, flags); 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->index = pci_num_controllers++;
p->pbms_same_domain = 0; p->pbms_same_domain = 0;
p->scan_bus = psycho_scan_bus; p->scan_bus = psycho_scan_bus;
...@@ -1484,9 +1491,10 @@ void __init psycho_init(int node, char *model_name) ...@@ -1484,9 +1491,10 @@ void __init psycho_init(int node, char *model_name)
prom_halt(); 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", 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 = p->pbm_A.config_space = p->pbm_B.config_space =
(pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE); (pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE);
......
...@@ -591,7 +591,6 @@ static unsigned int __init sabre_irq_build(struct pci_pbm_info *pbm, ...@@ -591,7 +591,6 @@ static unsigned int __init sabre_irq_build(struct pci_pbm_info *pbm,
struct pci_dev *pdev, struct pci_dev *pdev,
unsigned int ino) unsigned int ino)
{ {
struct pci_controller_info *p = pbm->parent;
struct ino_bucket *bucket; struct ino_bucket *bucket;
unsigned long imap, iclr; unsigned long imap, iclr;
unsigned long imap_off, iclr_off; unsigned long imap_off, iclr_off;
...@@ -616,11 +615,11 @@ static unsigned int __init sabre_irq_build(struct pci_pbm_info *pbm, ...@@ -616,11 +615,11 @@ static unsigned int __init sabre_irq_build(struct pci_pbm_info *pbm,
if (PIL_RESERVED(pil)) if (PIL_RESERVED(pil))
BUG(); BUG();
imap = p->controller_regs + imap_off; imap = pbm->controller_regs + imap_off;
imap += 4; imap += 4;
iclr_off = sabre_iclr_offset(ino); iclr_off = sabre_iclr_offset(ino);
iclr = p->controller_regs + iclr_off; iclr = pbm->controller_regs + iclr_off;
iclr += 4; iclr += 4;
if ((ino & 0x20) == 0) if ((ino & 0x20) == 0)
...@@ -698,7 +697,7 @@ static void sabre_check_iommu_error(struct pci_controller_info *p, ...@@ -698,7 +697,7 @@ static void sabre_check_iommu_error(struct pci_controller_info *p,
sabre_write(iommu->iommu_control, sabre_write(iommu->iommu_control,
(control | SABRE_IOMMUCTRL_DENAB)); (control | SABRE_IOMMUCTRL_DENAB));
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
unsigned long base = p->controller_regs; unsigned long base = p->pbm_A.controller_regs;
iommu_tag[i] = iommu_tag[i] =
sabre_read(base + SABRE_IOMMU_TAG + (i * 8UL)); sabre_read(base + SABRE_IOMMU_TAG + (i * 8UL));
...@@ -747,8 +746,8 @@ static void sabre_check_iommu_error(struct pci_controller_info *p, ...@@ -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) static irqreturn_t sabre_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct pci_controller_info *p = dev_id; struct pci_controller_info *p = dev_id;
unsigned long afsr_reg = p->controller_regs + SABRE_UE_AFSR; unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_UE_AFSR;
unsigned long afar_reg = p->controller_regs + SABRE_UECE_AFAR; unsigned long afar_reg = p->pbm_A.controller_regs + SABRE_UECE_AFAR;
unsigned long afsr, afar, error_bits; unsigned long afsr, afar, error_bits;
int reported; int reported;
...@@ -807,8 +806,8 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -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) static irqreturn_t sabre_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct pci_controller_info *p = dev_id; struct pci_controller_info *p = dev_id;
unsigned long afsr_reg = p->controller_regs + SABRE_CE_AFSR; unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_CE_AFSR;
unsigned long afar_reg = p->controller_regs + SABRE_UECE_AFAR; unsigned long afar_reg = p->pbm_A.controller_regs + SABRE_UECE_AFAR;
unsigned long afsr, afar, error_bits; unsigned long afsr, afar, error_bits;
int reported; int reported;
...@@ -867,8 +866,8 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs ...@@ -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; unsigned long afsr, afar, error_bits;
int reported; int reported;
afsr_reg = p->controller_regs + SABRE_PIOAFSR; afsr_reg = p->pbm_A.controller_regs + SABRE_PIOAFSR;
afar_reg = p->controller_regs + SABRE_PIOAFAR; afar_reg = p->pbm_A.controller_regs + SABRE_PIOAFAR;
/* Latch error status. */ /* Latch error status. */
afar = sabre_read(afar_reg); afar = sabre_read(afar_reg);
...@@ -962,8 +961,8 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs ...@@ -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) static void __init sabre_register_error_handlers(struct pci_controller_info *p)
{ {
struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */ struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */
unsigned long base = p->controller_regs; unsigned long base = pbm->controller_regs;
unsigned long irq, portid = p->portid; unsigned long irq, portid = pbm->portid;
u64 tmp; u64 tmp;
/* We clear the error bits in the appropriate AFSR before /* We clear the error bits in the appropriate AFSR before
...@@ -1011,13 +1010,12 @@ static void __init sabre_resource_adjust(struct pci_dev *pdev, ...@@ -1011,13 +1010,12 @@ static void __init sabre_resource_adjust(struct pci_dev *pdev,
struct resource *root) struct resource *root)
{ {
struct pci_pbm_info *pbm = pdev->bus->sysdata; struct pci_pbm_info *pbm = pdev->bus->sysdata;
struct pci_controller_info *p = pbm->parent;
unsigned long base; unsigned long base;
if (res->flags & IORESOURCE_IO) if (res->flags & IORESOURCE_IO)
base = p->controller_regs + SABRE_IOSPACE; base = pbm->controller_regs + SABRE_IOSPACE;
else else
base = p->controller_regs + SABRE_MEMSPACE; base = pbm->controller_regs + SABRE_MEMSPACE;
res->start += base; res->start += base;
res->end += base; res->end += base;
...@@ -1027,7 +1025,6 @@ static void __init sabre_base_address_update(struct pci_dev *pdev, int resource) ...@@ -1027,7 +1025,6 @@ static void __init sabre_base_address_update(struct pci_dev *pdev, int resource)
{ {
struct pcidev_cookie *pcp = pdev->sysdata; struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm = pcp->pbm; struct pci_pbm_info *pbm = pcp->pbm;
struct pci_controller_info *p = pbm->parent;
struct resource *res; struct resource *res;
unsigned long base; unsigned long base;
u32 reg; u32 reg;
...@@ -1045,9 +1042,9 @@ static void __init sabre_base_address_update(struct pci_dev *pdev, int resource) ...@@ -1045,9 +1042,9 @@ static void __init sabre_base_address_update(struct pci_dev *pdev, int resource)
is_64bit = 0; is_64bit = 0;
if (res->flags & IORESOURCE_IO) if (res->flags & IORESOURCE_IO)
base = p->controller_regs + SABRE_IOSPACE; base = pbm->controller_regs + SABRE_IOSPACE;
else { else {
base = p->controller_regs + SABRE_MEMSPACE; base = pbm->controller_regs + SABRE_MEMSPACE;
if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
== PCI_BASE_ADDRESS_MEM_TYPE_64) == PCI_BASE_ADDRESS_MEM_TYPE_64)
is_64bit = 1; is_64bit = 1;
...@@ -1229,21 +1226,21 @@ static void __init sabre_iommu_init(struct pci_controller_info *p, ...@@ -1229,21 +1226,21 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
iommu->iommu_cur_ctx = 0; iommu->iommu_cur_ctx = 0;
/* Register addresses. */ /* Register addresses. */
iommu->iommu_control = p->controller_regs + SABRE_IOMMU_CONTROL; iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL;
iommu->iommu_tsbbase = p->controller_regs + SABRE_IOMMU_TSBBASE; iommu->iommu_tsbbase = p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE;
iommu->iommu_flush = p->controller_regs + SABRE_IOMMU_FLUSH; iommu->iommu_flush = p->pbm_A.controller_regs + SABRE_IOMMU_FLUSH;
iommu->write_complete_reg = p->controller_regs + SABRE_WRSYNC; iommu->write_complete_reg = p->pbm_A.controller_regs + SABRE_WRSYNC;
/* Sabre's IOMMU lacks ctx flushing. */ /* Sabre's IOMMU lacks ctx flushing. */
iommu->iommu_ctxflush = 0; iommu->iommu_ctxflush = 0;
/* Invalidate TLB Entries. */ /* 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; 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++) { for(i = 0; i < 16; i++) {
sabre_write(p->controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0); sabre_write(p->pbm_A.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_DATA + (i * 8UL), 0);
} }
/* Leave diag mode enabled for full-flushing done /* Leave diag mode enabled for full-flushing done
...@@ -1260,9 +1257,9 @@ static void __init sabre_iommu_init(struct pci_controller_info *p, ...@@ -1260,9 +1257,9 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
iommu->dma_addr_mask = dma_mask; iommu->dma_addr_mask = dma_mask;
memset((char *)tsbbase, 0, PAGE_SIZE << order); 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_TSBSZ | SABRE_IOMMUCTRL_TBWSZ);
control |= SABRE_IOMMUCTRL_ENAB; control |= SABRE_IOMMUCTRL_ENAB;
switch(tsbsize) { switch(tsbsize) {
...@@ -1279,7 +1276,7 @@ static void __init sabre_iommu_init(struct pci_controller_info *p, ...@@ -1279,7 +1276,7 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
prom_halt(); prom_halt();
break; 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. */ /* We start with no consistent mappings. */
iommu->lowest_consistent_map = iommu->lowest_consistent_map =
...@@ -1295,8 +1292,8 @@ static void __init pbm_register_toplevel_resources(struct pci_controller_info *p ...@@ -1295,8 +1292,8 @@ static void __init pbm_register_toplevel_resources(struct pci_controller_info *p
struct pci_pbm_info *pbm) struct pci_pbm_info *pbm)
{ {
char *name = pbm->name; char *name = pbm->name;
unsigned long ibase = p->controller_regs + SABRE_IOSPACE; unsigned long ibase = p->pbm_A.controller_regs + SABRE_IOSPACE;
unsigned long mbase = p->controller_regs + SABRE_MEMSPACE; unsigned long mbase = p->pbm_A.controller_regs + SABRE_MEMSPACE;
unsigned int devfn; unsigned int devfn;
unsigned long first, last, i; unsigned long first, last, i;
u8 *addr, map; u8 *addr, map;
...@@ -1389,6 +1386,7 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node, ...@@ -1389,6 +1386,7 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node,
pbm = &p->pbm_B; pbm = &p->pbm_B;
else else
pbm = &p->pbm_A; pbm = &p->pbm_A;
pbm->chip_type = PBM_CHIP_TYPE_SABRE;
pbm->parent = p; pbm->parent = p;
pbm->prom_node = node; pbm->prom_node = node;
pbm->pci_first_slot = 1; pbm->pci_first_slot = 1;
...@@ -1475,11 +1473,11 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node, ...@@ -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; pbm->io_space.name = pbm->mem_space.name = pbm->name;
/* Hack up top-level resources. */ /* 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.end = pbm->io_space.start + (1UL << 24) - 1UL;
pbm->io_space.flags = IORESOURCE_IO; 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.end = pbm->mem_space.start + (unsigned long)dma_begin - 1UL;
pbm->mem_space.flags = IORESOURCE_MEM; pbm->mem_space.flags = IORESOURCE_MEM;
...@@ -1554,7 +1552,8 @@ void __init sabre_init(int pnode, char *model_name) ...@@ -1554,7 +1552,8 @@ void __init sabre_init(int pnode, char *model_name)
pci_controller_root = p; pci_controller_root = p;
spin_unlock_irqrestore(&pci_controller_lock, flags); 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->index = pci_num_controllers++;
p->pbms_same_domain = 1; p->pbms_same_domain = 1;
p->scan_bus = sabre_scan_bus; p->scan_bus = sabre_scan_bus;
...@@ -1577,30 +1576,31 @@ void __init sabre_init(int pnode, char *model_name) ...@@ -1577,30 +1576,31 @@ void __init sabre_init(int pnode, char *model_name)
/* /*
* First REG in property is base of entire SABRE register space. * First REG in property is base of entire SABRE register space.
*/ */
p->controller_regs = pr_regs[0].phys_addr; p->pbm_A.controller_regs = pr_regs[0].phys_addr;
pci_dma_wsync = p->controller_regs + SABRE_WRSYNC; 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", 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 */ /* Clear interrupts */
/* PCI first */ /* PCI first */
for (clear_irq = SABRE_ICLR_A_SLOT0; clear_irq < SABRE_ICLR_B_SLOT0 + 0x80; clear_irq += 8) 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 */ /* Then OBIO */
for (clear_irq = SABRE_ICLR_SCSI; clear_irq < SABRE_ICLR_SCSI + 0x80; clear_irq += 8) 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. */ /* 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_MRLEN | SABRE_PCICTRL_SERR |
SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN)); SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN));
/* Now map in PCI config space for entire SABRE. */ /* Now map in PCI config space for entire SABRE. */
p->pbm_A.config_space = p->pbm_B.config_space = 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", printk("SABRE: Shared PCI config space at %016lx\n",
p->pbm_A.config_space); p->pbm_A.config_space);
......
...@@ -46,13 +46,7 @@ ...@@ -46,13 +46,7 @@
* block requires more space in Schizo's address space than * block requires more space in Schizo's address space than
* they predicted, thus requiring an address space reorg when * they predicted, thus requiring an address space reorg when
* the newer Schizo is taped out. * 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. */ /* Streaming buffer control register. */
#define SCHIZO_STRBUF_CTRL_LPTR 0x00000000000000f0UL /* LRU Lock Pointer */ #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, ...@@ -336,17 +330,11 @@ static unsigned int __init schizo_irq_build(struct pci_pbm_info *pbm,
struct pci_dev *pdev, struct pci_dev *pdev,
unsigned int ino) unsigned int ino)
{ {
struct pci_controller_info *p = pbm->parent;
struct ino_bucket *bucket; struct ino_bucket *bucket;
unsigned long imap, iclr, pbm_off; unsigned long imap, iclr;
unsigned long imap_off, iclr_off; unsigned long imap_off, iclr_off;
int pil; 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; ino &= PCI_IRQ_INO;
imap_off = schizo_imap_offset(ino); imap_off = schizo_imap_offset(ino);
...@@ -356,11 +344,11 @@ static unsigned int __init schizo_irq_build(struct pci_pbm_info *pbm, ...@@ -356,11 +344,11 @@ static unsigned int __init schizo_irq_build(struct pci_pbm_info *pbm,
if (PIL_RESERVED(pil)) if (PIL_RESERVED(pil))
BUG(); BUG();
imap = p->controller_regs + pbm_off + imap_off; imap = pbm->pbm_regs + imap_off;
imap += 4; imap += 4;
iclr_off = schizo_iclr_offset(ino); iclr_off = schizo_iclr_offset(ino);
iclr = p->controller_regs + pbm_off + iclr_off; iclr = pbm->pbm_regs + iclr_off;
iclr += 4; iclr += 4;
/* On Schizo, no inofixup occurs. This is because each /* On Schizo, no inofixup occurs. This is because each
...@@ -385,6 +373,13 @@ static unsigned long stc_error_buf[128]; ...@@ -385,6 +373,13 @@ static unsigned long stc_error_buf[128];
static unsigned long stc_tag_buf[16]; static unsigned long stc_tag_buf[16];
static unsigned long stc_line_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) static void schizo_clear_other_err_intr(int irq)
{ {
struct ino_bucket *bucket = __bucket(irq); struct ino_bucket *bucket = __bucket(irq);
...@@ -416,18 +411,12 @@ static void schizo_clear_other_err_intr(int 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, static void __schizo_check_stc_error_pbm(struct pci_pbm_info *pbm,
enum schizo_error_type type) enum schizo_error_type type)
{ {
struct pci_controller_info *p = pbm->parent;
struct pci_strbuf *strbuf = &pbm->stc; 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; unsigned long err_base, tag_base, line_base;
u64 control; u64 control;
int i; 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; err_base = regbase + SCHIZO_STC_ERR;
tag_base = regbase + SCHIZO_STC_TAG; tag_base = regbase + SCHIZO_STC_TAG;
line_base = regbase + SCHIZO_STC_LINE; line_base = regbase + SCHIZO_STC_LINE;
...@@ -530,7 +519,6 @@ static void __schizo_check_stc_error_pbm(struct pci_pbm_info *pbm, ...@@ -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, static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm,
enum schizo_error_type type) enum schizo_error_type type)
{ {
struct pci_controller_info *p = pbm->parent;
struct pci_iommu *iommu = pbm->iommu; struct pci_iommu *iommu = pbm->iommu;
unsigned long iommu_tag[16]; unsigned long iommu_tag[16];
unsigned long iommu_data[16]; unsigned long iommu_data[16];
...@@ -579,11 +567,7 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, ...@@ -579,11 +567,7 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm,
schizo_write(iommu->iommu_control, schizo_write(iommu->iommu_control,
control | SCHIZO_IOMMU_CTRL_DENAB); control | SCHIZO_IOMMU_CTRL_DENAB);
base = p->controller_regs; base = pbm->pbm_regs;
if (pbm == &p->pbm_A)
base += SCHIZO_PBM_A_REGS_OFF;
else
base += SCHIZO_PBM_B_REGS_OFF;
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
iommu_tag[i] = iommu_tag[i] =
...@@ -671,8 +655,8 @@ static void schizo_check_iommu_error(struct pci_controller_info *p, ...@@ -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) static irqreturn_t schizo_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct pci_controller_info *p = dev_id; struct pci_controller_info *p = dev_id;
unsigned long afsr_reg = p->controller_regs + SCHIZO_UE_AFSR; unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFSR;
unsigned long afar_reg = p->controller_regs + SCHIZO_UE_AFAR; unsigned long afar_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFAR;
unsigned long afsr, afar, error_bits; unsigned long afsr, afar, error_bits;
int reported, limit; int reported, limit;
...@@ -761,8 +745,8 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -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) static irqreturn_t schizo_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct pci_controller_info *p = dev_id; struct pci_controller_info *p = dev_id;
unsigned long afsr_reg = p->controller_regs + SCHIZO_CE_AFSR; unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFSR;
unsigned long afar_reg = p->controller_regs + SCHIZO_CE_AFAR; unsigned long afar_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFAR;
unsigned long afsr, afar, error_bits; unsigned long afsr, afar, error_bits;
int reported, limit; int reported, limit;
...@@ -860,12 +844,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id, struct pt_regs *reg ...@@ -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; unsigned long afsr, afar, error_bits;
int reported; int reported;
base = p->controller_regs; base = pbm->pbm_regs;
if (pbm == &pbm->parent->pbm_A) {
base += SCHIZO_PBM_A_REGS_OFF;
} else {
base += SCHIZO_PBM_B_REGS_OFF;
}
afsr_reg = base + SCHIZO_PCI_AFSR; afsr_reg = base + SCHIZO_PCI_AFSR;
afar_reg = base + SCHIZO_PCI_AFAR; afar_reg = base + SCHIZO_PCI_AFAR;
...@@ -1019,8 +998,8 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs * ...@@ -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; struct pci_controller_info *p = dev_id;
u64 errlog; u64 errlog;
errlog = schizo_read(p->controller_regs + SCHIZO_SAFARI_ERRLOG); errlog = schizo_read(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRLOG);
schizo_write(p->controller_regs + SCHIZO_SAFARI_ERRLOG, schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRLOG,
errlog & ~(SAFARI_ERRLOG_ERROUT)); errlog & ~(SAFARI_ERRLOG_ERROUT));
if (!(errlog & BUS_ERROR_UNMAP)) { if (!(errlog & BUS_ERROR_UNMAP)) {
...@@ -1056,8 +1035,7 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs * ...@@ -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_PCIERR_B_INO 0x33 /* PBM B PCI bus error */
#define SCHIZO_SERR_INO 0x34 /* Safari interface error */ #define SCHIZO_SERR_INO 0x34 /* Safari interface error */
#define SCHIZO_PCIA_CTRL (SCHIZO_PBM_A_REGS_OFF + 0x2000UL) #define SCHIZO_PCI_CTRL (0x2000UL)
#define SCHIZO_PCIB_CTRL (SCHIZO_PBM_B_REGS_OFF + 0x2000UL)
#define SCHIZO_PCICTRL_BUS_UNUS (1UL << 63UL) /* Safari */ #define SCHIZO_PCICTRL_BUS_UNUS (1UL << 63UL) /* Safari */
#define SCHIZO_PCICTRL_ARB_PRIO (0x1ff << 52UL) /* Tomatillo */ #define SCHIZO_PCICTRL_ARB_PRIO (0x1ff << 52UL) /* Tomatillo */
#define SCHIZO_PCICTRL_ESLCK (1UL << 51UL) /* Safari */ #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 * ...@@ -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) static void __init tomatillo_register_error_handlers(struct pci_controller_info *p)
{ {
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
unsigned long base = p->controller_regs; unsigned int irq;
unsigned int irq, portid = p->portid;
struct ino_bucket *bucket; struct ino_bucket *bucket;
u64 tmp, err_mask; u64 tmp, err_mask;
int is_pbm_a; int is_pbm_a;
...@@ -1112,7 +1089,7 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info ...@@ -1112,7 +1089,7 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
is_pbm_a = 0; is_pbm_a = 0;
/* Build IRQs and register handlers. */ /* 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, if (request_irq(irq, schizo_ue_intr,
SA_SHIRQ, "TOMATILLO UE", p) < 0) { SA_SHIRQ, "TOMATILLO UE", p) < 0) {
prom_printf("TOMATILLO%d: Cannot register UE interrupt.\n", prom_printf("TOMATILLO%d: Cannot register UE interrupt.\n",
...@@ -1121,13 +1098,10 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info ...@@ -1121,13 +1098,10 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
} }
bucket = __bucket(irq); bucket = __bucket(irq);
tmp = readl(bucket->imap); tmp = readl(bucket->imap);
upa_writel(tmp, (base + upa_writel(tmp, (pbm->pbm_regs +
(is_pbm_a ?
SCHIZO_PBM_A_REGS_OFF :
SCHIZO_PBM_B_REGS_OFF) +
schizo_imap_offset(SCHIZO_UE_INO) + 4)); 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, if (request_irq(irq, schizo_ce_intr,
SA_SHIRQ, "TOMATILLO CE", p) < 0) { SA_SHIRQ, "TOMATILLO CE", p) < 0) {
prom_printf("TOMATILLO%d: Cannot register CE interrupt.\n", prom_printf("TOMATILLO%d: Cannot register CE interrupt.\n",
...@@ -1136,16 +1110,13 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info ...@@ -1136,16 +1110,13 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
} }
bucket = __bucket(irq); bucket = __bucket(irq);
tmp = upa_readl(bucket->imap); tmp = upa_readl(bucket->imap);
upa_writel(tmp, (base + upa_writel(tmp, (pbm->pbm_regs +
(is_pbm_a ?
SCHIZO_PBM_A_REGS_OFF :
SCHIZO_PBM_B_REGS_OFF) +
schizo_imap_offset(SCHIZO_CE_INO) + 4)); schizo_imap_offset(SCHIZO_CE_INO) + 4));
pbm = &p->pbm_A; pbm = &p->pbm_A;
is_pbm_a = 1; 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)); SCHIZO_PCIERR_A_INO));
if (request_irq(irq, schizo_pcierr_intr, if (request_irq(irq, schizo_pcierr_intr,
SA_SHIRQ, "TOMATILLO PCIERR", pbm) < 0) { SA_SHIRQ, "TOMATILLO PCIERR", pbm) < 0) {
...@@ -1155,16 +1126,13 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info ...@@ -1155,16 +1126,13 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
} }
bucket = __bucket(irq); bucket = __bucket(irq);
tmp = upa_readl(bucket->imap); tmp = upa_readl(bucket->imap);
upa_writel(tmp, (base + upa_writel(tmp, (pbm->pbm_regs +
(is_pbm_a ?
SCHIZO_PBM_A_REGS_OFF :
SCHIZO_PBM_B_REGS_OFF) +
schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));
pbm = &p->pbm_B; pbm = &p->pbm_B;
is_pbm_a = 0; 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)); SCHIZO_PCIERR_B_INO));
if (request_irq(irq, schizo_pcierr_intr, if (request_irq(irq, schizo_pcierr_intr,
SA_SHIRQ, "TOMATILLO PCIERR", pbm) < 0) { SA_SHIRQ, "TOMATILLO PCIERR", pbm) < 0) {
...@@ -1174,13 +1142,10 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info ...@@ -1174,13 +1142,10 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
} }
bucket = __bucket(irq); bucket = __bucket(irq);
tmp = upa_readl(bucket->imap); tmp = upa_readl(bucket->imap);
upa_writel(tmp, (base + upa_writel(tmp, (pbm->pbm_regs +
(is_pbm_a ?
SCHIZO_PBM_A_REGS_OFF :
SCHIZO_PBM_B_REGS_OFF) +
schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); 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, if (request_irq(irq, schizo_safarierr_intr,
SA_SHIRQ, "TOMATILLO SERR", p) < 0) { SA_SHIRQ, "TOMATILLO SERR", p) < 0) {
prom_printf("%s: Cannot register SafariERR interrupt.\n", prom_printf("%s: Cannot register SafariERR interrupt.\n",
...@@ -1189,14 +1154,16 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info ...@@ -1189,14 +1154,16 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
} }
bucket = __bucket(irq); bucket = __bucket(irq);
tmp = upa_readl(bucket->imap); tmp = upa_readl(bucket->imap);
upa_writel(tmp, (base + upa_writel(tmp, (pbm->pbm_regs +
(is_pbm_a ?
SCHIZO_PBM_A_REGS_OFF :
SCHIZO_PBM_B_REGS_OFF) +
schizo_imap_offset(SCHIZO_SERR_INO) + 4)); schizo_imap_offset(SCHIZO_SERR_INO) + 4));
/* Enable UE and CE interrupts for controller. */ /* 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_EE |
SCHIZO_ECCCTRL_UE | SCHIZO_ECCCTRL_UE |
SCHIZO_ECCCTRL_CE)); SCHIZO_ECCCTRL_CE));
...@@ -1211,27 +1178,23 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info ...@@ -1211,27 +1178,23 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
SCHIZO_PCICTRL_SERR | SCHIZO_PCICTRL_SERR |
SCHIZO_PCICTRL_EEN); SCHIZO_PCICTRL_EEN);
tmp = schizo_read(base + tmp = schizo_read(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL);
(is_pbm_a ?
SCHIZO_PCIA_CTRL :
SCHIZO_PCIB_CTRL));
tmp |= err_mask; tmp |= err_mask;
schizo_write(base + schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL, tmp);
(is_pbm_a ?
SCHIZO_PCIA_CTRL : tmp = schizo_read(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL);
SCHIZO_PCIB_CTRL), tmp); tmp |= err_mask;
schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL, tmp);
schizo_write(base +
(is_pbm_a ? err_mask = (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA |
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_PRTRY | SCHIZO_PCIAFSR_PPERR |
SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PTTO |
SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA | SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA |
SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR |
SCHIZO_PCIAFSR_STTO)); 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 | err_mask = (BUS_ERROR_BADCMD | BUS_ERROR_SNOOP_GR |
BUS_ERROR_SNOOP_PCI | BUS_ERROR_SNOOP_RD | BUS_ERROR_SNOOP_PCI | BUS_ERROR_SNOOP_RD |
...@@ -1243,10 +1206,14 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info ...@@ -1243,10 +1206,14 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
BUS_ERROR_APERR | BUS_ERROR_UNMAP | BUS_ERROR_APERR | BUS_ERROR_UNMAP |
BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT); 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_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))); (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));
} }
...@@ -1254,13 +1221,12 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p) ...@@ -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_a = &p->pbm_A;
struct pci_pbm_info *pbm_b = &p->pbm_B; struct pci_pbm_info *pbm_b = &p->pbm_B;
unsigned long base = p->controller_regs; unsigned int irq;
unsigned int irq, portid = p->portid;
struct ino_bucket *bucket; struct ino_bucket *bucket;
u64 tmp, err_mask; u64 tmp, err_mask;
/* Build IRQs and register handlers. */ /* 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, if (request_irq(irq, schizo_ue_intr,
SA_SHIRQ, "SCHIZO UE", p) < 0) { SA_SHIRQ, "SCHIZO UE", p) < 0) {
prom_printf("SCHIZO%d: Cannot register UE interrupt.\n", 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) ...@@ -1269,9 +1235,9 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
} }
bucket = __bucket(irq); bucket = __bucket(irq);
tmp = readl(bucket->imap); 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, if (request_irq(irq, schizo_ce_intr,
SA_SHIRQ, "SCHIZO CE", p) < 0) { SA_SHIRQ, "SCHIZO CE", p) < 0) {
prom_printf("SCHIZO%d: Cannot register CE interrupt.\n", 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) ...@@ -1280,9 +1246,9 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
} }
bucket = __bucket(irq); bucket = __bucket(irq);
tmp = upa_readl(bucket->imap); 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, if (request_irq(irq, schizo_pcierr_intr,
SA_SHIRQ, "SCHIZO PCIERR", pbm_a) < 0) { SA_SHIRQ, "SCHIZO PCIERR", pbm_a) < 0) {
prom_printf("SCHIZO%d(PBMA): Cannot register PciERR interrupt.\n", 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) ...@@ -1291,9 +1257,9 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
} }
bucket = __bucket(irq); bucket = __bucket(irq);
tmp = upa_readl(bucket->imap); 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, if (request_irq(irq, schizo_pcierr_intr,
SA_SHIRQ, "SCHIZO PCIERR", pbm_b) < 0) { SA_SHIRQ, "SCHIZO PCIERR", pbm_b) < 0) {
prom_printf("SCHIZO%d(PBMB): Cannot register PciERR interrupt.\n", 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) ...@@ -1302,9 +1268,9 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
} }
bucket = __bucket(irq); bucket = __bucket(irq);
tmp = upa_readl(bucket->imap); 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, if (request_irq(irq, schizo_safarierr_intr,
SA_SHIRQ, "SCHIZO SERR", p) < 0) { SA_SHIRQ, "SCHIZO SERR", p) < 0) {
prom_printf("SCHIZO%d(PBMB): Cannot register SafariERR interrupt.\n", 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) ...@@ -1313,10 +1279,10 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
} }
bucket = __bucket(irq); bucket = __bucket(irq);
tmp = upa_readl(bucket->imap); 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. */ /* 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_EE |
SCHIZO_ECCCTRL_UE | SCHIZO_ECCCTRL_UE |
SCHIZO_ECCCTRL_CE)); SCHIZO_ECCCTRL_CE));
...@@ -1334,11 +1300,11 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p) ...@@ -1334,11 +1300,11 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
/* Enable PCI Error interrupts and clear error /* Enable PCI Error interrupts and clear error
* bits for each PBM. * bits for each PBM.
*/ */
tmp = schizo_read(base + SCHIZO_PCIA_CTRL); tmp = schizo_read(pbm_a->pbm_regs + SCHIZO_PCI_CTRL);
tmp |= err_mask; 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_PMA | SCHIZO_PCIAFSR_PTA |
SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR |
SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS |
...@@ -1346,11 +1312,11 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p) ...@@ -1346,11 +1312,11 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR |
SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS)); 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; 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_PMA | SCHIZO_PCIAFSR_PTA |
SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR |
SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS |
...@@ -1383,10 +1349,10 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p) ...@@ -1383,10 +1349,10 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB); BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB);
#endif #endif
schizo_write(base + SCHIZO_SAFARI_ERRCTRL, schizo_write(pbm_a->controller_regs + SCHIZO_SAFARI_ERRCTRL,
(SCHIZO_SAFERRCTRL_EN | err_mask)); (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))); (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));
} }
...@@ -1436,10 +1402,10 @@ static void __init pbm_scan_bus(struct pci_controller_info *p, ...@@ -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, 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) { 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"); printk("PCI: Ignoring entire controller.\n");
return; return;
} }
...@@ -1456,7 +1422,7 @@ static void __init __schizo_scan_bus(struct pci_controller_info *p, ...@@ -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 /* After the PCI bus scan is complete, we can register
* the error interrupt handlers. * the error interrupt handlers.
*/ */
if (is_tomatillo) if (chip_type == PBM_CHIP_TYPE_TOMATILLO)
tomatillo_register_error_handlers(p); tomatillo_register_error_handlers(p);
else else
schizo_register_error_handlers(p); schizo_register_error_handlers(p);
...@@ -1464,12 +1430,12 @@ static void __init __schizo_scan_bus(struct pci_controller_info *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) 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) 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) 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, ...@@ -1525,73 +1491,70 @@ static void __init schizo_resource_adjust(struct pci_dev *pdev,
res->end += root->start; res->end += root->start;
} }
/* Interrogate Safari match/mask registers to figure out where /* Use ranges property to determine where PCI MEM, I/O, and Config
* PCI MEM, I/O, and Config space are for this PCI bus module. * space are for this PCI bus module.
*/ */
static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm)
#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)
{ {
u64 mem_match; int i, saw_cfg, saw_mem, saw_io;
u64 io_match;
u64 a;
if (is_pbm_a) { saw_cfg = saw_mem = saw_io = 0;
mem_match = reg_base + SCHIZO_PCI_A_MEM_MATCH; for (i = 0; i < pbm->num_pbm_ranges; i++) {
io_match = reg_base + SCHIZO_PCI_A_IO_MATCH; struct linux_prom_pci_ranges *pr = &pbm->pbm_ranges[i];
} else { unsigned long a;
mem_match = reg_base + SCHIZO_PCI_B_MEM_MATCH; int type;
io_match = reg_base + SCHIZO_PCI_B_IO_MATCH;
}
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) { switch (type) {
a += ((0x3UL << 41UL) | case 0:
((u64)pbm->parent->portid << 36UL)); /* PCI config space, 16MB */
} pbm->config_space = a;
saw_cfg = 1;
break;
/* It should be 2GB in size but the decode is set for the full case 1:
* 4GB so we have to add the 2G by hand. /* 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;
case 2:
/* 32-bit MEM space, 2GB */
pbm->mem_space.start = a; pbm->mem_space.start = a;
pbm->mem_space.end = a + 0x80000000; pbm->mem_space.end = a + (0x80000000UL - 1UL);
pbm->mem_space.flags = IORESOURCE_MEM; pbm->mem_space.flags = IORESOURCE_MEM;
saw_mem = 1;
break;
/* This 32MB area is divided into two pieces. The first default:
* 16MB is Config space, the next 16MB is I/O space. break;
*/ };
a = schizo_read(io_match) & ~0x8000000000000000UL;
if (is_tomatillo) {
a += ((0x3UL << 41UL) |
((u64)pbm->parent->portid << 36UL));
} }
pbm->config_space = a; if (!saw_cfg || !saw_io || !saw_mem) {
printk("%s: Local PCI config space at %016lx\n", prom_printf("%s: Fatal error, missing %s PBM range.\n",
pbm->name, pbm->config_space); pbm->name,
((!saw_cfg ?
"CFG" :
(!saw_io ?
"IO" : "MEM"))));
prom_halt();
}
a += (16UL * 1024UL * 1024UL); printk("%s: PCI CFG[%lx] IO[%lx] MEM[%lx]\n",
pbm->io_space.start = a; pbm->name,
pbm->io_space.end = a + ((16UL * 1024UL * 1024UL) - 1UL); pbm->config_space,
pbm->io_space.flags = IORESOURCE_IO; pbm->io_space.start,
pbm->mem_space.start);
} }
static void __init pbm_register_toplevel_resources(struct pci_controller_info *p, static void __init pbm_register_toplevel_resources(struct pci_controller_info *p,
struct pci_pbm_info *pbm, struct pci_pbm_info *pbm)
int is_tomatillo)
{ {
pbm->io_space.name = pbm->mem_space.name = pbm->name; 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 ...@@ -1601,45 +1564,28 @@ static void __init pbm_register_toplevel_resources(struct pci_controller_info *p
&pbm->mem_space); &pbm->mem_space);
} }
#define SCHIZO_STRBUF_CONTROL_A (SCHIZO_PBM_A_REGS_OFF + 0x02800UL) #define SCHIZO_STRBUF_CONTROL (0x02800UL)
#define SCHIZO_STRBUF_FLUSH_A (SCHIZO_PBM_A_REGS_OFF + 0x02808UL) #define SCHIZO_STRBUF_FLUSH (0x02808UL)
#define SCHIZO_STRBUF_FSYNC_A (SCHIZO_PBM_A_REGS_OFF + 0x02810UL) #define SCHIZO_STRBUF_FSYNC (0x02810UL)
#define SCHIZO_STRBUF_CTXFLUSH_A (SCHIZO_PBM_A_REGS_OFF + 0x02818UL) #define SCHIZO_STRBUF_CTXFLUSH (0x02818UL)
#define SCHIZO_STRBUF_CTXMATCH_A (SCHIZO_PBM_A_REGS_OFF + 0x10000UL) #define SCHIZO_STRBUF_CTXMATCH (0x10000UL)
#define SCHIZO_STRBUF_CONTROL_B (SCHIZO_PBM_B_REGS_OFF + 0x02800UL) static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm)
#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)
{ {
unsigned long base = p->controller_regs; unsigned long base = pbm->pbm_regs;
u64 control; u64 control;
if (is_tomatillo) { if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {
/* TOMATILLO lacks streaming cache. */ /* TOMATILLO lacks streaming cache. */
return; return;
} }
/* SCHIZO has context flushing. */ /* SCHIZO has context flushing. */
if (is_pbm_a) { pbm->stc.strbuf_control = base + SCHIZO_STRBUF_CONTROL;
pbm->stc.strbuf_control = base + SCHIZO_STRBUF_CONTROL_A; pbm->stc.strbuf_pflush = base + SCHIZO_STRBUF_FLUSH;
pbm->stc.strbuf_pflush = base + SCHIZO_STRBUF_FLUSH_A; pbm->stc.strbuf_fsync = base + SCHIZO_STRBUF_FSYNC;
pbm->stc.strbuf_fsync = base + SCHIZO_STRBUF_FSYNC_A; pbm->stc.strbuf_ctxflush = base + SCHIZO_STRBUF_CTXFLUSH;
pbm->stc.strbuf_ctxflush = base + SCHIZO_STRBUF_CTXFLUSH_A; pbm->stc.strbuf_ctxmatch_base = base + SCHIZO_STRBUF_CTXMATCH;
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_flushflag = (volatile unsigned long *) pbm->stc.strbuf_flushflag = (volatile unsigned long *)
((((unsigned long)&pbm->stc.__flushflag_buf[0]) ((((unsigned long)&pbm->stc.__flushflag_buf[0])
...@@ -1662,23 +1608,12 @@ static void schizo_pbm_strbuf_init(struct pci_controller_info *p, ...@@ -1662,23 +1608,12 @@ static void schizo_pbm_strbuf_init(struct pci_controller_info *p,
pbm->stc.strbuf_enabled = 1; pbm->stc.strbuf_enabled = 1;
} }
#define SCHIZO_IOMMU_CONTROL_A (SCHIZO_PBM_A_REGS_OFF + 0x00200UL) #define SCHIZO_IOMMU_CONTROL (0x00200UL)
#define SCHIZO_IOMMU_TSBBASE_A (SCHIZO_PBM_A_REGS_OFF + 0x00208UL) #define SCHIZO_IOMMU_TSBBASE (0x00208UL)
#define SCHIZO_IOMMU_FLUSH_A (SCHIZO_PBM_A_REGS_OFF + 0x00210UL) #define SCHIZO_IOMMU_FLUSH (0x00210UL)
#define SCHIZO_IOMMU_CTXFLUSH_A (SCHIZO_PBM_A_REGS_OFF + 0x00218UL) #define SCHIZO_IOMMU_CTXFLUSH (0x00218UL)
#define SCHIZO_IOMMU_TAG_A (SCHIZO_PBM_A_REGS_OFF + 0x0a580UL)
#define SCHIZO_IOMMU_DATA_A (SCHIZO_PBM_A_REGS_OFF + 0x0a600UL) static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
#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)
{ {
struct pci_iommu *iommu = pbm->iommu; struct pci_iommu *iommu = pbm->iommu;
unsigned long tsbbase, i, tagbase, database; unsigned long tsbbase, i, tagbase, database;
...@@ -1689,22 +1624,15 @@ static void schizo_pbm_iommu_init(struct pci_controller_info *p, ...@@ -1689,22 +1624,15 @@ static void schizo_pbm_iommu_init(struct pci_controller_info *p,
iommu->iommu_cur_ctx = 0; iommu->iommu_cur_ctx = 0;
/* Register addresses, SCHIZO has iommu ctx flushing. */ /* Register addresses, SCHIZO has iommu ctx flushing. */
if (is_pbm_a) { iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL;
iommu->iommu_control = p->controller_regs + SCHIZO_IOMMU_CONTROL_A; iommu->iommu_tsbbase = pbm->pbm_regs + SCHIZO_IOMMU_TSBBASE;
iommu->iommu_tsbbase = p->controller_regs + SCHIZO_IOMMU_TSBBASE_A; iommu->iommu_flush = pbm->pbm_regs + SCHIZO_IOMMU_FLUSH;
iommu->iommu_flush = p->controller_regs + SCHIZO_IOMMU_FLUSH_A; iommu->iommu_ctxflush = pbm->pbm_regs + SCHIZO_IOMMU_CTXFLUSH;
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;
}
/* We use the main control/status register of SCHIZO as the write /* We use the main control/status register of SCHIZO as the write
* completion register. * completion register.
*/ */
iommu->write_complete_reg = p->controller_regs + 0x10000UL; iommu->write_complete_reg = pbm->controller_regs + 0x10000UL;
/* /*
* Invalidate TLB Entries. * Invalidate TLB Entries.
...@@ -1713,13 +1641,11 @@ static void schizo_pbm_iommu_init(struct pci_controller_info *p, ...@@ -1713,13 +1641,11 @@ static void schizo_pbm_iommu_init(struct pci_controller_info *p,
control |= SCHIZO_IOMMU_CTRL_DENAB; control |= SCHIZO_IOMMU_CTRL_DENAB;
schizo_write(iommu->iommu_control, control); schizo_write(iommu->iommu_control, control);
if (is_pbm_a) tagbase = SCHIZO_IOMMU_TAG, database = SCHIZO_IOMMU_DATA;
tagbase = SCHIZO_IOMMU_TAG_A, database = SCHIZO_IOMMU_DATA_A;
else
tagbase = SCHIZO_IOMMU_TAG_B, database = SCHIZO_IOMMU_DATA_B;
for(i = 0; i < 16; i++) { for(i = 0; i < 16; i++) {
schizo_write(p->controller_regs + tagbase + (i * 8UL), 0); schizo_write(pbm->pbm_regs + tagbase + (i * 8UL), 0);
schizo_write(p->controller_regs + database + (i * 8UL), 0); schizo_write(pbm->pbm_regs + database + (i * 8UL), 0);
} }
/* Leave diag mode enabled for full-flushing done /* Leave diag mode enabled for full-flushing done
...@@ -1758,12 +1684,10 @@ static void schizo_pbm_iommu_init(struct pci_controller_info *p, ...@@ -1758,12 +1684,10 @@ static void schizo_pbm_iommu_init(struct pci_controller_info *p,
schizo_write(iommu->iommu_control, control); schizo_write(iommu->iommu_control, control);
} }
#define SCHIZO_PCIA_IRQ_RETRY (SCHIZO_PBM_A_REGS_OFF + 0x1a00UL) #define SCHIZO_PCI_IRQ_RETRY (0x1a00UL)
#define SCHIZO_PCIB_IRQ_RETRY (SCHIZO_PBM_B_REGS_OFF + 0x1a00UL)
#define SCHIZO_IRQ_RETRY_INF 0xffUL #define SCHIZO_IRQ_RETRY_INF 0xffUL
#define SCHIZO_PCIA_DIAG (SCHIZO_PBM_A_REGS_OFF + 0x2020UL) #define SCHIZO_PCI_DIAG (0x2020UL)
#define SCHIZO_PCIB_DIAG (SCHIZO_PBM_B_REGS_OFF + 0x2020UL)
#define SCHIZO_PCIDIAG_D_BADECC (1UL << 10UL) /* Disable BAD ECC errors (Schizo) */ #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_BYPASS (1UL << 9UL) /* Disable MMU bypass mode (Schizo/Tomatillo) */
#define SCHIZO_PCIDIAG_D_TTO (1UL << 8UL) /* Disable TTO errors (Schizo/Tomatillo) */ #define SCHIZO_PCIDIAG_D_TTO (1UL << 8UL) /* Disable TTO errors (Schizo/Tomatillo) */
...@@ -1774,94 +1698,164 @@ static void schizo_pbm_iommu_init(struct pci_controller_info *p, ...@@ -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_PIOD_PARITY (1UL << 2UL) /* Invert PIO data parity (Schizo/Tomatillo) */
#define SCHIZO_PCIDIAG_I_PIOA_PARITY (1UL << 1UL) /* Invert PIO address parity (Schizo/Tomatillo) */ #define 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, #define TOMATILLO_PCI_IOC_CSR (0x2248UL)
int is_pbm_a, int is_tomatillo) #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; u64 tmp;
/* Set IRQ retry to infinity. */ /* Set IRQ retry to infinity. */
schizo_write(p->controller_regs + schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY,
(is_pbm_a ?
SCHIZO_PCIA_IRQ_RETRY :
SCHIZO_PCIB_IRQ_RETRY),
SCHIZO_IRQ_RETRY_INF); SCHIZO_IRQ_RETRY_INF);
/* Enable arbiter for all PCI slots. Also, disable PCI interval /* Enable arbiter for all PCI slots. Also, disable PCI interval
* timer so that DTO (Discard TimeOuts) are not reported because * timer so that DTO (Discard TimeOuts) are not reported because
* some Schizo revisions report them erroneously. * some Schizo revisions report them erroneously.
*/ */
tmp = schizo_read(p->controller_regs + tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL);
(is_pbm_a ? if (pbm->chip_type == PBM_CHIP_TYPE_SCHIZO_PLUS &&
SCHIZO_PCIA_CTRL : pbm->chip_version == 0x5 &&
SCHIZO_PCIB_CTRL)); pbm->chip_revision == 0x1)
if (is_tomatillo) tmp |= 0x0f;
tmp |= SCHIZO_PCICTRL_ARB_T;
else else
tmp |= SCHIZO_PCICTRL_ARB_S; tmp |= 0xff;
if (is_tomatillo) {
#if 0 if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO &&
/* This is the recommended setting, but we'll just pbm->chip_version == 0x2) {
* leave the value alone for now.
*/
tmp &= ~SCHIZO_PCICTRL_PTO;
tmp |= 0x1UL << SCHIZO_PCICTRL_PTO_SHIFT;
#endif
/* XXX Prefetch settings? */
} else {
tmp &= ~SCHIZO_PCICTRL_PTO; tmp &= ~SCHIZO_PCICTRL_PTO;
tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT;
} }
schizo_write(p->controller_regs +
(is_pbm_a ? if (!prom_getbool(pbm->prom_node, "no-bus-parking"))
SCHIZO_PCIA_CTRL : tmp |= SCHIZO_PCICTRL_PARK;
SCHIZO_PCIB_CTRL), tmp);
if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO)
/* Leave this at OBP initialized value on Tomatillo. */ tmp |= SCHIZO_PCICTRL_MRM_PREF;
if (!is_tomatillo) {
/* Disable TTO error reporting (won't happen anyway since we schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp);
* disabled the PCI interval timer above) and retry arbitration
* (can cause hangs in some Schizo revisions). 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 + tmp = (TOMATILLO_IOC_PART_WPENAB |
(is_pbm_a ? (1 << TOMATILLO_IOC_PREF_OFF_SHIFT) |
SCHIZO_PCIA_DIAG : TOMATILLO_IOC_RDMULT_CPENAB |
SCHIZO_PCIB_DIAG)); TOMATILLO_IOC_RDONE_CPENAB |
tmp |= (SCHIZO_PCIDIAG_D_TTO | SCHIZO_PCIDIAG_D_RTRYARB); TOMATILLO_IOC_RDLINE_CPENAB);
schizo_write(p->controller_regs +
(is_pbm_a ? schizo_write(pbm->pbm_regs + TOMATILLO_PCI_IOC_CSR,
SCHIZO_PCIA_DIAG : tmp);
SCHIZO_PCIB_DIAG), tmp);
} }
} }
static void __init schizo_pbm_init(struct pci_controller_info *p, static void __init schizo_pbm_init(struct pci_controller_info *p,
int prom_node, int is_pbm_a, int prom_node, u32 portid,
int is_tomatillo) int chip_type)
{ {
struct linux_prom64_registers pr_regs[4];
unsigned int busrange[2]; unsigned int busrange[2];
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
const char *chipset_name;
int is_pbm_a;
int err; 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) if (is_pbm_a)
pbm = &p->pbm_A; pbm = &p->pbm_A;
else else
pbm = &p->pbm_B; pbm = &p->pbm_B;
pbm->portid = portid;
pbm->parent = p; pbm->parent = p;
pbm->prom_node = prom_node; pbm->prom_node = prom_node;
pbm->pci_first_slot = 1; 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, sprintf(pbm->name,
(is_tomatillo ? (chip_type == PBM_CHIP_TYPE_TOMATILLO ?
"TOMATILLO%d PBM%c" : "TOMATILLO%d PBM%c" :
"SCHIZO%d PBM%c"), "SCHIZO%d PBM%c"),
p->index, p->index,
(pbm == &p->pbm_A ? 'A' : 'B')); (pbm == &p->pbm_A ? 'A' : 'B'));
schizo_determine_mem_io_space(pbm, is_pbm_a, printk("%s: ver[%x:%x], portid %x, "
p->controller_regs, is_tomatillo); "cregs[%lx] pregs[%lx]\n",
pbm_register_toplevel_resources(p, pbm, is_tomatillo); 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", prom_getstring(prom_node, "name",
pbm->prom_name, pbm->prom_name,
...@@ -1870,11 +1864,17 @@ static void __init schizo_pbm_init(struct pci_controller_info *p, ...@@ -1870,11 +1864,17 @@ static void __init schizo_pbm_init(struct pci_controller_info *p,
err = prom_getproperty(prom_node, "ranges", err = prom_getproperty(prom_node, "ranges",
(char *) pbm->pbm_ranges, (char *) pbm->pbm_ranges,
sizeof(pbm->pbm_ranges)); sizeof(pbm->pbm_ranges));
if (err != -1) if (err == 0 || err == -1) {
prom_printf("%s: Fatal error, no ranges property.\n",
pbm->name);
prom_halt();
}
pbm->num_pbm_ranges = pbm->num_pbm_ranges =
(err / sizeof(struct linux_prom_pci_ranges)); (err / sizeof(struct linux_prom_pci_ranges));
else
pbm->num_pbm_ranges = 0; schizo_determine_mem_io_space(pbm);
pbm_register_toplevel_resources(p, pbm);
err = prom_getproperty(prom_node, "interrupt-map", err = prom_getproperty(prom_node, "interrupt-map",
(char *)pbm->pbm_intmap, (char *)pbm->pbm_intmap,
...@@ -1904,13 +1904,13 @@ static void __init schizo_pbm_init(struct pci_controller_info *p, ...@@ -1904,13 +1904,13 @@ static void __init schizo_pbm_init(struct pci_controller_info *p,
pbm->pci_first_busno = busrange[0]; pbm->pci_first_busno = busrange[0];
pbm->pci_last_busno = busrange[1]; pbm->pci_last_busno = busrange[1];
schizo_pbm_iommu_init(p, pbm, is_pbm_a, is_tomatillo); schizo_pbm_iommu_init(pbm);
schizo_pbm_strbuf_init(p, pbm, is_pbm_a, is_tomatillo); 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)) if (x == (y ^ 1))
return 1; return 1;
return 0; return 0;
...@@ -1918,29 +1918,31 @@ static inline int portid_compare(u32 x, u32 y, int is_tomatillo) ...@@ -1918,29 +1918,31 @@ static inline int portid_compare(u32 x, u32 y, int is_tomatillo)
return (x == y); 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_controller_info *p;
struct pci_iommu *iommu; struct pci_iommu *iommu;
unsigned long flags; unsigned long flags;
int is_pbm_a;
u32 portid; 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); portid = prom_getintdefault(node, "portid", 0xff);
spin_lock_irqsave(&pci_controller_lock, flags); spin_lock_irqsave(&pci_controller_lock, flags);
for(p = pci_controller_root; p; p = p->next) { 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); spin_unlock_irqrestore(&pci_controller_lock, flags);
is_pbm_a = (p->pbm_A.prom_node == 0); 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; return;
} }
} }
...@@ -1948,16 +1950,14 @@ static void __init __schizo_init(int node, char *model_name, int is_tomatillo) ...@@ -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); p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
if (!p) { if (!p) {
prom_printf("%s: Fatal memory allocation error.\n", prom_printf("SCHIZO: Fatal memory allocation error.\n");
chipset_name);
prom_halt(); prom_halt();
} }
memset(p, 0, sizeof(*p)); memset(p, 0, sizeof(*p));
iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC); iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
if (!iommu) { if (!iommu) {
prom_printf("%s: Fatal memory allocation error.\n", prom_printf("SCHIZO: Fatal memory allocation error.\n");
chipset_name);
prom_halt(); prom_halt();
} }
memset(iommu, 0, sizeof(*iommu)); memset(iommu, 0, sizeof(*iommu));
...@@ -1965,8 +1965,7 @@ static void __init __schizo_init(int node, char *model_name, int is_tomatillo) ...@@ -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); iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
if (!iommu) { if (!iommu) {
prom_printf("%s: Fatal memory allocation error.\n", prom_printf("SCHIZO: Fatal memory allocation error.\n");
chipset_name);
prom_halt(); prom_halt();
} }
memset(iommu, 0, sizeof(*iommu)); memset(iommu, 0, sizeof(*iommu));
...@@ -1977,54 +1976,33 @@ static void __init __schizo_init(int node, char *model_name, int is_tomatillo) ...@@ -1977,54 +1976,33 @@ static void __init __schizo_init(int node, char *model_name, int is_tomatillo)
pci_controller_root = p; pci_controller_root = p;
spin_unlock_irqrestore(&pci_controller_lock, flags); spin_unlock_irqrestore(&pci_controller_lock, flags);
p->portid = portid;
p->index = pci_num_controllers++; p->index = pci_num_controllers++;
p->pbms_same_domain = 0; 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->irq_build = schizo_irq_build;
p->base_address_update = schizo_base_address_update; p->base_address_update = schizo_base_address_update;
p->resource_adjust = schizo_resource_adjust; p->resource_adjust = schizo_resource_adjust;
p->pci_ops = &schizo_ops; 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. */ /* Like PSYCHO we have a 2GB aligned area for memory space. */
pci_memspace_mask = 0x7fffffffUL; pci_memspace_mask = 0x7fffffffUL;
is_pbm_a = ((pr_regs[0].phys_addr & 0x00700000) == 0x00600000); schizo_pbm_init(p, node, portid, chip_type);
schizo_pbm_init(p, node, is_pbm_a, is_tomatillo);
} }
void __init schizo_init(int node, char *model_name) 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) void __init tomatillo_init(int node, char *model_name)
{ {
__schizo_init(node, model_name, 1); __schizo_init(node, model_name, PBM_CHIP_TYPE_TOMATILLO);
} }
...@@ -128,6 +128,25 @@ struct pci_pbm_info { ...@@ -128,6 +128,25 @@ struct pci_pbm_info {
/* PCI controller we sit under. */ /* PCI controller we sit under. */
struct pci_controller_info *parent; 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. */ /* Name used for top-level resources. */
char name[64]; char name[64];
...@@ -170,12 +189,6 @@ struct pci_controller_info { ...@@ -170,12 +189,6 @@ struct pci_controller_info {
/* List of all PCI controllers. */ /* List of all PCI controllers. */
struct pci_controller_info *next; 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 /* Each controller gets a unique index, used mostly for
* error logging purposes. * error logging purposes.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment