include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / arch / arm / mach-ixp2000 / ixdp2800.c
index c4683aa..237b61a 100644 (file)
@@ -14,7 +14,6 @@
  *  Free Software Foundation;  either version 2 of the  License, or (at your
  *  option) any later version.
  */
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/bitops.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
-#include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 
-#include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/system.h>
-#include <asm/hardware.h>
+#include <mach/hardware.h>
 #include <asm/mach-types.h>
 
 #include <asm/mach/pci.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/arch.h>
 
-
-void ixdp2400_init_irq(void)
-{
-       ixdp2x00_init_irq(IXDP2800_CPLD_INT_STAT, IXDP2800_CPLD_INT_MASK, IXDP2400_NR_IRQS);
-}
-
 /*************************************************************************
  * IXDP2800 timer tick
  *************************************************************************/
@@ -65,19 +57,102 @@ static struct sys_timer ixdp2800_timer = {
 /*************************************************************************
  * IXDP2800 PCI
  *************************************************************************/
+static void __init ixdp2800_slave_disable_pci_master(void)
+{
+       *IXP2000_PCI_CMDSTAT &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+}
+
+static void __init ixdp2800_master_wait_for_slave(void)
+{
+       volatile u32 *addr;
+
+       printk(KERN_INFO "IXDP2800: waiting for slave NPU to configure "
+                        "its BAR sizes\n");
+
+       addr = ixp2000_pci_config_addr(0, IXDP2X00_SLAVE_NPU_DEVFN,
+                                       PCI_BASE_ADDRESS_1);
+       do {
+               *addr = 0xffffffff;
+               cpu_relax();
+       } while (*addr != 0xfe000008);
+
+       addr = ixp2000_pci_config_addr(0, IXDP2X00_SLAVE_NPU_DEVFN,
+                                       PCI_BASE_ADDRESS_2);
+       do {
+               *addr = 0xffffffff;
+               cpu_relax();
+       } while (*addr != 0xc0000008);
+
+       /*
+        * Configure the slave's SDRAM BAR by hand.
+        */
+       *addr = 0x40000008;
+}
+
+static void __init ixdp2800_slave_wait_for_master_enable(void)
+{
+       printk(KERN_INFO "IXDP2800: waiting for master NPU to enable us\n");
+
+       while ((*IXP2000_PCI_CMDSTAT & PCI_COMMAND_MASTER) == 0)
+               cpu_relax();
+}
+
 void __init ixdp2800_pci_preinit(void)
 {
        printk("ixdp2x00_pci_preinit called\n");
 
-       *IXP2000_PCI_ADDR_EXT =  0x0000e000;
+       *IXP2000_PCI_ADDR_EXT = 0x0001e000;
+
+       if (!ixdp2x00_master_npu())
+               ixdp2800_slave_disable_pci_master();
 
-       *IXP2000_PCI_DRAM_BASE_ADDR_MASK = (0x40000000 - 1) & ~0xfffff;
        *IXP2000_PCI_SRAM_BASE_ADDR_MASK = (0x2000000 - 1) & ~0x3ffff;
+       *IXP2000_PCI_DRAM_BASE_ADDR_MASK = (0x40000000 - 1) & ~0xfffff;
 
        ixp2000_pci_preinit();
+
+       if (ixdp2x00_master_npu()) {
+               /*
+                * Wait until the slave set its SRAM/SDRAM BAR sizes
+                * correctly before we proceed to scan and enumerate
+                * the bus.
+                */
+               ixdp2800_master_wait_for_slave();
+
+               /*
+                * We configure the SDRAM BARs by hand because they
+                * are 1G and fall outside of the regular allocated
+                * PCI address space.
+                */
+               *IXP2000_PCI_SDRAM_BAR = 0x00000008;
+       } else {
+               /*
+                * Wait for the master to complete scanning the bus
+                * and assigning resources before we proceed to scan
+                * the bus ourselves.  Set pci=firmware to honor the
+                * master's resource assignment.
+                */
+               ixdp2800_slave_wait_for_master_enable();
+               pcibios_setup("firmware");
+       }
+}
+
+/*
+ * We assign the SDRAM BARs for the two IXP2800 CPUs by hand, outside
+ * of the regular PCI window, because there's only 512M of outbound PCI
+ * memory window on each IXP, while we need 1G for each of the BARs.
+ */
+static void __devinit ixp2800_pci_fixup(struct pci_dev *dev)
+{
+       if (machine_is_ixdp2800()) {
+               dev->resource[2].start = 0;
+               dev->resource[2].end   = 0;
+               dev->resource[2].flags = 0;
+       }
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IXP2800, ixp2800_pci_fixup);
 
-int ixdp2800_pci_setup(int nr, struct pci_sys_data *sys)
+static int __init ixdp2800_pci_setup(int nr, struct pci_sys_data *sys)
 {
        sys->mem_offset = 0x00000000;
 
@@ -129,22 +204,47 @@ static int __init ixdp2800_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
        } else return IRQ_IXP2000_PCIB; /* Slave NIC interrupt */
 }
 
-static void ixdp2800_pci_postinit(void)
+static void __init ixdp2800_master_enable_slave(void)
 {
-       struct pci_dev *dev;
+       volatile u32 *addr;
 
-       if (ixdp2x00_master_npu()) {
-               dev = pci_find_slot(1, IXDP2800_SLAVE_ENET_DEVFN);
-               pci_remove_bus_device(dev);
-       } else {
-               dev = pci_find_slot(1, IXDP2800_MASTER_ENET_DEVFN);
-               pci_remove_bus_device(dev);
+       printk(KERN_INFO "IXDP2800: enabling slave NPU\n");
+
+       addr = (volatile u32 *)ixp2000_pci_config_addr(0,
+                                       IXDP2X00_SLAVE_NPU_DEVFN,
+                                       PCI_COMMAND);
+
+       *addr |= PCI_COMMAND_MASTER;
+}
+
+static void __init ixdp2800_master_wait_for_slave_bus_scan(void)
+{
+       volatile u32 *addr;
+
+       printk(KERN_INFO "IXDP2800: waiting for slave to finish bus scan\n");
+
+       addr = (volatile u32 *)ixp2000_pci_config_addr(0,
+                                       IXDP2X00_SLAVE_NPU_DEVFN,
+                                       PCI_COMMAND);
+       while ((*addr & PCI_COMMAND_MEMORY) == 0)
+               cpu_relax();
+}
+
+static void __init ixdp2800_slave_signal_bus_scan_completion(void)
+{
+       printk(KERN_INFO "IXDP2800: bus scan done, signaling master\n");
+       *IXP2000_PCI_CMDSTAT |= PCI_COMMAND_MEMORY;
+}
 
+static void __init ixdp2800_pci_postinit(void)
+{
+       if (!ixdp2x00_master_npu()) {
                ixdp2x00_slave_pci_postinit();
+               ixdp2800_slave_signal_bus_scan_completion();
        }
 }
 
-struct hw_pci ixdp2800_pci __initdata = {
+struct __initdata hw_pci ixdp2800_pci __initdata = {
        .nr_controllers = 1,
        .setup          = ixdp2800_pci_setup,
        .preinit        = ixdp2800_pci_preinit,
@@ -155,26 +255,42 @@ struct hw_pci ixdp2800_pci __initdata = {
 
 int __init ixdp2800_pci_init(void)
 {
-       if (machine_is_ixdp2800())
+       if (machine_is_ixdp2800()) {
+               struct pci_dev *dev;
+
                pci_common_init(&ixdp2800_pci);
+               if (ixdp2x00_master_npu()) {
+                       dev = pci_get_bus_and_slot(1, IXDP2800_SLAVE_ENET_DEVFN);
+                       pci_remove_bus_device(dev);
+                       pci_dev_put(dev);
+
+                       ixdp2800_master_enable_slave();
+                       ixdp2800_master_wait_for_slave_bus_scan();
+               } else {
+                       dev = pci_get_bus_and_slot(1, IXDP2800_MASTER_ENET_DEVFN);
+                       pci_remove_bus_device(dev);
+                       pci_dev_put(dev);
+               }
+       }
 
        return 0;
 }
 
 subsys_initcall(ixdp2800_pci_init);
 
-void ixdp2800_init_irq(void)
+void __init ixdp2800_init_irq(void)
 {
        ixdp2x00_init_irq(IXDP2800_CPLD_INT_STAT, IXDP2800_CPLD_INT_MASK, IXDP2800_NR_IRQS);
 }
 
 MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform")
-       MAINTAINER("MontaVista Software, Inc.")
-       BOOT_MEM(0x00000000, IXP2000_UART_PHYS_BASE, IXP2000_UART_VIRT_BASE)
-       BOOT_PARAMS(0x00000100)
-       MAPIO(ixdp2x00_map_io)
-       INITIRQ(ixdp2800_init_irq)
+       /* Maintainer: MontaVista Software, Inc. */
+       .phys_io        = IXP2000_UART_PHYS_BASE,
+       .io_pg_offst    = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
+       .boot_params    = 0x00000100,
+       .map_io         = ixdp2x00_map_io,
+       .init_irq       = ixdp2800_init_irq,
        .timer          = &ixdp2800_timer,
-       INIT_MACHINE(ixdp2x00_init_machine)
+       .init_machine   = ixdp2x00_init_machine,
 MACHINE_END