atheros: v3.18: remap PCI controller MMR memory

Honestly remap PCI controller MMR and use accessor functions to interact
with registers.

Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>

SVN-Revision: 44720
This commit is contained in:
Felix Fietkau 2015-03-13 03:00:43 +00:00
parent 862a89b8f7
commit 6ba3363290
2 changed files with 88 additions and 50 deletions

View file

@ -629,7 +629,7 @@
+#endif /* __ASM_MACH_ATH25_WAR_H */ +#endif /* __ASM_MACH_ATH25_WAR_H */
--- /dev/null --- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/ar2315_regs.h +++ b/arch/mips/include/asm/mach-ath25/ar2315_regs.h
@@ -0,0 +1,510 @@ @@ -0,0 +1,511 @@
+/* +/*
+ * Register definitions for AR2315+ + * Register definitions for AR2315+
+ * + *
@ -675,6 +675,7 @@
+#define AR2315_SPI_READ 0x08000000 /* SPI FLASH */ +#define AR2315_SPI_READ 0x08000000 /* SPI FLASH */
+#define AR2315_WLAN0 0x10000000 /* Wireless MMR */ +#define AR2315_WLAN0 0x10000000 /* Wireless MMR */
+#define AR2315_PCI 0x10100000 /* PCI MMR */ +#define AR2315_PCI 0x10100000 /* PCI MMR */
+#define AR2315_PCI_SIZE 0x00001000
+#define AR2315_SDRAMCTL 0x10300000 /* SDRAM MMR */ +#define AR2315_SDRAMCTL 0x10300000 /* SDRAM MMR */
+#define AR2315_LOCAL 0x10400000 /* LOCAL BUS MMR */ +#define AR2315_LOCAL 0x10400000 /* LOCAL BUS MMR */
+#define AR2315_ENET0 0x10500000 /* ETHERNET MMR */ +#define AR2315_ENET0 0x10500000 /* ETHERNET MMR */

View file

@ -10,7 +10,7 @@
obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o
--- /dev/null --- /dev/null
+++ b/arch/mips/pci/pci-ar2315.c +++ b/arch/mips/pci/pci-ar2315.c
@@ -0,0 +1,445 @@ @@ -0,0 +1,482 @@
+/* +/*
+ * This program is free software; you can redistribute it and/or + * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License + * modify it under the terms of the GNU General Public License
@ -67,11 +67,11 @@
+/* +/*
+ * PCI Bus Interface Registers + * PCI Bus Interface Registers
+ */ + */
+#define AR2315_PCI_1MS_REG (AR2315_PCI + 0x0008) +#define AR2315_PCI_1MS_REG 0x0008
+ +
+#define AR2315_PCI_1MS_MASK 0x3FFFF /* # of AHB clk cycles in 1ms */ +#define AR2315_PCI_1MS_MASK 0x3FFFF /* # of AHB clk cycles in 1ms */
+ +
+#define AR2315_PCI_MISC_CONFIG (AR2315_PCI + 0x000c) +#define AR2315_PCI_MISC_CONFIG 0x000c
+ +
+#define AR2315_PCIMISC_TXD_EN 0x00000001 /* Enable TXD for fragments */ +#define AR2315_PCIMISC_TXD_EN 0x00000001 /* Enable TXD for fragments */
+#define AR2315_PCIMISC_CFG_SEL 0x00000002 /* Mem or Config cycles */ +#define AR2315_PCIMISC_CFG_SEL 0x00000002 /* Mem or Config cycles */
@ -87,38 +87,38 @@
+#define AR2315_PCICACHE_DIS 0x00001000 /* PCI external access cache +#define AR2315_PCICACHE_DIS 0x00001000 /* PCI external access cache
+ * disable */ + * disable */
+ +
+#define AR2315_PCI_OUT_TSTAMP (AR2315_PCI + 0x0010) +#define AR2315_PCI_OUT_TSTAMP 0x0010
+ +
+#define AR2315_PCI_UNCACHE_CFG (AR2315_PCI + 0x0014) +#define AR2315_PCI_UNCACHE_CFG 0x0014
+ +
+#define AR2315_PCI_IN_EN (AR2315_PCI + 0x0100) +#define AR2315_PCI_IN_EN 0x0100
+ +
+#define AR2315_PCI_IN_EN0 0x01 /* Enable chain 0 */ +#define AR2315_PCI_IN_EN0 0x01 /* Enable chain 0 */
+#define AR2315_PCI_IN_EN1 0x02 /* Enable chain 1 */ +#define AR2315_PCI_IN_EN1 0x02 /* Enable chain 1 */
+#define AR2315_PCI_IN_EN2 0x04 /* Enable chain 2 */ +#define AR2315_PCI_IN_EN2 0x04 /* Enable chain 2 */
+#define AR2315_PCI_IN_EN3 0x08 /* Enable chain 3 */ +#define AR2315_PCI_IN_EN3 0x08 /* Enable chain 3 */
+ +
+#define AR2315_PCI_IN_DIS (AR2315_PCI + 0x0104) +#define AR2315_PCI_IN_DIS 0x0104
+ +
+#define AR2315_PCI_IN_DIS0 0x01 /* Disable chain 0 */ +#define AR2315_PCI_IN_DIS0 0x01 /* Disable chain 0 */
+#define AR2315_PCI_IN_DIS1 0x02 /* Disable chain 1 */ +#define AR2315_PCI_IN_DIS1 0x02 /* Disable chain 1 */
+#define AR2315_PCI_IN_DIS2 0x04 /* Disable chain 2 */ +#define AR2315_PCI_IN_DIS2 0x04 /* Disable chain 2 */
+#define AR2315_PCI_IN_DIS3 0x08 /* Disable chain 3 */ +#define AR2315_PCI_IN_DIS3 0x08 /* Disable chain 3 */
+ +
+#define AR2315_PCI_IN_PTR (AR2315_PCI + 0x0200) +#define AR2315_PCI_IN_PTR 0x0200
+ +
+#define AR2315_PCI_OUT_EN (AR2315_PCI + 0x0400) +#define AR2315_PCI_OUT_EN 0x0400
+ +
+#define AR2315_PCI_OUT_EN0 0x01 /* Enable chain 0 */ +#define AR2315_PCI_OUT_EN0 0x01 /* Enable chain 0 */
+ +
+#define AR2315_PCI_OUT_DIS (AR2315_PCI + 0x0404) +#define AR2315_PCI_OUT_DIS 0x0404
+ +
+#define AR2315_PCI_OUT_DIS0 0x01 /* Disable chain 0 */ +#define AR2315_PCI_OUT_DIS0 0x01 /* Disable chain 0 */
+ +
+#define AR2315_PCI_OUT_PTR (AR2315_PCI + 0x0408) +#define AR2315_PCI_OUT_PTR 0x0408
+ +
+/* PCI interrupt status (write one to clear) */ +/* PCI interrupt status (write one to clear) */
+#define AR2315_PCI_ISR (AR2315_PCI + 0x0500) +#define AR2315_PCI_ISR 0x0500
+ +
+#define AR2315_PCI_INT_TX 0x00000001 /* Desc In Completed */ +#define AR2315_PCI_INT_TX 0x00000001 /* Desc In Completed */
+#define AR2315_PCI_INT_TXOK 0x00000002 /* Desc In OK */ +#define AR2315_PCI_INT_TXOK 0x00000002 /* Desc In OK */
@ -134,20 +134,20 @@
+#define AR2315_PCI_INT_ABORT 0x04000000 /* PCI bus abort event */ +#define AR2315_PCI_INT_ABORT 0x04000000 /* PCI bus abort event */
+ +
+/* PCI interrupt mask */ +/* PCI interrupt mask */
+#define AR2315_PCI_IMR (AR2315_PCI + 0x0504) +#define AR2315_PCI_IMR 0x0504
+ +
+/* Global PCI interrupt enable */ +/* Global PCI interrupt enable */
+#define AR2315_PCI_IER (AR2315_PCI + 0x0508) +#define AR2315_PCI_IER 0x0508
+ +
+#define AR2315_PCI_IER_DISABLE 0x00 /* disable pci interrupts */ +#define AR2315_PCI_IER_DISABLE 0x00 /* disable pci interrupts */
+#define AR2315_PCI_IER_ENABLE 0x01 /* enable pci interrupts */ +#define AR2315_PCI_IER_ENABLE 0x01 /* enable pci interrupts */
+ +
+#define AR2315_PCI_HOST_IN_EN (AR2315_PCI + 0x0800) +#define AR2315_PCI_HOST_IN_EN 0x0800
+#define AR2315_PCI_HOST_IN_DIS (AR2315_PCI + 0x0804) +#define AR2315_PCI_HOST_IN_DIS 0x0804
+#define AR2315_PCI_HOST_IN_PTR (AR2315_PCI + 0x0810) +#define AR2315_PCI_HOST_IN_PTR 0x0810
+#define AR2315_PCI_HOST_OUT_EN (AR2315_PCI + 0x0900) +#define AR2315_PCI_HOST_OUT_EN 0x0900
+#define AR2315_PCI_HOST_OUT_DIS (AR2315_PCI + 0x0904) +#define AR2315_PCI_HOST_OUT_DIS 0x0904
+#define AR2315_PCI_HOST_OUT_PTR (AR2315_PCI + 0x0908) +#define AR2315_PCI_HOST_OUT_PTR 0x0908
+ +
+/* +/*
+ * PCI interrupts, which share IP5 + * PCI interrupts, which share IP5
@ -174,6 +174,7 @@
+ +
+struct ar2315_pci_ctrl { +struct ar2315_pci_ctrl {
+ void __iomem *cfg_mem; + void __iomem *cfg_mem;
+ void __iomem *mmr_mem;
+ struct pci_controller pci_ctrl; + struct pci_controller pci_ctrl;
+ struct resource mem_res; + struct resource mem_res;
+ struct resource io_res; + struct resource io_res;
@ -186,6 +187,27 @@
+ return container_of(hose, struct ar2315_pci_ctrl, pci_ctrl); + 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 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, +static int ar2315_pci_cfg_access(struct ar2315_pci_ctrl *apc, unsigned devfn,
+ int where, int size, u32 *ptr, bool write) + int where, int size, u32 *ptr, bool write)
+{ +{
@ -201,22 +223,24 @@
+ return PCIBIOS_DEVICE_NOT_FOUND; + return PCIBIOS_DEVICE_NOT_FOUND;
+ +
+ /* Clear pending errors */ + /* 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 */ + /* 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 */ + mb(); /* PCI must see space change before we begin */
+ +
+ value = __raw_readl(apc->cfg_mem + addr); + value = __raw_readl(apc->cfg_mem + addr);
+ +
+ isr = ar231x_read_reg(AR2315_PCI_ISR); + isr = ar2315_pci_reg_read(apc, AR2315_PCI_ISR);
+
+ if (isr & AR2315_PCI_INT_ABORT) + if (isr & AR2315_PCI_INT_ABORT)
+ goto exit_err; + goto exit_err;
+ +
+ if (write) { + if (write) {
+ value = (value & ~(mask << sh)) | *ptr << sh; + value = (value & ~(mask << sh)) | *ptr << sh;
+ __raw_writel(value, apc->cfg_mem + addr); + __raw_writel(value, apc->cfg_mem + addr);
+ isr = ar231x_read_reg(AR2315_PCI_ISR); + isr = ar2315_pci_reg_read(apc, AR2315_PCI_ISR);
+ if (isr & AR2315_PCI_INT_ABORT) + if (isr & AR2315_PCI_INT_ABORT)
+ goto exit_err; + goto exit_err;
+ } else { + } else {
@ -226,13 +250,14 @@
+ goto exit; + goto exit;
+ +
+exit_err: +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) + if (!write)
+ *ptr = 0xffffffff; + *ptr = 0xffffffff;
+ +
+exit: +exit:
+ /* Select Memory access */ + /* 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 : + return isr & AR2315_PCI_INT_ABORT ? PCIBIOS_DEVICE_NOT_FOUND :
+ PCIBIOS_SUCCESSFUL; + PCIBIOS_SUCCESSFUL;
@ -308,8 +333,9 @@
+ +
+static void ar2315_pci_irq_handler(unsigned irq, struct irq_desc *desc) +static void ar2315_pci_irq_handler(unsigned irq, struct irq_desc *desc)
+{ +{
+ u32 pending = ar231x_read_reg(AR2315_PCI_ISR) & + struct ar2315_pci_ctrl *apc = irq_get_handler_data(irq);
+ ar231x_read_reg(AR2315_PCI_IMR); + u32 pending = ar2315_pci_reg_read(apc, AR2315_PCI_ISR) &
+ ar2315_pci_reg_read(apc, AR2315_PCI_IMR);
+ +
+ if (pending & AR2315_PCI_INT_EXT) + if (pending & AR2315_PCI_INT_EXT)
+ generic_handle_irq(AR2315_PCI_IRQ_EXT); + generic_handle_irq(AR2315_PCI_IRQ_EXT);
@ -321,24 +347,27 @@
+ +
+static void ar2315_pci_irq_mask(struct irq_data *d) +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); + 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) +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); + 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);
+ ar231x_write_reg(AR2315_PCI_ISR, m); + ar2315_pci_reg_write(apc, AR2315_PCI_ISR, m);
+} +}
+ +
+static void ar2315_pci_irq_unmask(struct irq_data *d) +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); + 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 = { +static struct irq_chip ar2315_pci_irq_chip = {
@ -348,28 +377,30 @@
+ .irq_unmask = ar2315_pci_irq_unmask, + .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; + int i;
+ +
+ ar231x_mask_reg(AR2315_PCI_IER, AR2315_PCI_IER_ENABLE, 0); + ar2315_pci_reg_mask(apc, AR2315_PCI_IER, AR2315_PCI_IER_ENABLE, 0);
+ ar231x_mask_reg(AR2315_PCI_IMR, (AR2315_PCI_INT_ABORT | + ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, (AR2315_PCI_INT_ABORT |
+ AR2315_PCI_INT_EXT), 0); + AR2315_PCI_INT_EXT), 0);
+ +
+ for (i = 0; i < AR2315_PCI_IRQ_COUNT; ++i) { + for (i = 0; i < AR2315_PCI_IRQ_COUNT; ++i) {
+ int irq = AR2315_PCI_IRQ_BASE + i; + int irq = AR2315_PCI_IRQ_BASE + i;
+ +
+ irq_set_chip_and_handler(irq, &ar2315_pci_irq_chip, + irq_set_chip_and_handler(irq, &ar2315_pci_irq_chip,
+ handle_level_irq); + 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(AR2315_IRQ_LCBUS_PCI, ar2315_pci_irq_handler);
+ irq_set_handler_data(AR2315_IRQ_LCBUS_PCI, apc);
+ +
+ /* Clear any pending Abort or external Interrupts + /* Clear any pending Abort or external Interrupts
+ * and enable interrupt processing */ + * and enable interrupt processing */
+ ar231x_write_reg(AR2315_PCI_ISR, (AR2315_PCI_INT_ABORT | + ar2315_pci_reg_write(apc, AR2315_PCI_ISR, AR2315_PCI_INT_ABORT |
+ AR2315_PCI_INT_EXT)); + AR2315_PCI_INT_EXT);
+ ar231x_mask_reg(AR2315_PCI_IER, 0, AR2315_PCI_IER_ENABLE); + ar2315_pci_reg_mask(apc, AR2315_PCI_IER, 0, AR2315_PCI_IER_ENABLE);
+} +}
+ +
+static int ar2315_pci_probe(struct platform_device *pdev) +static int ar2315_pci_probe(struct platform_device *pdev)
@ -382,6 +413,10 @@
+ if (!apc) + if (!apc)
+ return -ENOMEM; + return -ENOMEM;
+ +
+ apc->mmr_mem = devm_ioremap_nocache(dev, AR2315_PCI, AR2315_PCI_SIZE);
+ if (!apc->mmr_mem)
+ return -ENOMEM;
+
+ apc->mem_res.name = "AR2315 PCI mem space"; + apc->mem_res.name = "AR2315 PCI mem space";
+ apc->mem_res.start = AR2315_PCIEXT; + apc->mem_res.start = AR2315_PCIEXT;
+ apc->mem_res.end = AR2315_PCIEXT + AR2315_PCIEXT_SZ - 1; + apc->mem_res.end = AR2315_PCIEXT + AR2315_PCIEXT_SZ - 1;
@ -396,19 +431,21 @@
+ } + }
+ +
+ /* Reset the PCI bus by setting bits 5-4 in PCI_MCFG */ + /* Reset the PCI bus by setting bits 5-4 in PCI_MCFG */
+ ar231x_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_RST_MODE, + ar2315_pci_reg_mask(apc, AR2315_PCI_MISC_CONFIG,
+ AR2315_PCIRST_LOW); + AR2315_PCIMISC_RST_MODE,
+ AR2315_PCIRST_LOW);
+ msleep(100); + msleep(100);
+ +
+ /* Bring the PCI out of reset */ + /* Bring the PCI out of reset */
+ ar231x_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_RST_MODE, + ar2315_pci_reg_mask(apc, AR2315_PCI_MISC_CONFIG,
+ AR2315_PCIRST_HIGH | AR2315_PCICACHE_DIS | 0x8); + AR2315_PCIMISC_RST_MODE,
+ AR2315_PCIRST_HIGH | AR2315_PCICACHE_DIS | 0x8);
+ +
+ ar231x_write_reg(AR2315_PCI_UNCACHE_CFG, + ar2315_pci_reg_write(apc, AR2315_PCI_UNCACHE_CFG,
+ 0x1E | /* 1GB uncached */ + 0x1E | /* 1GB uncached */
+ (1 << 5) | /* Enable uncached */ + (1 << 5) | /* Enable uncached */
+ (0x2 << 30) /* Base: 0x80000000 */); + (0x2 << 30) /* Base: 0x80000000 */);
+ ar231x_read_reg(AR2315_PCI_UNCACHE_CFG); + ar2315_pci_reg_read(apc, AR2315_PCI_UNCACHE_CFG);
+ +
+ msleep(500); + msleep(500);
+ +
@ -416,7 +453,7 @@
+ if (err) + if (err)
+ return err; + return err;
+ +
+ ar2315_pci_irq_init(); + ar2315_pci_irq_init(apc);
+ +
+ /* PCI controller does not support I/O ports */ + /* PCI controller does not support I/O ports */
+ apc->io_res.name = "AR2315 IO space"; + apc->io_res.name = "AR2315 IO space";