Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: ath25: add AR2315 PCI host controller driver

Add PCI host controller driver and DMA address calculation hook.

Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Cc: Linux MIPS <linux-mips@linux-mips.org>
Patchwork: https://patchwork.linux-mips.org/patch/8246/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Sergey Ryazanov and committed by
Ralf Baechle
3ed7a2a7 d58eaa7f

+597 -3
+7
arch/mips/ath25/Kconfig
··· 7 7 bool "Atheros AR2315+ SoC support" 8 8 depends on ATH25 9 9 default y 10 + 11 + config PCI_AR2315 12 + bool "Atheros AR2315 PCI controller support" 13 + depends on SOC_AR2315 14 + select HW_HAS_PCI 15 + select PCI 16 + default y
+57
arch/mips/ath25/ar2315.c
··· 19 19 #include <linux/bitops.h> 20 20 #include <linux/irqdomain.h> 21 21 #include <linux/interrupt.h> 22 + #include <linux/platform_device.h> 22 23 #include <linux/reboot.h> 23 24 #include <asm/bootinfo.h> 24 25 #include <asm/reboot.h> ··· 134 133 135 134 if (pending & CAUSEF_IP3) 136 135 do_IRQ(AR2315_IRQ_WLAN0); 136 + #ifdef CONFIG_PCI_AR2315 137 + else if (pending & CAUSEF_IP5) 138 + do_IRQ(AR2315_IRQ_LCBUS_PCI); 139 + #endif 137 140 else if (pending & CAUSEF_IP2) 138 141 do_IRQ(AR2315_IRQ_MISC); 139 142 else if (pending & CAUSEF_IP7) ··· 301 296 _machine_restart = ar2315_restart; 302 297 } 303 298 299 + #ifdef CONFIG_PCI_AR2315 300 + static struct resource ar2315_pci_res[] = { 301 + { 302 + .name = "ar2315-pci-ctrl", 303 + .flags = IORESOURCE_MEM, 304 + .start = AR2315_PCI_BASE, 305 + .end = AR2315_PCI_BASE + AR2315_PCI_SIZE - 1, 306 + }, 307 + { 308 + .name = "ar2315-pci-ext", 309 + .flags = IORESOURCE_MEM, 310 + .start = AR2315_PCI_EXT_BASE, 311 + .end = AR2315_PCI_EXT_BASE + AR2315_PCI_EXT_SIZE - 1, 312 + }, 313 + { 314 + .name = "ar2315-pci", 315 + .flags = IORESOURCE_IRQ, 316 + .start = AR2315_IRQ_LCBUS_PCI, 317 + .end = AR2315_IRQ_LCBUS_PCI, 318 + }, 319 + }; 320 + #endif 321 + 304 322 void __init ar2315_arch_init(void) 305 323 { 306 324 unsigned irq = irq_create_mapping(ar2315_misc_irq_domain, 307 325 AR2315_MISC_IRQ_UART0); 308 326 309 327 ath25_serial_setup(AR2315_UART0_BASE, irq, ar2315_apb_frequency()); 328 + 329 + #ifdef CONFIG_PCI_AR2315 330 + if (ath25_soc == ATH25_SOC_AR2315) { 331 + /* Reset PCI DMA logic */ 332 + ar2315_rst_reg_mask(AR2315_RESET, 0, AR2315_RESET_PCIDMA); 333 + msleep(20); 334 + ar2315_rst_reg_mask(AR2315_RESET, AR2315_RESET_PCIDMA, 0); 335 + msleep(20); 336 + 337 + /* Configure endians */ 338 + ar2315_rst_reg_mask(AR2315_ENDIAN_CTL, 0, AR2315_CONFIG_PCIAHB | 339 + AR2315_CONFIG_PCIAHB_BRIDGE); 340 + 341 + /* Configure as PCI host with DMA */ 342 + ar2315_rst_reg_write(AR2315_PCICLK, AR2315_PCICLK_PLLC_CLKM | 343 + (AR2315_PCICLK_IN_FREQ_DIV_6 << 344 + AR2315_PCICLK_DIV_S)); 345 + ar2315_rst_reg_mask(AR2315_AHB_ARB_CTL, 0, AR2315_ARB_PCI); 346 + ar2315_rst_reg_mask(AR2315_IF_CTL, AR2315_IF_PCI_CLK_MASK | 347 + AR2315_IF_MASK, AR2315_IF_PCI | 348 + AR2315_IF_PCI_HOST | AR2315_IF_PCI_INTR | 349 + (AR2315_IF_PCI_CLK_OUTPUT_CLK << 350 + AR2315_IF_PCI_CLK_SHIFT)); 351 + 352 + platform_device_register_simple("ar2315-pci", -1, 353 + ar2315_pci_res, 354 + ARRAY_SIZE(ar2315_pci_res)); 355 + } 356 + #endif 310 357 }
+21 -3
arch/mips/include/asm/mach-ath25/dma-coherence.h
··· 12 12 13 13 #include <linux/device.h> 14 14 15 + /* 16 + * We need some arbitrary non-zero value to be programmed to the BAR1 register 17 + * of PCI host controller to enable DMA. The same value should be used as the 18 + * offset to calculate the physical address of DMA buffer for PCI devices. 19 + */ 20 + #define AR2315_PCI_HOST_SDRAM_BASEADDR 0x20000000 21 + 22 + static inline dma_addr_t ath25_dev_offset(struct device *dev) 23 + { 24 + #ifdef CONFIG_PCI 25 + extern struct bus_type pci_bus_type; 26 + 27 + if (dev && dev->bus == &pci_bus_type) 28 + return AR2315_PCI_HOST_SDRAM_BASEADDR; 29 + #endif 30 + return 0; 31 + } 32 + 15 33 static inline dma_addr_t 16 34 plat_map_dma_mem(struct device *dev, void *addr, size_t size) 17 35 { 18 - return virt_to_phys(addr); 36 + return virt_to_phys(addr) + ath25_dev_offset(dev); 19 37 } 20 38 21 39 static inline dma_addr_t 22 40 plat_map_dma_mem_page(struct device *dev, struct page *page) 23 41 { 24 - return page_to_phys(page); 42 + return page_to_phys(page) + ath25_dev_offset(dev); 25 43 } 26 44 27 45 static inline unsigned long 28 46 plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr) 29 47 { 30 - return dma_addr; 48 + return dma_addr - ath25_dev_offset(dev); 31 49 } 32 50 33 51 static inline void
+1
arch/mips/pci/Makefile
··· 19 19 obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \ 20 20 ops-bcm63xx.o 21 21 obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o 22 + obj-$(CONFIG_PCI_AR2315) += pci-ar2315.o 22 23 obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o 23 24 obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o 24 25 obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o
+511
arch/mips/pci/pci-ar2315.c
··· 1 + /* 2 + * This program is free software; you can redistribute it and/or 3 + * modify it under the terms of the GNU General Public License 4 + * as published by the Free Software Foundation; either version 2 5 + * of the License, or (at your option) any later version. 6 + * 7 + * This program is distributed in the hope that it will be useful, 8 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 + * GNU General Public License for more details. 11 + * 12 + * You should have received a copy of the GNU General Public License 13 + * along with this program; if not, see <http://www.gnu.org/licenses/>. 14 + */ 15 + 16 + /** 17 + * Both AR2315 and AR2316 chips have PCI interface unit, which supports DMA 18 + * and interrupt. PCI interface supports MMIO access method, but does not 19 + * seem to support I/O ports. 20 + * 21 + * Read/write operation in the region 0x80000000-0xBFFFFFFF causes 22 + * a memory read/write command on the PCI bus. 30 LSBs of address on 23 + * the bus are taken from memory read/write request and 2 MSBs are 24 + * determined by PCI unit configuration. 25 + * 26 + * To work with the configuration space instead of memory is necessary set 27 + * the CFG_SEL bit in the PCI_MISC_CONFIG register. 28 + * 29 + * Devices on the bus can perform DMA requests via chip BAR1. PCI host 30 + * controller BARs are programmend as if an external device is programmed. 31 + * Which means that during configuration, IDSEL pin of the chip should be 32 + * asserted. 33 + * 34 + * We know (and support) only one board that uses the PCI interface - 35 + * Fonera 2.0g (FON2202). It has a USB EHCI controller connected to the 36 + * AR2315 PCI bus. IDSEL pin of USB controller is connected to AD[13] line 37 + * and IDSEL pin of AR2315 is connected to AD[16] line. 38 + */ 39 + 40 + #include <linux/types.h> 41 + #include <linux/pci.h> 42 + #include <linux/platform_device.h> 43 + #include <linux/kernel.h> 44 + #include <linux/init.h> 45 + #include <linux/mm.h> 46 + #include <linux/delay.h> 47 + #include <linux/bitops.h> 48 + #include <linux/irq.h> 49 + #include <linux/irqdomain.h> 50 + #include <linux/io.h> 51 + #include <asm/paccess.h> 52 + 53 + /* 54 + * PCI Bus Interface Registers 55 + */ 56 + #define AR2315_PCI_1MS_REG 0x0008 57 + 58 + #define AR2315_PCI_1MS_MASK 0x3FFFF /* # of AHB clk cycles in 1ms */ 59 + 60 + #define AR2315_PCI_MISC_CONFIG 0x000c 61 + 62 + #define AR2315_PCIMISC_TXD_EN 0x00000001 /* Enable TXD for fragments */ 63 + #define AR2315_PCIMISC_CFG_SEL 0x00000002 /* Mem or Config cycles */ 64 + #define AR2315_PCIMISC_GIG_MASK 0x0000000C /* bits 31-30 for pci req */ 65 + #define AR2315_PCIMISC_RST_MODE 0x00000030 66 + #define AR2315_PCIRST_INPUT 0x00000000 /* 4:5=0 rst is input */ 67 + #define AR2315_PCIRST_LOW 0x00000010 /* 4:5=1 rst to GND */ 68 + #define AR2315_PCIRST_HIGH 0x00000020 /* 4:5=2 rst to VDD */ 69 + #define AR2315_PCIGRANT_EN 0x00000000 /* 6:7=0 early grant en */ 70 + #define AR2315_PCIGRANT_FRAME 0x00000040 /* 6:7=1 grant waits 4 frame */ 71 + #define AR2315_PCIGRANT_IDLE 0x00000080 /* 6:7=2 grant waits 4 idle */ 72 + #define AR2315_PCIGRANT_GAP 0x00000000 /* 6:7=2 grant waits 4 idle */ 73 + #define AR2315_PCICACHE_DIS 0x00001000 /* PCI external access cache 74 + * disable */ 75 + 76 + #define AR2315_PCI_OUT_TSTAMP 0x0010 77 + 78 + #define AR2315_PCI_UNCACHE_CFG 0x0014 79 + 80 + #define AR2315_PCI_IN_EN 0x0100 81 + 82 + #define AR2315_PCI_IN_EN0 0x01 /* Enable chain 0 */ 83 + #define AR2315_PCI_IN_EN1 0x02 /* Enable chain 1 */ 84 + #define AR2315_PCI_IN_EN2 0x04 /* Enable chain 2 */ 85 + #define AR2315_PCI_IN_EN3 0x08 /* Enable chain 3 */ 86 + 87 + #define AR2315_PCI_IN_DIS 0x0104 88 + 89 + #define AR2315_PCI_IN_DIS0 0x01 /* Disable chain 0 */ 90 + #define AR2315_PCI_IN_DIS1 0x02 /* Disable chain 1 */ 91 + #define AR2315_PCI_IN_DIS2 0x04 /* Disable chain 2 */ 92 + #define AR2315_PCI_IN_DIS3 0x08 /* Disable chain 3 */ 93 + 94 + #define AR2315_PCI_IN_PTR 0x0200 95 + 96 + #define AR2315_PCI_OUT_EN 0x0400 97 + 98 + #define AR2315_PCI_OUT_EN0 0x01 /* Enable chain 0 */ 99 + 100 + #define AR2315_PCI_OUT_DIS 0x0404 101 + 102 + #define AR2315_PCI_OUT_DIS0 0x01 /* Disable chain 0 */ 103 + 104 + #define AR2315_PCI_OUT_PTR 0x0408 105 + 106 + /* PCI interrupt status (write one to clear) */ 107 + #define AR2315_PCI_ISR 0x0500 108 + 109 + #define AR2315_PCI_INT_TX 0x00000001 /* Desc In Completed */ 110 + #define AR2315_PCI_INT_TXOK 0x00000002 /* Desc In OK */ 111 + #define AR2315_PCI_INT_TXERR 0x00000004 /* Desc In ERR */ 112 + #define AR2315_PCI_INT_TXEOL 0x00000008 /* Desc In End-of-List */ 113 + #define AR2315_PCI_INT_RX 0x00000010 /* Desc Out Completed */ 114 + #define AR2315_PCI_INT_RXOK 0x00000020 /* Desc Out OK */ 115 + #define AR2315_PCI_INT_RXERR 0x00000040 /* Desc Out ERR */ 116 + #define AR2315_PCI_INT_RXEOL 0x00000080 /* Desc Out EOL */ 117 + #define AR2315_PCI_INT_TXOOD 0x00000200 /* Desc In Out-of-Desc */ 118 + #define AR2315_PCI_INT_DESCMASK 0x0000FFFF /* Desc Mask */ 119 + #define AR2315_PCI_INT_EXT 0x02000000 /* Extern PCI INTA */ 120 + #define AR2315_PCI_INT_ABORT 0x04000000 /* PCI bus abort event */ 121 + 122 + /* PCI interrupt mask */ 123 + #define AR2315_PCI_IMR 0x0504 124 + 125 + /* Global PCI interrupt enable */ 126 + #define AR2315_PCI_IER 0x0508 127 + 128 + #define AR2315_PCI_IER_DISABLE 0x00 /* disable pci interrupts */ 129 + #define AR2315_PCI_IER_ENABLE 0x01 /* enable pci interrupts */ 130 + 131 + #define AR2315_PCI_HOST_IN_EN 0x0800 132 + #define AR2315_PCI_HOST_IN_DIS 0x0804 133 + #define AR2315_PCI_HOST_IN_PTR 0x0810 134 + #define AR2315_PCI_HOST_OUT_EN 0x0900 135 + #define AR2315_PCI_HOST_OUT_DIS 0x0904 136 + #define AR2315_PCI_HOST_OUT_PTR 0x0908 137 + 138 + /* 139 + * PCI interrupts, which share IP5 140 + * Keep ordered according to AR2315_PCI_INT_XXX bits 141 + */ 142 + #define AR2315_PCI_IRQ_EXT 25 143 + #define AR2315_PCI_IRQ_ABORT 26 144 + #define AR2315_PCI_IRQ_COUNT 27 145 + 146 + /* Arbitrary size of memory region to access the configuration space */ 147 + #define AR2315_PCI_CFG_SIZE 0x00100000 148 + 149 + #define AR2315_PCI_HOST_SLOT 3 150 + #define AR2315_PCI_HOST_DEVID ((0xff18 << 16) | PCI_VENDOR_ID_ATHEROS) 151 + 152 + /* ??? access BAR */ 153 + #define AR2315_PCI_HOST_MBAR0 0x10000000 154 + /* RAM access BAR */ 155 + #define AR2315_PCI_HOST_MBAR1 AR2315_PCI_HOST_SDRAM_BASEADDR 156 + /* ??? access BAR */ 157 + #define AR2315_PCI_HOST_MBAR2 0x30000000 158 + 159 + struct ar2315_pci_ctrl { 160 + void __iomem *cfg_mem; 161 + void __iomem *mmr_mem; 162 + unsigned irq; 163 + unsigned irq_ext; 164 + struct irq_domain *domain; 165 + struct pci_controller pci_ctrl; 166 + struct resource mem_res; 167 + struct resource io_res; 168 + }; 169 + 170 + static inline struct ar2315_pci_ctrl *ar2315_pci_bus_to_apc(struct pci_bus *bus) 171 + { 172 + struct pci_controller *hose = bus->sysdata; 173 + 174 + return container_of(hose, struct ar2315_pci_ctrl, pci_ctrl); 175 + } 176 + 177 + static inline u32 ar2315_pci_reg_read(struct ar2315_pci_ctrl *apc, u32 reg) 178 + { 179 + return __raw_readl(apc->mmr_mem + reg); 180 + } 181 + 182 + static inline void ar2315_pci_reg_write(struct ar2315_pci_ctrl *apc, u32 reg, 183 + u32 val) 184 + { 185 + __raw_writel(val, apc->mmr_mem + reg); 186 + } 187 + 188 + static inline void ar2315_pci_reg_mask(struct ar2315_pci_ctrl *apc, u32 reg, 189 + u32 mask, u32 val) 190 + { 191 + u32 ret = ar2315_pci_reg_read(apc, reg); 192 + 193 + ret &= ~mask; 194 + ret |= val; 195 + ar2315_pci_reg_write(apc, reg, ret); 196 + } 197 + 198 + static int ar2315_pci_cfg_access(struct ar2315_pci_ctrl *apc, unsigned devfn, 199 + int where, int size, u32 *ptr, bool write) 200 + { 201 + int func = PCI_FUNC(devfn); 202 + int dev = PCI_SLOT(devfn); 203 + u32 addr = (1 << (13 + dev)) | (func << 8) | (where & ~3); 204 + u32 mask = 0xffffffff >> 8 * (4 - size); 205 + u32 sh = (where & 3) * 8; 206 + u32 value, isr; 207 + 208 + /* Prevent access past the remapped area */ 209 + if (addr >= AR2315_PCI_CFG_SIZE || dev > 18) 210 + return PCIBIOS_DEVICE_NOT_FOUND; 211 + 212 + /* Clear pending errors */ 213 + ar2315_pci_reg_write(apc, AR2315_PCI_ISR, AR2315_PCI_INT_ABORT); 214 + /* Select Configuration access */ 215 + ar2315_pci_reg_mask(apc, AR2315_PCI_MISC_CONFIG, 0, 216 + AR2315_PCIMISC_CFG_SEL); 217 + 218 + mb(); /* PCI must see space change before we begin */ 219 + 220 + value = __raw_readl(apc->cfg_mem + addr); 221 + 222 + isr = ar2315_pci_reg_read(apc, AR2315_PCI_ISR); 223 + 224 + if (isr & AR2315_PCI_INT_ABORT) 225 + goto exit_err; 226 + 227 + if (write) { 228 + value = (value & ~(mask << sh)) | *ptr << sh; 229 + __raw_writel(value, apc->cfg_mem + addr); 230 + isr = ar2315_pci_reg_read(apc, AR2315_PCI_ISR); 231 + if (isr & AR2315_PCI_INT_ABORT) 232 + goto exit_err; 233 + } else { 234 + *ptr = (value >> sh) & mask; 235 + } 236 + 237 + goto exit; 238 + 239 + exit_err: 240 + ar2315_pci_reg_write(apc, AR2315_PCI_ISR, AR2315_PCI_INT_ABORT); 241 + if (!write) 242 + *ptr = 0xffffffff; 243 + 244 + exit: 245 + /* Select Memory access */ 246 + ar2315_pci_reg_mask(apc, AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_CFG_SEL, 247 + 0); 248 + 249 + return isr & AR2315_PCI_INT_ABORT ? PCIBIOS_DEVICE_NOT_FOUND : 250 + PCIBIOS_SUCCESSFUL; 251 + } 252 + 253 + static inline int ar2315_pci_local_cfg_rd(struct ar2315_pci_ctrl *apc, 254 + unsigned devfn, int where, u32 *val) 255 + { 256 + return ar2315_pci_cfg_access(apc, devfn, where, sizeof(u32), val, 257 + false); 258 + } 259 + 260 + static inline int ar2315_pci_local_cfg_wr(struct ar2315_pci_ctrl *apc, 261 + unsigned devfn, int where, u32 val) 262 + { 263 + return ar2315_pci_cfg_access(apc, devfn, where, sizeof(u32), &val, 264 + true); 265 + } 266 + 267 + static int ar2315_pci_cfg_read(struct pci_bus *bus, unsigned devfn, int where, 268 + int size, u32 *value) 269 + { 270 + struct ar2315_pci_ctrl *apc = ar2315_pci_bus_to_apc(bus); 271 + 272 + if (PCI_SLOT(devfn) == AR2315_PCI_HOST_SLOT) 273 + return PCIBIOS_DEVICE_NOT_FOUND; 274 + 275 + return ar2315_pci_cfg_access(apc, devfn, where, size, value, false); 276 + } 277 + 278 + static int ar2315_pci_cfg_write(struct pci_bus *bus, unsigned devfn, int where, 279 + int size, u32 value) 280 + { 281 + struct ar2315_pci_ctrl *apc = ar2315_pci_bus_to_apc(bus); 282 + 283 + if (PCI_SLOT(devfn) == AR2315_PCI_HOST_SLOT) 284 + return PCIBIOS_DEVICE_NOT_FOUND; 285 + 286 + return ar2315_pci_cfg_access(apc, devfn, where, size, &value, true); 287 + } 288 + 289 + static struct pci_ops ar2315_pci_ops = { 290 + .read = ar2315_pci_cfg_read, 291 + .write = ar2315_pci_cfg_write, 292 + }; 293 + 294 + static int ar2315_pci_host_setup(struct ar2315_pci_ctrl *apc) 295 + { 296 + unsigned devfn = PCI_DEVFN(AR2315_PCI_HOST_SLOT, 0); 297 + int res; 298 + u32 id; 299 + 300 + res = ar2315_pci_local_cfg_rd(apc, devfn, PCI_VENDOR_ID, &id); 301 + if (res != PCIBIOS_SUCCESSFUL || id != AR2315_PCI_HOST_DEVID) 302 + return -ENODEV; 303 + 304 + /* Program MBARs */ 305 + ar2315_pci_local_cfg_wr(apc, devfn, PCI_BASE_ADDRESS_0, 306 + AR2315_PCI_HOST_MBAR0); 307 + ar2315_pci_local_cfg_wr(apc, devfn, PCI_BASE_ADDRESS_1, 308 + AR2315_PCI_HOST_MBAR1); 309 + ar2315_pci_local_cfg_wr(apc, devfn, PCI_BASE_ADDRESS_2, 310 + AR2315_PCI_HOST_MBAR2); 311 + 312 + /* Run */ 313 + ar2315_pci_local_cfg_wr(apc, devfn, PCI_COMMAND, PCI_COMMAND_MEMORY | 314 + PCI_COMMAND_MASTER | PCI_COMMAND_SPECIAL | 315 + PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | 316 + PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK); 317 + 318 + return 0; 319 + } 320 + 321 + static void ar2315_pci_irq_handler(unsigned irq, struct irq_desc *desc) 322 + { 323 + struct ar2315_pci_ctrl *apc = irq_get_handler_data(irq); 324 + u32 pending = ar2315_pci_reg_read(apc, AR2315_PCI_ISR) & 325 + ar2315_pci_reg_read(apc, AR2315_PCI_IMR); 326 + unsigned pci_irq = 0; 327 + 328 + if (pending) 329 + pci_irq = irq_find_mapping(apc->domain, __ffs(pending)); 330 + 331 + if (pci_irq) 332 + generic_handle_irq(pci_irq); 333 + else 334 + spurious_interrupt(); 335 + } 336 + 337 + static void ar2315_pci_irq_mask(struct irq_data *d) 338 + { 339 + struct ar2315_pci_ctrl *apc = irq_data_get_irq_chip_data(d); 340 + 341 + ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, BIT(d->hwirq), 0); 342 + } 343 + 344 + static void ar2315_pci_irq_mask_ack(struct irq_data *d) 345 + { 346 + struct ar2315_pci_ctrl *apc = irq_data_get_irq_chip_data(d); 347 + u32 m = BIT(d->hwirq); 348 + 349 + ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, m, 0); 350 + ar2315_pci_reg_write(apc, AR2315_PCI_ISR, m); 351 + } 352 + 353 + static void ar2315_pci_irq_unmask(struct irq_data *d) 354 + { 355 + struct ar2315_pci_ctrl *apc = irq_data_get_irq_chip_data(d); 356 + 357 + ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, 0, BIT(d->hwirq)); 358 + } 359 + 360 + static struct irq_chip ar2315_pci_irq_chip = { 361 + .name = "AR2315-PCI", 362 + .irq_mask = ar2315_pci_irq_mask, 363 + .irq_mask_ack = ar2315_pci_irq_mask_ack, 364 + .irq_unmask = ar2315_pci_irq_unmask, 365 + }; 366 + 367 + static int ar2315_pci_irq_map(struct irq_domain *d, unsigned irq, 368 + irq_hw_number_t hw) 369 + { 370 + irq_set_chip_and_handler(irq, &ar2315_pci_irq_chip, handle_level_irq); 371 + irq_set_chip_data(irq, d->host_data); 372 + return 0; 373 + } 374 + 375 + static struct irq_domain_ops ar2315_pci_irq_domain_ops = { 376 + .map = ar2315_pci_irq_map, 377 + }; 378 + 379 + static void ar2315_pci_irq_init(struct ar2315_pci_ctrl *apc) 380 + { 381 + ar2315_pci_reg_mask(apc, AR2315_PCI_IER, AR2315_PCI_IER_ENABLE, 0); 382 + ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, (AR2315_PCI_INT_ABORT | 383 + AR2315_PCI_INT_EXT), 0); 384 + 385 + apc->irq_ext = irq_create_mapping(apc->domain, AR2315_PCI_IRQ_EXT); 386 + 387 + irq_set_chained_handler(apc->irq, ar2315_pci_irq_handler); 388 + irq_set_handler_data(apc->irq, apc); 389 + 390 + /* Clear any pending Abort or external Interrupts 391 + * and enable interrupt processing */ 392 + ar2315_pci_reg_write(apc, AR2315_PCI_ISR, AR2315_PCI_INT_ABORT | 393 + AR2315_PCI_INT_EXT); 394 + ar2315_pci_reg_mask(apc, AR2315_PCI_IER, 0, AR2315_PCI_IER_ENABLE); 395 + } 396 + 397 + static int ar2315_pci_probe(struct platform_device *pdev) 398 + { 399 + struct ar2315_pci_ctrl *apc; 400 + struct device *dev = &pdev->dev; 401 + struct resource *res; 402 + int irq, err; 403 + 404 + apc = devm_kzalloc(dev, sizeof(*apc), GFP_KERNEL); 405 + if (!apc) 406 + return -ENOMEM; 407 + 408 + irq = platform_get_irq(pdev, 0); 409 + if (irq < 0) 410 + return -EINVAL; 411 + apc->irq = irq; 412 + 413 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 414 + "ar2315-pci-ctrl"); 415 + apc->mmr_mem = devm_ioremap_resource(dev, res); 416 + if (IS_ERR(apc->mmr_mem)) 417 + return PTR_ERR(apc->mmr_mem); 418 + 419 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 420 + "ar2315-pci-ext"); 421 + if (!res) 422 + return -EINVAL; 423 + 424 + apc->mem_res.name = "AR2315 PCI mem space"; 425 + apc->mem_res.parent = res; 426 + apc->mem_res.start = res->start; 427 + apc->mem_res.end = res->end; 428 + apc->mem_res.flags = IORESOURCE_MEM; 429 + 430 + /* Remap PCI config space */ 431 + apc->cfg_mem = devm_ioremap_nocache(dev, res->start, 432 + AR2315_PCI_CFG_SIZE); 433 + if (!apc->cfg_mem) { 434 + dev_err(dev, "failed to remap PCI config space\n"); 435 + return -ENOMEM; 436 + } 437 + 438 + /* Reset the PCI bus by setting bits 5-4 in PCI_MCFG */ 439 + ar2315_pci_reg_mask(apc, AR2315_PCI_MISC_CONFIG, 440 + AR2315_PCIMISC_RST_MODE, 441 + AR2315_PCIRST_LOW); 442 + msleep(100); 443 + 444 + /* Bring the PCI out of reset */ 445 + ar2315_pci_reg_mask(apc, AR2315_PCI_MISC_CONFIG, 446 + AR2315_PCIMISC_RST_MODE, 447 + AR2315_PCIRST_HIGH | AR2315_PCICACHE_DIS | 0x8); 448 + 449 + ar2315_pci_reg_write(apc, AR2315_PCI_UNCACHE_CFG, 450 + 0x1E | /* 1GB uncached */ 451 + (1 << 5) | /* Enable uncached */ 452 + (0x2 << 30) /* Base: 0x80000000 */); 453 + ar2315_pci_reg_read(apc, AR2315_PCI_UNCACHE_CFG); 454 + 455 + msleep(500); 456 + 457 + err = ar2315_pci_host_setup(apc); 458 + if (err) 459 + return err; 460 + 461 + apc->domain = irq_domain_add_linear(NULL, AR2315_PCI_IRQ_COUNT, 462 + &ar2315_pci_irq_domain_ops, apc); 463 + if (!apc->domain) { 464 + dev_err(dev, "failed to add IRQ domain\n"); 465 + return -ENOMEM; 466 + } 467 + 468 + ar2315_pci_irq_init(apc); 469 + 470 + /* PCI controller does not support I/O ports */ 471 + apc->io_res.name = "AR2315 IO space"; 472 + apc->io_res.start = 0; 473 + apc->io_res.end = 0; 474 + apc->io_res.flags = IORESOURCE_IO, 475 + 476 + apc->pci_ctrl.pci_ops = &ar2315_pci_ops; 477 + apc->pci_ctrl.mem_resource = &apc->mem_res, 478 + apc->pci_ctrl.io_resource = &apc->io_res, 479 + 480 + register_pci_controller(&apc->pci_ctrl); 481 + 482 + dev_info(dev, "register PCI controller\n"); 483 + 484 + return 0; 485 + } 486 + 487 + static struct platform_driver ar2315_pci_driver = { 488 + .probe = ar2315_pci_probe, 489 + .driver = { 490 + .name = "ar2315-pci", 491 + .owner = THIS_MODULE, 492 + }, 493 + }; 494 + 495 + static int __init ar2315_pci_init(void) 496 + { 497 + return platform_driver_register(&ar2315_pci_driver); 498 + } 499 + arch_initcall(ar2315_pci_init); 500 + 501 + int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 502 + { 503 + struct ar2315_pci_ctrl *apc = ar2315_pci_bus_to_apc(dev->bus); 504 + 505 + return slot ? 0 : apc->irq_ext; 506 + } 507 + 508 + int pcibios_plat_dev_init(struct pci_dev *dev) 509 + { 510 + return 0; 511 + }