blob: 04f433a823da5b55b5c47b5d0a9e328d8d0bbccd [file] [log] [blame]
Rene Bolldorf4ff40d52011-11-17 14:25:09 +00001/*
2 * Atheros 724x PCI support
3 *
4 * Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
9 */
10
Gabor Juhos4c07c7d2012-03-14 10:36:07 +010011#include <linux/irq.h>
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000012#include <linux/pci.h>
Gabor Juhos6015a852012-03-14 10:36:05 +010013#include <asm/mach-ath79/ath79.h>
Gabor Juhos4c07c7d2012-03-14 10:36:07 +010014#include <asm/mach-ath79/ar71xx_regs.h>
Gabor Juhos659243c2012-03-14 10:29:23 +010015#include <asm/mach-ath79/pci.h>
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000016
Gabor Juhosc1984412012-03-14 10:29:27 +010017#define AR724X_PCI_CFG_BASE 0x14000000
18#define AR724X_PCI_CFG_SIZE 0x1000
Gabor Juhos4c07c7d2012-03-14 10:36:07 +010019#define AR724X_PCI_CTRL_BASE (AR71XX_APB_BASE + 0x000f0000)
20#define AR724X_PCI_CTRL_SIZE 0x100
21
Gabor Juhosd624bd32012-03-14 10:29:26 +010022#define AR724X_PCI_MEM_BASE 0x10000000
23#define AR724X_PCI_MEM_SIZE 0x08000000
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000024
Gabor Juhos4c07c7d2012-03-14 10:36:07 +010025#define AR724X_PCI_REG_INT_STATUS 0x4c
26#define AR724X_PCI_REG_INT_MASK 0x50
27
28#define AR724X_PCI_INT_DEV0 BIT(14)
29
30#define AR724X_PCI_IRQ_COUNT 1
31
Gabor Juhos6015a852012-03-14 10:36:05 +010032#define AR7240_BAR0_WAR_VALUE 0xffff
33
Gabor Juhosd624bd32012-03-14 10:29:26 +010034static DEFINE_SPINLOCK(ar724x_pci_lock);
Gabor Juhosc1984412012-03-14 10:29:27 +010035static void __iomem *ar724x_pci_devcfg_base;
Gabor Juhos4c07c7d2012-03-14 10:36:07 +010036static void __iomem *ar724x_pci_ctrl_base;
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000037
Gabor Juhos6015a852012-03-14 10:36:05 +010038static u32 ar724x_pci_bar0_value;
39static bool ar724x_pci_bar0_is_cached;
40
Gabor Juhosd624bd32012-03-14 10:29:26 +010041static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000042 int size, uint32_t *value)
43{
Gabor Juhos64adb6b2012-03-14 10:36:04 +010044 unsigned long flags;
Gabor Juhosc1984412012-03-14 10:29:27 +010045 void __iomem *base;
Gabor Juhos64adb6b2012-03-14 10:36:04 +010046 u32 data;
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000047
48 if (devfn)
49 return PCIBIOS_DEVICE_NOT_FOUND;
50
Gabor Juhosc1984412012-03-14 10:29:27 +010051 base = ar724x_pci_devcfg_base;
52
Gabor Juhosd624bd32012-03-14 10:29:26 +010053 spin_lock_irqsave(&ar724x_pci_lock, flags);
Gabor Juhos64adb6b2012-03-14 10:36:04 +010054 data = __raw_readl(base + (where & ~3));
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000055
56 switch (size) {
57 case 1:
Gabor Juhos64adb6b2012-03-14 10:36:04 +010058 if (where & 1)
59 data >>= 8;
60 if (where & 2)
61 data >>= 16;
62 data &= 0xff;
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000063 break;
64 case 2:
Gabor Juhos64adb6b2012-03-14 10:36:04 +010065 if (where & 2)
66 data >>= 16;
67 data &= 0xffff;
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000068 break;
69 case 4:
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000070 break;
71 default:
Gabor Juhosd624bd32012-03-14 10:29:26 +010072 spin_unlock_irqrestore(&ar724x_pci_lock, flags);
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000073
74 return PCIBIOS_BAD_REGISTER_NUMBER;
75 }
76
Gabor Juhosd624bd32012-03-14 10:29:26 +010077 spin_unlock_irqrestore(&ar724x_pci_lock, flags);
Gabor Juhos6015a852012-03-14 10:36:05 +010078
79 if (where == PCI_BASE_ADDRESS_0 && size == 4 &&
80 ar724x_pci_bar0_is_cached) {
81 /* use the cached value */
82 *value = ar724x_pci_bar0_value;
83 } else {
84 *value = data;
85 }
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000086
87 return PCIBIOS_SUCCESSFUL;
88}
89
Gabor Juhosd624bd32012-03-14 10:29:26 +010090static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000091 int size, uint32_t value)
92{
Gabor Juhos64adb6b2012-03-14 10:36:04 +010093 unsigned long flags;
Gabor Juhosc1984412012-03-14 10:29:27 +010094 void __iomem *base;
Gabor Juhos64adb6b2012-03-14 10:36:04 +010095 u32 data;
96 int s;
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000097
98 if (devfn)
99 return PCIBIOS_DEVICE_NOT_FOUND;
100
Gabor Juhos6015a852012-03-14 10:36:05 +0100101 if (soc_is_ar7240() && where == PCI_BASE_ADDRESS_0 && size == 4) {
102 if (value != 0xffffffff) {
103 /*
104 * WAR for a hw issue. If the BAR0 register of the
105 * device is set to the proper base address, the
106 * memory space of the device is not accessible.
107 *
108 * Cache the intended value so it can be read back,
109 * and write a SoC specific constant value to the
110 * BAR0 register in order to make the device memory
111 * accessible.
112 */
113 ar724x_pci_bar0_is_cached = true;
114 ar724x_pci_bar0_value = value;
115
116 value = AR7240_BAR0_WAR_VALUE;
117 } else {
118 ar724x_pci_bar0_is_cached = false;
119 }
120 }
121
Gabor Juhosc1984412012-03-14 10:29:27 +0100122 base = ar724x_pci_devcfg_base;
123
Gabor Juhosd624bd32012-03-14 10:29:26 +0100124 spin_lock_irqsave(&ar724x_pci_lock, flags);
Gabor Juhos64adb6b2012-03-14 10:36:04 +0100125 data = __raw_readl(base + (where & ~3));
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000126
127 switch (size) {
128 case 1:
Gabor Juhos64adb6b2012-03-14 10:36:04 +0100129 s = ((where & 3) * 8);
130 data &= ~(0xff << s);
131 data |= ((value & 0xff) << s);
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000132 break;
133 case 2:
Gabor Juhos64adb6b2012-03-14 10:36:04 +0100134 s = ((where & 2) * 8);
135 data &= ~(0xffff << s);
136 data |= ((value & 0xffff) << s);
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000137 break;
138 case 4:
Gabor Juhos64adb6b2012-03-14 10:36:04 +0100139 data = value;
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000140 break;
141 default:
Gabor Juhosd624bd32012-03-14 10:29:26 +0100142 spin_unlock_irqrestore(&ar724x_pci_lock, flags);
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000143
144 return PCIBIOS_BAD_REGISTER_NUMBER;
145 }
146
Gabor Juhos64adb6b2012-03-14 10:36:04 +0100147 __raw_writel(data, base + (where & ~3));
148 /* flush write */
149 __raw_readl(base + (where & ~3));
Gabor Juhosd624bd32012-03-14 10:29:26 +0100150 spin_unlock_irqrestore(&ar724x_pci_lock, flags);
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000151
152 return PCIBIOS_SUCCESSFUL;
153}
154
Gabor Juhosd624bd32012-03-14 10:29:26 +0100155static struct pci_ops ar724x_pci_ops = {
156 .read = ar724x_pci_read,
157 .write = ar724x_pci_write,
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000158};
159
Gabor Juhosd624bd32012-03-14 10:29:26 +0100160static struct resource ar724x_io_resource = {
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000161 .name = "PCI IO space",
162 .start = 0,
163 .end = 0,
164 .flags = IORESOURCE_IO,
165};
166
Gabor Juhosd624bd32012-03-14 10:29:26 +0100167static struct resource ar724x_mem_resource = {
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000168 .name = "PCI memory space",
Gabor Juhosd624bd32012-03-14 10:29:26 +0100169 .start = AR724X_PCI_MEM_BASE,
170 .end = AR724X_PCI_MEM_BASE + AR724X_PCI_MEM_SIZE - 1,
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000171 .flags = IORESOURCE_MEM,
172};
173
Gabor Juhosd624bd32012-03-14 10:29:26 +0100174static struct pci_controller ar724x_pci_controller = {
175 .pci_ops = &ar724x_pci_ops,
176 .io_resource = &ar724x_io_resource,
177 .mem_resource = &ar724x_mem_resource,
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000178};
179
Gabor Juhos4c07c7d2012-03-14 10:36:07 +0100180static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000181{
Gabor Juhos4c07c7d2012-03-14 10:36:07 +0100182 void __iomem *base;
183 u32 pending;
184
185 base = ar724x_pci_ctrl_base;
186
187 pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) &
188 __raw_readl(base + AR724X_PCI_REG_INT_MASK);
189
190 if (pending & AR724X_PCI_INT_DEV0)
191 generic_handle_irq(ATH79_PCI_IRQ(0));
192
193 else
194 spurious_interrupt();
195}
196
197static void ar724x_pci_irq_unmask(struct irq_data *d)
198{
199 void __iomem *base;
200 u32 t;
201
202 base = ar724x_pci_ctrl_base;
203
204 switch (d->irq) {
205 case ATH79_PCI_IRQ(0):
206 t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
207 __raw_writel(t | AR724X_PCI_INT_DEV0,
208 base + AR724X_PCI_REG_INT_MASK);
209 /* flush write */
210 __raw_readl(base + AR724X_PCI_REG_INT_MASK);
211 }
212}
213
214static void ar724x_pci_irq_mask(struct irq_data *d)
215{
216 void __iomem *base;
217 u32 t;
218
219 base = ar724x_pci_ctrl_base;
220
221 switch (d->irq) {
222 case ATH79_PCI_IRQ(0):
223 t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
224 __raw_writel(t & ~AR724X_PCI_INT_DEV0,
225 base + AR724X_PCI_REG_INT_MASK);
226
227 /* flush write */
228 __raw_readl(base + AR724X_PCI_REG_INT_MASK);
229
230 t = __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
231 __raw_writel(t | AR724X_PCI_INT_DEV0,
232 base + AR724X_PCI_REG_INT_STATUS);
233
234 /* flush write */
235 __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
236 }
237}
238
239static struct irq_chip ar724x_pci_irq_chip = {
240 .name = "AR724X PCI ",
241 .irq_mask = ar724x_pci_irq_mask,
242 .irq_unmask = ar724x_pci_irq_unmask,
243 .irq_mask_ack = ar724x_pci_irq_mask,
244};
245
246static void __init ar724x_pci_irq_init(int irq)
247{
248 void __iomem *base;
249 int i;
250
251 base = ar724x_pci_ctrl_base;
252
253 __raw_writel(0, base + AR724X_PCI_REG_INT_MASK);
254 __raw_writel(0, base + AR724X_PCI_REG_INT_STATUS);
255
256 BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR724X_PCI_IRQ_COUNT);
257
258 for (i = ATH79_PCI_IRQ_BASE;
259 i < ATH79_PCI_IRQ_BASE + AR724X_PCI_IRQ_COUNT; i++)
260 irq_set_chip_and_handler(i, &ar724x_pci_irq_chip,
261 handle_level_irq);
262
263 irq_set_chained_handler(irq, ar724x_pci_irq_handler);
264}
265
266int __init ar724x_pcibios_init(int irq)
267{
268 int ret;
269
270 ret = -ENOMEM;
271
Gabor Juhosc1984412012-03-14 10:29:27 +0100272 ar724x_pci_devcfg_base = ioremap(AR724X_PCI_CFG_BASE,
273 AR724X_PCI_CFG_SIZE);
274 if (ar724x_pci_devcfg_base == NULL)
Gabor Juhos4c07c7d2012-03-14 10:36:07 +0100275 goto err;
Gabor Juhosc1984412012-03-14 10:29:27 +0100276
Gabor Juhos4c07c7d2012-03-14 10:36:07 +0100277 ar724x_pci_ctrl_base = ioremap(AR724X_PCI_CTRL_BASE,
278 AR724X_PCI_CTRL_SIZE);
279 if (ar724x_pci_ctrl_base == NULL)
280 goto err_unmap_devcfg;
281
282 ar724x_pci_irq_init(irq);
Gabor Juhosd624bd32012-03-14 10:29:26 +0100283 register_pci_controller(&ar724x_pci_controller);
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000284
285 return PCIBIOS_SUCCESSFUL;
Gabor Juhos4c07c7d2012-03-14 10:36:07 +0100286
287err_unmap_devcfg:
288 iounmap(ar724x_pci_devcfg_base);
289err:
290 return ret;
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000291}