Root/target/linux/ar71xx/patches-3.3/109-MIPS-ath79-add-a-workaround-for-a-PCI-controller-bug.patch

1From 14eaf9b1cda516b4182e56f61c21fa2eaa9ade6b Mon Sep 17 00:00:00 2001
2From: Gabor Juhos <juhosg@openwrt.org>
3Date: Wed, 14 Mar 2012 10:36:05 +0100
4Subject: [PATCH 14/47] MIPS: ath79: add a workaround for a PCI controller bug in AR7240 SoCs
5
6The PCI controller of the AR724X SoCs has a hardware
7bag. If the BAR0 register of the PCI device is set to
8the proper base address, the memory address space of
9the device is not accessible.
10
11When the device driver tries to access the memory
12address space of the PCI device, it leads to data
13bus error, similiar to this:
14
15Data bus error, epc == 801f69a0, ra == 801f698c
16Oops[#1]:
17Cpu 0
18$ 0 : 00000000 00000061 deadbeef 000000ff
19$ 4 : 00000000 000000ff 00000014 00000000
20$ 8 : ff000000 fffffffc 00000000 00000000
21$12 : 000001f5 00000006 00000000 6e637920
22$16 : 81ca4000 81ca0260 81ca4000 804d70f0
23$20 : fffffff4 0000002b 803ad4c4 00000000
24$24 : 00000003 00000000
25$28 : 81c20000 81c21c60 00000000 801f698c
26Hi : 00000000
27Lo : 00000000
28epc : 801f69a0 ath9k_hw_init+0xd0/0xa70
29    Not tainted
30ra : 801f698c ath9k_hw_init+0xbc/0xa70
31Status: 1000c103 KERNEL EXL IE
32Cause : 1080001c
33PrId : 00019374 (MIPS 24Kc)
34Modules linked in:
35Process swapper (pid: 1, threadinfo=81c20000, task=81c18000, tls=00000000)
36Stack : 00000000 00000000 00000000 00000000 81c21c78 81ca0260 00000000 804d70f0
37        81ca0260 81c21cc0 81ca0e80 81ca0260 81ca4000 804d70f0 fffffff4 0000002b
38        803ad4c4 00000000 00000000 801e3ae8 81c9d080 81ca0e80 b0000000 800b9b9c
39        00000008 81c9d000 8031aeb0 802d38a0 00000000 81c14c00 81c14c60 00000000
40        81ca0e80 81ca0260 b0000000 801f08a4 81c9c820 81c21d48 81c9c820 80144320
41        ...
42Call Trace:
43[<801f69a0>] ath9k_hw_init+0xd0/0xa70
44[<801e3ae8>] ath9k_init_device+0x174/0x680
45[<801f08a4>] ath_pci_probe+0x27c/0x380
46[<8019e490>] pci_device_probe+0x74/0x9c
47[<801bfadc>] driver_probe_device+0x9c/0x1b4
48[<801bfcb0>] __driver_attach+0xbc/0xc4
49[<801bea0c>] bus_for_each_dev+0x5c/0x98
50[<801bf394>] bus_add_driver+0x1d0/0x2a4
51[<801c0364>] driver_register+0x8c/0x16c
52[<8019e72c>] __pci_register_driver+0x4c/0xe4
53[<803d3d40>] ath9k_init+0x3c/0x88
54[<80060930>] do_one_initcall+0x3c/0x1cc
55[<803c297c>] kernel_init+0xa4/0x138
56[<80063c04>] kernel_thread_helper+0x10/0x18
57
58Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
59Cc: linux-mips@linux-mips.org
60Patchwork: https://patchwork.linux-mips.org/patch/3494/
61Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
62---
63 arch/mips/pci/pci-ar724x.c | 36 +++++++++++++++++++++++++++++++++++-
64 1 files changed, 35 insertions(+), 1 deletions(-)
65
66--- a/arch/mips/pci/pci-ar724x.c
67+++ b/arch/mips/pci/pci-ar724x.c
68@@ -9,6 +9,7 @@
69  */
70 
71 #include <linux/pci.h>
72+#include <asm/mach-ath79/ath79.h>
73 #include <asm/mach-ath79/pci.h>
74 
75 #define AR724X_PCI_CFG_BASE 0x14000000
76@@ -16,9 +17,14 @@
77 #define AR724X_PCI_MEM_BASE 0x10000000
78 #define AR724X_PCI_MEM_SIZE 0x08000000
79 
80+#define AR7240_BAR0_WAR_VALUE 0xffff
81+
82 static DEFINE_SPINLOCK(ar724x_pci_lock);
83 static void __iomem *ar724x_pci_devcfg_base;
84 
85+static u32 ar724x_pci_bar0_value;
86+static bool ar724x_pci_bar0_is_cached;
87+
88 static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
89                 int size, uint32_t *value)
90 {
91@@ -56,7 +62,14 @@ static int ar724x_pci_read(struct pci_bu
92     }
93 
94     spin_unlock_irqrestore(&ar724x_pci_lock, flags);
95- *value = data;
96+
97+ if (where == PCI_BASE_ADDRESS_0 && size == 4 &&
98+ ar724x_pci_bar0_is_cached) {
99+ /* use the cached value */
100+ *value = ar724x_pci_bar0_value;
101+ } else {
102+ *value = data;
103+ }
104 
105     return PCIBIOS_SUCCESSFUL;
106 }
107@@ -72,6 +85,27 @@ static int ar724x_pci_write(struct pci_b
108     if (devfn)
109         return PCIBIOS_DEVICE_NOT_FOUND;
110 
111+ if (soc_is_ar7240() && where == PCI_BASE_ADDRESS_0 && size == 4) {
112+ if (value != 0xffffffff) {
113+ /*
114+ * WAR for a hw issue. If the BAR0 register of the
115+ * device is set to the proper base address, the
116+ * memory space of the device is not accessible.
117+ *
118+ * Cache the intended value so it can be read back,
119+ * and write a SoC specific constant value to the
120+ * BAR0 register in order to make the device memory
121+ * accessible.
122+ */
123+ ar724x_pci_bar0_is_cached = true;
124+ ar724x_pci_bar0_value = value;
125+
126+ value = AR7240_BAR0_WAR_VALUE;
127+ } else {
128+ ar724x_pci_bar0_is_cached = false;
129+ }
130+ }
131+
132     base = ar724x_pci_devcfg_base;
133 
134     spin_lock_irqsave(&ar724x_pci_lock, flags);
135

Archive Download this file



interactive