Commit | Line | Data |
---|---|---|
f8365ec4 GJ |
1 | /* |
2 | * Atheros AR71xx PCI host controller driver | |
3 | * | |
4 | * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> | |
5 | * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> | |
6 | * | |
7 | * Parts of this file are based on Atheros' 2.6.15 BSP | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify it | |
10 | * under the terms of the GNU General Public License version 2 as published | |
11 | * by the Free Software Foundation. | |
12 | */ | |
13 | ||
14 | #include <linux/resource.h> | |
15 | #include <linux/types.h> | |
16 | #include <linux/delay.h> | |
17 | #include <linux/bitops.h> | |
18 | #include <linux/pci.h> | |
19 | #include <linux/pci_regs.h> | |
20 | #include <linux/interrupt.h> | |
fb167e89 GJ |
21 | #include <linux/module.h> |
22 | #include <linux/platform_device.h> | |
f8365ec4 GJ |
23 | |
24 | #include <asm/mach-ath79/ar71xx_regs.h> | |
25 | #include <asm/mach-ath79/ath79.h> | |
26 | #include <asm/mach-ath79/pci.h> | |
27 | ||
f8365ec4 GJ |
28 | #define AR71XX_PCI_REG_CRP_AD_CBE 0x00 |
29 | #define AR71XX_PCI_REG_CRP_WRDATA 0x04 | |
30 | #define AR71XX_PCI_REG_CRP_RDDATA 0x08 | |
31 | #define AR71XX_PCI_REG_CFG_AD 0x0c | |
32 | #define AR71XX_PCI_REG_CFG_CBE 0x10 | |
33 | #define AR71XX_PCI_REG_CFG_WRDATA 0x14 | |
34 | #define AR71XX_PCI_REG_CFG_RDDATA 0x18 | |
35 | #define AR71XX_PCI_REG_PCI_ERR 0x1c | |
36 | #define AR71XX_PCI_REG_PCI_ERR_ADDR 0x20 | |
37 | #define AR71XX_PCI_REG_AHB_ERR 0x24 | |
38 | #define AR71XX_PCI_REG_AHB_ERR_ADDR 0x28 | |
39 | ||
40 | #define AR71XX_PCI_CRP_CMD_WRITE 0x00010000 | |
41 | #define AR71XX_PCI_CRP_CMD_READ 0x00000000 | |
42 | #define AR71XX_PCI_CFG_CMD_READ 0x0000000a | |
43 | #define AR71XX_PCI_CFG_CMD_WRITE 0x0000000b | |
44 | ||
45 | #define AR71XX_PCI_INT_CORE BIT(4) | |
46 | #define AR71XX_PCI_INT_DEV2 BIT(2) | |
47 | #define AR71XX_PCI_INT_DEV1 BIT(1) | |
48 | #define AR71XX_PCI_INT_DEV0 BIT(0) | |
49 | ||
50 | #define AR71XX_PCI_IRQ_COUNT 5 | |
51 | ||
52 | static DEFINE_SPINLOCK(ar71xx_pci_lock); | |
53 | static void __iomem *ar71xx_pcicfg_base; | |
54 | ||
55 | /* Byte lane enable bits */ | |
56 | static const u8 ar71xx_pci_ble_table[4][4] = { | |
57 | {0x0, 0xf, 0xf, 0xf}, | |
58 | {0xe, 0xd, 0xb, 0x7}, | |
59 | {0xc, 0xf, 0x3, 0xf}, | |
60 | {0xf, 0xf, 0xf, 0xf}, | |
61 | }; | |
62 | ||
63 | static const u32 ar71xx_pci_read_mask[8] = { | |
64 | 0, 0xff, 0xffff, 0, 0xffffffff, 0, 0, 0 | |
65 | }; | |
66 | ||
67 | static inline u32 ar71xx_pci_get_ble(int where, int size, int local) | |
68 | { | |
69 | u32 t; | |
70 | ||
71 | t = ar71xx_pci_ble_table[size & 3][where & 3]; | |
72 | BUG_ON(t == 0xf); | |
73 | t <<= (local) ? 20 : 4; | |
74 | ||
75 | return t; | |
76 | } | |
77 | ||
78 | static inline u32 ar71xx_pci_bus_addr(struct pci_bus *bus, unsigned int devfn, | |
79 | int where) | |
80 | { | |
81 | u32 ret; | |
82 | ||
83 | if (!bus->number) { | |
84 | /* type 0 */ | |
85 | ret = (1 << PCI_SLOT(devfn)) | (PCI_FUNC(devfn) << 8) | | |
86 | (where & ~3); | |
87 | } else { | |
88 | /* type 1 */ | |
89 | ret = (bus->number << 16) | (PCI_SLOT(devfn) << 11) | | |
90 | (PCI_FUNC(devfn) << 8) | (where & ~3) | 1; | |
91 | } | |
92 | ||
93 | return ret; | |
94 | } | |
95 | ||
96 | static int ar71xx_pci_check_error(int quiet) | |
97 | { | |
98 | void __iomem *base = ar71xx_pcicfg_base; | |
99 | u32 pci_err; | |
100 | u32 ahb_err; | |
101 | ||
102 | pci_err = __raw_readl(base + AR71XX_PCI_REG_PCI_ERR) & 3; | |
103 | if (pci_err) { | |
104 | if (!quiet) { | |
105 | u32 addr; | |
106 | ||
107 | addr = __raw_readl(base + AR71XX_PCI_REG_PCI_ERR_ADDR); | |
108 | pr_crit("ar71xx: %s bus error %d at addr 0x%x\n", | |
109 | "PCI", pci_err, addr); | |
110 | } | |
111 | ||
112 | /* clear PCI error status */ | |
113 | __raw_writel(pci_err, base + AR71XX_PCI_REG_PCI_ERR); | |
114 | } | |
115 | ||
116 | ahb_err = __raw_readl(base + AR71XX_PCI_REG_AHB_ERR) & 1; | |
117 | if (ahb_err) { | |
118 | if (!quiet) { | |
119 | u32 addr; | |
120 | ||
121 | addr = __raw_readl(base + AR71XX_PCI_REG_AHB_ERR_ADDR); | |
122 | pr_crit("ar71xx: %s bus error %d at addr 0x%x\n", | |
123 | "AHB", ahb_err, addr); | |
124 | } | |
125 | ||
126 | /* clear AHB error status */ | |
127 | __raw_writel(ahb_err, base + AR71XX_PCI_REG_AHB_ERR); | |
128 | } | |
129 | ||
130 | return !!(ahb_err | pci_err); | |
131 | } | |
132 | ||
133 | static inline void ar71xx_pci_local_write(int where, int size, u32 value) | |
134 | { | |
135 | void __iomem *base = ar71xx_pcicfg_base; | |
136 | u32 ad_cbe; | |
137 | ||
138 | value = value << (8 * (where & 3)); | |
139 | ||
140 | ad_cbe = AR71XX_PCI_CRP_CMD_WRITE | (where & ~3); | |
141 | ad_cbe |= ar71xx_pci_get_ble(where, size, 1); | |
142 | ||
143 | __raw_writel(ad_cbe, base + AR71XX_PCI_REG_CRP_AD_CBE); | |
144 | __raw_writel(value, base + AR71XX_PCI_REG_CRP_WRDATA); | |
145 | } | |
146 | ||
147 | static inline int ar71xx_pci_set_cfgaddr(struct pci_bus *bus, | |
148 | unsigned int devfn, | |
149 | int where, int size, u32 cmd) | |
150 | { | |
151 | void __iomem *base = ar71xx_pcicfg_base; | |
152 | u32 addr; | |
153 | ||
154 | addr = ar71xx_pci_bus_addr(bus, devfn, where); | |
155 | ||
156 | __raw_writel(addr, base + AR71XX_PCI_REG_CFG_AD); | |
157 | __raw_writel(cmd | ar71xx_pci_get_ble(where, size, 0), | |
158 | base + AR71XX_PCI_REG_CFG_CBE); | |
159 | ||
160 | return ar71xx_pci_check_error(1); | |
161 | } | |
162 | ||
163 | static int ar71xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, | |
164 | int where, int size, u32 *value) | |
165 | { | |
166 | void __iomem *base = ar71xx_pcicfg_base; | |
167 | unsigned long flags; | |
168 | u32 data; | |
169 | int err; | |
170 | int ret; | |
171 | ||
172 | ret = PCIBIOS_SUCCESSFUL; | |
173 | data = ~0; | |
174 | ||
175 | spin_lock_irqsave(&ar71xx_pci_lock, flags); | |
176 | ||
177 | err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size, | |
178 | AR71XX_PCI_CFG_CMD_READ); | |
179 | if (err) | |
180 | ret = PCIBIOS_DEVICE_NOT_FOUND; | |
181 | else | |
182 | data = __raw_readl(base + AR71XX_PCI_REG_CFG_RDDATA); | |
183 | ||
184 | spin_unlock_irqrestore(&ar71xx_pci_lock, flags); | |
185 | ||
186 | *value = (data >> (8 * (where & 3))) & ar71xx_pci_read_mask[size & 7]; | |
187 | ||
188 | return ret; | |
189 | } | |
190 | ||
191 | static int ar71xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, | |
192 | int where, int size, u32 value) | |
193 | { | |
194 | void __iomem *base = ar71xx_pcicfg_base; | |
195 | unsigned long flags; | |
196 | int err; | |
197 | int ret; | |
198 | ||
199 | value = value << (8 * (where & 3)); | |
200 | ret = PCIBIOS_SUCCESSFUL; | |
201 | ||
202 | spin_lock_irqsave(&ar71xx_pci_lock, flags); | |
203 | ||
204 | err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size, | |
205 | AR71XX_PCI_CFG_CMD_WRITE); | |
206 | if (err) | |
207 | ret = PCIBIOS_DEVICE_NOT_FOUND; | |
208 | else | |
209 | __raw_writel(value, base + AR71XX_PCI_REG_CFG_WRDATA); | |
210 | ||
211 | spin_unlock_irqrestore(&ar71xx_pci_lock, flags); | |
212 | ||
213 | return ret; | |
214 | } | |
215 | ||
216 | static struct pci_ops ar71xx_pci_ops = { | |
217 | .read = ar71xx_pci_read_config, | |
218 | .write = ar71xx_pci_write_config, | |
219 | }; | |
220 | ||
221 | static struct resource ar71xx_pci_io_resource = { | |
222 | .name = "PCI IO space", | |
223 | .start = 0, | |
224 | .end = 0, | |
225 | .flags = IORESOURCE_IO, | |
226 | }; | |
227 | ||
228 | static struct resource ar71xx_pci_mem_resource = { | |
229 | .name = "PCI memory space", | |
230 | .start = AR71XX_PCI_MEM_BASE, | |
231 | .end = AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1, | |
232 | .flags = IORESOURCE_MEM | |
233 | }; | |
234 | ||
235 | static struct pci_controller ar71xx_pci_controller = { | |
236 | .pci_ops = &ar71xx_pci_ops, | |
237 | .mem_resource = &ar71xx_pci_mem_resource, | |
238 | .io_resource = &ar71xx_pci_io_resource, | |
239 | }; | |
240 | ||
241 | static void ar71xx_pci_irq_handler(unsigned int irq, struct irq_desc *desc) | |
242 | { | |
243 | void __iomem *base = ath79_reset_base; | |
244 | u32 pending; | |
245 | ||
246 | pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) & | |
247 | __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); | |
248 | ||
249 | if (pending & AR71XX_PCI_INT_DEV0) | |
250 | generic_handle_irq(ATH79_PCI_IRQ(0)); | |
251 | ||
252 | else if (pending & AR71XX_PCI_INT_DEV1) | |
253 | generic_handle_irq(ATH79_PCI_IRQ(1)); | |
254 | ||
255 | else if (pending & AR71XX_PCI_INT_DEV2) | |
256 | generic_handle_irq(ATH79_PCI_IRQ(2)); | |
257 | ||
258 | else if (pending & AR71XX_PCI_INT_CORE) | |
259 | generic_handle_irq(ATH79_PCI_IRQ(4)); | |
260 | ||
261 | else | |
262 | spurious_interrupt(); | |
263 | } | |
264 | ||
265 | static void ar71xx_pci_irq_unmask(struct irq_data *d) | |
266 | { | |
267 | unsigned int irq = d->irq - ATH79_PCI_IRQ_BASE; | |
268 | void __iomem *base = ath79_reset_base; | |
269 | u32 t; | |
270 | ||
271 | t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); | |
272 | __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); | |
273 | ||
274 | /* flush write */ | |
275 | __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); | |
276 | } | |
277 | ||
278 | static void ar71xx_pci_irq_mask(struct irq_data *d) | |
279 | { | |
280 | unsigned int irq = d->irq - ATH79_PCI_IRQ_BASE; | |
281 | void __iomem *base = ath79_reset_base; | |
282 | u32 t; | |
283 | ||
284 | t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); | |
285 | __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); | |
286 | ||
287 | /* flush write */ | |
288 | __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); | |
289 | } | |
290 | ||
291 | static struct irq_chip ar71xx_pci_irq_chip = { | |
292 | .name = "AR71XX PCI", | |
293 | .irq_mask = ar71xx_pci_irq_mask, | |
294 | .irq_unmask = ar71xx_pci_irq_unmask, | |
295 | .irq_mask_ack = ar71xx_pci_irq_mask, | |
296 | }; | |
297 | ||
fb167e89 | 298 | static void ar71xx_pci_irq_init(int irq) |
f8365ec4 GJ |
299 | { |
300 | void __iomem *base = ath79_reset_base; | |
301 | int i; | |
302 | ||
303 | __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_ENABLE); | |
304 | __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_STATUS); | |
305 | ||
306 | BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR71XX_PCI_IRQ_COUNT); | |
307 | ||
308 | for (i = ATH79_PCI_IRQ_BASE; | |
309 | i < ATH79_PCI_IRQ_BASE + AR71XX_PCI_IRQ_COUNT; i++) | |
310 | irq_set_chip_and_handler(i, &ar71xx_pci_irq_chip, | |
311 | handle_level_irq); | |
312 | ||
fb167e89 | 313 | irq_set_chained_handler(irq, ar71xx_pci_irq_handler); |
f8365ec4 GJ |
314 | } |
315 | ||
fb167e89 | 316 | static void ar71xx_pci_reset(void) |
f8365ec4 GJ |
317 | { |
318 | void __iomem *ddr_base = ath79_ddr_base; | |
319 | ||
320 | ath79_device_reset_set(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE); | |
321 | mdelay(100); | |
322 | ||
323 | ath79_device_reset_clear(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE); | |
324 | mdelay(100); | |
325 | ||
326 | __raw_writel(AR71XX_PCI_WIN0_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN0); | |
327 | __raw_writel(AR71XX_PCI_WIN1_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN1); | |
328 | __raw_writel(AR71XX_PCI_WIN2_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN2); | |
329 | __raw_writel(AR71XX_PCI_WIN3_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN3); | |
330 | __raw_writel(AR71XX_PCI_WIN4_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN4); | |
331 | __raw_writel(AR71XX_PCI_WIN5_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN5); | |
332 | __raw_writel(AR71XX_PCI_WIN6_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN6); | |
333 | __raw_writel(AR71XX_PCI_WIN7_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN7); | |
334 | ||
335 | mdelay(100); | |
336 | } | |
337 | ||
338 | __init int ar71xx_pcibios_init(void) | |
339 | { | |
340 | u32 t; | |
341 | ||
342 | ar71xx_pcicfg_base = ioremap(AR71XX_PCI_CFG_BASE, AR71XX_PCI_CFG_SIZE); | |
343 | if (ar71xx_pcicfg_base == NULL) | |
344 | return -ENOMEM; | |
345 | ||
346 | ar71xx_pci_reset(); | |
347 | ||
348 | /* setup COMMAND register */ | |
349 | t = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | |
350 | | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK; | |
351 | ar71xx_pci_local_write(PCI_COMMAND, 4, t); | |
352 | ||
353 | /* clear bus errors */ | |
354 | ar71xx_pci_check_error(1); | |
355 | ||
fb167e89 | 356 | ar71xx_pci_irq_init(ATH79_CPU_IRQ_IP2); |
f8365ec4 GJ |
357 | |
358 | register_pci_controller(&ar71xx_pci_controller); | |
359 | ||
360 | return 0; | |
361 | } | |
fb167e89 GJ |
362 | |
363 | static int ar71xx_pci_probe(struct platform_device *pdev) | |
364 | { | |
365 | struct resource *res; | |
366 | int irq; | |
367 | u32 t; | |
368 | ||
369 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base"); | |
370 | if (!res) | |
371 | return -EINVAL; | |
372 | ||
373 | ar71xx_pcicfg_base = devm_request_and_ioremap(&pdev->dev, res); | |
374 | if (!ar71xx_pcicfg_base) | |
375 | return -ENOMEM; | |
376 | ||
377 | irq = platform_get_irq(pdev, 0); | |
378 | if (irq < 0) | |
379 | return -EINVAL; | |
380 | ||
381 | ar71xx_pci_reset(); | |
382 | ||
383 | /* setup COMMAND register */ | |
384 | t = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | |
385 | | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK; | |
386 | ar71xx_pci_local_write(PCI_COMMAND, 4, t); | |
387 | ||
388 | /* clear bus errors */ | |
389 | ar71xx_pci_check_error(1); | |
390 | ||
391 | ar71xx_pci_irq_init(irq); | |
392 | ||
393 | register_pci_controller(&ar71xx_pci_controller); | |
394 | ||
395 | return 0; | |
396 | } | |
397 | ||
398 | static struct platform_driver ar71xx_pci_driver = { | |
399 | .probe = ar71xx_pci_probe, | |
400 | .driver = { | |
401 | .name = "ar71xx-pci", | |
402 | .owner = THIS_MODULE, | |
403 | }, | |
404 | }; | |
405 | ||
406 | static int __init ar71xx_pci_init(void) | |
407 | { | |
408 | return platform_driver_register(&ar71xx_pci_driver); | |
409 | } | |
410 | ||
411 | postcore_initcall(ar71xx_pci_init); |