m68knommu: fix MC68328.h defines
[linux-3.10.git] / arch / arm / mach-integrator / pci_v3.c
index af9ebcc..e7fcea7 100644 (file)
  */
 #include <linux/kernel.h>
 #include <linux/pci.h>
-#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
+#include <linux/io.h>
 
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <mach/irqs.h>
+
+#include <asm/signal.h>
 #include <asm/mach/pci.h>
+#include <asm/irq_regs.h>
 
 #include <asm/hardware/pci_v3.h>
 
 /*
  * The V3 PCI interface chip in Integrator provides several windows from
  * local bus memory into the PCI memory areas.   Unfortunately, there
- * are not really enough windows for our usage, therefore we reuse 
+ * are not really enough windows for our usage, therefore we reuse
  * one of the windows for access to PCI configuration space.  The
  * memory map is as follows:
- * 
+ *
  * Local Bus Memory         Usage
- * 
+ *
  * 40000000 - 4FFFFFFF      PCI memory.  256M non-prefetchable
  * 50000000 - 5FFFFFFF      PCI memory.  256M prefetchable
  * 60000000 - 60FFFFFF      PCI IO.  16M
  * 61000000 - 61FFFFFF      PCI Configuration. 16M
- * 
+ *
  * There are three V3 windows, each described by a pair of V3 registers.
  * These are LB_BASE0/LB_MAP0, LB_BASE1/LB_MAP1 and LB_BASE2/LB_MAP2.
  * Base0 and Base1 can be used for any type of PCI memory access.   Base2
  * can be used either for PCI I/O or for I20 accesses.  By default, uHAL
  * uses this only for PCI IO space.
- * 
+ *
  * Normally these spaces are mapped using the following base registers:
- * 
+ *
  * Usage Local Bus Memory         Base/Map registers used
- * 
+ *
  * Mem   40000000 - 4FFFFFFF      LB_BASE0/LB_MAP0
  * Mem   50000000 - 5FFFFFFF      LB_BASE1/LB_MAP1
  * IO    60000000 - 60FFFFFF      LB_BASE2/LB_MAP2
  * Cfg   61000000 - 61FFFFFF
- * 
+ *
  * This means that I20 and PCI configuration space accesses will fail.
- * When PCI configuration accesses are needed (via the uHAL PCI 
+ * When PCI configuration accesses are needed (via the uHAL PCI
  * configuration space primitives) we must remap the spaces as follows:
- * 
+ *
  * Usage Local Bus Memory         Base/Map registers used
- * 
+ *
  * Mem   40000000 - 4FFFFFFF      LB_BASE0/LB_MAP0
  * Mem   50000000 - 5FFFFFFF      LB_BASE0/LB_MAP0
  * IO    60000000 - 60FFFFFF      LB_BASE2/LB_MAP2
  * Cfg   61000000 - 61FFFFFF      LB_BASE1/LB_MAP1
- * 
+ *
  * To make this work, the code depends on overlapping windows working.
- * The V3 chip translates an address by checking its range within 
+ * The V3 chip translates an address by checking its range within
  * each of the BASE/MAP pairs in turn (in ascending register number
  * order).  It will use the first matching pair.   So, for example,
  * if the same address is mapped by both LB_BASE0/LB_MAP0 and
- * LB_BASE1/LB_MAP1, the V3 will use the translation from 
+ * LB_BASE1/LB_MAP1, the V3 will use the translation from
  * LB_BASE0/LB_MAP0.
- * 
+ *
  * To allow PCI Configuration space access, the code enlarges the
  * window mapped by LB_BASE0/LB_MAP0 from 256M to 512M.  This occludes
  * the windows currently mapped by LB_BASE1/LB_MAP1 so that it can
  * be remapped for use by configuration cycles.
- * 
- * At the end of the PCI Configuration space accesses, 
+ *
+ * At the end of the PCI Configuration space accesses,
  * LB_BASE1/LB_MAP1 is reset to map PCI Memory.  Finally the window
  * mapped by LB_BASE0/LB_MAP0 is reduced in size from 512M to 256M to
  * reveal the now restored LB_BASE1/LB_MAP1 window.
- * 
+ *
  * NOTE: We do not set up I2O mapping.  I suspect that this is only
  * for an intelligent (target) device.  Using I2O disables most of
  * the mappings into PCI memory.
  *
  * returns:    configuration address to play on the PCI bus
  *
- * To generate the appropriate PCI configuration cycles in the PCI 
- * configuration address space, you present the V3 with the following pattern 
+ * To generate the appropriate PCI configuration cycles in the PCI
+ * configuration address space, you present the V3 with the following pattern
  * (which is very nearly a type 1 (except that the lower two bits are 00 and
  * not 01).   In order for this mapping to work you need to set up one of
  * the local to PCI aperatures to 16Mbytes in length translating to
  *
  * Type 0:
  *
- *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
+ *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
  *  3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0|
  *
  * Type 1:
  *
- *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
+ *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
  *  3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
  *     15:11   Device number (5 bits)
  *     10:8    function number
  *      7:2    register number
- *  
+ *
  */
-static DEFINE_SPINLOCK(v3_lock);
+static DEFINE_RAW_SPINLOCK(v3_lock);
 
 #define PCI_BUS_NONMEM_START   0x00000000
 #define PCI_BUS_NONMEM_SIZE    SZ_256M
@@ -179,7 +181,7 @@ static DEFINE_SPINLOCK(v3_lock);
 #undef V3_LB_BASE_PREFETCH
 #define V3_LB_BASE_PREFETCH 0
 
-static unsigned long v3_open_config_window(struct pci_bus *bus,
+static void __iomem *v3_open_config_window(struct pci_bus *bus,
                                           unsigned int devfn, int offset)
 {
        unsigned int address, mapaddress, busnr;
@@ -189,12 +191,9 @@ static unsigned long v3_open_config_window(struct pci_bus *bus,
        /*
         * Trap out illegal values
         */
-       if (offset > 255)
-               BUG();
-       if (busnr > 255)
-               BUG();
-       if (devfn > 255)
-               BUG();
+       BUG_ON(offset > 255);
+       BUG_ON(busnr > 255);
+       BUG_ON(devfn > 255);
 
        if (busnr == 0) {
                int slot = PCI_SLOT(devfn);
@@ -278,11 +277,11 @@ static void v3_close_config_window(void)
 static int v3_read_config(struct pci_bus *bus, unsigned int devfn, int where,
                          int size, u32 *val)
 {
-       unsigned long addr;
+       void __iomem *addr;
        unsigned long flags;
        u32 v;
 
-       spin_lock_irqsave(&v3_lock, flags);
+       raw_spin_lock_irqsave(&v3_lock, flags);
        addr = v3_open_config_window(bus, devfn, where);
 
        switch (size) {
@@ -300,7 +299,7 @@ static int v3_read_config(struct pci_bus *bus, unsigned int devfn, int where,
        }
 
        v3_close_config_window();
-       spin_unlock_irqrestore(&v3_lock, flags);
+       raw_spin_unlock_irqrestore(&v3_lock, flags);
 
        *val = v;
        return PCIBIOS_SUCCESSFUL;
@@ -309,10 +308,10 @@ static int v3_read_config(struct pci_bus *bus, unsigned int devfn, int where,
 static int v3_write_config(struct pci_bus *bus, unsigned int devfn, int where,
                           int size, u32 val)
 {
-       unsigned long addr;
+       void __iomem *addr;
        unsigned long flags;
 
-       spin_lock_irqsave(&v3_lock, flags);
+       raw_spin_lock_irqsave(&v3_lock, flags);
        addr = v3_open_config_window(bus, devfn, where);
 
        switch (size) {
@@ -333,12 +332,12 @@ static int v3_write_config(struct pci_bus *bus, unsigned int devfn, int where,
        }
 
        v3_close_config_window();
-       spin_unlock_irqrestore(&v3_lock, flags);
+       raw_spin_unlock_irqrestore(&v3_lock, flags);
 
        return PCIBIOS_SUCCESSFUL;
 }
 
-static struct pci_ops pci_v3_ops = {
+struct pci_ops pci_v3_ops = {
        .read   = v3_read_config,
        .write  = v3_write_config,
 };
@@ -357,7 +356,7 @@ static struct resource pre_mem = {
        .flags  = IORESOURCE_MEM | IORESOURCE_PREFETCH,
 };
 
-static int __init pci_v3_setup_resources(struct resource **resource)
+static int __init pci_v3_setup_resources(struct pci_sys_data *sys)
 {
        if (request_resource(&iomem_resource, &non_mem)) {
                printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
@@ -372,13 +371,11 @@ static int __init pci_v3_setup_resources(struct resource **resource)
        }
 
        /*
-        * bus->resource[0] is the IO resource for this bus
-        * bus->resource[1] is the mem resource for this bus
-        * bus->resource[2] is the prefetch mem resource for this bus
+        * the mem resource for this bus
+        * the prefetch mem resource for this bus
         */
-       resource[0] = &ioport_resource;
-       resource[1] = &non_mem;
-       resource[2] = &pre_mem;
+       pci_add_resource_offset(&sys->resources, &non_mem, sys->mem_offset);
+       pci_add_resource_offset(&sys->resources, &pre_mem, sys->mem_offset);
 
        return 1;
 }
@@ -388,9 +385,10 @@ static int __init pci_v3_setup_resources(struct resource **resource)
  * means I can't get additional information on the reason for the pm2fb
  * problems.  I suppose I'll just have to mind-meld with the machine. ;)
  */
-#define SC_PCI     (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_PCIENABLE_OFFSET)
-#define SC_LBFADDR (IO_ADDRESS(INTEGRATOR_SC_BASE) + 0x20)
-#define SC_LBFCODE (IO_ADDRESS(INTEGRATOR_SC_BASE) + 0x24)
+static void __iomem *ap_syscon_base;
+#define INTEGRATOR_SC_PCIENABLE_OFFSET 0x18
+#define INTEGRATOR_SC_LBFADDR_OFFSET   0x20
+#define INTEGRATOR_SC_LBFCODE_OFFSET   0x24
 
 static int
 v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
@@ -401,14 +399,13 @@ v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        char buf[128];
 
        sprintf(buf, "V3 fault: addr 0x%08lx, FSR 0x%03x, PC 0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n",
-               addr, fsr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255,
+               addr, fsr, pc, instr, __raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFADDR_OFFSET), __raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFCODE_OFFSET) & 255,
                v3_readb(V3_LB_ISTAT));
        printk(KERN_DEBUG "%s", buf);
-       printascii(buf);
 #endif
 
        v3_writeb(V3_LB_ISTAT, 0);
-       __raw_writel(3, SC_PCI);
+       __raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET);
 
        /*
         * If the instruction being executed was a read,
@@ -439,23 +436,26 @@ v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        return 1;
 }
 
-static irqreturn_t v3_irq(int irq, void *devid)
+static irqreturn_t v3_irq(int dummy, void *devid)
 {
 #ifdef CONFIG_DEBUG_LL
        struct pt_regs *regs = get_irq_regs();
        unsigned long pc = instruction_pointer(regs);
        unsigned long instr = *(unsigned long *)pc;
        char buf[128];
+       extern void printascii(const char *);
 
-       sprintf(buf, "V3 int %d: pc=0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n", irq,
-               pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255,
+       sprintf(buf, "V3 int %d: pc=0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x "
+               "ISTAT=%02x\n", IRQ_AP_V3INT, pc, instr,
+               __raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFADDR_OFFSET),
+               __raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFCODE_OFFSET) & 255,
                v3_readb(V3_LB_ISTAT));
        printascii(buf);
 #endif
 
        v3_writew(V3_PCI_STAT, 0xf000);
        v3_writeb(V3_LB_ISTAT, 0);
-       __raw_writel(3, SC_PCI);
+       __raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET);
 
 #ifdef CONFIG_DEBUG_LL
        /*
@@ -475,19 +475,17 @@ int __init pci_v3_setup(int nr, struct pci_sys_data *sys)
 {
        int ret = 0;
 
+       if (!ap_syscon_base)
+               return -EINVAL;
+
        if (nr == 0) {
                sys->mem_offset = PHYS_PCI_MEM_BASE;
-               ret = pci_v3_setup_resources(sys->resource);
+               ret = pci_v3_setup_resources(sys);
        }
 
        return ret;
 }
 
-struct pci_bus *pci_v3_scan_bus(int nr, struct pci_sys_data *sys)
-{
-       return pci_scan_bus(sys->busnr, &pci_v3_ops, sys);
-}
-
 /*
  * V3_LB_BASE? - local bus address
  * V3_LB_MAP?  - pci bus address
@@ -498,15 +496,24 @@ void __init pci_v3_preinit(void)
        unsigned int temp;
        int ret;
 
+       /* Remap the Integrator system controller */
+       ap_syscon_base = ioremap(INTEGRATOR_SC_BASE, 0x100);
+       if (!ap_syscon_base) {
+               pr_err("unable to remap the AP syscon for PCIv3\n");
+               return;
+       }
+
+       pcibios_min_mem = 0x00100000;
+
        /*
         * Hook in our fault handler for PCI errors
         */
-       hook_fault_code(4, v3_pci_fault, SIGBUS, "external abort on linefetch");
-       hook_fault_code(6, v3_pci_fault, SIGBUS, "external abort on linefetch");
-       hook_fault_code(8, v3_pci_fault, SIGBUS, "external abort on non-linefetch");
-       hook_fault_code(10, v3_pci_fault, SIGBUS, "external abort on non-linefetch");
+       hook_fault_code(4, v3_pci_fault, SIGBUS, 0, "external abort on linefetch");
+       hook_fault_code(6, v3_pci_fault, SIGBUS, 0, "external abort on linefetch");
+       hook_fault_code(8, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
+       hook_fault_code(10, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
 
-       spin_lock_irqsave(&v3_lock, flags);
+       raw_spin_lock_irqsave(&v3_lock, flags);
 
        /*
         * Unlock V3 registers, but only if they were previously locked.
@@ -569,7 +576,7 @@ void __init pci_v3_preinit(void)
        v3_writeb(V3_LB_ISTAT, 0);
        v3_writew(V3_LB_CFG, v3_readw(V3_LB_CFG) | (1 << 10));
        v3_writeb(V3_LB_IMASK, 0x28);
-       __raw_writel(3, SC_PCI);
+       __raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET);
 
        /*
         * Grab the PCI error interrupt.
@@ -579,7 +586,7 @@ void __init pci_v3_preinit(void)
                printk(KERN_ERR "PCI: unable to grab PCI error "
                       "interrupt: %d\n", ret);
 
-       spin_unlock_irqrestore(&v3_lock, flags);
+       raw_spin_unlock_irqrestore(&v3_lock, flags);
 }
 
 void __init pci_v3_postinit(void)