aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGabor Juhos <juhosg@openwrt.org>2013-02-03 09:52:47 -0500
committerJohn Crispin <blogic@openwrt.org>2013-02-16 19:25:39 -0500
commit12401fc28d40aa5bf8bda6991a96b6d7a3dae3ac (patch)
treed882d6fc588107ee1ba9a5c3d92660641451b2df
parent8b66d461187ff61c5755001af7296e6edde48423 (diff)
MIPS: pci-ar724x: setup command register of the PCI controller
The command register of the PCI controller is not initialized correctly by the bootloader on some boards and this leads to non working PCI bus. Add code to initialize the command register from the Linux code to avoid this. Signed-off-by: Gabor Juhos <juhosg@openwrt.org> Patchwork: http://patchwork.linux-mips.org/patch/4916/ Signed-off-by: John Crispin <blogic@openwrt.org>
-rw-r--r--arch/mips/ath79/pci.c10
-rw-r--r--arch/mips/include/asm/mach-ath79/ar71xx_regs.h2
-rw-r--r--arch/mips/pci/pci-ar724x.c63
3 files changed, 74 insertions, 1 deletions
diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c
index 45d1112de50d..942e3f9184f0 100644
--- a/arch/mips/ath79/pci.c
+++ b/arch/mips/ath79/pci.c
@@ -139,13 +139,14 @@ static struct platform_device *
139ath79_register_pci_ar724x(int id, 139ath79_register_pci_ar724x(int id,
140 unsigned long cfg_base, 140 unsigned long cfg_base,
141 unsigned long ctrl_base, 141 unsigned long ctrl_base,
142 unsigned long crp_base,
142 unsigned long mem_base, 143 unsigned long mem_base,
143 unsigned long mem_size, 144 unsigned long mem_size,
144 unsigned long io_base, 145 unsigned long io_base,
145 int irq) 146 int irq)
146{ 147{
147 struct platform_device *pdev; 148 struct platform_device *pdev;
148 struct resource res[5]; 149 struct resource res[6];
149 150
150 memset(res, 0, sizeof(res)); 151 memset(res, 0, sizeof(res));
151 152
@@ -173,6 +174,11 @@ ath79_register_pci_ar724x(int id,
173 res[4].start = io_base; 174 res[4].start = io_base;
174 res[4].end = io_base; 175 res[4].end = io_base;
175 176
177 res[5].name = "crp_base";
178 res[5].flags = IORESOURCE_MEM;
179 res[5].start = crp_base;
180 res[5].end = crp_base + AR724X_PCI_CRP_SIZE - 1;
181
176 pdev = platform_device_register_simple("ar724x-pci", id, 182 pdev = platform_device_register_simple("ar724x-pci", id,
177 res, ARRAY_SIZE(res)); 183 res, ARRAY_SIZE(res));
178 return pdev; 184 return pdev;
@@ -188,6 +194,7 @@ int __init ath79_register_pci(void)
188 pdev = ath79_register_pci_ar724x(-1, 194 pdev = ath79_register_pci_ar724x(-1,
189 AR724X_PCI_CFG_BASE, 195 AR724X_PCI_CFG_BASE,
190 AR724X_PCI_CTRL_BASE, 196 AR724X_PCI_CTRL_BASE,
197 AR724X_PCI_CRP_BASE,
191 AR724X_PCI_MEM_BASE, 198 AR724X_PCI_MEM_BASE,
192 AR724X_PCI_MEM_SIZE, 199 AR724X_PCI_MEM_SIZE,
193 0, 200 0,
@@ -203,6 +210,7 @@ int __init ath79_register_pci(void)
203 pdev = ath79_register_pci_ar724x(-1, 210 pdev = ath79_register_pci_ar724x(-1,
204 AR724X_PCI_CFG_BASE, 211 AR724X_PCI_CFG_BASE,
205 AR724X_PCI_CTRL_BASE, 212 AR724X_PCI_CTRL_BASE,
213 AR724X_PCI_CRP_BASE,
206 AR724X_PCI_MEM_BASE, 214 AR724X_PCI_MEM_BASE,
207 AR724X_PCI_MEM_SIZE, 215 AR724X_PCI_MEM_SIZE,
208 0, 216 0,
diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
index 7c87bfe6e4ff..a77f6ee70ec1 100644
--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
@@ -67,6 +67,8 @@
67 67
68#define AR724X_PCI_CFG_BASE 0x14000000 68#define AR724X_PCI_CFG_BASE 0x14000000
69#define AR724X_PCI_CFG_SIZE 0x1000 69#define AR724X_PCI_CFG_SIZE 0x1000
70#define AR724X_PCI_CRP_BASE (AR71XX_APB_BASE + 0x000c0000)
71#define AR724X_PCI_CRP_SIZE 0x1000
70#define AR724X_PCI_CTRL_BASE (AR71XX_APB_BASE + 0x000f0000) 72#define AR724X_PCI_CTRL_BASE (AR71XX_APB_BASE + 0x000f0000)
71#define AR724X_PCI_CTRL_SIZE 0x100 73#define AR724X_PCI_CTRL_SIZE 0x100
72 74
diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
index 0440d8800f8a..8a0700d448fe 100644
--- a/arch/mips/pci/pci-ar724x.c
+++ b/arch/mips/pci/pci-ar724x.c
@@ -29,9 +29,17 @@
29 29
30#define AR7240_BAR0_WAR_VALUE 0xffff 30#define AR7240_BAR0_WAR_VALUE 0xffff
31 31
32#define AR724X_PCI_CMD_INIT (PCI_COMMAND_MEMORY | \
33 PCI_COMMAND_MASTER | \
34 PCI_COMMAND_INVALIDATE | \
35 PCI_COMMAND_PARITY | \
36 PCI_COMMAND_SERR | \
37 PCI_COMMAND_FAST_BACK)
38
32struct ar724x_pci_controller { 39struct ar724x_pci_controller {
33 void __iomem *devcfg_base; 40 void __iomem *devcfg_base;
34 void __iomem *ctrl_base; 41 void __iomem *ctrl_base;
42 void __iomem *crp_base;
35 43
36 int irq; 44 int irq;
37 int irq_base; 45 int irq_base;
@@ -64,6 +72,51 @@ pci_bus_to_ar724x_controller(struct pci_bus *bus)
64 return container_of(hose, struct ar724x_pci_controller, pci_controller); 72 return container_of(hose, struct ar724x_pci_controller, pci_controller);
65} 73}
66 74
75static int ar724x_pci_local_write(struct ar724x_pci_controller *apc,
76 int where, int size, u32 value)
77{
78 unsigned long flags;
79 void __iomem *base;
80 u32 data;
81 int s;
82
83 WARN_ON(where & (size - 1));
84
85 if (!apc->link_up)
86 return PCIBIOS_DEVICE_NOT_FOUND;
87
88 base = apc->crp_base;
89
90 spin_lock_irqsave(&apc->lock, flags);
91 data = __raw_readl(base + (where & ~3));
92
93 switch (size) {
94 case 1:
95 s = ((where & 3) * 8);
96 data &= ~(0xff << s);
97 data |= ((value & 0xff) << s);
98 break;
99 case 2:
100 s = ((where & 2) * 8);
101 data &= ~(0xffff << s);
102 data |= ((value & 0xffff) << s);
103 break;
104 case 4:
105 data = value;
106 break;
107 default:
108 spin_unlock_irqrestore(&apc->lock, flags);
109 return PCIBIOS_BAD_REGISTER_NUMBER;
110 }
111
112 __raw_writel(data, base + (where & ~3));
113 /* flush write */
114 __raw_readl(base + (where & ~3));
115 spin_unlock_irqrestore(&apc->lock, flags);
116
117 return PCIBIOS_SUCCESSFUL;
118}
119
67static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, 120static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
68 int size, uint32_t *value) 121 int size, uint32_t *value)
69{ 122{
@@ -324,6 +377,14 @@ static int ar724x_pci_probe(struct platform_device *pdev)
324 if (!apc->devcfg_base) 377 if (!apc->devcfg_base)
325 return -EBUSY; 378 return -EBUSY;
326 379
380 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "crp_base");
381 if (!res)
382 return -EINVAL;
383
384 apc->crp_base = devm_request_and_ioremap(&pdev->dev, res);
385 if (apc->crp_base == NULL)
386 return -EBUSY;
387
327 apc->irq = platform_get_irq(pdev, 0); 388 apc->irq = platform_get_irq(pdev, 0);
328 if (apc->irq < 0) 389 if (apc->irq < 0)
329 return -EINVAL; 390 return -EINVAL;
@@ -360,6 +421,8 @@ static int ar724x_pci_probe(struct platform_device *pdev)
360 421
361 ar724x_pci_irq_init(apc, id); 422 ar724x_pci_irq_init(apc, id);
362 423
424 ar724x_pci_local_write(apc, PCI_COMMAND, 4, AR724X_PCI_CMD_INIT);
425
363 register_pci_controller(&apc->pci_controller); 426 register_pci_controller(&apc->pci_controller);
364 427
365 return 0; 428 return 0;