summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAlban Bedel <albeu@free.fr>2015-04-19 08:30:03 -0400
committerRalf Baechle <ralf@linux-mips.org>2015-06-21 15:53:51 -0400
commit24b0e3e84fbf460ea904f4eb85e414e6001c8f37 (patch)
treed36ca7c03e58d5ecd392d5ad05a939add416d04e /arch
parent626a0695a6d98338063c528d113d9ee4ba00cd78 (diff)
MIPS: ath79: Improve the DDR controller interface
The DDR controller need to be used by the IRQ controller to flush the write buffer of some devices before running the IRQ handler. It is also used by the PCI controller to setup the PCI memory windows. The current interface used to access the DDR controller doesn't provides any useful abstraction and simply rely on a shared global pointer. Replace this by a simple API to setup the PCI memory windows and use the write buffer flush independently of the SoC type. That remove the need for the shared global pointer, simplify the IRQ handler code. [ralf@linux-mips.org: Folded in Alban Bedel's follup fix.] Signed-off-by: Alban Bedel <albeu@free.fr> Cc: linux-mips@linux-mips.org Cc: Andrew Bresticker <abrestic@chromium.org> Cc: Qais Yousef <qais.yousef@imgtec.com> Cc: Wolfram Sang <wsa@the-dreams.de> Cc: Sergey Ryazanov <ryazanov.s.a@gmail.com> Cc: Gabor Juhos <juhosg@openwrt.org> Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/9773/ Patchwork: http://patchwork.linux-mips.org/patch/10543/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/ath79/common.c35
-rw-r--r--arch/mips/ath79/common.h1
-rw-r--r--arch/mips/ath79/irq.c137
-rw-r--r--arch/mips/ath79/setup.c3
-rw-r--r--arch/mips/include/asm/mach-ath79/ath79.h3
-rw-r--r--arch/mips/pci/pci-ar71xx.c12
6 files changed, 66 insertions, 125 deletions
diff --git a/arch/mips/ath79/common.c b/arch/mips/ath79/common.c
index eb3966cd8cfc..3cedd1f95e0f 100644
--- a/arch/mips/ath79/common.c
+++ b/arch/mips/ath79/common.c
@@ -38,11 +38,27 @@ unsigned int ath79_soc_rev;
38void __iomem *ath79_pll_base; 38void __iomem *ath79_pll_base;
39void __iomem *ath79_reset_base; 39void __iomem *ath79_reset_base;
40EXPORT_SYMBOL_GPL(ath79_reset_base); 40EXPORT_SYMBOL_GPL(ath79_reset_base);
41void __iomem *ath79_ddr_base; 41static void __iomem *ath79_ddr_base;
42static void __iomem *ath79_ddr_wb_flush_base;
43static void __iomem *ath79_ddr_pci_win_base;
44
45void ath79_ddr_ctrl_init(void)
46{
47 ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE,
48 AR71XX_DDR_CTRL_SIZE);
49 if (soc_is_ar71xx() || soc_is_ar934x()) {
50 ath79_ddr_wb_flush_base = ath79_ddr_base + 0x9c;
51 ath79_ddr_pci_win_base = ath79_ddr_base + 0x7c;
52 } else {
53 ath79_ddr_wb_flush_base = ath79_ddr_base + 0x7c;
54 ath79_ddr_pci_win_base = 0;
55 }
56}
57EXPORT_SYMBOL_GPL(ath79_ddr_ctrl_init);
42 58
43void ath79_ddr_wb_flush(u32 reg) 59void ath79_ddr_wb_flush(u32 reg)
44{ 60{
45 void __iomem *flush_reg = ath79_ddr_base + reg; 61 void __iomem *flush_reg = ath79_ddr_wb_flush_base + reg;
46 62
47 /* Flush the DDR write buffer. */ 63 /* Flush the DDR write buffer. */
48 __raw_writel(0x1, flush_reg); 64 __raw_writel(0x1, flush_reg);
@@ -56,6 +72,21 @@ void ath79_ddr_wb_flush(u32 reg)
56} 72}
57EXPORT_SYMBOL_GPL(ath79_ddr_wb_flush); 73EXPORT_SYMBOL_GPL(ath79_ddr_wb_flush);
58 74
75void ath79_ddr_set_pci_windows(void)
76{
77 BUG_ON(!ath79_ddr_pci_win_base);
78
79 __raw_writel(AR71XX_PCI_WIN0_OFFS, ath79_ddr_pci_win_base + 0);
80 __raw_writel(AR71XX_PCI_WIN1_OFFS, ath79_ddr_pci_win_base + 1);
81 __raw_writel(AR71XX_PCI_WIN2_OFFS, ath79_ddr_pci_win_base + 2);
82 __raw_writel(AR71XX_PCI_WIN3_OFFS, ath79_ddr_pci_win_base + 3);
83 __raw_writel(AR71XX_PCI_WIN4_OFFS, ath79_ddr_pci_win_base + 4);
84 __raw_writel(AR71XX_PCI_WIN5_OFFS, ath79_ddr_pci_win_base + 5);
85 __raw_writel(AR71XX_PCI_WIN6_OFFS, ath79_ddr_pci_win_base + 6);
86 __raw_writel(AR71XX_PCI_WIN7_OFFS, ath79_ddr_pci_win_base + 7);
87}
88EXPORT_SYMBOL_GPL(ath79_ddr_set_pci_windows);
89
59void ath79_device_reset_set(u32 mask) 90void ath79_device_reset_set(u32 mask)
60{ 91{
61 unsigned long flags; 92 unsigned long flags;
diff --git a/arch/mips/ath79/common.h b/arch/mips/ath79/common.h
index c39de61f9b36..e5ea71277f0c 100644
--- a/arch/mips/ath79/common.h
+++ b/arch/mips/ath79/common.h
@@ -22,6 +22,7 @@
22void ath79_clocks_init(void); 22void ath79_clocks_init(void);
23unsigned long ath79_get_sys_clk_rate(const char *id); 23unsigned long ath79_get_sys_clk_rate(const char *id);
24 24
25void ath79_ddr_ctrl_init(void);
25void ath79_ddr_wb_flush(unsigned int reg); 26void ath79_ddr_wb_flush(unsigned int reg);
26 27
27void ath79_gpio_function_enable(u32 mask); 28void ath79_gpio_function_enable(u32 mask);
diff --git a/arch/mips/ath79/irq.c b/arch/mips/ath79/irq.c
index 6adae366f11a..2c3991a4e512 100644
--- a/arch/mips/ath79/irq.c
+++ b/arch/mips/ath79/irq.c
@@ -24,9 +24,6 @@
24#include <asm/mach-ath79/ar71xx_regs.h> 24#include <asm/mach-ath79/ar71xx_regs.h>
25#include "common.h" 25#include "common.h"
26 26
27static void (*ath79_ip2_handler)(void);
28static void (*ath79_ip3_handler)(void);
29
30static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc) 27static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc)
31{ 28{
32 void __iomem *base = ath79_reset_base; 29 void __iomem *base = ath79_reset_base;
@@ -129,10 +126,10 @@ static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
129 status = ath79_reset_rr(AR934X_RESET_REG_PCIE_WMAC_INT_STATUS); 126 status = ath79_reset_rr(AR934X_RESET_REG_PCIE_WMAC_INT_STATUS);
130 127
131 if (status & AR934X_PCIE_WMAC_INT_PCIE_ALL) { 128 if (status & AR934X_PCIE_WMAC_INT_PCIE_ALL) {
132 ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_PCIE); 129 ath79_ddr_wb_flush(3);
133 generic_handle_irq(ATH79_IP2_IRQ(0)); 130 generic_handle_irq(ATH79_IP2_IRQ(0));
134 } else if (status & AR934X_PCIE_WMAC_INT_WMAC_ALL) { 131 } else if (status & AR934X_PCIE_WMAC_INT_WMAC_ALL) {
135 ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_WMAC); 132 ath79_ddr_wb_flush(4);
136 generic_handle_irq(ATH79_IP2_IRQ(1)); 133 generic_handle_irq(ATH79_IP2_IRQ(1));
137 } else { 134 } else {
138 spurious_interrupt(); 135 spurious_interrupt();
@@ -235,128 +232,50 @@ static void qca955x_irq_init(void)
235 irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch); 232 irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch);
236} 233}
237 234
238asmlinkage void plat_irq_dispatch(void)
239{
240 unsigned long pending;
241
242 pending = read_c0_status() & read_c0_cause() & ST0_IM;
243
244 if (pending & STATUSF_IP7)
245 do_IRQ(ATH79_CPU_IRQ(7));
246
247 else if (pending & STATUSF_IP2)
248 ath79_ip2_handler();
249
250 else if (pending & STATUSF_IP4)
251 do_IRQ(ATH79_CPU_IRQ(4));
252
253 else if (pending & STATUSF_IP5)
254 do_IRQ(ATH79_CPU_IRQ(5));
255
256 else if (pending & STATUSF_IP3)
257 ath79_ip3_handler();
258
259 else if (pending & STATUSF_IP6)
260 do_IRQ(ATH79_CPU_IRQ(6));
261
262 else
263 spurious_interrupt();
264}
265
266/* 235/*
267 * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for 236 * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for
268 * these devices typically allocate coherent DMA memory, however the 237 * these devices typically allocate coherent DMA memory, however the
269 * DMA controller may still have some unsynchronized data in the FIFO. 238 * DMA controller may still have some unsynchronized data in the FIFO.
270 * Issue a flush in the handlers to ensure that the driver sees 239 * Issue a flush in the handlers to ensure that the driver sees
271 * the update. 240 * the update.
241 *
242 * This array map the interrupt lines to the DDR write buffer channels.
272 */ 243 */
273 244
274static void ath79_default_ip2_handler(void) 245static unsigned irq_wb_chan[8] = {
275{ 246 -1, -1, -1, -1, -1, -1, -1, -1,
276 do_IRQ(ATH79_CPU_IRQ(2)); 247};
277}
278
279static void ath79_default_ip3_handler(void)
280{
281 do_IRQ(ATH79_CPU_IRQ(3));
282}
283
284static void ar71xx_ip2_handler(void)
285{
286 ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI);
287 do_IRQ(ATH79_CPU_IRQ(2));
288}
289
290static void ar724x_ip2_handler(void)
291{
292 ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_PCIE);
293 do_IRQ(ATH79_CPU_IRQ(2));
294}
295
296static void ar913x_ip2_handler(void)
297{
298 ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_WMAC);
299 do_IRQ(ATH79_CPU_IRQ(2));
300}
301
302static void ar933x_ip2_handler(void)
303{
304 ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_WMAC);
305 do_IRQ(ATH79_CPU_IRQ(2));
306}
307
308static void ar71xx_ip3_handler(void)
309{
310 ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB);
311 do_IRQ(ATH79_CPU_IRQ(3));
312}
313 248
314static void ar724x_ip3_handler(void) 249asmlinkage void plat_irq_dispatch(void)
315{ 250{
316 ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_USB); 251 unsigned long pending;
317 do_IRQ(ATH79_CPU_IRQ(3)); 252 int irq;
318}
319 253
320static void ar913x_ip3_handler(void) 254 pending = read_c0_status() & read_c0_cause() & ST0_IM;
321{
322 ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_USB);
323 do_IRQ(ATH79_CPU_IRQ(3));
324}
325 255
326static void ar933x_ip3_handler(void) 256 if (!pending) {
327{ 257 spurious_interrupt();
328 ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_USB); 258 return;
329 do_IRQ(ATH79_CPU_IRQ(3)); 259 }
330}
331 260
332static void ar934x_ip3_handler(void) 261 pending >>= CAUSEB_IP;
333{ 262 while (pending) {
334 ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_USB); 263 irq = fls(pending) - 1;
335 do_IRQ(ATH79_CPU_IRQ(3)); 264 if (irq < ARRAY_SIZE(irq_wb_chan) && irq_wb_chan[irq] != -1)
265 ath79_ddr_wb_flush(irq_wb_chan[irq]);
266 do_IRQ(MIPS_CPU_IRQ_BASE + irq);
267 pending &= ~BIT(irq);
268 }
336} 269}
337 270
338void __init arch_init_irq(void) 271void __init arch_init_irq(void)
339{ 272{
340 if (soc_is_ar71xx()) { 273 if (soc_is_ar71xx() || soc_is_ar724x() ||
341 ath79_ip2_handler = ar71xx_ip2_handler; 274 soc_is_ar913x() || soc_is_ar933x()) {
342 ath79_ip3_handler = ar71xx_ip3_handler; 275 irq_wb_chan[2] = 3;
343 } else if (soc_is_ar724x()) { 276 irq_wb_chan[3] = 2;
344 ath79_ip2_handler = ar724x_ip2_handler;
345 ath79_ip3_handler = ar724x_ip3_handler;
346 } else if (soc_is_ar913x()) {
347 ath79_ip2_handler = ar913x_ip2_handler;
348 ath79_ip3_handler = ar913x_ip3_handler;
349 } else if (soc_is_ar933x()) {
350 ath79_ip2_handler = ar933x_ip2_handler;
351 ath79_ip3_handler = ar933x_ip3_handler;
352 } else if (soc_is_ar934x()) { 277 } else if (soc_is_ar934x()) {
353 ath79_ip2_handler = ath79_default_ip2_handler; 278 irq_wb_chan[3] = 2;
354 ath79_ip3_handler = ar934x_ip3_handler;
355 } else if (soc_is_qca955x()) {
356 ath79_ip2_handler = ath79_default_ip2_handler;
357 ath79_ip3_handler = ath79_default_ip3_handler;
358 } else {
359 BUG();
360 } 279 }
361 280
362 mips_cpu_irq_init(); 281 mips_cpu_irq_init();
diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c
index 7fc8397d16f2..74f1af7eeefc 100644
--- a/arch/mips/ath79/setup.c
+++ b/arch/mips/ath79/setup.c
@@ -200,8 +200,7 @@ void __init plat_mem_setup(void)
200 AR71XX_RESET_SIZE); 200 AR71XX_RESET_SIZE);
201 ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE, 201 ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE,
202 AR71XX_PLL_SIZE); 202 AR71XX_PLL_SIZE);
203 ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE, 203 ath79_ddr_ctrl_init();
204 AR71XX_DDR_CTRL_SIZE);
205 204
206 ath79_detect_sys_type(); 205 ath79_detect_sys_type();
207 detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX); 206 detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX);
diff --git a/arch/mips/include/asm/mach-ath79/ath79.h b/arch/mips/include/asm/mach-ath79/ath79.h
index 1557934aaca9..4eee221b0cf0 100644
--- a/arch/mips/include/asm/mach-ath79/ath79.h
+++ b/arch/mips/include/asm/mach-ath79/ath79.h
@@ -115,7 +115,8 @@ static inline int soc_is_qca955x(void)
115 return soc_is_qca9556() || soc_is_qca9558(); 115 return soc_is_qca9556() || soc_is_qca9558();
116} 116}
117 117
118extern void __iomem *ath79_ddr_base; 118void ath79_ddr_set_pci_windows(void);
119
119extern void __iomem *ath79_pll_base; 120extern void __iomem *ath79_pll_base;
120extern void __iomem *ath79_reset_base; 121extern void __iomem *ath79_reset_base;
121 122
diff --git a/arch/mips/pci/pci-ar71xx.c b/arch/mips/pci/pci-ar71xx.c
index dac6a07c45bf..283157f8dc64 100644
--- a/arch/mips/pci/pci-ar71xx.c
+++ b/arch/mips/pci/pci-ar71xx.c
@@ -318,23 +318,13 @@ static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc)
318 318
319static void ar71xx_pci_reset(void) 319static void ar71xx_pci_reset(void)
320{ 320{
321 void __iomem *ddr_base = ath79_ddr_base;
322
323 ath79_device_reset_set(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE); 321 ath79_device_reset_set(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE);
324 mdelay(100); 322 mdelay(100);
325 323
326 ath79_device_reset_clear(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE); 324 ath79_device_reset_clear(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE);
327 mdelay(100); 325 mdelay(100);
328 326
329 __raw_writel(AR71XX_PCI_WIN0_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN0); 327 ath79_ddr_set_pci_windows();
330 __raw_writel(AR71XX_PCI_WIN1_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN1);
331 __raw_writel(AR71XX_PCI_WIN2_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN2);
332 __raw_writel(AR71XX_PCI_WIN3_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN3);
333 __raw_writel(AR71XX_PCI_WIN4_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN4);
334 __raw_writel(AR71XX_PCI_WIN5_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN5);
335 __raw_writel(AR71XX_PCI_WIN6_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN6);
336 __raw_writel(AR71XX_PCI_WIN7_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN7);
337
338 mdelay(100); 328 mdelay(100);
339} 329}
340 330