Root/target/linux/ar71xx/patches-3.3/114-MIPS-ath79-add-support-for-the-PCI-host-controller-o.patch

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

Archive Download this file



interactive