Say Y here if you want to run your kernel on the Thecus n2100
          NAS appliance.
 
+config IOP3XX_ATU
+        bool "Enable the PCI Controller"
+        default y
+        help
+          Say Y here if you want the IOP to initialize its PCI Controller.
+          Say N if the IOP is an add in card, the host system owns the PCI
+          bus in this case.
+
 endmenu
 
 endif
 
 
 static int __init iq31244_pci_init(void)
 {
-       if (is_ep80219())
-               pci_common_init(&ep80219_pci);
-       else if (machine_is_iq31244()) {
+       if (is_ep80219()) {
+               if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE)
+                       pci_common_init(&ep80219_pci);
+       } else if (machine_is_iq31244()) {
                if (is_80219()) {
                        printk("note: iq31244 board type has been selected\n");
                        printk("note: to select ep80219 operation:\n");
                        printk("\t2/ update boot loader to pass"
                                " the ep80219 id: %d\n", MACH_TYPE_EP80219);
                }
-               pci_common_init(&iq31244_pci);
+
+               if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE)
+                       pci_common_init(&iq31244_pci);
        }
 
        return 0;
 
 
 static int __init iq80321_pci_init(void)
 {
-       if (machine_is_iq80321())
+       if ((iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) &&
+               machine_is_iq80321())
                pci_common_init(&iq80321_pci);
 
        return 0;
 
          Say Y here if you want to run your kernel on the Intel IQ80332
          evaluation kit for the IOP332 chipset.
 
+config IOP3XX_ATU
+       bool "Enable the PCI Controller"
+       default y
+       help
+         Say Y here if you want the IOP to initialize its PCI Controller.
+         Say N if the IOP is an add in card, the host system owns the PCI
+         bus in this case.
+
 endmenu
 
 endif
 
 
 static int __init iq80331_pci_init(void)
 {
-       if (machine_is_iq80331())
+       if ((iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) &&
+               machine_is_iq80331())
                pci_common_init(&iq80331_pci);
 
        return 0;
 
 
 static int __init iq80332_pci_init(void)
 {
-       if (machine_is_iq80332())
+       if ((iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) &&
+               machine_is_iq80332())
                pci_common_init(&iq80332_pci);
 
        return 0;
 
  * This routine checks the status of the last configuration cycle.  If an error
  * was detected it returns a 1, else it returns a 0.  The errors being checked
  * are parity, master abort, target abort (master and target).  These types of
- * errors occure during a config cycle where there is no device, like during
+ * errors occur during a config cycle where there is no device, like during
  * the discovery stage.
  */
 static int iop3xx_pci_status(void)
        return pci_scan_bus(sys->busnr, &iop3xx_ops, sys);
 }
 
+void __init iop3xx_atu_setup(void)
+{
+       /* BAR 0 ( Disabled ) */
+       *IOP3XX_IAUBAR0 = 0x0;
+       *IOP3XX_IABAR0  = 0x0;
+       *IOP3XX_IATVR0  = 0x0;
+       *IOP3XX_IALR0   = 0x0;
+
+       /* BAR 1 ( Disabled ) */
+       *IOP3XX_IAUBAR1 = 0x0;
+       *IOP3XX_IABAR1  = 0x0;
+       *IOP3XX_IALR1   = 0x0;
+
+       /* BAR 2 (1:1 mapping with Physical RAM) */
+       /* Set limit and enable */
+       *IOP3XX_IALR2 = ~((u32)IOP3XX_MAX_RAM_SIZE - 1) & ~0x1;
+       *IOP3XX_IAUBAR2 = 0x0;
+
+       /* Align the inbound bar with the base of memory */
+       *IOP3XX_IABAR2 = PHYS_OFFSET |
+                              PCI_BASE_ADDRESS_MEM_TYPE_64 |
+                              PCI_BASE_ADDRESS_MEM_PREFETCH;
+
+       *IOP3XX_IATVR2 = PHYS_OFFSET;
+
+       /* Outbound window 0 */
+       *IOP3XX_OMWTVR0 = IOP3XX_PCI_LOWER_MEM_PA;
+       *IOP3XX_OUMWTVR0 = 0;
+
+       /* Outbound window 1 */
+       *IOP3XX_OMWTVR1 = IOP3XX_PCI_LOWER_MEM_PA + IOP3XX_PCI_MEM_WINDOW_SIZE;
+       *IOP3XX_OUMWTVR1 = 0;
+
+       /* BAR 3 ( Disabled ) */
+       *IOP3XX_IAUBAR3 = 0x0;
+       *IOP3XX_IABAR3  = 0x0;
+       *IOP3XX_IATVR3  = 0x0;
+       *IOP3XX_IALR3   = 0x0;
+
+       /* Setup the I/O Bar
+        */
+       *IOP3XX_OIOWTVR = IOP3XX_PCI_LOWER_IO_PA;;
+
+       /* Enable inbound and outbound cycles
+        */
+       *IOP3XX_ATUCMD |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+                              PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+       *IOP3XX_ATUCR |= IOP3XX_ATUCR_OUT_EN;
+}
+
+void __init iop3xx_atu_disable(void)
+{
+       *IOP3XX_ATUCMD = 0;
+       *IOP3XX_ATUCR = 0;
+
+       /* wait for cycles to quiesce */
+       while (*IOP3XX_PCSR & (IOP3XX_PCSR_OUT_Q_BUSY |
+                                    IOP3XX_PCSR_IN_Q_BUSY))
+               cpu_relax();
+
+       /* BAR 0 ( Disabled ) */
+       *IOP3XX_IAUBAR0 = 0x0;
+       *IOP3XX_IABAR0  = 0x0;
+       *IOP3XX_IATVR0  = 0x0;
+       *IOP3XX_IALR0   = 0x0;
+
+       /* BAR 1 ( Disabled ) */
+       *IOP3XX_IAUBAR1 = 0x0;
+       *IOP3XX_IABAR1  = 0x0;
+       *IOP3XX_IALR1   = 0x0;
+
+       /* BAR 2 ( Disabled ) */
+       *IOP3XX_IAUBAR2 = 0x0;
+       *IOP3XX_IABAR2  = 0x0;
+       *IOP3XX_IATVR2  = 0x0;
+       *IOP3XX_IALR2   = 0x0;
+
+       /* BAR 3 ( Disabled ) */
+       *IOP3XX_IAUBAR3 = 0x0;
+       *IOP3XX_IABAR3  = 0x0;
+       *IOP3XX_IATVR3  = 0x0;
+       *IOP3XX_IALR3   = 0x0;
+
+       /* Clear the outbound windows */
+       *IOP3XX_OIOWTVR  = 0;
+
+       /* Outbound window 0 */
+       *IOP3XX_OMWTVR0 = 0;
+       *IOP3XX_OUMWTVR0 = 0;
+
+       /* Outbound window 1 */
+       *IOP3XX_OMWTVR1 = 0;
+       *IOP3XX_OUMWTVR1 = 0;
+}
+
+/* Flag to determine whether the ATU is initialized and the PCI bus scanned */
+int init_atu;
+
 void iop3xx_pci_preinit(void)
 {
+       if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) {
+               iop3xx_atu_disable();
+               iop3xx_atu_setup();
+       }
+
        DBG("PCI:  Intel 803xx PCI init code.\n");
        DBG("ATU: IOP3XX_ATUCMD=0x%04x\n", *IOP3XX_ATUCMD);
        DBG("ATU: IOP3XX_OMWTVR0=0x%04x, IOP3XX_OIOWTVR=0x%04x\n",
 
        hook_fault_code(16+6, iop3xx_pci_abort, SIGBUS, "imprecise external abort");
 }
+
+/* allow init_atu to be user overridden */
+static int __init iop3xx_init_atu_setup(char *str)
+{
+       init_atu = IOP3XX_INIT_ATU_DEFAULT;
+       if (str) {
+               while (*str != '\0') {
+                       switch (*str) {
+                       case 'y':
+                       case 'Y':
+                               init_atu = IOP3XX_INIT_ATU_ENABLE;
+                               break;
+                       case 'n':
+                       case 'N':
+                               init_atu = IOP3XX_INIT_ATU_DISABLE;
+                               break;
+                       case ',':
+                       case '=':
+                               break;
+                       default:
+                               printk(KERN_DEBUG "\"%s\" malformed at "
+                                           "character: \'%c\'",
+                                           __FUNCTION__,
+                                           *str);
+                               *(str + 1) = '\0';
+                       }
+                       str++;
+               }
+       }
+
+       return 1;
+}
+
+__setup("iop3xx_init_atu", iop3xx_init_atu_setup);
+
 
 
 #include <asm/hardware/iop3xx.h>
 
+/* ATU Parameters
+ * set up a 1:1 bus to physical ram relationship
+ * w/ physical ram on top of pci in the memory map
+ */
+#define IOP32X_MAX_RAM_SIZE            0x40000000UL
+#define IOP3XX_MAX_RAM_SIZE            IOP32X_MAX_RAM_SIZE
+#define IOP3XX_PCI_LOWER_MEM_BA        0x80000000
+#define IOP32X_PCI_MEM_WINDOW_SIZE     0x04000000
+#define IOP3XX_PCI_MEM_WINDOW_SIZE     IOP32X_PCI_MEM_WINDOW_SIZE
 
 #endif
 
  * bus_to_virt: Used to convert an address for DMA operations
  *             to an address that the kernel can use.
  */
-#define __virt_to_bus(x)       (((__virt_to_phys(x)) & ~(*IOP3XX_IATVR2)) | ((*IOP3XX_IABAR2) & 0xfffffff0))
-#define __bus_to_virt(x)       (__phys_to_virt(((x) & ~(*IOP3XX_IALR2)) | ( *IOP3XX_IATVR2)))
+#define __virt_to_bus(x)       (__virt_to_phys(x))
+#define __bus_to_virt(x)       (__phys_to_virt(x))
 
 
 #endif
 
 #define IOP33X_UART1_PHYS      (IOP3XX_PERIPHERAL_PHYS_BASE + 0x1740)
 #define IOP33X_UART1_VIRT      (IOP3XX_PERIPHERAL_VIRT_BASE + 0x1740)
 
+/* ATU Parameters
+ * set up a 1:1 bus to physical ram relationship
+ * w/ pci on top of physical ram in memory map
+ */
+#define IOP33X_MAX_RAM_SIZE            0x80000000UL
+#define IOP3XX_MAX_RAM_SIZE            IOP33X_MAX_RAM_SIZE
+#define IOP3XX_PCI_LOWER_MEM_BA        (PHYS_OFFSET + IOP33X_MAX_RAM_SIZE)
+#define IOP33X_PCI_MEM_WINDOW_SIZE     0x08000000
+#define IOP3XX_PCI_MEM_WINDOW_SIZE     IOP33X_PCI_MEM_WINDOW_SIZE
+
 
 #endif
 
  * bus_to_virt: Used to convert an address for DMA operations
  *             to an address that the kernel can use.
  */
-#define __virt_to_bus(x)       (((__virt_to_phys(x)) & ~(*IOP3XX_IATVR2)) | ((*IOP3XX_IABAR2) & 0xfffffff0))
-#define __bus_to_virt(x)       (__phys_to_virt(((x) & ~(*IOP3XX_IALR2)) | ( *IOP3XX_IATVR2)))
+#define __virt_to_bus(x)       (__virt_to_phys(x))
+#define __bus_to_virt(x)       (__phys_to_virt(x))
 
 
 #endif
 
 extern void gpio_line_config(int line, int direction);
 extern int  gpio_line_get(int line);
 extern void gpio_line_set(int line, int value);
+extern int init_atu;
 #endif
 
 
 #define IOP3XX_PCIXCMD         (volatile u16 *)IOP3XX_REG_ADDR(0x01e2)
 #define IOP3XX_PCIXSR          (volatile u32 *)IOP3XX_REG_ADDR(0x01e4)
 #define IOP3XX_PCIIRSR         (volatile u32 *)IOP3XX_REG_ADDR(0x01ec)
+#define IOP3XX_PCSR_OUT_Q_BUSY (1 << 15)
+#define IOP3XX_PCSR_IN_Q_BUSY  (1 << 14)
+#define IOP3XX_ATUCR_OUT_EN    (1 << 1)
+
+#define IOP3XX_INIT_ATU_DEFAULT 0
+#define IOP3XX_INIT_ATU_DISABLE -1
+#define IOP3XX_INIT_ATU_ENABLE  1
+
+#ifdef CONFIG_IOP3XX_ATU
+#define iop3xx_get_init_atu(x) (init_atu == IOP3XX_INIT_ATU_DEFAULT ?\
+                               IOP3XX_INIT_ATU_ENABLE : init_atu)
+#else
+#define iop3xx_get_init_atu(x) (init_atu == IOP3XX_INIT_ATU_DEFAULT ?\
+                               IOP3XX_INIT_ATU_DISABLE : init_atu)
+#endif
 
 /* Messaging Unit  */
 #define IOP3XX_IMR0            (volatile u32 *)IOP3XX_REG_ADDR(0x0310)
 /*
  * IOP3XX I/O and Mem space regions for PCI autoconfiguration
  */
-#define IOP3XX_PCI_MEM_WINDOW_SIZE     0x04000000
-#define IOP3XX_PCI_LOWER_MEM_PA                0x80000000
-#define IOP3XX_PCI_LOWER_MEM_BA                (*IOP3XX_OMWTVR0)
+#define IOP3XX_PCI_LOWER_MEM_PA        0x80000000
 
 #define IOP3XX_PCI_IO_WINDOW_SIZE      0x00010000
 #define IOP3XX_PCI_LOWER_IO_PA         0x90000000
 #define IOP3XX_PCI_LOWER_IO_VA         0xfe000000
-#define IOP3XX_PCI_LOWER_IO_BA         (*IOP3XX_OIOWTVR)
+#define IOP3XX_PCI_LOWER_IO_BA         0x90000000
 #define IOP3XX_PCI_UPPER_IO_PA         (IOP3XX_PCI_LOWER_IO_PA +\
                                        IOP3XX_PCI_IO_WINDOW_SIZE - 1)
 #define IOP3XX_PCI_UPPER_IO_VA         (IOP3XX_PCI_LOWER_IO_VA +\