gemini: drop Linux 4.1 support
[openwrt/staging/yousong.git] / target / linux / gemini / patches-4.1 / 140-arm-gemini-add-pci-support.patch
diff --git a/target/linux/gemini/patches-4.1/140-arm-gemini-add-pci-support.patch b/target/linux/gemini/patches-4.1/140-arm-gemini-add-pci-support.patch
deleted file mode 100644 (file)
index 141799b..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
---- a/arch/arm/Kconfig
-+++ b/arch/arm/Kconfig
-@@ -381,6 +381,7 @@ config ARCH_GEMINI
-       select CLKSRC_MMIO
-       select CPU_FA526
-       select GENERIC_CLOCKEVENTS
-+      select MIGHT_HAVE_PCI
-       help
-         Support for the Cortina Systems Gemini family SoCs
---- a/arch/arm/mach-gemini/include/mach/hardware.h
-+++ b/arch/arm/mach-gemini/include/mach/hardware.h
-@@ -71,4 +71,9 @@
-  */
- #define IO_ADDRESS(x) IOMEM((((x) & 0xFFF00000) >> 4) | ((x) & 0x000FFFFF) | 0xF0000000)
-+/*
-+ * PCI subsystem macros
-+ */
-+#define pcibios_assign_all_busses()   1
-+
- #endif
---- a/arch/arm/mach-gemini/include/mach/irqs.h
-+++ b/arch/arm/mach-gemini/include/mach/irqs.h
-@@ -43,11 +43,14 @@
- #define NORMAL_IRQ_NUM        32
--#define GPIO_IRQ_BASE NORMAL_IRQ_NUM
-+#define PCI_IRQ_BASE  NORMAL_IRQ_NUM
-+#define PCI_IRQ_NUM   4
-+
-+#define GPIO_IRQ_BASE (NORMAL_IRQ_NUM + PCI_IRQ_NUM)
- #define GPIO_IRQ_NUM  (3 * 32)
- #define ARCH_TIMER_IRQ        IRQ_TIMER2
--#define NR_IRQS               (NORMAL_IRQ_NUM + GPIO_IRQ_NUM)
-+#define NR_IRQS               (NORMAL_IRQ_NUM + PCI_IRQ_NUM + GPIO_IRQ_NUM)
- #endif /* __MACH_IRQS_H__ */
---- a/arch/arm/mach-gemini/Makefile
-+++ b/arch/arm/mach-gemini/Makefile
-@@ -6,6 +6,8 @@
- obj-y                 := irq.o mm.o time.o devices.o gpio.o idle.o reset.o
-+obj-$(CONFIG_PCI)     += pci.o
-+
- # Board-specific support
- obj-$(CONFIG_MACH_NAS4220B)   += board-nas4220b.o
- obj-$(CONFIG_MACH_RUT100)     += board-rut1xx.o
---- a/arch/arm/mach-gemini/mm.c
-+++ b/arch/arm/mach-gemini/mm.c
-@@ -59,6 +59,11 @@ static struct map_desc gemini_io_desc[]
-               .length         = SZ_512K,
-               .type           = MT_DEVICE,
-       }, {
-+              .virtual        = (unsigned long)IO_ADDRESS(GEMINI_PCI_IO_BASE),
-+              .pfn            = __phys_to_pfn(GEMINI_PCI_IO_BASE),
-+              .length         = SZ_512K,
-+              .type           = MT_DEVICE,
-+      }, {
-               .virtual        = (unsigned long)IO_ADDRESS(GEMINI_FLASH_CTRL_BASE),
-               .pfn            = __phys_to_pfn(GEMINI_FLASH_CTRL_BASE),
-               .length         = SZ_512K,
---- /dev/null
-+++ b/arch/arm/mach-gemini/pci.c
-@@ -0,0 +1,320 @@
-+/*
-+ *  Support for Gemini PCI Controller
-+ *
-+ *  Copyright (C) 2009 Janos Laube <janos.dev@gmail.com>
-+ *  Copyright (C) 2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
-+ *
-+ * based on SL2312 PCI controller code
-+ *   Storlink (C) 2003
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/pci.h>
-+#include <linux/irq.h>
-+#include <linux/gpio.h>
-+
-+#include <asm/mach/pci.h>
-+
-+#include <mach/irqs.h>
-+#include <mach/hardware.h>
-+
-+#define GEMINI_PCI_IOSIZE_1M          0x0000
-+
-+#define GEMINI_PCI_PMC                        0x40
-+#define GEMINI_PCI_PMCSR              0x44
-+#define GEMINI_PCI_CTRL1              0x48
-+#define GEMINI_PCI_CTRL2              0x4C
-+#define GEMINI_PCI_MEM1_BASE_SIZE     0x50
-+#define GEMINI_PCI_MEM2_BASE_SIZE     0x54
-+#define GEMINI_PCI_MEM3_BASE_SIZE     0x58
-+
-+#define PCI_CTRL2_INTSTS_OFFSET               28
-+#define PCI_CTRL2_INTMASK_OFFSET      22
-+
-+#define GEMINI_PCI_DMA_MASK           0xFFF00000
-+#define GEMINI_PCI_DMA_MEM1_BASE      0x00000000
-+#define GEMINI_PCI_DMA_MEM2_BASE      0x00000000
-+#define GEMINI_PCI_DMA_MEM3_BASE      0x00000000
-+#define GEMINI_PCI_DMA_MEM1_SIZE      7
-+#define GEMINI_PCI_DMA_MEM2_SIZE      6
-+#define GEMINI_PCI_DMA_MEM3_SIZE      6
-+
-+#define PCI_CONF_ENABLE               (1 << 31)
-+#define PCI_CONF_WHERE(r)     ((r) & 0xFC)
-+#define PCI_CONF_BUS(b)               (((b) & 0xFF) << 16)
-+#define PCI_CONF_DEVICE(d)    (((d) & 0x1F) << 11)
-+#define PCI_CONF_FUNCTION(f)  (((f) & 0x07) << 8)
-+
-+#define PCI_IOSIZE_REG        (IO_ADDRESS(GEMINI_PCI_IO_BASE))
-+#define PCI_PROT_REG  (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x04)
-+#define PCI_CTRL_REG  (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x08)
-+#define PCI_SOFTRST_REG       (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x10)
-+#define PCI_CONFIG_REG        (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x28)
-+#define PCI_DATA_REG  (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x2C)
-+
-+
-+static DEFINE_SPINLOCK(gemini_pci_lock);
-+
-+static int gemini_pci_read_config(struct pci_bus* bus, unsigned int fn,
-+                                int config, int size, u32* value)
-+{
-+      unsigned long irq_flags;
-+
-+      spin_lock_irqsave(&gemini_pci_lock, irq_flags);
-+
-+      __raw_writel(PCI_CONF_BUS(bus->number) |
-+                      PCI_CONF_DEVICE(PCI_SLOT(fn)) |
-+                      PCI_CONF_FUNCTION(PCI_FUNC(fn)) |
-+                      PCI_CONF_WHERE(config) |
-+                      PCI_CONF_ENABLE,
-+                      PCI_CONFIG_REG);
-+
-+      *value = __raw_readl(PCI_DATA_REG);
-+
-+      if (size == 1)
-+              *value = (*value >> (8 * (config & 3))) & 0xFF;
-+      else if (size == 2)
-+              *value = (*value >> (8 * (config & 3))) & 0xFFFF;
-+
-+      spin_unlock_irqrestore(&gemini_pci_lock, irq_flags);
-+
-+      dev_dbg(&bus->dev,
-+              "[read]  slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
-+              PCI_SLOT(fn), PCI_FUNC(fn), config, size, *value);
-+
-+      return PCIBIOS_SUCCESSFUL;
-+}
-+
-+static int gemini_pci_write_config(struct pci_bus* bus, unsigned int fn,
-+                                 int config, int size, u32 value)
-+{
-+      unsigned long irq_flags = 0;
-+      int ret = PCIBIOS_SUCCESSFUL;
-+
-+      dev_dbg(&bus->dev,
-+              "[write] slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
-+              PCI_SLOT(fn), PCI_FUNC(fn), config, size, value);
-+
-+      spin_lock_irqsave(&gemini_pci_lock, irq_flags);
-+
-+      __raw_writel(PCI_CONF_BUS(bus->number) |
-+                      PCI_CONF_DEVICE(PCI_SLOT(fn)) |
-+                      PCI_CONF_FUNCTION(PCI_FUNC(fn)) |
-+                      PCI_CONF_WHERE(config) |
-+                      PCI_CONF_ENABLE,
-+                      PCI_CONFIG_REG);
-+
-+      switch(size) {
-+      case 4:
-+              __raw_writel(value, PCI_DATA_REG);
-+              break;
-+      case 2:
-+              __raw_writew(value, PCI_DATA_REG + (config & 3));
-+              break;
-+      case 1:
-+              __raw_writeb(value, PCI_DATA_REG + (config & 3));
-+              break;
-+      default:
-+              ret = PCIBIOS_BAD_REGISTER_NUMBER;
-+      }
-+
-+      spin_unlock_irqrestore(&gemini_pci_lock, irq_flags);
-+
-+      return ret;
-+}
-+
-+static struct pci_ops gemini_pci_ops = {
-+      .read   = gemini_pci_read_config,
-+      .write  = gemini_pci_write_config,
-+};
-+
-+static struct resource gemini_pci_resource_io = {
-+      .name   = "PCI I/O Space",
-+      .start  = GEMINI_PCI_IO_BASE,
-+      .end    = GEMINI_PCI_IO_BASE + SZ_1M - 1,
-+      .flags  = IORESOURCE_IO,
-+};
-+
-+static struct resource gemini_pci_resource_mem = {
-+      .name   = "PCI Memory Space",
-+      .start  = GEMINI_PCI_MEM_BASE,
-+      .end    = GEMINI_PCI_MEM_BASE + SZ_128M - 1,
-+      .flags  = IORESOURCE_MEM,
-+};
-+
-+static int __init gemini_pci_request_resources(struct pci_sys_data *sys)
-+{
-+      if (request_resource(&ioport_resource, &gemini_pci_resource_io))
-+              goto bad_resources;
-+      if (request_resource(&iomem_resource, &gemini_pci_resource_mem))
-+              goto bad_resources;
-+
-+      pci_add_resource(&sys->resources, &gemini_pci_resource_io);
-+      pci_add_resource(&sys->resources, &gemini_pci_resource_mem);
-+
-+      return 0;
-+
-+bad_resources:
-+      pr_err("Gemini PCI: request_resource() failed. "
-+                      "Abort PCI bus enumeration.\n");
-+      return -1;
-+}
-+
-+static int __init gemini_pci_setup(int nr, struct pci_sys_data *sys)
-+{
-+      unsigned int cmd;
-+
-+      pcibios_min_io = 0x100;
-+      pcibios_min_mem = 0;
-+
-+      if ((nr > 0) || gemini_pci_request_resources(sys))
-+              return 0;
-+
-+      /* setup I/O space to 1MB size */
-+      __raw_writel(GEMINI_PCI_IOSIZE_1M, PCI_IOSIZE_REG);
-+
-+      /* setup hostbridge */
-+      cmd = __raw_readl(PCI_CTRL_REG);
-+      cmd |= PCI_COMMAND_IO;
-+      cmd |= PCI_COMMAND_MEMORY;
-+      cmd |= PCI_COMMAND_MASTER;
-+      __raw_writel(cmd, PCI_CTRL_REG);
-+
-+      return 1;
-+}
-+
-+static struct pci_bus* __init gemini_pci_scan_bus(int nr, struct pci_sys_data* sys)
-+{
-+      unsigned int reg = 0;
-+      struct pci_bus* bus = 0;
-+
-+      bus = pci_scan_bus(nr, &gemini_pci_ops, sys);
-+      if (bus) {
-+              dev_dbg(&bus->dev, "setting up PCI DMA\n");
-+              reg = (GEMINI_PCI_DMA_MEM1_BASE & GEMINI_PCI_DMA_MASK)
-+                      | (GEMINI_PCI_DMA_MEM1_SIZE << 16);
-+              gemini_pci_write_config(bus, 0, GEMINI_PCI_MEM1_BASE_SIZE, 4, reg);
-+              reg =   (GEMINI_PCI_DMA_MEM2_BASE & GEMINI_PCI_DMA_MASK)
-+                      | (GEMINI_PCI_DMA_MEM2_SIZE << 16);
-+              gemini_pci_write_config(bus, 0, GEMINI_PCI_MEM2_BASE_SIZE, 4, reg);
-+              reg = (GEMINI_PCI_DMA_MEM3_BASE & GEMINI_PCI_DMA_MASK)
-+                      | (GEMINI_PCI_DMA_MEM3_SIZE << 16);
-+              gemini_pci_write_config(bus, 0, GEMINI_PCI_MEM3_BASE_SIZE, 4, reg);
-+      }
-+
-+      return bus;
-+}
-+
-+/* Should work with all boards based on original Storlink EVB */
-+static int __init gemini_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-+{
-+      if (slot < 9 || slot > 12)
-+              return -1;
-+
-+      return PCI_IRQ_BASE + (((slot - 9) + (pin - 1)) & 0x3);
-+}
-+
-+static struct hw_pci gemini_hw_pci __initdata = {
-+      .nr_controllers = 1,
-+      .setup          = gemini_pci_setup,
-+      .scan           = gemini_pci_scan_bus,
-+      .map_irq        = gemini_pci_map_irq,
-+};
-+
-+/* we need this for muxed PCI interrupts handling */
-+static struct pci_bus bogus_pci_bus;
-+
-+static void gemini_pci_ack_irq(struct irq_data *d)
-+{
-+      unsigned int irq = d->irq;
-+      unsigned int reg;
-+
-+      gemini_pci_read_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, &reg);
-+      reg &= ~(0xF << PCI_CTRL2_INTSTS_OFFSET);
-+      reg |= 1 << (irq - PCI_IRQ_BASE + PCI_CTRL2_INTSTS_OFFSET);
-+      gemini_pci_write_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, reg);
-+}
-+
-+static void gemini_pci_mask_irq(struct irq_data *d)
-+{
-+      unsigned int irq = d->irq;
-+      unsigned int reg;
-+
-+      gemini_pci_read_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, &reg);
-+      reg &= ~((0xF << PCI_CTRL2_INTSTS_OFFSET)
-+              | (1 << (irq - PCI_IRQ_BASE + PCI_CTRL2_INTMASK_OFFSET)));
-+      gemini_pci_write_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, reg);
-+}
-+
-+static void gemini_pci_unmask_irq(struct irq_data *d)
-+{
-+      unsigned int irq = d->irq;
-+      unsigned int reg;
-+
-+      gemini_pci_read_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, &reg);
-+      reg &= ~(0xF << PCI_CTRL2_INTSTS_OFFSET);
-+      reg |= 1 << (irq - PCI_IRQ_BASE + PCI_CTRL2_INTMASK_OFFSET);
-+      gemini_pci_write_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, reg);
-+}
-+
-+static void gemini_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
-+{
-+      unsigned int pci_irq_no, irq_stat, reg, i;
-+
-+      gemini_pci_read_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, &reg);
-+      irq_stat = reg >> PCI_CTRL2_INTSTS_OFFSET;
-+
-+      for (i = 0; i < 4; i++) {
-+
-+              if ((irq_stat & (1 << i)) == 0)
-+                      continue;
-+
-+              pci_irq_no = PCI_IRQ_BASE + i;
-+
-+              BUG_ON(!(irq_desc[pci_irq_no].handle_irq));
-+              irq_desc[pci_irq_no].handle_irq(pci_irq_no,
-+                              &irq_desc[pci_irq_no]);
-+      }
-+}
-+
-+static struct irq_chip gemini_pci_irq_chip = {
-+      .name = "PCI",
-+      .irq_ack = gemini_pci_ack_irq,
-+      .irq_mask = gemini_pci_mask_irq,
-+      .irq_unmask = gemini_pci_unmask_irq,
-+};
-+
-+static int __init gemini_pci_init(void)
-+{
-+      int i;
-+
-+      for (i = 72; i <= 95; i++)
-+              gpio_request(i, "PCI");
-+
-+      /* initialize our bogus bus */
-+      dev_set_name(&bogus_pci_bus.dev, "PCI IRQ handler");
-+      bogus_pci_bus.number = 0;
-+
-+      /* mask and clear all interrupts */
-+      gemini_pci_write_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2 + 2, 2,
-+                              0xF000);
-+
-+      for (i = PCI_IRQ_BASE; i < PCI_IRQ_BASE + 4; i++) {
-+              irq_set_chip_and_handler(i, &gemini_pci_irq_chip,
-+                                       handle_level_irq);
-+              set_irq_flags(i, IRQF_VALID);
-+      }
-+
-+      irq_set_chained_handler(IRQ_PCI, gemini_pci_irq_handler);
-+
-+      pci_common_init(&gemini_hw_pci);
-+
-+      return 0;
-+}
-+
-+subsys_initcall(gemini_pci_init);