]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/powerpc/platforms/iseries/pci.c
Merge branch 'isdn-cleanups' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik...
[linux-2.6-omap-h63xx.git] / arch / powerpc / platforms / iseries / pci.c
index 8e2ac3d0c81a60251921d690f4aaf14a94fb091a..02a634faedbeb23007488513c4a51d98150edd9f 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2001 Allan Trautman, IBM Corporation
+ * Copyright (C) 2005,2007  Stephen Rothwell, IBM Corp
  *
  * iSeries specific routines for PCI.
  *
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
+
+#undef DEBUG
+
+#include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/of.h>
 
+#include <asm/types.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
@@ -35,6 +42,7 @@
 #include <asm/abs_addr.h>
 #include <asm/firmware.h>
 
+#include <asm/iseries/hv_types.h>
 #include <asm/iseries/hv_call_xm.h>
 #include <asm/iseries/mf.h>
 #include <asm/iseries/iommu.h>
@@ -55,6 +63,7 @@ static int limit_pci_retries = 1;     /* Set Retry Error on. */
 #define IOMM_TABLE_MAX_ENTRIES 1024
 #define IOMM_TABLE_ENTRY_SIZE  0x0000000000400000UL
 #define BASE_IO_MEMORY         0xE000000000000000UL
+#define END_IO_MEMORY          0xEFFFFFFFFFFFFFFFUL
 
 static unsigned long max_io_memory = BASE_IO_MEMORY;
 static long current_iomm_table_entry;
@@ -63,11 +72,236 @@ static long current_iomm_table_entry;
  * Lookup Tables.
  */
 static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES];
-static u8 iobar_table[IOMM_TABLE_MAX_ENTRIES];
+static u64 ds_addr_table[IOMM_TABLE_MAX_ENTRIES];
 
-static const char pci_io_text[] = "iSeries PCI I/O";
 static DEFINE_SPINLOCK(iomm_table_lock);
 
+/*
+ * Generate a Direct Select Address for the Hypervisor
+ */
+static inline u64 iseries_ds_addr(struct device_node *node)
+{
+       struct pci_dn *pdn = PCI_DN(node);
+       const u32 *sbp = of_get_property(node, "linux,subbus", NULL);
+
+       return ((u64)pdn->busno << 48) + ((u64)(sbp ? *sbp : 0) << 40)
+                       + ((u64)0x10 << 32);
+}
+
+/*
+ * Size of Bus VPD data
+ */
+#define BUS_VPDSIZE      1024
+
+/*
+ * Bus Vpd Tags
+ */
+#define VPD_END_OF_AREA                0x79
+#define VPD_ID_STRING          0x82
+#define VPD_VENDOR_AREA                0x84
+
+/*
+ * Mfg Area Tags
+ */
+#define VPD_FRU_FRAME_ID       0x4649  /* "FI" */
+#define VPD_SLOT_MAP_FORMAT    0x4D46  /* "MF" */
+#define VPD_SLOT_MAP           0x534D  /* "SM" */
+
+/*
+ * Structures of the areas
+ */
+struct mfg_vpd_area {
+       u16     tag;
+       u8      length;
+       u8      data1;
+       u8      data2;
+};
+#define MFG_ENTRY_SIZE   3
+
+struct slot_map {
+       u8      agent;
+       u8      secondary_agent;
+       u8      phb;
+       char    card_location[3];
+       char    parms[8];
+       char    reserved[2];
+};
+#define SLOT_ENTRY_SIZE   16
+
+/*
+ * Parse the Slot Area
+ */
+static void __init iseries_parse_slot_area(struct slot_map *map, int len,
+               HvAgentId agent, u8 *phb, char card[4])
+{
+       /*
+        * Parse Slot label until we find the one requested
+        */
+       while (len > 0) {
+               if (map->agent == agent) {
+                       /*
+                        * If Phb wasn't found, grab the entry first one found.
+                        */
+                       if (*phb == 0xff)
+                               *phb = map->phb;
+                       /* Found it, extract the data. */
+                       if (map->phb == *phb) {
+                               memcpy(card, &map->card_location, 3);
+                               card[3]  = 0;
+                               break;
+                       }
+               }
+               /* Point to the next Slot */
+               map = (struct slot_map *)((char *)map + SLOT_ENTRY_SIZE);
+               len -= SLOT_ENTRY_SIZE;
+       }
+}
+
+/*
+ * Parse the Mfg Area
+ */
+static void __init iseries_parse_mfg_area(struct mfg_vpd_area *area, int len,
+               HvAgentId agent, u8 *phb, u8 *frame, char card[4])
+{
+       u16 slot_map_fmt = 0;
+
+       /* Parse Mfg Data */
+       while (len > 0) {
+               int mfg_tag_len = area->length;
+               /* Frame ID         (FI 4649020310 ) */
+               if (area->tag == VPD_FRU_FRAME_ID)
+                       *frame = area->data1;
+               /* Slot Map Format  (MF 4D46020004 ) */
+               else if (area->tag == VPD_SLOT_MAP_FORMAT)
+                       slot_map_fmt = (area->data1 * 256)
+                               + area->data2;
+               /* Slot Map         (SM 534D90 */
+               else if (area->tag == VPD_SLOT_MAP) {
+                       struct slot_map *slot_map;
+
+                       if (slot_map_fmt == 0x1004)
+                               slot_map = (struct slot_map *)((char *)area
+                                               + MFG_ENTRY_SIZE + 1);
+                       else
+                               slot_map = (struct slot_map *)((char *)area
+                                               + MFG_ENTRY_SIZE);
+                       iseries_parse_slot_area(slot_map, mfg_tag_len,
+                                       agent, phb, card);
+               }
+               /*
+                * Point to the next Mfg Area
+                * Use defined size, sizeof give wrong answer
+                */
+               area = (struct mfg_vpd_area *)((char *)area + mfg_tag_len
+                               + MFG_ENTRY_SIZE);
+               len -= (mfg_tag_len + MFG_ENTRY_SIZE);
+       }
+}
+
+/*
+ * Look for "BUS".. Data is not Null terminated.
+ * PHBID of 0xFF indicates PHB was not found in VPD Data.
+ */
+static u8 __init iseries_parse_phbid(u8 *area, int len)
+{
+       while (len > 0) {
+               if ((*area == 'B') && (*(area + 1) == 'U')
+                               && (*(area + 2) == 'S')) {
+                       area += 3;
+                       while (*area == ' ')
+                               area++;
+                       return *area & 0x0F;
+               }
+               area++;
+               len--;
+       }
+       return 0xff;
+}
+
+/*
+ * Parse out the VPD Areas
+ */
+static void __init iseries_parse_vpd(u8 *data, int data_len,
+               HvAgentId agent, u8 *frame, char card[4])
+{
+       u8 phb = 0xff;
+
+       while (data_len > 0) {
+               int len;
+               u8 tag = *data;
+
+               if (tag == VPD_END_OF_AREA)
+                       break;
+               len = *(data + 1) + (*(data + 2) * 256);
+               data += 3;
+               data_len -= 3;
+               if (tag == VPD_ID_STRING)
+                       phb = iseries_parse_phbid(data, len);
+               else if (tag == VPD_VENDOR_AREA)
+                       iseries_parse_mfg_area((struct mfg_vpd_area *)data, len,
+                                       agent, &phb, frame, card);
+               /* Point to next Area. */
+               data += len;
+               data_len -= len;
+       }
+}
+
+static int __init iseries_get_location_code(u16 bus, HvAgentId agent,
+               u8 *frame, char card[4])
+{
+       int status = 0;
+       int bus_vpd_len = 0;
+       u8 *bus_vpd = kmalloc(BUS_VPDSIZE, GFP_KERNEL);
+
+       if (bus_vpd == NULL) {
+               printk("PCI: Bus VPD Buffer allocation failure.\n");
+               return 0;
+       }
+       bus_vpd_len = HvCallPci_getBusVpd(bus, iseries_hv_addr(bus_vpd),
+                                       BUS_VPDSIZE);
+       if (bus_vpd_len == 0) {
+               printk("PCI: Bus VPD Buffer zero length.\n");
+               goto out_free;
+       }
+       /* printk("PCI: bus_vpd: %p, %d\n",bus_vpd, bus_vpd_len); */
+       /* Make sure this is what I think it is */
+       if (*bus_vpd != VPD_ID_STRING) {
+               printk("PCI: Bus VPD Buffer missing starting tag.\n");
+               goto out_free;
+       }
+       iseries_parse_vpd(bus_vpd, bus_vpd_len, agent, frame, card);
+       status = 1;
+out_free:
+       kfree(bus_vpd);
+       return status;
+}
+
+/*
+ * Prints the device information.
+ * - Pass in pci_dev* pointer to the device.
+ * - Pass in the device count
+ *
+ * Format:
+ * PCI: Bus  0, Device 26, Vendor 0x12AE  Frame  1, Card  C10  Ethernet
+ * controller
+ */
+static void __init iseries_device_information(struct pci_dev *pdev,
+                                             u16 bus, HvSubBusNumber subbus)
+{
+       u8 frame = 0;
+       char card[4];
+       HvAgentId agent;
+
+       agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus),
+                       ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus));
+
+       if (iseries_get_location_code(bus, agent, &frame, card)) {
+               printk(KERN_INFO "PCI: %s, Vendor %04X Frame%3d, "
+                      "Card %4s  0x%04X\n", pci_name(pdev), pdev->vendor,
+                      frame, card, (int)(pdev->class >> 8));
+       }
+}
+
 /*
  * iomm_table_allocate_entry
  *
@@ -94,7 +328,6 @@ static void __init iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
         * Set Resource values.
         */
        spin_lock(&iomm_table_lock);
-       bar_res->name = pci_io_text;
        bar_res->start = BASE_IO_MEMORY +
                IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
        bar_res->end = bar_res->start + bar_size - 1;
@@ -103,7 +336,8 @@ static void __init iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
         */
        while (bar_size > 0 ) {
                iomm_table[current_iomm_table_entry] = dev->sysdata;
-               iobar_table[current_iomm_table_entry] = bar_num;
+               ds_addr_table[current_iomm_table_entry] =
+                       iseries_ds_addr(dev->sysdata) | (bar_num << 24);
                bar_size -= IOMM_TABLE_ENTRY_SIZE;
                ++current_iomm_table_entry;
        }
@@ -164,63 +398,62 @@ static struct device_node *find_device_node(int bus, int devfn)
 }
 
 /*
- * iSeries_pci_final_fixup(void)
+ * iSeries_pcibios_fixup_resources
+ *
+ * Fixes up all resources for devices
  */
-void __init iSeries_pci_final_fixup(void)
+void __init iSeries_pcibios_fixup_resources(struct pci_dev *pdev)
 {
-       struct pci_dev *pdev = NULL;
+       const u32 *agent;
+       const u32 *sub_bus;
+       unsigned char bus = pdev->bus->number;
        struct device_node *node;
-       int num_dev = 0;
-
-       /* Fix up at the device node and pci_dev relationship */
-       mf_display_src(0xC9000100);
-
-       printk("pcibios_final_fixup\n");
-       for_each_pci_dev(pdev) {
-               struct pci_dn *pdn;
-               const u32 *agent;
-
-               node = find_device_node(pdev->bus->number, pdev->devfn);
-               printk("pci dev %p (%x.%x), node %p\n", pdev,
-                      pdev->bus->number, pdev->devfn, node);
-               if (!node) {
-                       printk("PCI: Device Tree not found for 0x%016lX\n",
-                                       (unsigned long)pdev);
-                       continue;
-               }
-
-               pdn = PCI_DN(node);
-               agent = of_get_property(node, "linux,agent-id", NULL);
-               if (pdn && agent) {
-                       u8 irq = iSeries_allocate_IRQ(pdn->busno, 0,
-                                       pdn->bussubno);
-                       int err;
-
-                       err = HvCallXm_connectBusUnit(pdn->busno, pdn->bussubno,
-                                       *agent, irq);
+       int i;
+
+       node = find_device_node(bus, pdev->devfn);
+       pr_debug("PCI: iSeries %s, pdev %p, node %p\n",
+                pci_name(pdev), pdev, node);
+       if (!node) {
+               printk("PCI: %s disabled, device tree entry not found !\n",
+                      pci_name(pdev));
+               for (i = 0; i <= PCI_ROM_RESOURCE; i++)
+                       pdev->resource[i].flags = 0;
+               return;
+       }
+       sub_bus = of_get_property(node, "linux,subbus", NULL);
+       agent = of_get_property(node, "linux,agent-id", NULL);
+       if (agent && sub_bus) {
+               u8 irq = iSeries_allocate_IRQ(bus, 0, *sub_bus);
+               int err;
+
+               err = HvCallXm_connectBusUnit(bus, *sub_bus, *agent, irq);
+               if (err)
+                       pci_log_error("Connect Bus Unit",
+                                     bus, *sub_bus, *agent, err);
+               else {
+                       err = HvCallPci_configStore8(bus, *sub_bus,
+                                       *agent, PCI_INTERRUPT_LINE, irq);
                        if (err)
-                               pci_log_error("Connect Bus Unit",
-                                       pdn->busno, pdn->bussubno, *agent, err);
-                       else {
-                               err = HvCallPci_configStore8(pdn->busno,
-                                       pdn->bussubno, *agent,
-                                       PCI_INTERRUPT_LINE, irq);
-                               if (err)
-                                       pci_log_error("PciCfgStore Irq Failed!",
-                                               pdn->busno, pdn->bussubno,
-                                               *agent, err);
-                               else
-                                       pdev->irq = irq;
-                       }
+                               pci_log_error("PciCfgStore Irq Failed!",
+                                               bus, *sub_bus, *agent, err);
+                       else
+                               pdev->irq = irq;
                }
-
-               num_dev++;
-               pdev->sysdata = node;
-               PCI_DN(node)->pcidev = pdev;
-               allocate_device_bars(pdev);
-               iSeries_Device_Information(pdev, num_dev);
-               iommu_devnode_init_iSeries(pdev, node);
        }
+
+       pdev->sysdata = node;
+       allocate_device_bars(pdev);
+       iseries_device_information(pdev, bus, *sub_bus);
+       iommu_devnode_init_iSeries(pdev, node);
+}
+
+/*
+ * iSeries_pci_final_fixup(void)
+ */
+void __init iSeries_pci_final_fixup(void)
+{
+       /* Fix up at the device node and pci_dev relationship */
+       mf_display_src(0xC9000100);
        iSeries_activate_IRQs();
        mf_display_src(0xC9000200);
 }
@@ -342,7 +575,7 @@ static int check_return_code(char *type, struct device_node *dn,
  */
 static inline struct device_node *xlate_iomm_address(
                const volatile void __iomem *addr,
-               u64 *dsaptr, u64 *bar_offset)
+               u64 *dsaptr, u64 *bar_offset, const char *func)
 {
        unsigned long orig_addr;
        unsigned long base_addr;
@@ -350,15 +583,26 @@ static inline struct device_node *xlate_iomm_address(
        struct device_node *dn;
 
        orig_addr = (unsigned long __force)addr;
-       if ((orig_addr < BASE_IO_MEMORY) || (orig_addr >= max_io_memory))
+       if ((orig_addr < BASE_IO_MEMORY) || (orig_addr >= max_io_memory)) {
+               static unsigned long last_jiffies;
+               static int num_printed;
+
+               if (time_after(jiffies, last_jiffies + 60 * HZ)) {
+                       last_jiffies = jiffies;
+                       num_printed = 0;
+               }
+               if (num_printed++ < 10)
+                       printk(KERN_ERR
+                               "iSeries_%s: invalid access at IO address %p\n",
+                               func, addr);
                return NULL;
+       }
        base_addr = orig_addr - BASE_IO_MEMORY;
        ind = base_addr / IOMM_TABLE_ENTRY_SIZE;
        dn = iomm_table[ind];
 
        if (dn != NULL) {
-               int barnum = iobar_table[ind];
-               *dsaptr = iseries_ds_addr(dn) | (barnum << 24);
+               *dsaptr = ds_addr_table[ind];
                *bar_offset = base_addr % IOMM_TABLE_ENTRY_SIZE;
        } else
                panic("PCI: Invalid PCI IO address detected!\n");
@@ -370,28 +614,17 @@ static inline struct device_node *xlate_iomm_address(
  * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal
  * else, data is returned in Big Endian format.
  */
-static u8 iSeries_read_byte(const volatile void __iomem *addr)
+static u8 iseries_readb(const volatile void __iomem *addr)
 {
        u64 bar_offset;
        u64 dsa;
        int retry = 0;
        struct HvCallPci_LoadReturn ret;
        struct device_node *dn =
-               xlate_iomm_address(addr, &dsa, &bar_offset);
+               xlate_iomm_address(addr, &dsa, &bar_offset, "read_byte");
 
-       if (dn == NULL) {
-               static unsigned long last_jiffies;
-               static int num_printed;
-
-               if ((jiffies - last_jiffies) > 60 * HZ) {
-                       last_jiffies = jiffies;
-                       num_printed = 0;
-               }
-               if (num_printed++ < 10)
-                       printk(KERN_ERR "iSeries_read_byte: invalid access at IO address %p\n",
-                              addr);
+       if (dn == NULL)
                return 0xff;
-       }
        do {
                HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, bar_offset, 0);
        } while (check_return_code("RDB", dn, &retry, ret.rc) != 0);
@@ -399,28 +632,17 @@ static u8 iSeries_read_byte(const volatile void __iomem *addr)
        return ret.value;
 }
 
-static u16 iSeries_read_word(const volatile void __iomem *addr)
+static u16 iseries_readw_be(const volatile void __iomem *addr)
 {
        u64 bar_offset;
        u64 dsa;
        int retry = 0;
        struct HvCallPci_LoadReturn ret;
        struct device_node *dn =
-               xlate_iomm_address(addr, &dsa, &bar_offset);
-
-       if (dn == NULL) {
-               static unsigned long last_jiffies;
-               static int num_printed;
+               xlate_iomm_address(addr, &dsa, &bar_offset, "read_word");
 
-               if ((jiffies - last_jiffies) > 60 * HZ) {
-                       last_jiffies = jiffies;
-                       num_printed = 0;
-               }
-               if (num_printed++ < 10)
-                       printk(KERN_ERR "iSeries_read_word: invalid access at IO address %p\n",
-                              addr);
+       if (dn == NULL)
                return 0xffff;
-       }
        do {
                HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
                                bar_offset, 0);
@@ -429,28 +651,17 @@ static u16 iSeries_read_word(const volatile void __iomem *addr)
        return ret.value;
 }
 
-static u32 iSeries_read_long(const volatile void __iomem *addr)
+static u32 iseries_readl_be(const volatile void __iomem *addr)
 {
        u64 bar_offset;
        u64 dsa;
        int retry = 0;
        struct HvCallPci_LoadReturn ret;
        struct device_node *dn =
-               xlate_iomm_address(addr, &dsa, &bar_offset);
+               xlate_iomm_address(addr, &dsa, &bar_offset, "read_long");
 
-       if (dn == NULL) {
-               static unsigned long last_jiffies;
-               static int num_printed;
-
-               if ((jiffies - last_jiffies) > 60 * HZ) {
-                       last_jiffies = jiffies;
-                       num_printed = 0;
-               }
-               if (num_printed++ < 10)
-                       printk(KERN_ERR "iSeries_read_long: invalid access at IO address %p\n",
-                              addr);
+       if (dn == NULL)
                return 0xffffffff;
-       }
        do {
                HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
                                bar_offset, 0);
@@ -463,134 +674,72 @@ static u32 iSeries_read_long(const volatile void __iomem *addr)
  * Write MM I/O Instructions for the iSeries
  *
  */
-static void iSeries_write_byte(u8 data, volatile void __iomem *addr)
+static void iseries_writeb(u8 data, volatile void __iomem *addr)
 {
        u64 bar_offset;
        u64 dsa;
        int retry = 0;
        u64 rc;
        struct device_node *dn =
-               xlate_iomm_address(addr, &dsa, &bar_offset);
+               xlate_iomm_address(addr, &dsa, &bar_offset, "write_byte");
 
-       if (dn == NULL) {
-               static unsigned long last_jiffies;
-               static int num_printed;
-
-               if ((jiffies - last_jiffies) > 60 * HZ) {
-                       last_jiffies = jiffies;
-                       num_printed = 0;
-               }
-               if (num_printed++ < 10)
-                       printk(KERN_ERR "iSeries_write_byte: invalid access at IO address %p\n", addr);
+       if (dn == NULL)
                return;
-       }
        do {
                rc = HvCall4(HvCallPciBarStore8, dsa, bar_offset, data, 0);
        } while (check_return_code("WWB", dn, &retry, rc) != 0);
 }
 
-static void iSeries_write_word(u16 data, volatile void __iomem *addr)
+static void iseries_writew_be(u16 data, volatile void __iomem *addr)
 {
        u64 bar_offset;
        u64 dsa;
        int retry = 0;
        u64 rc;
        struct device_node *dn =
-               xlate_iomm_address(addr, &dsa, &bar_offset);
-
-       if (dn == NULL) {
-               static unsigned long last_jiffies;
-               static int num_printed;
+               xlate_iomm_address(addr, &dsa, &bar_offset, "write_word");
 
-               if ((jiffies - last_jiffies) > 60 * HZ) {
-                       last_jiffies = jiffies;
-                       num_printed = 0;
-               }
-               if (num_printed++ < 10)
-                       printk(KERN_ERR "iSeries_write_word: invalid access at IO address %p\n",
-                              addr);
+       if (dn == NULL)
                return;
-       }
        do {
                rc = HvCall4(HvCallPciBarStore16, dsa, bar_offset, data, 0);
        } while (check_return_code("WWW", dn, &retry, rc) != 0);
 }
 
-static void iSeries_write_long(u32 data, volatile void __iomem *addr)
+static void iseries_writel_be(u32 data, volatile void __iomem *addr)
 {
        u64 bar_offset;
        u64 dsa;
        int retry = 0;
        u64 rc;
        struct device_node *dn =
-               xlate_iomm_address(addr, &dsa, &bar_offset);
+               xlate_iomm_address(addr, &dsa, &bar_offset, "write_long");
 
-       if (dn == NULL) {
-               static unsigned long last_jiffies;
-               static int num_printed;
-
-               if ((jiffies - last_jiffies) > 60 * HZ) {
-                       last_jiffies = jiffies;
-                       num_printed = 0;
-               }
-               if (num_printed++ < 10)
-                       printk(KERN_ERR "iSeries_write_long: invalid access at IO address %p\n",
-                              addr);
+       if (dn == NULL)
                return;
-       }
        do {
                rc = HvCall4(HvCallPciBarStore32, dsa, bar_offset, data, 0);
        } while (check_return_code("WWL", dn, &retry, rc) != 0);
 }
 
-static u8 iseries_readb(const volatile void __iomem *addr)
-{
-       return iSeries_read_byte(addr);
-}
-
 static u16 iseries_readw(const volatile void __iomem *addr)
 {
-       return le16_to_cpu(iSeries_read_word(addr));
+       return le16_to_cpu(iseries_readw_be(addr));
 }
 
 static u32 iseries_readl(const volatile void __iomem *addr)
 {
-       return le32_to_cpu(iSeries_read_long(addr));
-}
-
-static u16 iseries_readw_be(const volatile void __iomem *addr)
-{
-       return iSeries_read_word(addr);
-}
-
-static u32 iseries_readl_be(const volatile void __iomem *addr)
-{
-       return iSeries_read_long(addr);
-}
-
-static void iseries_writeb(u8 data, volatile void __iomem *addr)
-{
-       iSeries_write_byte(data, addr);
+       return le32_to_cpu(iseries_readl_be(addr));
 }
 
 static void iseries_writew(u16 data, volatile void __iomem *addr)
 {
-       iSeries_write_word(cpu_to_le16(data), addr);
+       iseries_writew_be(cpu_to_le16(data), addr);
 }
 
 static void iseries_writel(u32 data, volatile void __iomem *addr)
 {
-       iSeries_write_long(cpu_to_le32(data), addr);
-}
-
-static void iseries_writew_be(u16 data, volatile void __iomem *addr)
-{
-       iSeries_write_word(data, addr);
-}
-
-static void iseries_writel_be(u32 data, volatile void __iomem *addr)
-{
-       iSeries_write_long(data, addr);
+       iseries_writel(cpu_to_le32(data), addr);
 }
 
 static void iseries_readsb(const volatile void __iomem *addr, void *buf,
@@ -598,7 +747,7 @@ static void iseries_readsb(const volatile void __iomem *addr, void *buf,
 {
        u8 *dst = buf;
        while(count-- > 0)
-               *(dst++) = iSeries_read_byte(addr);
+               *(dst++) = iseries_readb(addr);
 }
 
 static void iseries_readsw(const volatile void __iomem *addr, void *buf,
@@ -606,7 +755,7 @@ static void iseries_readsw(const volatile void __iomem *addr, void *buf,
 {
        u16 *dst = buf;
        while(count-- > 0)
-               *(dst++) = iSeries_read_word(addr);
+               *(dst++) = iseries_readw_be(addr);
 }
 
 static void iseries_readsl(const volatile void __iomem *addr, void *buf,
@@ -614,7 +763,7 @@ static void iseries_readsl(const volatile void __iomem *addr, void *buf,
 {
        u32 *dst = buf;
        while(count-- > 0)
-               *(dst++) = iSeries_read_long(addr);
+               *(dst++) = iseries_readl_be(addr);
 }
 
 static void iseries_writesb(volatile void __iomem *addr, const void *buf,
@@ -622,7 +771,7 @@ static void iseries_writesb(volatile void __iomem *addr, const void *buf,
 {
        const u8 *src = buf;
        while(count-- > 0)
-               iSeries_write_byte(*(src++), addr);
+               iseries_writeb(*(src++), addr);
 }
 
 static void iseries_writesw(volatile void __iomem *addr, const void *buf,
@@ -630,7 +779,7 @@ static void iseries_writesw(volatile void __iomem *addr, const void *buf,
 {
        const u16 *src = buf;
        while(count-- > 0)
-               iSeries_write_word(*(src++), addr);
+               iseries_writew_be(*(src++), addr);
 }
 
 static void iseries_writesl(volatile void __iomem *addr, const void *buf,
@@ -638,7 +787,7 @@ static void iseries_writesl(volatile void __iomem *addr, const void *buf,
 {
        const u32 *src = buf;
        while(count-- > 0)
-               iSeries_write_long(*(src++), addr);
+               iseries_writel_be(*(src++), addr);
 }
 
 static void iseries_memset_io(volatile void __iomem *addr, int c,
@@ -647,7 +796,7 @@ static void iseries_memset_io(volatile void __iomem *addr, int c,
        volatile char __iomem *d = addr;
 
        while (n-- > 0)
-               iSeries_write_byte(c, d++);
+               iseries_writeb(c, d++);
 }
 
 static void iseries_memcpy_fromio(void *dest, const volatile void __iomem *src,
@@ -657,7 +806,7 @@ static void iseries_memcpy_fromio(void *dest, const volatile void __iomem *src,
        const volatile char __iomem *s = src;
 
        while (n-- > 0)
-               *d++ = iSeries_read_byte(s++);
+               *d++ = iseries_readb(s++);
 }
 
 static void iseries_memcpy_toio(volatile void __iomem *dest, const void *src,
@@ -667,7 +816,7 @@ static void iseries_memcpy_toio(volatile void __iomem *dest, const void *src,
        volatile char __iomem *d = dest;
 
        while (n-- > 0)
-               iSeries_write_byte(*s++, d++);
+               iseries_writeb(*s++, d++);
 }
 
 /* We only set MMIO ops. The default PIO ops will be default
@@ -720,6 +869,8 @@ void __init iSeries_pcibios_init(void)
        /* Install IO hooks */
        ppc_pci_io = iseries_pci_io;
 
+       pci_probe_only = 1;
+
        /* iSeries has no IO space in the common sense, it needs to set
         * the IO base to 0
         */
@@ -745,11 +896,21 @@ void __init iSeries_pcibios_init(void)
                phb = pcibios_alloc_controller(node);
                if (phb == NULL)
                        continue;
+               /* All legacy iSeries PHBs are in domain zero */
+               phb->global_number = 0;
 
-               phb->pci_mem_offset = bus;
                phb->first_busno = bus;
                phb->last_busno = bus;
                phb->ops = &iSeries_pci_ops;
+               phb->io_base_virt = (void __iomem *)_IO_BASE;
+               phb->io_resource.flags = IORESOURCE_IO;
+               phb->io_resource.start = BASE_IO_MEMORY;
+               phb->io_resource.end = END_IO_MEMORY;
+               phb->io_resource.name = "iSeries PCI IO";
+               phb->mem_resources[0].flags = IORESOURCE_MEM;
+               phb->mem_resources[0].start = BASE_IO_MEMORY;
+               phb->mem_resources[0].end = END_IO_MEMORY;
+               phb->mem_resources[0].name = "Series PCI MEM";
        }
 
        of_node_put(root);