083e0c7f1e66542af44819de36402acfdfcb020f
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-4.19 / 950-0474-dwc_otg-Choose-appropriate-IRQ-handover-strategy.patch
1 From 856c8fdf68e589c89ed0518aab727c54fdff5afa Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.org>
3 Date: Tue, 21 May 2019 13:36:52 +0100
4 Subject: [PATCH] dwc_otg: Choose appropriate IRQ handover strategy
5
6 2711 has no MPHI peripheral, but the ARM Control block can fake
7 interrupts. Use the size of the DTB "mphi" reg block to determine
8 which is required.
9
10 Signed-off-by: Phil Elwell <phil@raspberrypi.org>
11 ---
12 drivers/usb/host/dwc_otg/dwc_otg_driver.c | 9 +++--
13 drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 21 ++++++----
14 drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 2 +
15 drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 12 ++++--
16 drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 41 +++++++++++++-------
17 drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 3 ++
18 6 files changed, 60 insertions(+), 28 deletions(-)
19
20 --- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
21 +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
22 @@ -806,14 +806,15 @@ static int dwc_otg_driver_probe(
23 if (!request_mem_region(_dev->resource[1].start,
24 _dev->resource[1].end - _dev->resource[1].start + 1,
25 "dwc_otg")) {
26 - dev_dbg(&_dev->dev, "error reserving mapped memory\n");
27 - retval = -EFAULT;
28 - goto fail;
29 - }
30 + dev_dbg(&_dev->dev, "error reserving mapped memory\n");
31 + retval = -EFAULT;
32 + goto fail;
33 + }
34
35 dwc_otg_device->os_dep.mphi_base = ioremap_nocache(_dev->resource[1].start,
36 _dev->resource[1].end -
37 _dev->resource[1].start + 1);
38 + dwc_otg_device->os_dep.use_swirq = (_dev->resource[1].end - _dev->resource[1].start) == 0x200;
39 }
40
41 #else
42 --- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
43 +++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
44 @@ -1347,8 +1347,12 @@ void notrace dwc_otg_fiq_fsm(struct fiq_
45 /* We got an interrupt, didn't handle it. */
46 if (kick_irq) {
47 state->mphi_int_count++;
48 - FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
49 - FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
50 + if (state->mphi_regs.swirq_set) {
51 + FIQ_WRITE(state->mphi_regs.swirq_set, 1);
52 + } else {
53 + FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
54 + FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
55 + }
56
57 }
58 state->fiq_done++;
59 @@ -1406,11 +1410,14 @@ void notrace dwc_otg_fiq_nop(struct fiq_
60 state->mphi_int_count++;
61 gintmsk.d32 &= state->gintmsk_saved.d32;
62 FIQ_WRITE(state->dwc_regs_base + GINTMSK, gintmsk.d32);
63 - /* Force a clear before another dummy send */
64 - FIQ_WRITE(state->mphi_regs.intstat, (1<<29));
65 - FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
66 - FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
67 -
68 + if (state->mphi_regs.swirq_set) {
69 + FIQ_WRITE(state->mphi_regs.swirq_set, 1);
70 + } else {
71 + /* Force a clear before another dummy send */
72 + FIQ_WRITE(state->mphi_regs.intstat, (1<<29));
73 + FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
74 + FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
75 + }
76 }
77 state->fiq_done++;
78 mb();
79 --- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
80 +++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
81 @@ -118,6 +118,8 @@ typedef struct {
82 volatile void* outdda;
83 volatile void* outddb;
84 volatile void* intstat;
85 + volatile void* swirq_set;
86 + volatile void* swirq_clr;
87 } mphi_regs_t;
88
89 enum fiq_debug_level {
90 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
91 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
92 @@ -220,16 +220,20 @@ exit_handler_routine:
93
94 /* The FIQ could have sneaked another interrupt in. If so, don't clear MPHI */
95 if ((gintmsk_new.d32 == ~0) && (haintmsk_new.d32 == 0x0000FFFF)) {
96 + if (dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr) {
97 + DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr, 1);
98 + } else {
99 DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.intstat, (1<<16));
100 - if (dwc_otg_hcd->fiq_state->mphi_int_count >= 50) {
101 - fiq_print(FIQDBG_INT, dwc_otg_hcd->fiq_state, "MPHI CLR");
102 + }
103 + if (dwc_otg_hcd->fiq_state->mphi_int_count >= 50) {
104 + fiq_print(FIQDBG_INT, dwc_otg_hcd->fiq_state, "MPHI CLR");
105 DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, ((1<<31) + (1<<16)));
106 while (!(DWC_READ_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & (1 << 17)))
107 ;
108 DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, (1<<31));
109 dwc_otg_hcd->fiq_state->mphi_int_count = 0;
110 - }
111 - int_done++;
112 + }
113 + int_done++;
114 }
115 haintmsk.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk);
116 /* Re-enable interrupts that the FIQ masked (first time round) */
117 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
118 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
119 @@ -474,22 +474,37 @@ static void hcd_init_fiq(void *cookie)
120 set_fiq_regs(&regs);
121 #endif
122
123 - //Set the mphi periph to the required registers
124 - dwc_otg_hcd->fiq_state->mphi_regs.base = otg_dev->os_dep.mphi_base;
125 - dwc_otg_hcd->fiq_state->mphi_regs.ctrl = otg_dev->os_dep.mphi_base + 0x4c;
126 - dwc_otg_hcd->fiq_state->mphi_regs.outdda = otg_dev->os_dep.mphi_base + 0x28;
127 - dwc_otg_hcd->fiq_state->mphi_regs.outddb = otg_dev->os_dep.mphi_base + 0x2c;
128 - dwc_otg_hcd->fiq_state->mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
129 dwc_otg_hcd->fiq_state->dwc_regs_base = otg_dev->os_dep.base;
130 - DWC_WARN("MPHI regs_base at %px", dwc_otg_hcd->fiq_state->mphi_regs.base);
131 - //Enable mphi peripheral
132 - writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl);
133 + //Set the mphi periph to the required registers
134 + dwc_otg_hcd->fiq_state->mphi_regs.base = otg_dev->os_dep.mphi_base;
135 + if (otg_dev->os_dep.use_swirq) {
136 + dwc_otg_hcd->fiq_state->mphi_regs.swirq_set =
137 + otg_dev->os_dep.mphi_base + 0x1f0;
138 + dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr =
139 + otg_dev->os_dep.mphi_base + 0x1f4;
140 + DWC_WARN("Fake MPHI regs_base at 0x%08x",
141 + (int)dwc_otg_hcd->fiq_state->mphi_regs.base);
142 + } else {
143 + dwc_otg_hcd->fiq_state->mphi_regs.ctrl =
144 + otg_dev->os_dep.mphi_base + 0x4c;
145 + dwc_otg_hcd->fiq_state->mphi_regs.outdda
146 + = otg_dev->os_dep.mphi_base + 0x28;
147 + dwc_otg_hcd->fiq_state->mphi_regs.outddb
148 + = otg_dev->os_dep.mphi_base + 0x2c;
149 + dwc_otg_hcd->fiq_state->mphi_regs.intstat
150 + = otg_dev->os_dep.mphi_base + 0x50;
151 + DWC_WARN("MPHI regs_base at %px",
152 + dwc_otg_hcd->fiq_state->mphi_regs.base);
153 +
154 + //Enable mphi peripheral
155 + writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl);
156 #ifdef DEBUG
157 - if (readl(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & 0x80000000)
158 - DWC_WARN("MPHI periph has been enabled");
159 - else
160 - DWC_WARN("MPHI periph has NOT been enabled");
161 + if (readl(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & 0x80000000)
162 + DWC_WARN("MPHI periph has been enabled");
163 + else
164 + DWC_WARN("MPHI periph has NOT been enabled");
165 #endif
166 + }
167 // Enable FIQ interrupt from USB peripheral
168 #ifdef CONFIG_ARM64
169 irq = otg_dev->os_dep.fiq_num;
170 --- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
171 +++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
172 @@ -102,6 +102,9 @@ typedef struct os_dependent {
173 /** Base address for MPHI peripheral */
174 void *mphi_base;
175
176 + /** mphi_base actually points to the SWIRQ block */
177 + bool use_swirq;
178 +
179 /** IRQ number (<0 if not valid) */
180 int irq_num;
181