Skip to content

Commit 24b0e3e

Browse files
AlbanBedelralfbaechle
authored andcommitted
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. [[email protected]: Folded in Alban Bedel's follup fix.] Signed-off-by: Alban Bedel <[email protected]> Cc: [email protected] Cc: Andrew Bresticker <[email protected]> Cc: Qais Yousef <[email protected]> Cc: Wolfram Sang <[email protected]> Cc: Sergey Ryazanov <[email protected]> Cc: Gabor Juhos <[email protected]> Cc: [email protected] Patchwork: https://patchwork.linux-mips.org/patch/9773/ Patchwork: http://patchwork.linux-mips.org/patch/10543/ Signed-off-by: Ralf Baechle <[email protected]>
1 parent 626a069 commit 24b0e3e

File tree

6 files changed

+66
-125
lines changed

6 files changed

+66
-125
lines changed

arch/mips/ath79/common.c

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,27 @@ unsigned int ath79_soc_rev;
3838
void __iomem *ath79_pll_base;
3939
void __iomem *ath79_reset_base;
4040
EXPORT_SYMBOL_GPL(ath79_reset_base);
41-
void __iomem *ath79_ddr_base;
41+
static void __iomem *ath79_ddr_base;
42+
static void __iomem *ath79_ddr_wb_flush_base;
43+
static void __iomem *ath79_ddr_pci_win_base;
44+
45+
void 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+
}
57+
EXPORT_SYMBOL_GPL(ath79_ddr_ctrl_init);
4258

4359
void ath79_ddr_wb_flush(u32 reg)
4460
{
45-
void __iomem *flush_reg = ath79_ddr_base + reg;
61+
void __iomem *flush_reg = ath79_ddr_wb_flush_base + reg;
4662

4763
/* Flush the DDR write buffer. */
4864
__raw_writel(0x1, flush_reg);
@@ -56,6 +72,21 @@ void ath79_ddr_wb_flush(u32 reg)
5672
}
5773
EXPORT_SYMBOL_GPL(ath79_ddr_wb_flush);
5874

75+
void 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+
}
88+
EXPORT_SYMBOL_GPL(ath79_ddr_set_pci_windows);
89+
5990
void ath79_device_reset_set(u32 mask)
6091
{
6192
unsigned long flags;

arch/mips/ath79/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
void ath79_clocks_init(void);
2323
unsigned long ath79_get_sys_clk_rate(const char *id);
2424

25+
void ath79_ddr_ctrl_init(void);
2526
void ath79_ddr_wb_flush(unsigned int reg);
2627

2728
void ath79_gpio_function_enable(u32 mask);

arch/mips/ath79/irq.c

Lines changed: 28 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@
2424
#include <asm/mach-ath79/ar71xx_regs.h>
2525
#include "common.h"
2626

27-
static void (*ath79_ip2_handler)(void);
28-
static void (*ath79_ip3_handler)(void);
29-
3027
static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc)
3128
{
3229
void __iomem *base = ath79_reset_base;
@@ -129,10 +126,10 @@ static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
129126
status = ath79_reset_rr(AR934X_RESET_REG_PCIE_WMAC_INT_STATUS);
130127

131128
if (status & AR934X_PCIE_WMAC_INT_PCIE_ALL) {
132-
ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_PCIE);
129+
ath79_ddr_wb_flush(3);
133130
generic_handle_irq(ATH79_IP2_IRQ(0));
134131
} 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);
136133
generic_handle_irq(ATH79_IP2_IRQ(1));
137134
} else {
138135
spurious_interrupt();
@@ -235,128 +232,50 @@ static void qca955x_irq_init(void)
235232
irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch);
236233
}
237234

238-
asmlinkage 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-
266235
/*
267236
* The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for
268237
* these devices typically allocate coherent DMA memory, however the
269238
* DMA controller may still have some unsynchronized data in the FIFO.
270239
* Issue a flush in the handlers to ensure that the driver sees
271240
* the update.
241+
*
242+
* This array map the interrupt lines to the DDR write buffer channels.
272243
*/
273244

274-
static void ath79_default_ip2_handler(void)
275-
{
276-
do_IRQ(ATH79_CPU_IRQ(2));
277-
}
278-
279-
static void ath79_default_ip3_handler(void)
280-
{
281-
do_IRQ(ATH79_CPU_IRQ(3));
282-
}
283-
284-
static 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-
290-
static 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-
296-
static 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-
302-
static 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-
308-
static void ar71xx_ip3_handler(void)
309-
{
310-
ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB);
311-
do_IRQ(ATH79_CPU_IRQ(3));
312-
}
245+
static unsigned irq_wb_chan[8] = {
246+
-1, -1, -1, -1, -1, -1, -1, -1,
247+
};
313248

314-
static void ar724x_ip3_handler(void)
249+
asmlinkage void plat_irq_dispatch(void)
315250
{
316-
ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_USB);
317-
do_IRQ(ATH79_CPU_IRQ(3));
318-
}
251+
unsigned long pending;
252+
int irq;
319253

320-
static void ar913x_ip3_handler(void)
321-
{
322-
ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_USB);
323-
do_IRQ(ATH79_CPU_IRQ(3));
324-
}
254+
pending = read_c0_status() & read_c0_cause() & ST0_IM;
325255

326-
static void ar933x_ip3_handler(void)
327-
{
328-
ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_USB);
329-
do_IRQ(ATH79_CPU_IRQ(3));
330-
}
256+
if (!pending) {
257+
spurious_interrupt();
258+
return;
259+
}
331260

332-
static void ar934x_ip3_handler(void)
333-
{
334-
ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_USB);
335-
do_IRQ(ATH79_CPU_IRQ(3));
261+
pending >>= CAUSEB_IP;
262+
while (pending) {
263+
irq = fls(pending) - 1;
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+
}
336269
}
337270

338271
void __init arch_init_irq(void)
339272
{
340-
if (soc_is_ar71xx()) {
341-
ath79_ip2_handler = ar71xx_ip2_handler;
342-
ath79_ip3_handler = ar71xx_ip3_handler;
343-
} else if (soc_is_ar724x()) {
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;
273+
if (soc_is_ar71xx() || soc_is_ar724x() ||
274+
soc_is_ar913x() || soc_is_ar933x()) {
275+
irq_wb_chan[2] = 3;
276+
irq_wb_chan[3] = 2;
352277
} else if (soc_is_ar934x()) {
353-
ath79_ip2_handler = ath79_default_ip2_handler;
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();
278+
irq_wb_chan[3] = 2;
360279
}
361280

362281
mips_cpu_irq_init();

arch/mips/ath79/setup.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,7 @@ void __init plat_mem_setup(void)
200200
AR71XX_RESET_SIZE);
201201
ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE,
202202
AR71XX_PLL_SIZE);
203-
ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE,
204-
AR71XX_DDR_CTRL_SIZE);
203+
ath79_ddr_ctrl_init();
205204

206205
ath79_detect_sys_type();
207206
detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX);

arch/mips/include/asm/mach-ath79/ath79.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ static inline int soc_is_qca955x(void)
115115
return soc_is_qca9556() || soc_is_qca9558();
116116
}
117117

118-
extern void __iomem *ath79_ddr_base;
118+
void ath79_ddr_set_pci_windows(void);
119+
119120
extern void __iomem *ath79_pll_base;
120121
extern void __iomem *ath79_reset_base;
121122

arch/mips/pci/pci-ar71xx.c

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -318,23 +318,13 @@ static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc)
318318

319319
static void ar71xx_pci_reset(void)
320320
{
321-
void __iomem *ddr_base = ath79_ddr_base;
322-
323321
ath79_device_reset_set(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE);
324322
mdelay(100);
325323

326324
ath79_device_reset_clear(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE);
327325
mdelay(100);
328326

329-
__raw_writel(AR71XX_PCI_WIN0_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN0);
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-
327+
ath79_ddr_set_pci_windows();
338328
mdelay(100);
339329
}
340330

0 commit comments

Comments
 (0)