obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o
--- /dev/null
+++ b/arch/mips/pci/pci-ar2315.c
-@@ -0,0 +1,345 @@
+@@ -0,0 +1,494 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/paccess.h>
-+#include <ar231x_platform.h>
-+#include <ar231x.h>
-+#include <ar2315_regs.h>
++
++/*
++ * PCI Bus Interface Registers
++ */
++#define AR2315_PCI_1MS_REG 0x0008
++
++#define AR2315_PCI_1MS_MASK 0x3FFFF /* # of AHB clk cycles in 1ms */
++
++#define AR2315_PCI_MISC_CONFIG 0x000c
++
++#define AR2315_PCIMISC_TXD_EN 0x00000001 /* Enable TXD for fragments */
++#define AR2315_PCIMISC_CFG_SEL 0x00000002 /* Mem or Config cycles */
++#define AR2315_PCIMISC_GIG_MASK 0x0000000C /* bits 31-30 for pci req */
++#define AR2315_PCIMISC_RST_MODE 0x00000030
++#define AR2315_PCIRST_INPUT 0x00000000 /* 4:5=0 rst is input */
++#define AR2315_PCIRST_LOW 0x00000010 /* 4:5=1 rst to GND */
++#define AR2315_PCIRST_HIGH 0x00000020 /* 4:5=2 rst to VDD */
++#define AR2315_PCIGRANT_EN 0x00000000 /* 6:7=0 early grant en */
++#define AR2315_PCIGRANT_FRAME 0x00000040 /* 6:7=1 grant waits 4 frame */
++#define AR2315_PCIGRANT_IDLE 0x00000080 /* 6:7=2 grant waits 4 idle */
++#define AR2315_PCIGRANT_GAP 0x00000000 /* 6:7=2 grant waits 4 idle */
++#define AR2315_PCICACHE_DIS 0x00001000 /* PCI external access cache
++ * disable */
++
++#define AR2315_PCI_OUT_TSTAMP 0x0010
++
++#define AR2315_PCI_UNCACHE_CFG 0x0014
++
++#define AR2315_PCI_IN_EN 0x0100
++
++#define AR2315_PCI_IN_EN0 0x01 /* Enable chain 0 */
++#define AR2315_PCI_IN_EN1 0x02 /* Enable chain 1 */
++#define AR2315_PCI_IN_EN2 0x04 /* Enable chain 2 */
++#define AR2315_PCI_IN_EN3 0x08 /* Enable chain 3 */
++
++#define AR2315_PCI_IN_DIS 0x0104
++
++#define AR2315_PCI_IN_DIS0 0x01 /* Disable chain 0 */
++#define AR2315_PCI_IN_DIS1 0x02 /* Disable chain 1 */
++#define AR2315_PCI_IN_DIS2 0x04 /* Disable chain 2 */
++#define AR2315_PCI_IN_DIS3 0x08 /* Disable chain 3 */
++
++#define AR2315_PCI_IN_PTR 0x0200
++
++#define AR2315_PCI_OUT_EN 0x0400
++
++#define AR2315_PCI_OUT_EN0 0x01 /* Enable chain 0 */
++
++#define AR2315_PCI_OUT_DIS 0x0404
++
++#define AR2315_PCI_OUT_DIS0 0x01 /* Disable chain 0 */
++
++#define AR2315_PCI_OUT_PTR 0x0408
++
++/* PCI interrupt status (write one to clear) */
++#define AR2315_PCI_ISR 0x0500
++
++#define AR2315_PCI_INT_TX 0x00000001 /* Desc In Completed */
++#define AR2315_PCI_INT_TXOK 0x00000002 /* Desc In OK */
++#define AR2315_PCI_INT_TXERR 0x00000004 /* Desc In ERR */
++#define AR2315_PCI_INT_TXEOL 0x00000008 /* Desc In End-of-List */
++#define AR2315_PCI_INT_RX 0x00000010 /* Desc Out Completed */
++#define AR2315_PCI_INT_RXOK 0x00000020 /* Desc Out OK */
++#define AR2315_PCI_INT_RXERR 0x00000040 /* Desc Out ERR */
++#define AR2315_PCI_INT_RXEOL 0x00000080 /* Desc Out EOL */
++#define AR2315_PCI_INT_TXOOD 0x00000200 /* Desc In Out-of-Desc */
++#define AR2315_PCI_INT_DESCMASK 0x0000FFFF /* Desc Mask */
++#define AR2315_PCI_INT_EXT 0x02000000 /* Extern PCI INTA */
++#define AR2315_PCI_INT_ABORT 0x04000000 /* PCI bus abort event */
++
++/* PCI interrupt mask */
++#define AR2315_PCI_IMR 0x0504
++
++/* Global PCI interrupt enable */
++#define AR2315_PCI_IER 0x0508
++
++#define AR2315_PCI_IER_DISABLE 0x00 /* disable pci interrupts */
++#define AR2315_PCI_IER_ENABLE 0x01 /* enable pci interrupts */
++
++#define AR2315_PCI_HOST_IN_EN 0x0800
++#define AR2315_PCI_HOST_IN_DIS 0x0804
++#define AR2315_PCI_HOST_IN_PTR 0x0810
++#define AR2315_PCI_HOST_OUT_EN 0x0900
++#define AR2315_PCI_HOST_OUT_DIS 0x0904
++#define AR2315_PCI_HOST_OUT_PTR 0x0908
++
++/*
++ * PCI interrupts, which share IP5
++ * Keep ordered according to AR2315_PCI_INT_XXX bits
++ */
++#define AR2315_PCI_IRQ_BASE 0x50
++#define AR2315_PCI_IRQ_EXT (AR2315_PCI_IRQ_BASE+0)
++#define AR2315_PCI_IRQ_ABORT (AR2315_PCI_IRQ_BASE+1)
++#define AR2315_PCI_IRQ_COUNT 2
++#define AR2315_PCI_IRQ_SHIFT 25 /* in AR2315_PCI_INT_STATUS */
+
+/* Arbitrary size of memory region to access the configuration space */
+#define AR2315_PCI_CFG_SIZE 0x00100000
+#define AR2315_PCI_HOST_SLOT 3
+#define AR2315_PCI_HOST_DEVID ((0xff18 << 16) | PCI_VENDOR_ID_ATHEROS)
+
-+static void __iomem *ar2315_pci_cfg_mem;
++/* ??? access BAR */
++#define AR2315_PCI_HOST_MBAR0 0x10000000
++/* RAM access BAR */
++#define AR2315_PCI_HOST_MBAR1 AR2315_PCI_HOST_SDRAM_BASEADDR
++/* ??? access BAR */
++#define AR2315_PCI_HOST_MBAR2 0x30000000
++
++struct ar2315_pci_ctrl {
++ void __iomem *cfg_mem;
++ void __iomem *mmr_mem;
++ unsigned irq;
++ struct pci_controller pci_ctrl;
++ struct resource mem_res;
++ struct resource io_res;
++};
++
++static inline struct ar2315_pci_ctrl *ar2315_pci_bus_to_apc(struct pci_bus *bus)
++{
++ struct pci_controller *hose = bus->sysdata;
++
++ return container_of(hose, struct ar2315_pci_ctrl, pci_ctrl);
++}
++
++static inline u32 ar2315_pci_reg_read(struct ar2315_pci_ctrl *apc, u32 reg)
++{
++ return __raw_readl(apc->mmr_mem + reg);
++}
++
++static inline void ar2315_pci_reg_write(struct ar2315_pci_ctrl *apc, u32 reg,
++ u32 val)
++{
++ __raw_writel(val, apc->mmr_mem + reg);
++}
+
-+static int ar2315_pci_cfg_access(int devfn, int where, int size, u32 *ptr,
-+ bool write)
++static inline void ar2315_pci_reg_mask(struct ar2315_pci_ctrl *apc, u32 reg,
++ u32 mask, u32 val)
++{
++ u32 ret = ar2315_pci_reg_read(apc, reg);
++
++ ret &= ~mask;
++ ret |= val;
++ ar2315_pci_reg_write(apc, reg, ret);
++}
++
++static int ar2315_pci_cfg_access(struct ar2315_pci_ctrl *apc, unsigned devfn,
++ int where, int size, u32 *ptr, bool write)
+{
+ int func = PCI_FUNC(devfn);
+ int dev = PCI_SLOT(devfn);
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /* Clear pending errors */
-+ ar231x_write_reg(AR2315_PCI_ISR, AR2315_PCI_INT_ABORT);
++ ar2315_pci_reg_write(apc, AR2315_PCI_ISR, AR2315_PCI_INT_ABORT);
+ /* Select Configuration access */
-+ ar231x_mask_reg(AR2315_PCI_MISC_CONFIG, 0, AR2315_PCIMISC_CFG_SEL);
++ ar2315_pci_reg_mask(apc, AR2315_PCI_MISC_CONFIG, 0,
++ AR2315_PCIMISC_CFG_SEL);
+
+ mb(); /* PCI must see space change before we begin */
+
-+ value = __raw_readl(ar2315_pci_cfg_mem + addr);
++ value = __raw_readl(apc->cfg_mem + addr);
++
++ isr = ar2315_pci_reg_read(apc, AR2315_PCI_ISR);
+
-+ isr = ar231x_read_reg(AR2315_PCI_ISR);
+ if (isr & AR2315_PCI_INT_ABORT)
+ goto exit_err;
+
+ if (write) {
+ value = (value & ~(mask << sh)) | *ptr << sh;
-+ __raw_writel(value, ar2315_pci_cfg_mem + addr);
-+ isr = ar231x_read_reg(AR2315_PCI_ISR);
++ __raw_writel(value, apc->cfg_mem + addr);
++ isr = ar2315_pci_reg_read(apc, AR2315_PCI_ISR);
+ if (isr & AR2315_PCI_INT_ABORT)
+ goto exit_err;
+ } else {
+ goto exit;
+
+exit_err:
-+ ar231x_write_reg(AR2315_PCI_ISR, AR2315_PCI_INT_ABORT);
++ ar2315_pci_reg_write(apc, AR2315_PCI_ISR, AR2315_PCI_INT_ABORT);
+ if (!write)
+ *ptr = 0xffffffff;
+
+exit:
+ /* Select Memory access */
-+ ar231x_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_CFG_SEL, 0);
++ ar2315_pci_reg_mask(apc, AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_CFG_SEL,
++ 0);
+
+ return isr & AR2315_PCI_INT_ABORT ? PCIBIOS_DEVICE_NOT_FOUND :
+ PCIBIOS_SUCCESSFUL;
+}
+
-+static inline int ar2315_pci_local_cfg_rd(unsigned devfn, int where, u32 *val)
++static inline int ar2315_pci_local_cfg_rd(struct ar2315_pci_ctrl *apc,
++ unsigned devfn, int where, u32 *val)
+{
-+ return ar2315_pci_cfg_access(devfn, where, sizeof(u32), val, false);
++ return ar2315_pci_cfg_access(apc, devfn, where, sizeof(u32), val,
++ false);
+}
+
-+static inline int ar2315_pci_local_cfg_wr(unsigned devfn, int where, u32 val)
++static inline int ar2315_pci_local_cfg_wr(struct ar2315_pci_ctrl *apc,
++ unsigned devfn, int where, u32 val)
+{
-+ return ar2315_pci_cfg_access(devfn, where, sizeof(u32), &val, true);
++ return ar2315_pci_cfg_access(apc, devfn, where, sizeof(u32), &val,
++ true);
+}
+
-+static int ar2315_pci_cfg_read(struct pci_bus *bus, unsigned int devfn,
-+ int where, int size, u32 *value)
++static int ar2315_pci_cfg_read(struct pci_bus *bus, unsigned devfn, int where,
++ int size, u32 *value)
+{
++ struct ar2315_pci_ctrl *apc = ar2315_pci_bus_to_apc(bus);
++
+ if (PCI_SLOT(devfn) == AR2315_PCI_HOST_SLOT)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
-+ return ar2315_pci_cfg_access(devfn, where, size, value, 0);
++ return ar2315_pci_cfg_access(apc, devfn, where, size, value, false);
+}
+
-+static int ar2315_pci_cfg_write(struct pci_bus *bus, unsigned int devfn,
-+ int where, int size, u32 value)
++static int ar2315_pci_cfg_write(struct pci_bus *bus, unsigned devfn, int where,
++ int size, u32 value)
+{
++ struct ar2315_pci_ctrl *apc = ar2315_pci_bus_to_apc(bus);
++
+ if (PCI_SLOT(devfn) == AR2315_PCI_HOST_SLOT)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
-+ return ar2315_pci_cfg_access(devfn, where, size, &value, 1);
++ return ar2315_pci_cfg_access(apc, devfn, where, size, &value, true);
+}
+
+static struct pci_ops ar2315_pci_ops = {
+ .write = ar2315_pci_cfg_write,
+};
+
-+static struct resource ar2315_mem_resource = {
-+ .name = "ar2315-pci-mem",
-+ .start = AR2315_PCIEXT,
-+ .end = AR2315_PCIEXT + AR2315_PCIEXT_SZ - 1,
-+ .flags = IORESOURCE_MEM,
-+};
-+
-+/* PCI controller does not support I/O ports */
-+static struct resource ar2315_io_resource = {
-+ .name = "ar2315-pci-io",
-+ .start = 0,
-+ .end = 0,
-+ .flags = IORESOURCE_IO,
-+};
-+
-+static struct pci_controller ar2315_pci_controller = {
-+ .pci_ops = &ar2315_pci_ops,
-+ .mem_resource = &ar2315_mem_resource,
-+ .io_resource = &ar2315_io_resource,
-+ .mem_offset = 0x00000000UL,
-+ .io_offset = 0x00000000UL,
-+};
-+
-+static int ar2315_pci_host_setup(void)
++static int ar2315_pci_host_setup(struct ar2315_pci_ctrl *apc)
+{
+ unsigned devfn = PCI_DEVFN(AR2315_PCI_HOST_SLOT, 0);
+ int res;
+ u32 id;
+
-+ res = ar2315_pci_local_cfg_rd(devfn, PCI_VENDOR_ID, &id);
++ res = ar2315_pci_local_cfg_rd(apc, devfn, PCI_VENDOR_ID, &id);
+ if (res != PCIBIOS_SUCCESSFUL || id != AR2315_PCI_HOST_DEVID)
+ return -ENODEV;
+
+ /* Program MBARs */
-+ ar2315_pci_local_cfg_wr(devfn, PCI_BASE_ADDRESS_0,
++ ar2315_pci_local_cfg_wr(apc, devfn, PCI_BASE_ADDRESS_0,
+ AR2315_PCI_HOST_MBAR0);
-+ ar2315_pci_local_cfg_wr(devfn, PCI_BASE_ADDRESS_1,
++ ar2315_pci_local_cfg_wr(apc, devfn, PCI_BASE_ADDRESS_1,
+ AR2315_PCI_HOST_MBAR1);
-+ ar2315_pci_local_cfg_wr(devfn, PCI_BASE_ADDRESS_2,
++ ar2315_pci_local_cfg_wr(apc, devfn, PCI_BASE_ADDRESS_2,
+ AR2315_PCI_HOST_MBAR2);
+
+ /* Run */
-+ ar2315_pci_local_cfg_wr(devfn, PCI_COMMAND, PCI_COMMAND_MEMORY |
++ ar2315_pci_local_cfg_wr(apc, devfn, PCI_COMMAND, PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER | PCI_COMMAND_SPECIAL |
+ PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY |
+ PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK);
+
+static void ar2315_pci_irq_handler(unsigned irq, struct irq_desc *desc)
+{
-+ u32 pending = ar231x_read_reg(AR2315_PCI_ISR) &
-+ ar231x_read_reg(AR2315_PCI_IMR);
++ struct ar2315_pci_ctrl *apc = irq_get_handler_data(irq);
++ u32 pending = ar2315_pci_reg_read(apc, AR2315_PCI_ISR) &
++ ar2315_pci_reg_read(apc, AR2315_PCI_IMR);
+
+ if (pending & AR2315_PCI_INT_EXT)
+ generic_handle_irq(AR2315_PCI_IRQ_EXT);
+
+static void ar2315_pci_irq_mask(struct irq_data *d)
+{
++ struct ar2315_pci_ctrl *apc = irq_data_get_irq_chip_data(d);
+ u32 m = 1 << (d->irq - AR2315_PCI_IRQ_BASE + AR2315_PCI_IRQ_SHIFT);
+
-+ ar231x_mask_reg(AR2315_PCI_IMR, m, 0);
++ ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, m, 0);
+}
+
+static void ar2315_pci_irq_mask_ack(struct irq_data *d)
+{
++ struct ar2315_pci_ctrl *apc = irq_data_get_irq_chip_data(d);
+ u32 m = 1 << (d->irq - AR2315_PCI_IRQ_BASE + AR2315_PCI_IRQ_SHIFT);
+
-+ ar231x_mask_reg(AR2315_PCI_IMR, m, 0);
-+ ar231x_write_reg(AR2315_PCI_ISR, m);
++ ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, m, 0);
++ ar2315_pci_reg_write(apc, AR2315_PCI_ISR, m);
+}
+
+static void ar2315_pci_irq_unmask(struct irq_data *d)
+{
++ struct ar2315_pci_ctrl *apc = irq_data_get_irq_chip_data(d);
+ u32 m = 1 << (d->irq - AR2315_PCI_IRQ_BASE + AR2315_PCI_IRQ_SHIFT);
+
-+ ar231x_mask_reg(AR2315_PCI_IMR, 0, m);
++ ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, 0, m);
+}
+
+static struct irq_chip ar2315_pci_irq_chip = {
+ .irq_unmask = ar2315_pci_irq_unmask,
+};
+
-+static void ar2315_pci_irq_init(void)
++static void ar2315_pci_irq_init(struct ar2315_pci_ctrl *apc)
+{
+ int i;
+
-+ ar231x_mask_reg(AR2315_PCI_IER, AR2315_PCI_IER_ENABLE, 0);
-+ ar231x_mask_reg(AR2315_PCI_IMR, (AR2315_PCI_INT_ABORT |
-+ AR2315_PCI_INT_EXT), 0);
++ ar2315_pci_reg_mask(apc, AR2315_PCI_IER, AR2315_PCI_IER_ENABLE, 0);
++ ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, (AR2315_PCI_INT_ABORT |
++ AR2315_PCI_INT_EXT), 0);
+
+ for (i = 0; i < AR2315_PCI_IRQ_COUNT; ++i) {
+ int irq = AR2315_PCI_IRQ_BASE + i;
+
+ irq_set_chip_and_handler(irq, &ar2315_pci_irq_chip,
+ handle_level_irq);
++ irq_set_chip_data(irq, apc);
+ }
+
-+ irq_set_chained_handler(AR2315_IRQ_LCBUS_PCI, ar2315_pci_irq_handler);
++ irq_set_chained_handler(apc->irq, ar2315_pci_irq_handler);
++ irq_set_handler_data(apc->irq, apc);
+
+ /* Clear any pending Abort or external Interrupts
+ * and enable interrupt processing */
-+ ar231x_write_reg(AR2315_PCI_ISR, (AR2315_PCI_INT_ABORT |
-+ AR2315_PCI_INT_EXT));
-+ ar231x_mask_reg(AR2315_PCI_IER, 0, AR2315_PCI_IER_ENABLE);
++ ar2315_pci_reg_write(apc, AR2315_PCI_ISR, AR2315_PCI_INT_ABORT |
++ AR2315_PCI_INT_EXT);
++ ar2315_pci_reg_mask(apc, AR2315_PCI_IER, 0, AR2315_PCI_IER_ENABLE);
+}
+
+static int ar2315_pci_probe(struct platform_device *pdev)
+{
++ struct ar2315_pci_ctrl *apc;
+ struct device *dev = &pdev->dev;
-+ u32 reg;
-+ int res;
++ struct resource *res;
++ int irq, err;
+
-+ /* Remap PCI config space */
-+ ar2315_pci_cfg_mem = devm_ioremap_nocache(dev, AR2315_PCIEXT,
-+ AR2315_PCI_CFG_SIZE);
-+ if (!ar2315_pci_cfg_mem) {
-+ dev_err(dev, "failed to remap PCI config space\n");
++ apc = devm_kzalloc(dev, sizeof(*apc), GFP_KERNEL);
++ if (!apc)
+ return -ENOMEM;
-+ }
+
-+ /* Reset PCI DMA logic */
-+ reg = ar231x_mask_reg(AR2315_RESET, 0, AR2315_RESET_PCIDMA);
-+ msleep(20);
-+ reg &= ~AR2315_RESET_PCIDMA;
-+ ar231x_write_reg(AR2315_RESET, reg);
-+ msleep(20);
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0)
++ return -EINVAL;
++ apc->irq = irq;
+
-+ ar231x_mask_reg(AR2315_ENDIAN_CTL, 0,
-+ AR2315_CONFIG_PCIAHB | AR2315_CONFIG_PCIAHB_BRIDGE);
++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
++ "ar2315-pci-ctrl");
++ apc->mmr_mem = devm_ioremap_resource(dev, res);
++ if (IS_ERR(apc->mmr_mem))
++ return PTR_ERR(apc->mmr_mem);
+
-+ ar231x_write_reg(AR2315_PCICLK, AR2315_PCICLK_PLLC_CLKM |
-+ (AR2315_PCICLK_IN_FREQ_DIV_6 << AR2315_PCICLK_DIV_S));
-+ ar231x_mask_reg(AR2315_AHB_ARB_CTL, 0, AR2315_ARB_PCI);
-+ ar231x_mask_reg(AR2315_IF_CTL, AR2315_IF_PCI_CLK_MASK | AR2315_IF_MASK,
-+ AR2315_IF_PCI | AR2315_IF_PCI_HOST |
-+ AR2315_IF_PCI_INTR | (AR2315_IF_PCI_CLK_OUTPUT_CLK <<
-+ AR2315_IF_PCI_CLK_SHIFT));
++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
++ "ar2315-pci-ext");
++ if (!res)
++ return -EINVAL;
++
++ apc->mem_res.name = "AR2315 PCI mem space";
++ apc->mem_res.parent = res;
++ apc->mem_res.start = res->start;
++ apc->mem_res.end = res->end;
++ apc->mem_res.flags = IORESOURCE_MEM;
++
++ /* Remap PCI config space */
++ apc->cfg_mem = devm_ioremap_nocache(dev, res->start,
++ AR2315_PCI_CFG_SIZE);
++ if (!apc->cfg_mem) {
++ dev_err(dev, "failed to remap PCI config space\n");
++ return -ENOMEM;
++ }
+
+ /* Reset the PCI bus by setting bits 5-4 in PCI_MCFG */
-+ ar231x_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_RST_MODE,
-+ AR2315_PCIRST_LOW);
++ ar2315_pci_reg_mask(apc, AR2315_PCI_MISC_CONFIG,
++ AR2315_PCIMISC_RST_MODE,
++ AR2315_PCIRST_LOW);
+ msleep(100);
+
+ /* Bring the PCI out of reset */
-+ ar231x_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_RST_MODE,
-+ AR2315_PCIRST_HIGH | AR2315_PCICACHE_DIS | 0x8);
++ ar2315_pci_reg_mask(apc, AR2315_PCI_MISC_CONFIG,
++ AR2315_PCIMISC_RST_MODE,
++ AR2315_PCIRST_HIGH | AR2315_PCICACHE_DIS | 0x8);
+
-+ ar231x_write_reg(AR2315_PCI_UNCACHE_CFG,
-+ 0x1E | /* 1GB uncached */
-+ (1 << 5) | /* Enable uncached */
-+ (0x2 << 30) /* Base: 0x80000000 */);
-+ ar231x_read_reg(AR2315_PCI_UNCACHE_CFG);
++ ar2315_pci_reg_write(apc, AR2315_PCI_UNCACHE_CFG,
++ 0x1E | /* 1GB uncached */
++ (1 << 5) | /* Enable uncached */
++ (0x2 << 30) /* Base: 0x80000000 */);
++ ar2315_pci_reg_read(apc, AR2315_PCI_UNCACHE_CFG);
+
+ msleep(500);
+
-+ res = ar2315_pci_host_setup();
-+ if (res)
-+ return res;
++ err = ar2315_pci_host_setup(apc);
++ if (err)
++ return err;
++
++ ar2315_pci_irq_init(apc);
++
++ /* PCI controller does not support I/O ports */
++ apc->io_res.name = "AR2315 IO space";
++ apc->io_res.start = 0;
++ apc->io_res.end = 0;
++ apc->io_res.flags = IORESOURCE_IO,
+
-+ ar2315_pci_irq_init();
++ apc->pci_ctrl.pci_ops = &ar2315_pci_ops;
++ apc->pci_ctrl.mem_resource = &apc->mem_res,
++ apc->pci_ctrl.io_resource = &apc->io_res,
+
-+ register_pci_controller(&ar2315_pci_controller);
++ register_pci_controller(&apc->pci_ctrl);
+
+ return 0;
+}
+ default y
--- a/arch/mips/ath25/ar2315.c
+++ b/arch/mips/ath25/ar2315.c
-@@ -77,6 +77,10 @@ ar2315_irq_dispatch(void)
+@@ -137,6 +137,10 @@ static void ar2315_irq_dispatch(void)
do_IRQ(AR2315_IRQ_WLAN0_INTRS);
else if (pending & CAUSEF_IP4)
do_IRQ(AR2315_IRQ_ENET0_INTRS);
else if (pending & CAUSEF_IP2)
do_IRQ(AR2315_IRQ_MISC_INTRS);
else if (pending & CAUSEF_IP7)
-@@ -458,3 +462,18 @@ ar2315_plat_setup(void)
- ar231x_serial_setup(AR2315_UART0, AR2315_MISC_IRQ_UART0,
- ar2315_apb_frequency());
+@@ -450,8 +454,60 @@ void __init ar2315_plat_mem_setup(void)
+ _machine_restart = ar2315_restart;
}
-+
+
+#ifdef CONFIG_PCI_AR2315
-+static int __init ar2315_pci_init(void)
-+{
-+ struct platform_device *pdev;
-+
-+ if (!is_2315() || ar231x_devtype != DEV_TYPE_AR2315)
-+ return -ENODEV;
++static struct resource ar2315_pci_res[] = {
++ {
++ .name = "ar2315-pci-ctrl",
++ .flags = IORESOURCE_MEM,
++ .start = AR2315_PCI,
++ .end = AR2315_PCI + AR2315_PCI_SIZE - 1,
++ },
++ {
++ .name = "ar2315-pci-ext",
++ .flags = IORESOURCE_MEM,
++ .start = AR2315_PCIEXT,
++ .end = AR2315_PCIEXT + AR2315_PCIEXT_SZ - 1,
++ },
++ {
++ .name = "ar2315-pci",
++ .flags = IORESOURCE_IRQ,
++ .start = AR2315_IRQ_LCBUS_PCI,
++ .end = AR2315_IRQ_LCBUS_PCI,
++ },
++};
++#endif
+
-+ pdev = platform_device_register_simple("ar2315-pci", -1, NULL, 0);
+ void __init ar2315_arch_init(void)
+ {
+ ath25_serial_setup(AR2315_UART0, AR2315_MISC_IRQ_UART0,
+ ar2315_apb_frequency());
+
-+ return pdev ? 0 : -ENODEV;
-+}
-+arch_initcall(ar2315_pci_init);
++#ifdef CONFIG_PCI_AR2315
++ if (ath25_soc == ATH25_SOC_AR2315) {
++ /* Reset PCI DMA logic */
++ ar2315_rst_reg_mask(AR2315_RESET, 0, AR2315_RESET_PCIDMA);
++ msleep(20);
++ ar2315_rst_reg_mask(AR2315_RESET, AR2315_RESET_PCIDMA, 0);
++ msleep(20);
++
++ /* Configure endians */
++ ar2315_rst_reg_mask(AR2315_ENDIAN_CTL, 0, AR2315_CONFIG_PCIAHB |
++ AR2315_CONFIG_PCIAHB_BRIDGE);
++
++ /* Configure as PCI host with DMA */
++ ar2315_rst_reg_write(AR2315_PCICLK, AR2315_PCICLK_PLLC_CLKM |
++ (AR2315_PCICLK_IN_FREQ_DIV_6 <<
++ AR2315_PCICLK_DIV_S));
++ ar2315_rst_reg_mask(AR2315_AHB_ARB_CTL, 0, AR2315_ARB_PCI);
++ ar2315_rst_reg_mask(AR2315_IF_CTL, AR2315_IF_PCI_CLK_MASK |
++ AR2315_IF_MASK, AR2315_IF_PCI |
++ AR2315_IF_PCI_HOST | AR2315_IF_PCI_INTR |
++ (AR2315_IF_PCI_CLK_OUTPUT_CLK <<
++ AR2315_IF_PCI_CLK_SHIFT));
++
++ platform_device_register_simple("ar2315-pci", -1,
++ ar2315_pci_res,
++ ARRAY_SIZE(ar2315_pci_res));
++ }
+#endif
+ }