OpenWrt – Blame information for rev 4
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
4 | office | 1 | From 99c33b6e418cefebb461fee0ad3a927a0c4127f1 Mon Sep 17 00:00:00 2001 |
2 | From: Michael Zoran <mzoran@crowfest.net> |
||
3 | Date: Sat, 14 Jan 2017 21:33:51 -0800 |
||
4 | Subject: [PATCH] ARM64/DWC_OTG: Port dwc_otg driver to ARM64 |
||
5 | |||
6 | In ARM64, the FIQ mechanism used by this driver is not current |
||
7 | implemented. As a workaround, reqular IRQ is used instead |
||
8 | of FIQ. |
||
9 | |||
10 | In a separate change, the IRQ-CPU mapping is round robined |
||
11 | on ARM64 to increase concurrency and allow multiple interrupts |
||
12 | to be serviced at a time. This reduces the need for FIQ. |
||
13 | |||
14 | Tests Run: |
||
15 | |||
16 | This mechanism is most likely to break when multiple USB devices |
||
17 | are attached at the same time. So the system was tested under |
||
18 | stress. |
||
19 | |||
20 | Devices: |
||
21 | |||
22 | 1. USB Speakers playing back a FLAC audio through VLC |
||
23 | at 96KHz.(Higher then typically, but supported on my speakers). |
||
24 | |||
25 | 2. sftp transferring large files through the buildin ethernet |
||
26 | connection which is connected through USB. |
||
27 | |||
28 | 3. Keyboard and mouse attached and being used. |
||
29 | |||
30 | Although I do occasionally hear some glitches, the music seems to |
||
31 | play quite well. |
||
32 | |||
33 | Signed-off-by: Michael Zoran <mzoran@crowfest.net> |
||
34 | --- |
||
35 | drivers/usb/host/dwc_otg/Makefile | 3 ++ |
||
36 | drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 17 +++++++ |
||
37 | drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 24 ++++++++++ |
||
38 | drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 4 ++ |
||
39 | drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 4 ++ |
||
40 | drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 3 +- |
||
41 | drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 72 ++++++++++++++++++++++++++++ |
||
42 | drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 2 + |
||
43 | 8 files changed, 128 insertions(+), 1 deletion(-) |
||
44 | |||
45 | --- a/drivers/usb/host/dwc_otg/Makefile |
||
46 | +++ b/drivers/usb/host/dwc_otg/Makefile |
||
47 | @@ -37,7 +37,10 @@ dwc_otg-objs += dwc_otg_pcd_linux.o dwc_ |
||
48 | dwc_otg-objs += dwc_otg_hcd.o dwc_otg_hcd_linux.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o dwc_otg_hcd_ddma.o |
||
49 | dwc_otg-objs += dwc_otg_adp.o |
||
50 | dwc_otg-objs += dwc_otg_fiq_fsm.o |
||
51 | +ifneq ($(CONFIG_ARM64),y) |
||
52 | dwc_otg-objs += dwc_otg_fiq_stub.o |
||
53 | +endif |
||
54 | + |
||
55 | ifneq ($(CFI),) |
||
56 | dwc_otg-objs += dwc_otg_cfi.o |
||
57 | endif |
||
58 | --- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c |
||
59 | +++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c |
||
60 | @@ -74,6 +74,21 @@ void notrace _fiq_print(enum fiq_debug_l |
||
61 | } |
||
62 | } |
||
63 | |||
64 | + |
||
65 | +#ifdef CONFIG_ARM64 |
||
66 | + |
||
67 | +inline void fiq_fsm_spin_lock(fiq_lock_t *lock) |
||
68 | +{ |
||
69 | + spin_lock((spinlock_t *)lock); |
||
70 | +} |
||
71 | + |
||
72 | +inline void fiq_fsm_spin_unlock(fiq_lock_t *lock) |
||
73 | +{ |
||
74 | + spin_unlock((spinlock_t *)lock); |
||
75 | +} |
||
76 | + |
||
77 | +#else |
||
78 | + |
||
79 | /** |
||
80 | * fiq_fsm_spin_lock() - ARMv6+ bare bones spinlock |
||
81 | * Must be called with local interrupts and FIQ disabled. |
||
82 | @@ -122,6 +137,8 @@ inline void fiq_fsm_spin_unlock(fiq_lock |
||
83 | inline void fiq_fsm_spin_unlock(fiq_lock_t *lock) { } |
||
84 | #endif |
||
85 | |||
86 | +#endif |
||
87 | + |
||
88 | /** |
||
89 | * fiq_fsm_restart_channel() - Poke channel enable bit for a split transaction |
||
90 | * @channel: channel to re-enable |
||
91 | --- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h |
||
92 | +++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h |
||
93 | @@ -127,6 +127,12 @@ enum fiq_debug_level { |
||
94 | FIQDBG_PORTHUB = (1 << 3), |
||
95 | }; |
||
96 | |||
97 | +#ifdef CONFIG_ARM64 |
||
98 | + |
||
99 | +typedef spinlock_t fiq_lock_t; |
||
100 | + |
||
101 | +#else |
||
102 | + |
||
103 | typedef struct { |
||
104 | union { |
||
105 | uint32_t slock; |
||
106 | @@ -137,6 +143,8 @@ typedef struct { |
||
107 | }; |
||
108 | } fiq_lock_t; |
||
109 | |||
110 | +#endif |
||
111 | + |
||
112 | struct fiq_state; |
||
113 | |||
114 | extern void _fiq_print (enum fiq_debug_level dbg_lvl, volatile struct fiq_state *state, char *fmt, ...); |
||
115 | @@ -355,6 +363,22 @@ struct fiq_state { |
||
116 | struct fiq_channel_state channel[0]; |
||
117 | }; |
||
118 | |||
119 | +#ifdef CONFIG_ARM64 |
||
120 | + |
||
121 | +#ifdef local_fiq_enable |
||
122 | +#undef local_fiq_enable |
||
123 | +#endif |
||
124 | + |
||
125 | +#ifdef local_fiq_disable |
||
126 | +#undef local_fiq_disable |
||
127 | +#endif |
||
128 | + |
||
129 | +extern void local_fiq_enable(void); |
||
130 | + |
||
131 | +extern void local_fiq_disable(void); |
||
132 | + |
||
133 | +#endif |
||
134 | + |
||
135 | extern void fiq_fsm_spin_lock(fiq_lock_t *lock); |
||
136 | |||
137 | extern void fiq_fsm_spin_unlock(fiq_lock_t *lock); |
||
138 | --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c |
||
139 | +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c |
||
140 | @@ -1021,6 +1021,10 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd |
||
141 | } |
||
142 | DWC_MEMSET(hcd->fiq_state, 0, (sizeof(struct fiq_state) + (sizeof(struct fiq_channel_state) * num_channels))); |
||
143 | |||
144 | +#ifdef CONFIG_ARM64 |
||
145 | + spin_lock_init(&hcd->fiq_state->lock); |
||
146 | +#endif |
||
147 | + |
||
148 | for (i = 0; i < num_channels; i++) { |
||
149 | hcd->fiq_state->channel[i].fsm = FIQ_PASSTHROUGH; |
||
150 | } |
||
151 | --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h |
||
152 | +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h |
||
153 | @@ -116,7 +116,11 @@ extern int32_t dwc_otg_hcd_handle_intr(d |
||
154 | /** This function is used to handle the fast interrupt |
||
155 | * |
||
156 | */ |
||
157 | +#ifdef CONFIG_ARM64 |
||
158 | +extern void dwc_otg_hcd_handle_fiq(void); |
||
159 | +#else |
||
160 | extern void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void); |
||
161 | +#endif |
||
162 | |||
163 | /** |
||
164 | * Returns private data set by |
||
165 | --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c |
||
166 | +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c |
||
167 | @@ -36,8 +36,9 @@ |
||
168 | #include "dwc_otg_regs.h" |
||
169 | |||
170 | #include <linux/jiffies.h> |
||
171 | +#ifdef CONFIG_ARM |
||
172 | #include <asm/fiq.h> |
||
173 | - |
||
174 | +#endif |
||
175 | |||
176 | extern bool microframe_schedule; |
||
177 | |||
178 | --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c |
||
179 | +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c |
||
180 | @@ -51,7 +51,9 @@ |
||
181 | #include <linux/dma-mapping.h> |
||
182 | #include <linux/version.h> |
||
183 | #include <asm/io.h> |
||
184 | +#ifdef CONFIG_ARM |
||
185 | #include <asm/fiq.h> |
||
186 | +#endif |
||
187 | #include <linux/usb.h> |
||
188 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) |
||
189 | #include <../drivers/usb/core/hcd.h> |
||
190 | @@ -71,6 +73,13 @@ |
||
191 | #include "dwc_otg_driver.h" |
||
192 | #include "dwc_otg_hcd.h" |
||
193 | |||
194 | +#ifndef __virt_to_bus |
||
195 | +#define __virt_to_bus __virt_to_phys |
||
196 | +#define __bus_to_virt __phys_to_virt |
||
197 | +#define __pfn_to_bus(x) __pfn_to_phys(x) |
||
198 | +#define __bus_to_pfn(x) __phys_to_pfn(x) |
||
199 | +#endif |
||
200 | + |
||
201 | extern unsigned char _dwc_otg_fiq_stub, _dwc_otg_fiq_stub_end; |
||
202 | |||
203 | /** |
||
204 | @@ -393,14 +402,49 @@ static struct dwc_otg_hcd_function_ops h |
||
205 | .get_b_hnp_enable = _get_b_hnp_enable, |
||
206 | }; |
||
207 | |||
208 | +#ifdef CONFIG_ARM64 |
||
209 | + |
||
210 | +static int simfiq_irq = -1; |
||
211 | + |
||
212 | +void local_fiq_enable(void) |
||
213 | +{ |
||
214 | + if (simfiq_irq >= 0) |
||
215 | + enable_irq(simfiq_irq); |
||
216 | +} |
||
217 | + |
||
218 | +void local_fiq_disable(void) |
||
219 | +{ |
||
220 | + if (simfiq_irq >= 0) |
||
221 | + disable_irq(simfiq_irq); |
||
222 | +} |
||
223 | + |
||
224 | +irqreturn_t fiq_irq_handler(int irq, void *dev_id) |
||
225 | +{ |
||
226 | + dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *)dev_id; |
||
227 | + |
||
228 | + if (fiq_fsm_enable) |
||
229 | + dwc_otg_fiq_fsm(dwc_otg_hcd->fiq_state, dwc_otg_hcd->core_if->core_params->host_channels); |
||
230 | + else |
||
231 | + dwc_otg_fiq_nop(dwc_otg_hcd->fiq_state); |
||
232 | + |
||
233 | + return IRQ_HANDLED; |
||
234 | +} |
||
235 | + |
||
236 | +#else |
||
237 | static struct fiq_handler fh = { |
||
238 | .name = "usb_fiq", |
||
239 | }; |
||
240 | |||
241 | +#endif |
||
242 | + |
||
243 | static void hcd_init_fiq(void *cookie) |
||
244 | { |
||
245 | dwc_otg_device_t *otg_dev = cookie; |
||
246 | dwc_otg_hcd_t *dwc_otg_hcd = otg_dev->hcd; |
||
247 | +#ifdef CONFIG_ARM64 |
||
248 | + int retval = 0; |
||
249 | + int irq; |
||
250 | +#else |
||
251 | struct pt_regs regs; |
||
252 | int irq; |
||
253 | |||
254 | @@ -428,6 +472,7 @@ static void hcd_init_fiq(void *cookie) |
||
255 | |||
256 | // __show_regs(®s); |
||
257 | set_fiq_regs(®s); |
||
258 | +#endif |
||
259 | |||
260 | //Set the mphi periph to the required registers |
||
261 | dwc_otg_hcd->fiq_state->mphi_regs.base = otg_dev->os_dep.mphi_base; |
||
262 | @@ -446,6 +491,23 @@ static void hcd_init_fiq(void *cookie) |
||
263 | DWC_WARN("MPHI periph has NOT been enabled"); |
||
264 | #endif |
||
265 | // Enable FIQ interrupt from USB peripheral |
||
266 | +#ifdef CONFIG_ARM64 |
||
267 | + irq = platform_get_irq(otg_dev->os_dep.platformdev, 1); |
||
268 | + |
||
269 | + if (irq < 0) { |
||
270 | + DWC_ERROR("Can't get SIM-FIQ irq"); |
||
271 | + return; |
||
272 | + } |
||
273 | + |
||
274 | + retval = request_irq(irq, fiq_irq_handler, 0, "dwc_otg_sim-fiq", dwc_otg_hcd); |
||
275 | + |
||
276 | + if (retval < 0) { |
||
277 | + DWC_ERROR("Unable to request SIM-FIQ irq\n"); |
||
278 | + return; |
||
279 | + } |
||
280 | + |
||
281 | + simfiq_irq = irq; |
||
282 | +#else |
||
283 | #ifdef CONFIG_MULTI_IRQ_HANDLER |
||
284 | irq = platform_get_irq(otg_dev->os_dep.platformdev, 1); |
||
285 | #else |
||
286 | @@ -457,6 +519,8 @@ static void hcd_init_fiq(void *cookie) |
||
287 | } |
||
288 | enable_fiq(irq); |
||
289 | local_fiq_enable(); |
||
290 | +#endif |
||
291 | + |
||
292 | } |
||
293 | |||
294 | /** |
||
295 | @@ -519,6 +583,13 @@ int hcd_init(dwc_bus_dev_t *_dev) |
||
296 | otg_dev->hcd = dwc_otg_hcd; |
||
297 | otg_dev->hcd->otg_dev = otg_dev; |
||
298 | |||
299 | +#ifdef CONFIG_ARM64 |
||
300 | + if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) |
||
301 | + goto error2; |
||
302 | + |
||
303 | + if (fiq_enable) |
||
304 | + hcd_init_fiq(otg_dev); |
||
305 | +#else |
||
306 | if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) { |
||
307 | goto error2; |
||
308 | } |
||
309 | @@ -531,6 +602,7 @@ int hcd_init(dwc_bus_dev_t *_dev) |
||
310 | smp_call_function_single(0, hcd_init_fiq, otg_dev, 1); |
||
311 | } |
||
312 | } |
||
313 | +#endif |
||
314 | |||
315 | hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd); |
||
316 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel) |
||
317 | --- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h |
||
318 | +++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h |
||
319 | @@ -76,8 +76,10 @@ |
||
320 | |||
321 | #ifdef PLATFORM_INTERFACE |
||
322 | #include <linux/platform_device.h> |
||
323 | +#ifdef CONFIG_ARM |
||
324 | #include <asm/mach/map.h> |
||
325 | #endif |
||
326 | +#endif |
||
327 | |||
328 | /** The OS page size */ |
||
329 | #define DWC_OS_PAGE_SIZE PAGE_SIZE |