1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2692183efSGabor Juhos /*
3e9b62e8eSGabor Juhos * Atheros AR724X PCI host controller driver
4692183efSGabor Juhos *
5692183efSGabor Juhos * Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
6e9b62e8eSGabor Juhos * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
7692183efSGabor Juhos */
8692183efSGabor Juhos
94c07c7dfSGabor Juhos #include <linux/irq.h>
10692183efSGabor Juhos #include <linux/pci.h>
112722090aSPaul Gortmaker #include <linux/init.h>
120316b053SMathias Kresin #include <linux/delay.h>
1358d2e9bcSGabor Juhos #include <linux/platform_device.h>
146015a856SGabor Juhos #include <asm/mach-ath79/ath79.h>
154c07c7dfSGabor Juhos #include <asm/mach-ath79/ar71xx_regs.h>
16692183efSGabor Juhos
170316b053SMathias Kresin #define AR724X_PCI_REG_APP 0x00
18a1dca315SGabor Juhos #define AR724X_PCI_REG_RESET 0x18
194c07c7dfSGabor Juhos #define AR724X_PCI_REG_INT_STATUS 0x4c
204c07c7dfSGabor Juhos #define AR724X_PCI_REG_INT_MASK 0x50
214c07c7dfSGabor Juhos
220316b053SMathias Kresin #define AR724X_PCI_APP_LTSSM_ENABLE BIT(0)
230316b053SMathias Kresin
24a1dca315SGabor Juhos #define AR724X_PCI_RESET_LINK_UP BIT(0)
25a1dca315SGabor Juhos
264c07c7dfSGabor Juhos #define AR724X_PCI_INT_DEV0 BIT(14)
274c07c7dfSGabor Juhos
284c07c7dfSGabor Juhos #define AR724X_PCI_IRQ_COUNT 1
294c07c7dfSGabor Juhos
306015a856SGabor Juhos #define AR7240_BAR0_WAR_VALUE 0xffff
316015a856SGabor Juhos
3212401fc2SGabor Juhos #define AR724X_PCI_CMD_INIT (PCI_COMMAND_MEMORY | \
3312401fc2SGabor Juhos PCI_COMMAND_MASTER | \
3412401fc2SGabor Juhos PCI_COMMAND_INVALIDATE | \
3512401fc2SGabor Juhos PCI_COMMAND_PARITY | \
3612401fc2SGabor Juhos PCI_COMMAND_SERR | \
3712401fc2SGabor Juhos PCI_COMMAND_FAST_BACK)
3812401fc2SGabor Juhos
39908339efSGabor Juhos struct ar724x_pci_controller {
40908339efSGabor Juhos void __iomem *devcfg_base;
41908339efSGabor Juhos void __iomem *ctrl_base;
4212401fc2SGabor Juhos void __iomem *crp_base;
43692183efSGabor Juhos
44908339efSGabor Juhos int irq;
458b66d461SGabor Juhos int irq_base;
46a1dca315SGabor Juhos
47908339efSGabor Juhos bool link_up;
48908339efSGabor Juhos bool bar0_is_cached;
49908339efSGabor Juhos u32 bar0_value;
50908339efSGabor Juhos
51908339efSGabor Juhos struct pci_controller pci_controller;
5234b134aeSGabor Juhos struct resource io_res;
5334b134aeSGabor Juhos struct resource mem_res;
54908339efSGabor Juhos };
55908339efSGabor Juhos
ar724x_pci_check_link(struct ar724x_pci_controller * apc)56908339efSGabor Juhos static inline bool ar724x_pci_check_link(struct ar724x_pci_controller *apc)
57a1dca315SGabor Juhos {
58a1dca315SGabor Juhos u32 reset;
59a1dca315SGabor Juhos
60908339efSGabor Juhos reset = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_RESET);
61a1dca315SGabor Juhos return reset & AR724X_PCI_RESET_LINK_UP;
62a1dca315SGabor Juhos }
636015a856SGabor Juhos
64908339efSGabor Juhos static inline struct ar724x_pci_controller *
pci_bus_to_ar724x_controller(struct pci_bus * bus)65908339efSGabor Juhos pci_bus_to_ar724x_controller(struct pci_bus *bus)
66908339efSGabor Juhos {
67908339efSGabor Juhos struct pci_controller *hose;
68908339efSGabor Juhos
69908339efSGabor Juhos hose = (struct pci_controller *) bus->sysdata;
70908339efSGabor Juhos return container_of(hose, struct ar724x_pci_controller, pci_controller);
71908339efSGabor Juhos }
72908339efSGabor Juhos
ar724x_pci_local_write(struct ar724x_pci_controller * apc,int where,int size,u32 value)7312401fc2SGabor Juhos static int ar724x_pci_local_write(struct ar724x_pci_controller *apc,
7412401fc2SGabor Juhos int where, int size, u32 value)
7512401fc2SGabor Juhos {
7612401fc2SGabor Juhos void __iomem *base;
7712401fc2SGabor Juhos u32 data;
7812401fc2SGabor Juhos int s;
7912401fc2SGabor Juhos
8012401fc2SGabor Juhos WARN_ON(where & (size - 1));
8112401fc2SGabor Juhos
8212401fc2SGabor Juhos if (!apc->link_up)
8312401fc2SGabor Juhos return PCIBIOS_DEVICE_NOT_FOUND;
8412401fc2SGabor Juhos
8512401fc2SGabor Juhos base = apc->crp_base;
8612401fc2SGabor Juhos data = __raw_readl(base + (where & ~3));
8712401fc2SGabor Juhos
8812401fc2SGabor Juhos switch (size) {
8912401fc2SGabor Juhos case 1:
9012401fc2SGabor Juhos s = ((where & 3) * 8);
9112401fc2SGabor Juhos data &= ~(0xff << s);
9212401fc2SGabor Juhos data |= ((value & 0xff) << s);
9312401fc2SGabor Juhos break;
9412401fc2SGabor Juhos case 2:
9512401fc2SGabor Juhos s = ((where & 2) * 8);
9612401fc2SGabor Juhos data &= ~(0xffff << s);
9712401fc2SGabor Juhos data |= ((value & 0xffff) << s);
9812401fc2SGabor Juhos break;
9912401fc2SGabor Juhos case 4:
10012401fc2SGabor Juhos data = value;
10112401fc2SGabor Juhos break;
10212401fc2SGabor Juhos default:
10312401fc2SGabor Juhos return PCIBIOS_BAD_REGISTER_NUMBER;
10412401fc2SGabor Juhos }
10512401fc2SGabor Juhos
10612401fc2SGabor Juhos __raw_writel(data, base + (where & ~3));
10712401fc2SGabor Juhos /* flush write */
10812401fc2SGabor Juhos __raw_readl(base + (where & ~3));
10912401fc2SGabor Juhos
11012401fc2SGabor Juhos return PCIBIOS_SUCCESSFUL;
11112401fc2SGabor Juhos }
11212401fc2SGabor Juhos
ar724x_pci_read(struct pci_bus * bus,unsigned int devfn,int where,int size,uint32_t * value)113d624bd3cSGabor Juhos static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
114692183efSGabor Juhos int size, uint32_t *value)
115692183efSGabor Juhos {
116908339efSGabor Juhos struct ar724x_pci_controller *apc;
117c198441aSGabor Juhos void __iomem *base;
11864adb6bbSGabor Juhos u32 data;
119692183efSGabor Juhos
120908339efSGabor Juhos apc = pci_bus_to_ar724x_controller(bus);
121908339efSGabor Juhos if (!apc->link_up)
122a1dca315SGabor Juhos return PCIBIOS_DEVICE_NOT_FOUND;
123a1dca315SGabor Juhos
124692183efSGabor Juhos if (devfn)
125692183efSGabor Juhos return PCIBIOS_DEVICE_NOT_FOUND;
126692183efSGabor Juhos
127908339efSGabor Juhos base = apc->devcfg_base;
12864adb6bbSGabor Juhos data = __raw_readl(base + (where & ~3));
129692183efSGabor Juhos
130692183efSGabor Juhos switch (size) {
131692183efSGabor Juhos case 1:
13264adb6bbSGabor Juhos if (where & 1)
13364adb6bbSGabor Juhos data >>= 8;
13464adb6bbSGabor Juhos if (where & 2)
13564adb6bbSGabor Juhos data >>= 16;
13664adb6bbSGabor Juhos data &= 0xff;
137692183efSGabor Juhos break;
138692183efSGabor Juhos case 2:
13964adb6bbSGabor Juhos if (where & 2)
14064adb6bbSGabor Juhos data >>= 16;
14164adb6bbSGabor Juhos data &= 0xffff;
142692183efSGabor Juhos break;
143692183efSGabor Juhos case 4:
144692183efSGabor Juhos break;
145692183efSGabor Juhos default:
146692183efSGabor Juhos return PCIBIOS_BAD_REGISTER_NUMBER;
147692183efSGabor Juhos }
148692183efSGabor Juhos
1496015a856SGabor Juhos if (where == PCI_BASE_ADDRESS_0 && size == 4 &&
150908339efSGabor Juhos apc->bar0_is_cached) {
1516015a856SGabor Juhos /* use the cached value */
152908339efSGabor Juhos *value = apc->bar0_value;
1536015a856SGabor Juhos } else {
15464adb6bbSGabor Juhos *value = data;
1556015a856SGabor Juhos }
156692183efSGabor Juhos
157692183efSGabor Juhos return PCIBIOS_SUCCESSFUL;
158692183efSGabor Juhos }
159692183efSGabor Juhos
ar724x_pci_write(struct pci_bus * bus,unsigned int devfn,int where,int size,uint32_t value)160d624bd3cSGabor Juhos static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
161692183efSGabor Juhos int size, uint32_t value)
162692183efSGabor Juhos {
163908339efSGabor Juhos struct ar724x_pci_controller *apc;
164c198441aSGabor Juhos void __iomem *base;
16564adb6bbSGabor Juhos u32 data;
16664adb6bbSGabor Juhos int s;
167692183efSGabor Juhos
168908339efSGabor Juhos apc = pci_bus_to_ar724x_controller(bus);
169908339efSGabor Juhos if (!apc->link_up)
170a1dca315SGabor Juhos return PCIBIOS_DEVICE_NOT_FOUND;
171a1dca315SGabor Juhos
172692183efSGabor Juhos if (devfn)
173692183efSGabor Juhos return PCIBIOS_DEVICE_NOT_FOUND;
174692183efSGabor Juhos
1756015a856SGabor Juhos if (soc_is_ar7240() && where == PCI_BASE_ADDRESS_0 && size == 4) {
1766015a856SGabor Juhos if (value != 0xffffffff) {
1776015a856SGabor Juhos /*
1786015a856SGabor Juhos * WAR for a hw issue. If the BAR0 register of the
1796015a856SGabor Juhos * device is set to the proper base address, the
1806015a856SGabor Juhos * memory space of the device is not accessible.
1816015a856SGabor Juhos *
1826015a856SGabor Juhos * Cache the intended value so it can be read back,
1836015a856SGabor Juhos * and write a SoC specific constant value to the
1846015a856SGabor Juhos * BAR0 register in order to make the device memory
1856015a856SGabor Juhos * accessible.
1866015a856SGabor Juhos */
187908339efSGabor Juhos apc->bar0_is_cached = true;
188908339efSGabor Juhos apc->bar0_value = value;
1896015a856SGabor Juhos
1906015a856SGabor Juhos value = AR7240_BAR0_WAR_VALUE;
1916015a856SGabor Juhos } else {
192908339efSGabor Juhos apc->bar0_is_cached = false;
1936015a856SGabor Juhos }
1946015a856SGabor Juhos }
1956015a856SGabor Juhos
196908339efSGabor Juhos base = apc->devcfg_base;
19764adb6bbSGabor Juhos data = __raw_readl(base + (where & ~3));
198692183efSGabor Juhos
199692183efSGabor Juhos switch (size) {
200692183efSGabor Juhos case 1:
20164adb6bbSGabor Juhos s = ((where & 3) * 8);
20264adb6bbSGabor Juhos data &= ~(0xff << s);
20364adb6bbSGabor Juhos data |= ((value & 0xff) << s);
204692183efSGabor Juhos break;
205692183efSGabor Juhos case 2:
20664adb6bbSGabor Juhos s = ((where & 2) * 8);
20764adb6bbSGabor Juhos data &= ~(0xffff << s);
20864adb6bbSGabor Juhos data |= ((value & 0xffff) << s);
209692183efSGabor Juhos break;
210692183efSGabor Juhos case 4:
21164adb6bbSGabor Juhos data = value;
212692183efSGabor Juhos break;
213692183efSGabor Juhos default:
214692183efSGabor Juhos return PCIBIOS_BAD_REGISTER_NUMBER;
215692183efSGabor Juhos }
216692183efSGabor Juhos
21764adb6bbSGabor Juhos __raw_writel(data, base + (where & ~3));
21864adb6bbSGabor Juhos /* flush write */
21964adb6bbSGabor Juhos __raw_readl(base + (where & ~3));
220692183efSGabor Juhos
221692183efSGabor Juhos return PCIBIOS_SUCCESSFUL;
222692183efSGabor Juhos }
223692183efSGabor Juhos
224d624bd3cSGabor Juhos static struct pci_ops ar724x_pci_ops = {
225d624bd3cSGabor Juhos .read = ar724x_pci_read,
226d624bd3cSGabor Juhos .write = ar724x_pci_write,
227692183efSGabor Juhos };
228692183efSGabor Juhos
ar724x_pci_irq_handler(struct irq_desc * desc)229bd0b9ac4SThomas Gleixner static void ar724x_pci_irq_handler(struct irq_desc *desc)
230692183efSGabor Juhos {
231908339efSGabor Juhos struct ar724x_pci_controller *apc;
2324c07c7dfSGabor Juhos void __iomem *base;
2334c07c7dfSGabor Juhos u32 pending;
2344c07c7dfSGabor Juhos
23525aae561SJiang Liu apc = irq_desc_get_handler_data(desc);
236908339efSGabor Juhos base = apc->ctrl_base;
2374c07c7dfSGabor Juhos
2384c07c7dfSGabor Juhos pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) &
2394c07c7dfSGabor Juhos __raw_readl(base + AR724X_PCI_REG_INT_MASK);
2404c07c7dfSGabor Juhos
2414c07c7dfSGabor Juhos if (pending & AR724X_PCI_INT_DEV0)
2428b66d461SGabor Juhos generic_handle_irq(apc->irq_base + 0);
2434c07c7dfSGabor Juhos
2444c07c7dfSGabor Juhos else
2454c07c7dfSGabor Juhos spurious_interrupt();
2464c07c7dfSGabor Juhos }
2474c07c7dfSGabor Juhos
ar724x_pci_irq_unmask(struct irq_data * d)2484c07c7dfSGabor Juhos static void ar724x_pci_irq_unmask(struct irq_data *d)
2494c07c7dfSGabor Juhos {
250908339efSGabor Juhos struct ar724x_pci_controller *apc;
2514c07c7dfSGabor Juhos void __iomem *base;
2528b66d461SGabor Juhos int offset;
2534c07c7dfSGabor Juhos u32 t;
2544c07c7dfSGabor Juhos
255908339efSGabor Juhos apc = irq_data_get_irq_chip_data(d);
256908339efSGabor Juhos base = apc->ctrl_base;
2578b66d461SGabor Juhos offset = apc->irq_base - d->irq;
2584c07c7dfSGabor Juhos
2598b66d461SGabor Juhos switch (offset) {
2608b66d461SGabor Juhos case 0:
2614c07c7dfSGabor Juhos t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
2624c07c7dfSGabor Juhos __raw_writel(t | AR724X_PCI_INT_DEV0,
2634c07c7dfSGabor Juhos base + AR724X_PCI_REG_INT_MASK);
2644c07c7dfSGabor Juhos /* flush write */
2654c07c7dfSGabor Juhos __raw_readl(base + AR724X_PCI_REG_INT_MASK);
2664c07c7dfSGabor Juhos }
2674c07c7dfSGabor Juhos }
2684c07c7dfSGabor Juhos
ar724x_pci_irq_mask(struct irq_data * d)2694c07c7dfSGabor Juhos static void ar724x_pci_irq_mask(struct irq_data *d)
2704c07c7dfSGabor Juhos {
271908339efSGabor Juhos struct ar724x_pci_controller *apc;
2724c07c7dfSGabor Juhos void __iomem *base;
2738b66d461SGabor Juhos int offset;
2744c07c7dfSGabor Juhos u32 t;
2754c07c7dfSGabor Juhos
276908339efSGabor Juhos apc = irq_data_get_irq_chip_data(d);
277908339efSGabor Juhos base = apc->ctrl_base;
2788b66d461SGabor Juhos offset = apc->irq_base - d->irq;
2794c07c7dfSGabor Juhos
2808b66d461SGabor Juhos switch (offset) {
2818b66d461SGabor Juhos case 0:
2824c07c7dfSGabor Juhos t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
2834c07c7dfSGabor Juhos __raw_writel(t & ~AR724X_PCI_INT_DEV0,
2844c07c7dfSGabor Juhos base + AR724X_PCI_REG_INT_MASK);
2854c07c7dfSGabor Juhos
2864c07c7dfSGabor Juhos /* flush write */
2874c07c7dfSGabor Juhos __raw_readl(base + AR724X_PCI_REG_INT_MASK);
2884c07c7dfSGabor Juhos
2894c07c7dfSGabor Juhos t = __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
2904c07c7dfSGabor Juhos __raw_writel(t | AR724X_PCI_INT_DEV0,
2914c07c7dfSGabor Juhos base + AR724X_PCI_REG_INT_STATUS);
2924c07c7dfSGabor Juhos
2934c07c7dfSGabor Juhos /* flush write */
2944c07c7dfSGabor Juhos __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
2954c07c7dfSGabor Juhos }
2964c07c7dfSGabor Juhos }
2974c07c7dfSGabor Juhos
2984c07c7dfSGabor Juhos static struct irq_chip ar724x_pci_irq_chip = {
2994c07c7dfSGabor Juhos .name = "AR724X PCI ",
3004c07c7dfSGabor Juhos .irq_mask = ar724x_pci_irq_mask,
3014c07c7dfSGabor Juhos .irq_unmask = ar724x_pci_irq_unmask,
3024c07c7dfSGabor Juhos .irq_mask_ack = ar724x_pci_irq_mask,
3034c07c7dfSGabor Juhos };
3044c07c7dfSGabor Juhos
ar724x_pci_irq_init(struct ar724x_pci_controller * apc,int id)3058b66d461SGabor Juhos static void ar724x_pci_irq_init(struct ar724x_pci_controller *apc,
3068b66d461SGabor Juhos int id)
3074c07c7dfSGabor Juhos {
3084c07c7dfSGabor Juhos void __iomem *base;
3094c07c7dfSGabor Juhos int i;
3104c07c7dfSGabor Juhos
311908339efSGabor Juhos base = apc->ctrl_base;
3124c07c7dfSGabor Juhos
3134c07c7dfSGabor Juhos __raw_writel(0, base + AR724X_PCI_REG_INT_MASK);
3144c07c7dfSGabor Juhos __raw_writel(0, base + AR724X_PCI_REG_INT_STATUS);
3154c07c7dfSGabor Juhos
3168b66d461SGabor Juhos apc->irq_base = ATH79_PCI_IRQ_BASE + (id * AR724X_PCI_IRQ_COUNT);
3174c07c7dfSGabor Juhos
3188b66d461SGabor Juhos for (i = apc->irq_base;
3198b66d461SGabor Juhos i < apc->irq_base + AR724X_PCI_IRQ_COUNT; i++) {
3204c07c7dfSGabor Juhos irq_set_chip_and_handler(i, &ar724x_pci_irq_chip,
3214c07c7dfSGabor Juhos handle_level_irq);
322908339efSGabor Juhos irq_set_chip_data(i, apc);
323908339efSGabor Juhos }
3244c07c7dfSGabor Juhos
3254d3f77d8SThomas Gleixner irq_set_chained_handler_and_data(apc->irq, ar724x_pci_irq_handler,
3264d3f77d8SThomas Gleixner apc);
3274c07c7dfSGabor Juhos }
3284c07c7dfSGabor Juhos
ar724x_pci_hw_init(struct ar724x_pci_controller * apc)3290316b053SMathias Kresin static void ar724x_pci_hw_init(struct ar724x_pci_controller *apc)
3300316b053SMathias Kresin {
3310316b053SMathias Kresin u32 ppl, app;
3320316b053SMathias Kresin int wait = 0;
3330316b053SMathias Kresin
3340316b053SMathias Kresin /* deassert PCIe host controller and PCIe PHY reset */
3350316b053SMathias Kresin ath79_device_reset_clear(AR724X_RESET_PCIE);
3360316b053SMathias Kresin ath79_device_reset_clear(AR724X_RESET_PCIE_PHY);
3370316b053SMathias Kresin
3380316b053SMathias Kresin /* remove the reset of the PCIE PLL */
3390316b053SMathias Kresin ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG);
3400316b053SMathias Kresin ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET;
3410316b053SMathias Kresin ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl);
3420316b053SMathias Kresin
3430316b053SMathias Kresin /* deassert bypass for the PCIE PLL */
3440316b053SMathias Kresin ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG);
3450316b053SMathias Kresin ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_BYPASS;
3460316b053SMathias Kresin ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl);
3470316b053SMathias Kresin
3480316b053SMathias Kresin /* set PCIE Application Control to ready */
3490316b053SMathias Kresin app = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_APP);
3500316b053SMathias Kresin app |= AR724X_PCI_APP_LTSSM_ENABLE;
3510316b053SMathias Kresin __raw_writel(app, apc->ctrl_base + AR724X_PCI_REG_APP);
3520316b053SMathias Kresin
3530316b053SMathias Kresin /* wait up to 100ms for PHY link up */
3540316b053SMathias Kresin do {
3550316b053SMathias Kresin mdelay(10);
3560316b053SMathias Kresin wait++;
3570316b053SMathias Kresin } while (wait < 10 && !ar724x_pci_check_link(apc));
3580316b053SMathias Kresin }
3590316b053SMathias Kresin
ar724x_pci_probe(struct platform_device * pdev)36058d2e9bcSGabor Juhos static int ar724x_pci_probe(struct platform_device *pdev)
36158d2e9bcSGabor Juhos {
362908339efSGabor Juhos struct ar724x_pci_controller *apc;
36358d2e9bcSGabor Juhos struct resource *res;
3648b66d461SGabor Juhos int id;
3658b66d461SGabor Juhos
3668b66d461SGabor Juhos id = pdev->id;
3678b66d461SGabor Juhos if (id == -1)
3688b66d461SGabor Juhos id = 0;
369908339efSGabor Juhos
370908339efSGabor Juhos apc = devm_kzalloc(&pdev->dev, sizeof(struct ar724x_pci_controller),
371908339efSGabor Juhos GFP_KERNEL);
372908339efSGabor Juhos if (!apc)
373908339efSGabor Juhos return -ENOMEM;
37458d2e9bcSGabor Juhos
375*b0a1c290SZhang Qilong apc->ctrl_base = devm_platform_ioremap_resource_byname(pdev, "ctrl_base");
376f560fabdSSilviu-Mihai Popescu if (IS_ERR(apc->ctrl_base))
377f560fabdSSilviu-Mihai Popescu return PTR_ERR(apc->ctrl_base);
37858d2e9bcSGabor Juhos
379*b0a1c290SZhang Qilong apc->devcfg_base = devm_platform_ioremap_resource_byname(pdev, "cfg_base");
380f560fabdSSilviu-Mihai Popescu if (IS_ERR(apc->devcfg_base))
381f560fabdSSilviu-Mihai Popescu return PTR_ERR(apc->devcfg_base);
38258d2e9bcSGabor Juhos
383*b0a1c290SZhang Qilong apc->crp_base = devm_platform_ioremap_resource_byname(pdev, "crp_base");
384f560fabdSSilviu-Mihai Popescu if (IS_ERR(apc->crp_base))
385f560fabdSSilviu-Mihai Popescu return PTR_ERR(apc->crp_base);
38612401fc2SGabor Juhos
387908339efSGabor Juhos apc->irq = platform_get_irq(pdev, 0);
388908339efSGabor Juhos if (apc->irq < 0)
38958d2e9bcSGabor Juhos return -EINVAL;
39058d2e9bcSGabor Juhos
39134b134aeSGabor Juhos res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base");
39234b134aeSGabor Juhos if (!res)
39334b134aeSGabor Juhos return -EINVAL;
39434b134aeSGabor Juhos
39534b134aeSGabor Juhos apc->io_res.parent = res;
39634b134aeSGabor Juhos apc->io_res.name = "PCI IO space";
39734b134aeSGabor Juhos apc->io_res.start = res->start;
39834b134aeSGabor Juhos apc->io_res.end = res->end;
39934b134aeSGabor Juhos apc->io_res.flags = IORESOURCE_IO;
40034b134aeSGabor Juhos
40134b134aeSGabor Juhos res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base");
40234b134aeSGabor Juhos if (!res)
40334b134aeSGabor Juhos return -EINVAL;
40434b134aeSGabor Juhos
40534b134aeSGabor Juhos apc->mem_res.parent = res;
40634b134aeSGabor Juhos apc->mem_res.name = "PCI memory space";
40734b134aeSGabor Juhos apc->mem_res.start = res->start;
40834b134aeSGabor Juhos apc->mem_res.end = res->end;
40934b134aeSGabor Juhos apc->mem_res.flags = IORESOURCE_MEM;
41034b134aeSGabor Juhos
411908339efSGabor Juhos apc->pci_controller.pci_ops = &ar724x_pci_ops;
41234b134aeSGabor Juhos apc->pci_controller.io_resource = &apc->io_res;
41334b134aeSGabor Juhos apc->pci_controller.mem_resource = &apc->mem_res;
414908339efSGabor Juhos
4150316b053SMathias Kresin /*
4160316b053SMathias Kresin * Do the full PCIE Root Complex Initialization Sequence if the PCIe
4170316b053SMathias Kresin * host controller is in reset.
4180316b053SMathias Kresin */
4190316b053SMathias Kresin if (ath79_reset_rr(AR724X_RESET_REG_RESET_MODULE) & AR724X_RESET_PCIE)
4200316b053SMathias Kresin ar724x_pci_hw_init(apc);
4210316b053SMathias Kresin
422908339efSGabor Juhos apc->link_up = ar724x_pci_check_link(apc);
423908339efSGabor Juhos if (!apc->link_up)
42458d2e9bcSGabor Juhos dev_warn(&pdev->dev, "PCIe link is down\n");
42558d2e9bcSGabor Juhos
4268b66d461SGabor Juhos ar724x_pci_irq_init(apc, id);
42758d2e9bcSGabor Juhos
42812401fc2SGabor Juhos ar724x_pci_local_write(apc, PCI_COMMAND, 4, AR724X_PCI_CMD_INIT);
42912401fc2SGabor Juhos
430908339efSGabor Juhos register_pci_controller(&apc->pci_controller);
43158d2e9bcSGabor Juhos
43258d2e9bcSGabor Juhos return 0;
43358d2e9bcSGabor Juhos }
43458d2e9bcSGabor Juhos
43558d2e9bcSGabor Juhos static struct platform_driver ar724x_pci_driver = {
43658d2e9bcSGabor Juhos .probe = ar724x_pci_probe,
43758d2e9bcSGabor Juhos .driver = {
43858d2e9bcSGabor Juhos .name = "ar724x-pci",
43958d2e9bcSGabor Juhos },
44058d2e9bcSGabor Juhos };
44158d2e9bcSGabor Juhos
ar724x_pci_init(void)44258d2e9bcSGabor Juhos static int __init ar724x_pci_init(void)
44358d2e9bcSGabor Juhos {
44458d2e9bcSGabor Juhos return platform_driver_register(&ar724x_pci_driver);
44558d2e9bcSGabor Juhos }
44658d2e9bcSGabor Juhos
44758d2e9bcSGabor Juhos postcore_initcall(ar724x_pci_init);
448