[SPARC64]: Move index info pci_pbm_info.
[powerpc.git] / arch / sparc64 / kernel / pci_schizo.c
index f16449c..72743ac 100644 (file)
@@ -1,7 +1,6 @@
-/* $Id: pci_schizo.c,v 1.24 2002/01/23 11:27:32 davem Exp $
- * pci_schizo.c: SCHIZO/TOMATILLO specific PCI controller support.
+/* pci_schizo.c: SCHIZO/TOMATILLO specific PCI controller support.
  *
- * Copyright (C) 2001, 2002, 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2001, 2002, 2003, 2007 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/kernel.h>
@@ -126,6 +125,9 @@ static int schizo_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
        u16 tmp16;
        u8 tmp8;
 
+       if (bus_dev == pbm->pci_bus && devfn == 0x00)
+               return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
+                                                   size, value);
        switch (size) {
        case 1:
                *value = 0xff;
@@ -179,6 +181,9 @@ static int schizo_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
        unsigned char bus = bus_dev->number;
        u32 *addr;
 
+       if (bus_dev == pbm->pci_bus && devfn == 0x00)
+               return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
+                                                    size, value);
        addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where);
        if (!addr)
                return PCIBIOS_SUCCESSFUL;
@@ -217,116 +222,6 @@ static struct pci_ops schizo_ops = {
        .write =        schizo_write_pci_cfg,
 };
 
-/* SCHIZO interrupt mapping support.  Unlike Psycho, for this controller the
- * imap/iclr registers are per-PBM.
- */
-#define SCHIZO_IMAP_BASE       0x1000UL
-#define SCHIZO_ICLR_BASE       0x1400UL
-
-static unsigned long schizo_imap_offset(unsigned long ino)
-{
-       return SCHIZO_IMAP_BASE + (ino * 8UL);
-}
-
-static unsigned long schizo_iclr_offset(unsigned long ino)
-{
-       return SCHIZO_ICLR_BASE + (ino * 8UL);
-}
-
-static void tomatillo_wsync_handler(unsigned int ino, void *_arg1, void *_arg2)
-{
-       unsigned long sync_reg = (unsigned long) _arg2;
-       u64 mask = 1UL << (ino & IMAP_INO);
-       u64 val;
-       int limit;
-
-       schizo_write(sync_reg, mask);
-
-       limit = 100000;
-       val = 0;
-       while (--limit) {
-               val = schizo_read(sync_reg);
-               if (!(val & mask))
-                       break;
-       }
-       if (limit <= 0) {
-               printk("tomatillo_wsync_handler: DMA won't sync [%lx:%lx]\n",
-                      val, mask);
-       }
-
-       if (_arg1) {
-               static unsigned char cacheline[64]
-                       __attribute__ ((aligned (64)));
-
-               __asm__ __volatile__("rd %%fprs, %0\n\t"
-                                    "or %0, %4, %1\n\t"
-                                    "wr %1, 0x0, %%fprs\n\t"
-                                    "stda %%f0, [%5] %6\n\t"
-                                    "wr %0, 0x0, %%fprs\n\t"
-                                    "membar #Sync"
-                                    : "=&r" (mask), "=&r" (val)
-                                    : "0" (mask), "1" (val),
-                                    "i" (FPRS_FEF), "r" (&cacheline[0]),
-                                    "i" (ASI_BLK_COMMIT_P));
-       }
-}
-
-static unsigned long schizo_ino_to_iclr(struct pci_pbm_info *pbm,
-                                       unsigned int ino)
-{
-       ino &= PCI_IRQ_INO;
-       return pbm->pbm_regs + schizo_iclr_offset(ino) + 4;
-}
-
-static unsigned long schizo_ino_to_imap(struct pci_pbm_info *pbm,
-                                       unsigned int ino)
-{
-       ino &= PCI_IRQ_INO;
-       return pbm->pbm_regs + schizo_imap_offset(ino) + 4;
-}
-
-static unsigned int schizo_irq_build(struct pci_pbm_info *pbm,
-                                    struct pci_dev *pdev,
-                                    unsigned int ino)
-{
-       unsigned long imap, iclr;
-       int ign_fixup;
-       int virt_irq;
-
-       ino &= PCI_IRQ_INO;
-
-       /* Now build the IRQ bucket. */
-       imap = schizo_ino_to_imap(pbm, ino);
-       iclr = schizo_ino_to_iclr(pbm, ino);
-
-       /* On Schizo, no inofixup occurs.  This is because each
-        * INO has it's own IMAP register.  On Psycho and Sabre
-        * there is only one IMAP register for each PCI slot even
-        * though four different INOs can be generated by each
-        * PCI slot.
-        *
-        * But, for JBUS variants (essentially, Tomatillo), we have
-        * to fixup the lowest bit of the interrupt group number.
-        */
-       ign_fixup = 0;
-       if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {
-               if (pbm->portid & 1)
-                       ign_fixup = (1 << 6);
-       }
-
-       virt_irq = build_irq(ign_fixup, iclr, imap);
-
-       if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {
-               irq_install_pre_handler(virt_irq,
-                                       tomatillo_wsync_handler,
-                                       ((pbm->chip_version <= 4) ?
-                                        (void *) 1 : (void *) 0),
-                                       (void *) pbm->sync_reg);
-       }
-
-       return virt_irq;
-}
-
 /* SCHIZO error handling support. */
 enum schizo_error_type {
        UE_ERR, CE_ERR, PCI_ERR, SAFARI_ERR
@@ -343,53 +238,6 @@ static unsigned long stc_line_buf[16];
 #define SCHIZO_PCIERR_B_INO    0x33 /* PBM B PCI bus error */
 #define SCHIZO_SERR_INO                0x34 /* Safari interface error */
 
-struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino)
-{
-       ino &= IMAP_INO;
-       if (p->pbm_A.ino_bitmap & (1UL << ino))
-               return &p->pbm_A;
-       if (p->pbm_B.ino_bitmap & (1UL << ino))
-               return &p->pbm_B;
-
-       printk("PCI%d: No ino_bitmap entry for ino[%x], bitmaps "
-              "PBM_A[%016lx] PBM_B[%016lx]",
-              p->index, ino,
-              p->pbm_A.ino_bitmap,
-              p->pbm_B.ino_bitmap);
-       printk("PCI%d: Using PBM_A, report this problem immediately.\n",
-              p->index);
-
-       return &p->pbm_A;
-}
-
-static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq)
-{
-       struct pci_pbm_info *pbm;
-       unsigned long iclr;
-
-       /* Do not clear the interrupt for the other PCI bus.
-        *
-        * This "ACK both PBM IRQs" only needs to be performed
-        * for chip-wide error interrupts.
-        */
-       if ((irq & IMAP_INO) == SCHIZO_PCIERR_A_INO ||
-           (irq & IMAP_INO) == SCHIZO_PCIERR_B_INO)
-               return;
-
-       pbm = pbm_for_ino(p, irq);
-       if (pbm == &p->pbm_A)
-               pbm = &p->pbm_B;
-       else
-               pbm = &p->pbm_A;
-
-       schizo_irq_build(pbm, NULL,
-                        (pbm->portid << 6) | (irq & IMAP_INO));
-
-       iclr = schizo_ino_to_iclr(pbm,
-                                 (pbm->portid << 6) | (irq & IMAP_INO));
-       upa_writel(ICLR_IDLE, iclr);
-}
-
 #define SCHIZO_STC_ERR 0xb800UL /* --> 0xba00 */
 #define SCHIZO_STC_TAG 0xba00UL /* --> 0xba80 */
 #define SCHIZO_STC_LINE        0xbb00UL /* --> 0xbb80 */
@@ -412,7 +260,7 @@ static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq)
 static void __schizo_check_stc_error_pbm(struct pci_pbm_info *pbm,
                                         enum schizo_error_type type)
 {
-       struct pci_strbuf *strbuf = &pbm->stc;
+       struct strbuf *strbuf = &pbm->stc;
        unsigned long regbase = pbm->pbm_regs;
        unsigned long err_base, tag_base, line_base;
        u64 control;
@@ -520,7 +368,7 @@ 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_iommu *iommu = pbm->iommu;
+       struct iommu *iommu = pbm->iommu;
        unsigned long iommu_tag[16];
        unsigned long iommu_data[16];
        unsigned long flags;
@@ -653,11 +501,12 @@ static void schizo_check_iommu_error(struct pci_controller_info *p,
 #define SCHIZO_UEAFSR_MTAG     0x000000000000e000UL /* Safari */
 #define SCHIZO_UEAFSR_ECCSYND  0x00000000000001ffUL /* Safari */
 
-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 pci_controller_info *p = dev_id;
-       unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFSR;
-       unsigned long afar_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFAR;
+       struct pci_pbm_info *pbm = dev_id;
+       struct pci_controller_info *p = pbm->parent;
+       unsigned long afsr_reg = pbm->controller_regs + SCHIZO_UE_AFSR;
+       unsigned long afar_reg = pbm->controller_regs + SCHIZO_UE_AFAR;
        unsigned long afsr, afar, error_bits;
        int reported, limit;
 
@@ -682,28 +531,28 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
        schizo_write(afsr_reg, error_bits);
 
        /* Log the error. */
-       printk("PCI%d: Uncorrectable Error, primary error type[%s]\n",
-              p->index,
+       printk("%s: Uncorrectable Error, primary error type[%s]\n",
+              pbm->name,
               (((error_bits & SCHIZO_UEAFSR_PPIO) ?
                 "PIO" :
                 ((error_bits & SCHIZO_UEAFSR_PDRD) ?
                  "DMA Read" :
                  ((error_bits & SCHIZO_UEAFSR_PDWR) ?
                   "DMA Write" : "???")))));
-       printk("PCI%d: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n",
-              p->index,
+       printk("%s: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n",
+              pbm->name,
               (afsr & SCHIZO_UEAFSR_BMSK) >> 32UL,
               (afsr & SCHIZO_UEAFSR_QOFF) >> 30UL,
               (afsr & SCHIZO_UEAFSR_AID) >> 24UL);
-       printk("PCI%d: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n",
-              p->index,
+       printk("%s: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n",
+              pbm->name,
               (afsr & SCHIZO_UEAFSR_PARTIAL) ? 1 : 0,
               (afsr & SCHIZO_UEAFSR_OWNEDIN) ? 1 : 0,
               (afsr & SCHIZO_UEAFSR_MTAG) >> 13UL,
               (afsr & SCHIZO_UEAFSR_MTAGSYND) >> 16UL,
               (afsr & SCHIZO_UEAFSR_ECCSYND) >> 0UL);
-       printk("PCI%d: UE AFAR [%016lx]\n", p->index, afar);
-       printk("PCI%d: UE Secondary errors [", p->index);
+       printk("%s: UE AFAR [%016lx]\n", pbm->name, afar);
+       printk("%s: UE Secondary errors [", pbm->name);
        reported = 0;
        if (afsr & SCHIZO_UEAFSR_SPIO) {
                reported++;
@@ -720,8 +569,6 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
        /* Interrogate IOMMU for error status. */
        schizo_check_iommu_error(p, UE_ERR);
 
-       schizo_clear_other_err_intr(p, irq);
-
        return IRQ_HANDLED;
 }
 
@@ -743,11 +590,11 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
 #define SCHIZO_CEAFSR_MTAG     0x000000000000e000UL
 #define SCHIZO_CEAFSR_ECCSYND  0x00000000000001ffUL
 
-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 pci_controller_info *p = dev_id;
-       unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFSR;
-       unsigned long afar_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFAR;
+       struct pci_pbm_info *pbm = dev_id;
+       unsigned long afsr_reg = pbm->controller_regs + SCHIZO_CE_AFSR;
+       unsigned long afar_reg = pbm->controller_regs + SCHIZO_CE_AFAR;
        unsigned long afsr, afar, error_bits;
        int reported, limit;
 
@@ -772,8 +619,8 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
        schizo_write(afsr_reg, error_bits);
 
        /* Log the error. */
-       printk("PCI%d: Correctable Error, primary error type[%s]\n",
-              p->index,
+       printk("%s: Correctable Error, primary error type[%s]\n",
+              pbm->name,
               (((error_bits & SCHIZO_CEAFSR_PPIO) ?
                 "PIO" :
                 ((error_bits & SCHIZO_CEAFSR_PDRD) ?
@@ -784,20 +631,20 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
        /* XXX Use syndrome and afar to print out module string just like
         * XXX UDB CE trap handler does... -DaveM
         */
-       printk("PCI%d: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n",
-              p->index,
+       printk("%s: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n",
+              pbm->name,
               (afsr & SCHIZO_UEAFSR_BMSK) >> 32UL,
               (afsr & SCHIZO_UEAFSR_QOFF) >> 30UL,
               (afsr & SCHIZO_UEAFSR_AID) >> 24UL);
-       printk("PCI%d: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n",
-              p->index,
+       printk("%s: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n",
+              pbm->name,
               (afsr & SCHIZO_UEAFSR_PARTIAL) ? 1 : 0,
               (afsr & SCHIZO_UEAFSR_OWNEDIN) ? 1 : 0,
               (afsr & SCHIZO_UEAFSR_MTAG) >> 13UL,
               (afsr & SCHIZO_UEAFSR_MTAGSYND) >> 16UL,
               (afsr & SCHIZO_UEAFSR_ECCSYND) >> 0UL);
-       printk("PCI%d: CE AFAR [%016lx]\n", p->index, afar);
-       printk("PCI%d: CE Secondary errors [", p->index);
+       printk("%s: CE AFAR [%016lx]\n", pbm->name, afar);
+       printk("%s: CE Secondary errors [", pbm->name);
        reported = 0;
        if (afsr & SCHIZO_CEAFSR_SPIO) {
                reported++;
@@ -811,8 +658,6 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
                printk("(none)");
        printk("]\n");
 
-       schizo_clear_other_err_intr(p, irq);
-
        return IRQ_HANDLED;
 }
 
@@ -920,7 +765,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm)
        return ret;
 }
 
-static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id)
 {
        struct pci_pbm_info *pbm = dev_id;
        struct pci_controller_info *p = pbm->parent;
@@ -1018,10 +863,10 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id, struct pt_regs *reg
         */
        if (error_bits & (SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_STA)) {
                schizo_check_iommu_error(p, PCI_ERR);
-               pci_scan_for_target_abort(p, pbm, pbm->pci_bus);
+               pci_scan_for_target_abort(pbm, pbm->pci_bus);
        }
        if (error_bits & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_SMA))
-               pci_scan_for_master_abort(p, pbm, pbm->pci_bus);
+               pci_scan_for_master_abort(pbm, pbm->pci_bus);
 
        /* For excessive retries, PSYCHO/PBM will abort the device
         * and there is no way to specifically check for excessive
@@ -1031,9 +876,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id, struct pt_regs *reg
         */
 
        if (error_bits & (SCHIZO_PCIAFSR_PPERR | SCHIZO_PCIAFSR_SPERR))
-               pci_scan_for_parity_error(p, pbm, pbm->pci_bus);
-
-       schizo_clear_other_err_intr(p, irq);
+               pci_scan_for_parity_error(pbm, pbm->pci_bus);
 
        return IRQ_HANDLED;
 }
@@ -1077,28 +920,27 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id, struct pt_regs *reg
 /* We only expect UNMAP errors here.  The rest of the Safari errors
  * are marked fatal and thus cause a system reset.
  */
-static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id)
 {
-       struct pci_controller_info *p = dev_id;
+       struct pci_pbm_info *pbm = dev_id;
+       struct pci_controller_info *p = pbm->parent;
        u64 errlog;
 
-       errlog = schizo_read(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRLOG);
-       schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRLOG,
+       errlog = schizo_read(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG);
+       schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG,
                     errlog & ~(SAFARI_ERRLOG_ERROUT));
 
        if (!(errlog & BUS_ERROR_UNMAP)) {
-               printk("PCI%d: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n",
-                      p->index, errlog);
+               printk("%s: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n",
+                      pbm->name, errlog);
 
-               schizo_clear_other_err_intr(p, irq);
                return IRQ_HANDLED;
        }
 
-       printk("PCI%d: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n",
-              p->index);
+       printk("%s: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n",
+              pbm->name);
        schizo_check_iommu_error(p, SAFARI_ERR);
 
-       schizo_clear_other_err_intr(p, irq);
        return IRQ_HANDLED;
 }
 
@@ -1113,6 +955,16 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *
 #define SCHIZO_SAFARI_IRQCTRL  0x10010UL
 #define  SCHIZO_SAFIRQCTRL_EN   0x8000000000000000UL
 
+static int pbm_routes_this_ino(struct pci_pbm_info *pbm, u32 ino)
+{
+       ino &= IMAP_INO;
+
+       if (pbm->ino_bitmap & (1UL << ino))
+               return 1;
+
+       return 0;
+}
+
 /* How the Tomatillo IRQs are routed around is pure guesswork here.
  *
  * All the Tomatillo devices I see in prtconf dumps seem to have only
@@ -1127,85 +979,40 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *
  * PCI bus units of the same Tomatillo.  I still have not really
  * figured this out...
  */
-static void tomatillo_register_error_handlers(struct pci_controller_info *p)
+static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm)
 {
-       struct pci_pbm_info *pbm;
-       unsigned int irq;
+       struct of_device *op = of_find_device_by_node(pbm->prom_node);
        u64 tmp, err_mask, err_no_mask;
 
-       /* Build IRQs and register handlers. */
-       pbm = pbm_for_ino(p, SCHIZO_UE_INO);
-       irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_UE_INO);
-       if (request_irq(irq, schizo_ue_intr,
-                       SA_SHIRQ, "TOMATILLO UE", p) < 0) {
-               prom_printf("%s: Cannot register UE interrupt.\n",
-                           pbm->name);
-               prom_halt();
-       }
-       tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO));
-       upa_writel(tmp, (pbm->pbm_regs +
-                        schizo_imap_offset(SCHIZO_UE_INO) + 4));
-
-       pbm = pbm_for_ino(p, SCHIZO_CE_INO);
-       irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_CE_INO);
-       if (request_irq(irq, schizo_ce_intr,
-                       SA_SHIRQ, "TOMATILLO CE", p) < 0) {
-               prom_printf("%s: Cannot register CE interrupt.\n",
-                           pbm->name);
-               prom_halt();
-       }
-       tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO));
-       upa_writel(tmp, (pbm->pbm_regs +
-                        schizo_imap_offset(SCHIZO_CE_INO) + 4));
-
-       pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO);
-       irq = schizo_irq_build(pbm, NULL, ((pbm->portid << 6) |
-                                          SCHIZO_PCIERR_A_INO));
-       if (request_irq(irq, schizo_pcierr_intr,
-                       SA_SHIRQ, "TOMATILLO PCIERR", pbm) < 0) {
-               prom_printf("%s: Cannot register PBM A PciERR interrupt.\n",
-                           pbm->name);
-               prom_halt();
-       }
-       tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) |
-                                                SCHIZO_PCIERR_A_INO)));
-       upa_writel(tmp, (pbm->pbm_regs +
-                        schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));
-
-       pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO);
-       irq = schizo_irq_build(pbm, NULL, ((pbm->portid << 6) |
-                                           SCHIZO_PCIERR_B_INO));
-       if (request_irq(irq, schizo_pcierr_intr,
-                       SA_SHIRQ, "TOMATILLO PCIERR", pbm) < 0) {
-               prom_printf("%s: Cannot register PBM B PciERR interrupt.\n",
-                           pbm->name);
-               prom_halt();
-       }
-       tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) |
-                                                SCHIZO_PCIERR_B_INO)));
-       upa_writel(tmp, (pbm->pbm_regs +
-                        schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4));
-
-       pbm = pbm_for_ino(p, SCHIZO_SERR_INO);
-       irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_SERR_INO);
-       if (request_irq(irq, schizo_safarierr_intr,
-                       SA_SHIRQ, "TOMATILLO SERR", p) < 0) {
-               prom_printf("%s: Cannot register SafariERR interrupt.\n",
-                           pbm->name);
-               prom_halt();
-       }
-       tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) |
-                                                SCHIZO_SERR_INO)));
-       upa_writel(tmp, (pbm->pbm_regs +
-                        schizo_imap_offset(SCHIZO_SERR_INO) + 4));
+       /* Tomatillo IRQ property layout is:
+        * 0: PCIERR
+        * 1: UE ERR
+        * 2: CE ERR
+        * 3: SERR
+        * 4: POWER FAIL?
+        */
 
-       /* Enable UE and CE interrupts for controller. */
-       schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL,
-                    (SCHIZO_ECCCTRL_EE |
-                     SCHIZO_ECCCTRL_UE |
-                     SCHIZO_ECCCTRL_CE));
+       if (pbm_routes_this_ino(pbm, SCHIZO_UE_INO))
+               request_irq(op->irqs[1], schizo_ue_intr, 0,
+                           "TOMATILLO_UE", pbm);
 
-       schizo_write(p->pbm_B.controller_regs + SCHIZO_ECC_CTRL,
+       if (pbm_routes_this_ino(pbm, SCHIZO_CE_INO))
+               request_irq(op->irqs[2], schizo_ce_intr, 0,
+                           "TOMATILLO_CE", pbm);
+
+       if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_A_INO))
+               request_irq(op->irqs[0], schizo_pcierr_intr, 0,
+                           "TOMATILLO_PCIERR", pbm);
+       else if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_B_INO))
+               request_irq(op->irqs[0], schizo_pcierr_intr, 0,
+                           "TOMATILLO_PCIERR", pbm);
+
+       if (pbm_routes_this_ino(pbm, SCHIZO_SERR_INO))
+               request_irq(op->irqs[3], schizo_safarierr_intr, 0,
+                           "TOMATILLO_SERR", pbm);
+
+       /* Enable UE and CE interrupts for controller. */
+       schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL,
                     (SCHIZO_ECCCTRL_EE |
                      SCHIZO_ECCCTRL_UE |
                      SCHIZO_ECCCTRL_CE));
@@ -1221,15 +1028,10 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p)
 
        err_no_mask = SCHIZO_PCICTRL_DTO_ERR;
 
-       tmp = schizo_read(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL);
-       tmp |= err_mask;
-       tmp &= ~err_no_mask;
-       schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL, tmp);
-
-       tmp = schizo_read(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL);
+       tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL);
        tmp |= err_mask;
        tmp &= ~err_no_mask;
-       schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL, tmp);
+       schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp);
 
        err_mask = (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA |
                    SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR |
@@ -1238,8 +1040,7 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p)
                    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);
+       schizo_write(pbm->pbm_regs + SCHIZO_PCI_AFSR, err_mask);
 
        err_mask = (BUS_ERROR_BADCMD | BUS_ERROR_SNOOP_GR |
                    BUS_ERROR_SNOOP_PCI | BUS_ERROR_SNOOP_RD |
@@ -1251,81 +1052,47 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p)
                    BUS_ERROR_APERR | BUS_ERROR_UNMAP |
                    BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT);
 
-       schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_ERRCTRL,
-                    (SCHIZO_SAFERRCTRL_EN | err_mask));
-       schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRCTRL,
+       schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL,
                     (SCHIZO_SAFERRCTRL_EN | err_mask));
 
-       schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_IRQCTRL,
-                    (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));
-       schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_IRQCTRL,
+       schizo_write(pbm->controller_regs + SCHIZO_SAFARI_IRQCTRL,
                     (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));
 }
 
-static void schizo_register_error_handlers(struct pci_controller_info *p)
+static void schizo_register_error_handlers(struct pci_pbm_info *pbm)
 {
-       struct pci_pbm_info *pbm;
-       unsigned int irq;
+       struct of_device *op = of_find_device_by_node(pbm->prom_node);
        u64 tmp, err_mask, err_no_mask;
 
-       /* Build IRQs and register handlers. */
-       pbm = pbm_for_ino(p, SCHIZO_UE_INO);
-       irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_UE_INO);
-       if (request_irq(irq, schizo_ue_intr,
-                       SA_SHIRQ, "SCHIZO UE", p) < 0) {
-               prom_printf("%s: Cannot register UE interrupt.\n",
-                           pbm->name);
-               prom_halt();
-       }
-       tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO));
-       upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4));
-
-       pbm = pbm_for_ino(p, SCHIZO_CE_INO);
-       irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_CE_INO);
-       if (request_irq(irq, schizo_ce_intr,
-                       SA_SHIRQ, "SCHIZO CE", p) < 0) {
-               prom_printf("%s: Cannot register CE interrupt.\n",
-                           pbm->name);
-               prom_halt();
-       }
-       tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO));
-       upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4));
-
-       pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO);
-       irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_PCIERR_A_INO);
-       if (request_irq(irq, schizo_pcierr_intr,
-                       SA_SHIRQ, "SCHIZO PCIERR", pbm) < 0) {
-               prom_printf("%s: Cannot register PBM A PciERR interrupt.\n",
-                           pbm->name);
-               prom_halt();
-       }
-       tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_A_INO));
-       upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));
-
-       pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO);
-       irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_PCIERR_B_INO);
-       if (request_irq(irq, schizo_pcierr_intr,
-                       SA_SHIRQ, "SCHIZO PCIERR", &p->pbm_B) < 0) {
-               prom_printf("%s: Cannot register PBM B PciERR interrupt.\n",
-                           pbm->name);
-               prom_halt();
-       }
-       tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_B_INO));
-       upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4));
-
-       pbm = pbm_for_ino(p, SCHIZO_SERR_INO);
-       irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_SERR_INO);
-       if (request_irq(irq, schizo_safarierr_intr,
-                       SA_SHIRQ, "SCHIZO SERR", p) < 0) {
-               prom_printf("%s: Cannot register SafariERR interrupt.\n",
-                           pbm->name);
-               prom_halt();
-       }
-       tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_SERR_INO));
-       upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4));
+       /* Schizo IRQ property layout is:
+        * 0: PCIERR
+        * 1: UE ERR
+        * 2: CE ERR
+        * 3: SERR
+        * 4: POWER FAIL?
+        */
+
+       if (pbm_routes_this_ino(pbm, SCHIZO_UE_INO))
+               request_irq(op->irqs[1], schizo_ue_intr, 0,
+                           "SCHIZO_UE", pbm);
+
+       if (pbm_routes_this_ino(pbm, SCHIZO_CE_INO))
+               request_irq(op->irqs[2], schizo_ce_intr, 0,
+                           "SCHIZO_CE", pbm);
+
+       if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_A_INO))
+               request_irq(op->irqs[0], schizo_pcierr_intr, 0,
+                           "SCHIZO_PCIERR", pbm);
+       else if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_B_INO))
+               request_irq(op->irqs[0], schizo_pcierr_intr, 0,
+                           "SCHIZO_PCIERR", pbm);
+
+       if (pbm_routes_this_ino(pbm, SCHIZO_SERR_INO))
+               request_irq(op->irqs[3], schizo_safarierr_intr, 0,
+                           "SCHIZO_SERR", pbm);
 
        /* Enable UE and CE interrupts for controller. */
-       schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL,
+       schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL,
                     (SCHIZO_ECCCTRL_EE |
                      SCHIZO_ECCCTRL_UE |
                      SCHIZO_ECCCTRL_CE));
@@ -1344,25 +1111,12 @@ static void schizo_register_error_handlers(struct pci_controller_info *p)
        /* Enable PCI Error interrupts and clear error
         * bits for each PBM.
         */
-       tmp = schizo_read(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL);
-       tmp |= err_mask;
-       tmp &= ~err_no_mask;
-       schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL, tmp);
-
-       schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_AFSR,
-                    (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA |
-                     SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR |
-                     SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS |
-                     SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA |
-                     SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR |
-                     SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS));
-
-       tmp = schizo_read(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL);
+       tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL);
        tmp |= err_mask;
        tmp &= ~err_no_mask;
-       schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL, tmp);
+       schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp);
 
-       schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_AFSR,
+       schizo_write(pbm->pbm_regs + SCHIZO_PCI_AFSR,
                     (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA |
                      SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR |
                      SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS |
@@ -1395,11 +1149,8 @@ static void schizo_register_error_handlers(struct pci_controller_info *p)
                      BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB);
 #endif
 
-       schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_ERRCTRL,
+       schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL,
                     (SCHIZO_SAFERRCTRL_EN | err_mask));
-
-       schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_IRQCTRL,
-                    (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));
 }
 
 static void pbm_config_busmastering(struct pci_pbm_info *pbm)
@@ -1419,196 +1170,19 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm)
        pci_config_write8(addr, 64);
 }
 
-static void pbm_scan_bus(struct pci_controller_info *p,
-                        struct pci_pbm_info *pbm)
+static void schizo_scan_bus(struct pci_pbm_info *pbm)
 {
-       struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
-
-       if (!cookie) {
-               prom_printf("%s: Critical allocation failure.\n", pbm->name);
-               prom_halt();
-       }
-
-       /* All we care about is the PBM. */
-       cookie->pbm = pbm;
-
-       pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno,
-                                   p->pci_ops,
-                                   pbm);
-       pci_fixup_host_bridge_self(pbm->pci_bus);
-       pbm->pci_bus->self->sysdata = cookie;
-
-       pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
-       pci_record_assignments(pbm, pbm->pci_bus);
-       pci_assign_unassigned(pbm, pbm->pci_bus);
-       pci_fixup_irq(pbm, pbm->pci_bus);
-       pci_determine_66mhz_disposition(pbm, pbm->pci_bus);
-       pci_setup_busmastering(pbm, pbm->pci_bus);
-}
-
-static void __schizo_scan_bus(struct pci_controller_info *p,
-                             int chip_type)
-{
-       if (!p->pbm_B.prom_node || !p->pbm_A.prom_node) {
-               printk("PCI: Only one PCI bus module of controller found.\n");
-               printk("PCI: Ignoring entire controller.\n");
-               return;
-       }
-
-       pbm_config_busmastering(&p->pbm_B);
-       p->pbm_B.is_66mhz_capable =
-               (of_find_property(p->pbm_B.prom_node, "66mhz-capable", NULL)
-                != NULL);
-       pbm_config_busmastering(&p->pbm_A);
-       p->pbm_A.is_66mhz_capable =
-               (of_find_property(p->pbm_A.prom_node, "66mhz-capable", NULL)
+       pbm_config_busmastering(pbm);
+       pbm->is_66mhz_capable =
+               (of_find_property(pbm->prom_node, "66mhz-capable", NULL)
                 != NULL);
-       pbm_scan_bus(p, &p->pbm_B);
-       pbm_scan_bus(p, &p->pbm_A);
 
-       /* After the PCI bus scan is complete, we can register
-        * the error interrupt handlers.
-        */
-       if (chip_type == PBM_CHIP_TYPE_TOMATILLO)
-               tomatillo_register_error_handlers(p);
-       else
-               schizo_register_error_handlers(p);
-}
-
-static void schizo_scan_bus(struct pci_controller_info *p)
-{
-       __schizo_scan_bus(p, PBM_CHIP_TYPE_SCHIZO);
-}
+       pbm->pci_bus = pci_scan_one_pbm(pbm);
 
-static void tomatillo_scan_bus(struct pci_controller_info *p)
-{
-       __schizo_scan_bus(p, PBM_CHIP_TYPE_TOMATILLO);
-}
-
-static void schizo_base_address_update(struct pci_dev *pdev, int resource)
-{
-       struct pcidev_cookie *pcp = pdev->sysdata;
-       struct pci_pbm_info *pbm = pcp->pbm;
-       struct resource *res, *root;
-       u32 reg;
-       int where, size, is_64bit;
-
-       res = &pdev->resource[resource];
-       if (resource < 6) {
-               where = PCI_BASE_ADDRESS_0 + (resource * 4);
-       } else if (resource == PCI_ROM_RESOURCE) {
-               where = pdev->rom_base_reg;
-       } else {
-               /* Somebody might have asked allocation of a non-standard resource */
-               return;
-       }
-
-       is_64bit = 0;
-       if (res->flags & IORESOURCE_IO)
-               root = &pbm->io_space;
-       else {
-               root = &pbm->mem_space;
-               if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
-                   == PCI_BASE_ADDRESS_MEM_TYPE_64)
-                       is_64bit = 1;
-       }
-
-       size = res->end - res->start;
-       pci_read_config_dword(pdev, where, &reg);
-       reg = ((reg & size) |
-              (((u32)(res->start - root->start)) & ~size));
-       if (resource == PCI_ROM_RESOURCE) {
-               reg |= PCI_ROM_ADDRESS_ENABLE;
-               res->flags |= IORESOURCE_ROM_ENABLE;
-       }
-       pci_write_config_dword(pdev, where, reg);
-
-       /* This knows that the upper 32-bits of the address
-        * must be zero.  Our PCI common layer enforces this.
-        */
-       if (is_64bit)
-               pci_write_config_dword(pdev, where + 4, 0);
-}
-
-static void schizo_resource_adjust(struct pci_dev *pdev,
-                                  struct resource *res,
-                                  struct resource *root)
-{
-       res->start += root->start;
-       res->end += root->start;
-}
-
-/* Use ranges property to determine where PCI MEM, I/O, and Config
- * space are for this PCI bus module.
- */
-static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm)
-{
-       int i, saw_cfg, saw_mem, saw_io;
-
-       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;
-
-               type = (pr->child_phys_hi >> 24) & 0x3;
-               a = (((unsigned long)pr->parent_phys_hi << 32UL) |
-                    ((unsigned long)pr->parent_phys_lo  <<  0UL));
-
-               switch (type) {
-               case 0:
-                       /* PCI config space, 16MB */
-                       pbm->config_space = a;
-                       saw_cfg = 1;
-                       break;
-
-               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;
-
-               case 2:
-                       /* 32-bit MEM space, 2GB */
-                       pbm->mem_space.start = a;
-                       pbm->mem_space.end = a + (0x80000000UL - 1UL);
-                       pbm->mem_space.flags = IORESOURCE_MEM;
-                       saw_mem = 1;
-                       break;
-
-               default:
-                       break;
-               };
-       }
-
-       if (!saw_cfg || !saw_io || !saw_mem) {
-               prom_printf("%s: Fatal error, missing %s PBM range.\n",
-                           pbm->name,
-                           ((!saw_cfg ?
-                             "CFG" :
-                             (!saw_io ?
-                              "IO" : "MEM"))));
-               prom_halt();
-       }
-
-       printk("%s: PCI CFG[%lx] IO[%lx] MEM[%lx]\n",
-              pbm->name,
-              pbm->config_space,
-              pbm->io_space.start,
-              pbm->mem_space.start);
-}
-
-static void pbm_register_toplevel_resources(struct pci_controller_info *p,
-                                           struct pci_pbm_info *pbm)
-{
-       pbm->io_space.name = pbm->mem_space.name = pbm->name;
-
-       request_resource(&ioport_resource, &pbm->io_space);
-       request_resource(&iomem_resource, &pbm->mem_space);
-       pci_register_legacy_regions(&pbm->io_space,
-                                   &pbm->mem_space);
+       if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO)
+               tomatillo_register_error_handlers(pbm);
+       else
+               schizo_register_error_handlers(pbm);
 }
 
 #define SCHIZO_STRBUF_CONTROL          (0x02800UL)
@@ -1662,7 +1236,7 @@ static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm)
 
 static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
 {
-       struct pci_iommu *iommu = pbm->iommu;
+       struct iommu *iommu = pbm->iommu;
        unsigned long i, tagbase, database;
        struct property *prop;
        u32 vdma[2], dma_mask;
@@ -1844,14 +1418,10 @@ static void schizo_pbm_init(struct pci_controller_info *p,
                            struct device_node *dp, u32 portid,
                            int chip_type)
 {
-       struct linux_prom64_registers *regs;
-       struct property *prop;
-       unsigned int *busrange;
+       const struct linux_prom64_registers *regs;
        struct pci_pbm_info *pbm;
        const char *chipset_name;
-       u32 *ino_bitmap;
        int is_pbm_a;
-       int len;
 
        switch (chip_type) {
        case PBM_CHIP_TYPE_TOMATILLO:
@@ -1879,30 +1449,29 @@ static void schizo_pbm_init(struct pci_controller_info *p,
         * 3) PBM PCI config space
         * 4) Ichip regs
         */
-       prop = of_find_property(dp, "reg", NULL);
-       regs = prop->value;
+       regs = of_get_property(dp, "reg", NULL);
 
        is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000);
-
        if (is_pbm_a)
                pbm = &p->pbm_A;
        else
                pbm = &p->pbm_B;
 
+       pbm->next = pci_pbm_root;
+       pci_pbm_root = pbm;
+
+       pbm->scan_bus = schizo_scan_bus;
+       pbm->pci_ops = &schizo_ops;
+
+       pbm->index = pci_num_pbms++;
+
        pbm->portid = portid;
        pbm->parent = p;
        pbm->prom_node = dp;
-       pbm->pci_first_slot = 1;
 
        pbm->chip_type = chip_type;
-       pbm->chip_version = 0;
-       prop = of_find_property(dp, "version#", NULL);
-       if (prop)
-               pbm->chip_version = *(int *) prop->value;
-       pbm->chip_revision = 0;
-       prop = of_find_property(dp, "module-revision#", NULL);
-       if (prop)
-               pbm->chip_revision = *(int *) prop->value;
+       pbm->chip_version = of_getintprop_default(dp, "version#", 0);
+       pbm->chip_revision = of_getintprop_default(dp, "module-version#", 0);
 
        pbm->pbm_regs = regs[0].phys_addr;
        pbm->controller_regs = regs[1].phys_addr - 0x10000UL;
@@ -1913,42 +1482,14 @@ static void schizo_pbm_init(struct pci_controller_info *p,
        pbm->name = dp->full_name;
 
        printk("%s: %s PCI Bus Module ver[%x:%x]\n",
-              pbm->name,
-              (chip_type == PBM_CHIP_TYPE_TOMATILLO ?
-               "TOMATILLO" : "SCHIZO"),
+              pbm->name, chipset_name,
               pbm->chip_version, pbm->chip_revision);
 
        schizo_pbm_hw_init(pbm);
 
-       prop = of_find_property(dp, "ranges", &len);
-       pbm->pbm_ranges = prop->value;
-       pbm->num_pbm_ranges =
-               (len / sizeof(struct linux_prom_pci_ranges));
-
-       schizo_determine_mem_io_space(pbm);
-       pbm_register_toplevel_resources(p, pbm);
+       pci_determine_mem_io_space(pbm);
 
-       prop = of_find_property(dp, "interrupt-map", &len);
-       if (prop) {
-               pbm->pbm_intmap = prop->value;
-               pbm->num_pbm_intmap =
-                       (len / sizeof(struct linux_prom_pci_intmap));
-
-               prop = of_find_property(dp, "interrupt-map-mask", NULL);
-               pbm->pbm_intmask = prop->value;
-       } else {
-               pbm->num_pbm_intmap = 0;
-       }
-
-       prop = of_find_property(dp, "ino-bitmap", NULL);
-       ino_bitmap = prop->value;
-       pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) |
-                          ((u64)ino_bitmap[0] <<  0UL));
-
-       prop = of_find_property(dp, "bus-range", NULL);
-       busrange = prop->value;
-       pbm->pci_first_busno = busrange[0];
-       pbm->pci_last_busno = busrange[1];
+       pci_get_pbm_props(pbm);
 
        schizo_pbm_iommu_init(pbm);
        schizo_pbm_strbuf_init(pbm);
@@ -1967,70 +1508,44 @@ static inline int portid_compare(u32 x, u32 y, int chip_type)
 static void __schizo_init(struct device_node *dp, char *model_name, int chip_type)
 {
        struct pci_controller_info *p;
-       struct pci_iommu *iommu;
-       struct property *prop;
-       int is_pbm_a;
+       struct pci_pbm_info *pbm;
+       struct iommu *iommu;
        u32 portid;
 
-       portid = 0xff;
-       prop = of_find_property(dp, "portid", NULL);
-       if (prop)
-               portid = *(u32 *) prop->value;
-
-       for (p = pci_controller_root; p; p = p->next) {
-               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);
+       portid = of_getintprop_default(dp, "portid", 0xff);
 
+       for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
                if (portid_compare(pbm->portid, portid, chip_type)) {
-                       is_pbm_a = (p->pbm_A.prom_node == NULL);
-                       schizo_pbm_init(p, dp, portid, chip_type);
+                       schizo_pbm_init(pbm->parent, dp, portid, chip_type);
                        return;
                }
        }
 
        p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
-       if (!p) {
-               prom_printf("SCHIZO: Fatal memory allocation error.\n");
-               prom_halt();
-       }
+       if (!p)
+               goto memfail;
 
-       iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
-       if (!iommu) {
-               prom_printf("SCHIZO: Fatal memory allocation error.\n");
-               prom_halt();
-       }
-       p->pbm_A.iommu = iommu;
+       iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
+       if (!iommu)
+               goto memfail;
 
-       iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
-       if (!iommu) {
-               prom_printf("SCHIZO: Fatal memory allocation error.\n");
-               prom_halt();
-       }
-       p->pbm_B.iommu = iommu;
+       p->pbm_A.iommu = iommu;
 
-       p->next = pci_controller_root;
-       pci_controller_root = p;
+       iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
+       if (!iommu)
+               goto memfail;
 
-       p->index = pci_num_controllers++;
-       p->pbms_same_domain = 0;
-       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;
+       p->pbm_B.iommu = iommu;
 
        /* Like PSYCHO we have a 2GB aligned area for memory space. */
        pci_memspace_mask = 0x7fffffffUL;
 
        schizo_pbm_init(p, dp, portid, chip_type);
+       return;
+
+memfail:
+       prom_printf("SCHIZO: Fatal memory allocation error.\n");
+       prom_halt();
 }
 
 void schizo_init(struct device_node *dp, char *model_name)