Commit | Line | Data |
---|---|---|
e8d548d5 KM |
1 | /* |
2 | * Renesas USB driver | |
3 | * | |
4 | * Copyright (C) 2011 Renesas Solutions Corp. | |
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | |
6 | * | |
7 | * This program is distributed in the hope that it will be useful, | |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
10 | * GNU General Public License for more details. | |
11 | * | |
12 | * You should have received a copy of the GNU General Public License | |
13 | * along with this program; if not, write to the Free Software | |
14 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
15 | * | |
16 | */ | |
17 | #include <linux/delay.h> | |
18 | #include <linux/io.h> | |
19 | #include "./common.h" | |
20 | #include "./pipe.h" | |
21 | ||
d3af90a5 KM |
22 | #define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo)) |
23 | ||
d77e3f4e KM |
24 | #define usbhsf_fifo_is_busy(f) ((f)->pipe) /* see usbhs_pipe_select_fifo */ |
25 | ||
4bd04811 KM |
26 | /* |
27 | * packet info function | |
28 | */ | |
97664a20 | 29 | static int usbhsf_null_handle(struct usbhs_pkt *pkt, int *is_done) |
dad67397 KM |
30 | { |
31 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pkt->pipe); | |
32 | struct device *dev = usbhs_priv_to_dev(priv); | |
33 | ||
34 | dev_err(dev, "null handler\n"); | |
35 | ||
36 | return -EINVAL; | |
37 | } | |
38 | ||
39 | static struct usbhs_pkt_handle usbhsf_null_handler = { | |
40 | .prepare = usbhsf_null_handle, | |
41 | .try_run = usbhsf_null_handle, | |
42 | }; | |
43 | ||
6acb95d4 KM |
44 | void usbhs_pkt_init(struct usbhs_pkt *pkt) |
45 | { | |
46 | INIT_LIST_HEAD(&pkt->node); | |
47 | } | |
48 | ||
659d4954 | 49 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, |
dad67397 | 50 | struct usbhs_pkt_handle *handler, |
659d4954 | 51 | void *buf, int len, int zero) |
6acb95d4 | 52 | { |
dad67397 KM |
53 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
54 | struct device *dev = usbhs_priv_to_dev(priv); | |
97664a20 KM |
55 | unsigned long flags; |
56 | ||
57 | /******************** spin lock ********************/ | |
58 | usbhs_lock(priv, flags); | |
dad67397 KM |
59 | |
60 | if (!handler) { | |
61 | dev_err(dev, "no handler function\n"); | |
62 | handler = &usbhsf_null_handler; | |
63 | } | |
64 | ||
6acb95d4 KM |
65 | list_del_init(&pkt->node); |
66 | list_add_tail(&pkt->node, &pipe->list); | |
67 | ||
659d4954 KM |
68 | pkt->pipe = pipe; |
69 | pkt->buf = buf; | |
dad67397 | 70 | pkt->handler = handler; |
659d4954 KM |
71 | pkt->length = len; |
72 | pkt->zero = zero; | |
73 | pkt->actual = 0; | |
97664a20 KM |
74 | |
75 | usbhs_unlock(priv, flags); | |
76 | /******************** spin unlock ******************/ | |
6acb95d4 KM |
77 | } |
78 | ||
97664a20 | 79 | static void __usbhsf_pkt_del(struct usbhs_pkt *pkt) |
6acb95d4 KM |
80 | { |
81 | list_del_init(&pkt->node); | |
82 | } | |
83 | ||
97664a20 | 84 | static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe) |
6acb95d4 KM |
85 | { |
86 | if (list_empty(&pipe->list)) | |
87 | return NULL; | |
88 | ||
89 | return list_entry(pipe->list.next, struct usbhs_pkt, node); | |
90 | } | |
91 | ||
97664a20 KM |
92 | struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) |
93 | { | |
94 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | |
95 | unsigned long flags; | |
96 | ||
97 | /******************** spin lock ********************/ | |
98 | usbhs_lock(priv, flags); | |
99 | ||
100 | if (!pkt) | |
101 | pkt = __usbhsf_pkt_get(pipe); | |
102 | ||
103 | if (pkt) | |
104 | __usbhsf_pkt_del(pkt); | |
105 | ||
106 | usbhs_unlock(priv, flags); | |
107 | /******************** spin unlock ******************/ | |
108 | ||
109 | return pkt; | |
110 | } | |
111 | ||
112 | int __usbhs_pkt_handler(struct usbhs_pipe *pipe, int type) | |
113 | { | |
114 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | |
115 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); | |
116 | struct usbhs_pkt *pkt; | |
117 | struct device *dev = usbhs_priv_to_dev(priv); | |
118 | int (*func)(struct usbhs_pkt *pkt, int *is_done); | |
119 | unsigned long flags; | |
120 | int ret = 0; | |
121 | int is_done = 0; | |
122 | ||
123 | /******************** spin lock ********************/ | |
124 | usbhs_lock(priv, flags); | |
125 | ||
126 | pkt = __usbhsf_pkt_get(pipe); | |
127 | if (!pkt) | |
128 | goto __usbhs_pkt_handler_end; | |
129 | ||
130 | switch (type) { | |
131 | case USBHSF_PKT_PREPARE: | |
132 | func = pkt->handler->prepare; | |
133 | break; | |
134 | case USBHSF_PKT_TRY_RUN: | |
135 | func = pkt->handler->try_run; | |
136 | break; | |
137 | default: | |
138 | dev_err(dev, "unknown pkt hander\n"); | |
139 | goto __usbhs_pkt_handler_end; | |
140 | } | |
141 | ||
142 | ret = func(pkt, &is_done); | |
143 | ||
144 | if (is_done) | |
145 | __usbhsf_pkt_del(pkt); | |
146 | ||
147 | __usbhs_pkt_handler_end: | |
148 | usbhs_unlock(priv, flags); | |
149 | /******************** spin unlock ******************/ | |
150 | ||
151 | if (is_done) | |
152 | info->done(pkt); | |
153 | ||
154 | return ret; | |
155 | } | |
156 | ||
659d4954 KM |
157 | /* |
158 | * irq enable/disable function | |
159 | */ | |
160 | #define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, bempsts, e) | |
161 | #define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, brdysts, e) | |
162 | #define usbhsf_irq_callback_ctrl(pipe, status, enable) \ | |
163 | ({ \ | |
164 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); \ | |
165 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); \ | |
166 | u16 status = (1 << usbhs_pipe_number(pipe)); \ | |
167 | if (!mod) \ | |
168 | return; \ | |
169 | if (enable) \ | |
170 | mod->irq_##status |= status; \ | |
171 | else \ | |
172 | mod->irq_##status &= ~status; \ | |
173 | usbhs_irq_callback_update(priv, mod); \ | |
174 | }) | |
175 | ||
176 | static void usbhsf_tx_irq_ctrl(struct usbhs_pipe *pipe, int enable) | |
177 | { | |
178 | /* | |
179 | * And DCP pipe can NOT use "ready interrupt" for "send" | |
180 | * it should use "empty" interrupt. | |
181 | * see | |
182 | * "Operation" - "Interrupt Function" - "BRDY Interrupt" | |
183 | * | |
184 | * on the other hand, normal pipe can use "ready interrupt" for "send" | |
185 | * even though it is single/double buffer | |
186 | */ | |
187 | if (usbhs_pipe_is_dcp(pipe)) | |
188 | usbhsf_irq_empty_ctrl(pipe, enable); | |
189 | else | |
190 | usbhsf_irq_ready_ctrl(pipe, enable); | |
191 | } | |
192 | ||
193 | static void usbhsf_rx_irq_ctrl(struct usbhs_pipe *pipe, int enable) | |
194 | { | |
195 | usbhsf_irq_ready_ctrl(pipe, enable); | |
196 | } | |
197 | ||
e8d548d5 KM |
198 | /* |
199 | * FIFO ctrl | |
200 | */ | |
d3af90a5 KM |
201 | static void usbhsf_send_terminator(struct usbhs_pipe *pipe, |
202 | struct usbhs_fifo *fifo) | |
e8d548d5 KM |
203 | { |
204 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | |
205 | ||
d3af90a5 | 206 | usbhs_bset(priv, fifo->ctr, BVAL, BVAL); |
e8d548d5 KM |
207 | } |
208 | ||
d3af90a5 KM |
209 | static int usbhsf_fifo_barrier(struct usbhs_priv *priv, |
210 | struct usbhs_fifo *fifo) | |
e8d548d5 KM |
211 | { |
212 | int timeout = 1024; | |
213 | ||
214 | do { | |
215 | /* The FIFO port is accessible */ | |
d3af90a5 | 216 | if (usbhs_read(priv, fifo->ctr) & FRDY) |
e8d548d5 KM |
217 | return 0; |
218 | ||
219 | udelay(10); | |
220 | } while (timeout--); | |
221 | ||
222 | return -EBUSY; | |
223 | } | |
224 | ||
d3af90a5 KM |
225 | static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, |
226 | struct usbhs_fifo *fifo) | |
e8d548d5 KM |
227 | { |
228 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | |
229 | ||
230 | if (!usbhs_pipe_is_dcp(pipe)) | |
d3af90a5 | 231 | usbhsf_fifo_barrier(priv, fifo); |
e8d548d5 | 232 | |
d3af90a5 | 233 | usbhs_write(priv, fifo->ctr, BCLR); |
e8d548d5 KM |
234 | } |
235 | ||
d3af90a5 KM |
236 | static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv, |
237 | struct usbhs_fifo *fifo) | |
e8d548d5 | 238 | { |
d3af90a5 | 239 | return usbhs_read(priv, fifo->ctr) & DTLN_MASK; |
e8d548d5 KM |
240 | } |
241 | ||
d77e3f4e KM |
242 | static void usbhsf_fifo_unselect(struct usbhs_pipe *pipe, |
243 | struct usbhs_fifo *fifo) | |
244 | { | |
245 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | |
246 | ||
247 | usbhs_pipe_select_fifo(pipe, NULL); | |
248 | usbhs_write(priv, fifo->sel, 0); | |
249 | } | |
250 | ||
d3af90a5 KM |
251 | static int usbhsf_fifo_select(struct usbhs_pipe *pipe, |
252 | struct usbhs_fifo *fifo, | |
253 | int write) | |
e8d548d5 KM |
254 | { |
255 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | |
256 | struct device *dev = usbhs_priv_to_dev(priv); | |
257 | int timeout = 1024; | |
258 | u16 mask = ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */ | |
259 | u16 base = usbhs_pipe_number(pipe); /* CURPIPE */ | |
260 | ||
d77e3f4e KM |
261 | if (usbhs_pipe_is_busy(pipe) || |
262 | usbhsf_fifo_is_busy(fifo)) | |
263 | return -EBUSY; | |
264 | ||
e8d548d5 KM |
265 | if (usbhs_pipe_is_dcp(pipe)) |
266 | base |= (1 == write) << 5; /* ISEL */ | |
267 | ||
268 | /* "base" will be used below */ | |
d3af90a5 | 269 | usbhs_write(priv, fifo->sel, base | MBW_32); |
e8d548d5 KM |
270 | |
271 | /* check ISEL and CURPIPE value */ | |
272 | while (timeout--) { | |
d77e3f4e KM |
273 | if (base == (mask & usbhs_read(priv, fifo->sel))) { |
274 | usbhs_pipe_select_fifo(pipe, fifo); | |
e8d548d5 | 275 | return 0; |
d77e3f4e | 276 | } |
e8d548d5 KM |
277 | udelay(10); |
278 | } | |
279 | ||
280 | dev_err(dev, "fifo select error\n"); | |
281 | ||
282 | return -EIO; | |
283 | } | |
284 | ||
285 | /* | |
286 | * PIO fifo functions | |
287 | */ | |
97664a20 | 288 | static int usbhsf_try_push(struct usbhs_pkt *pkt, int *is_done) |
e8d548d5 | 289 | { |
4bd04811 | 290 | struct usbhs_pipe *pipe = pkt->pipe; |
e8d548d5 | 291 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
659d4954 | 292 | struct device *dev = usbhs_priv_to_dev(priv); |
d3af90a5 KM |
293 | struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ |
294 | void __iomem *addr = priv->base + fifo->port; | |
659d4954 | 295 | u8 *buf; |
e8d548d5 KM |
296 | int maxp = usbhs_pipe_get_maxpacket(pipe); |
297 | int total_len; | |
4bd04811 | 298 | int i, ret, len; |
97664a20 | 299 | int is_short; |
e8d548d5 | 300 | |
d3af90a5 | 301 | ret = usbhsf_fifo_select(pipe, fifo, 1); |
e8d548d5 | 302 | if (ret < 0) |
d77e3f4e | 303 | return 0; |
e8d548d5 | 304 | |
dad67397 | 305 | ret = usbhs_pipe_is_accessible(pipe); |
e8d548d5 | 306 | if (ret < 0) |
659d4954 | 307 | goto usbhs_fifo_write_busy; |
e8d548d5 | 308 | |
d3af90a5 | 309 | ret = usbhsf_fifo_barrier(priv, fifo); |
e8d548d5 | 310 | if (ret < 0) |
659d4954 | 311 | goto usbhs_fifo_write_busy; |
e8d548d5 | 312 | |
659d4954 KM |
313 | buf = pkt->buf + pkt->actual; |
314 | len = pkt->length - pkt->actual; | |
315 | len = min(len, maxp); | |
316 | total_len = len; | |
317 | is_short = total_len < maxp; | |
e8d548d5 KM |
318 | |
319 | /* | |
320 | * FIXME | |
321 | * | |
322 | * 32-bit access only | |
323 | */ | |
659d4954 | 324 | if (len >= 4 && !((unsigned long)buf & 0x03)) { |
e8d548d5 KM |
325 | iowrite32_rep(addr, buf, len / 4); |
326 | len %= 4; | |
327 | buf += total_len - len; | |
328 | } | |
329 | ||
330 | /* the rest operation */ | |
331 | for (i = 0; i < len; i++) | |
332 | iowrite8(buf[i], addr + (0x03 - (i & 0x03))); | |
333 | ||
659d4954 KM |
334 | /* |
335 | * variable update | |
336 | */ | |
337 | pkt->actual += total_len; | |
338 | ||
339 | if (pkt->actual < pkt->length) | |
97664a20 | 340 | *is_done = 0; /* there are remainder data */ |
659d4954 | 341 | else if (is_short) |
97664a20 | 342 | *is_done = 1; /* short packet */ |
659d4954 | 343 | else |
97664a20 | 344 | *is_done = !pkt->zero; /* send zero packet ? */ |
659d4954 KM |
345 | |
346 | /* | |
347 | * pipe/irq handling | |
348 | */ | |
349 | if (is_short) | |
d3af90a5 | 350 | usbhsf_send_terminator(pipe, fifo); |
e8d548d5 | 351 | |
97664a20 | 352 | usbhsf_tx_irq_ctrl(pipe, !*is_done); |
4bd04811 KM |
353 | usbhs_pipe_enable(pipe); |
354 | ||
659d4954 KM |
355 | dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n", |
356 | usbhs_pipe_number(pipe), | |
97664a20 | 357 | pkt->length, pkt->actual, *is_done, pkt->zero); |
659d4954 KM |
358 | |
359 | /* | |
360 | * Transmission end | |
361 | */ | |
97664a20 | 362 | if (*is_done) { |
659d4954 KM |
363 | if (usbhs_pipe_is_dcp(pipe)) |
364 | usbhs_dcp_control_transfer_done(pipe); | |
4bd04811 KM |
365 | } |
366 | ||
d77e3f4e KM |
367 | usbhsf_fifo_unselect(pipe, fifo); |
368 | ||
4bd04811 | 369 | return 0; |
659d4954 KM |
370 | |
371 | usbhs_fifo_write_busy: | |
d77e3f4e KM |
372 | usbhsf_fifo_unselect(pipe, fifo); |
373 | ||
659d4954 KM |
374 | /* |
375 | * pipe is busy. | |
376 | * retry in interrupt | |
377 | */ | |
378 | usbhsf_tx_irq_ctrl(pipe, 1); | |
379 | ||
380 | return ret; | |
e8d548d5 KM |
381 | } |
382 | ||
dad67397 KM |
383 | struct usbhs_pkt_handle usbhs_fifo_push_handler = { |
384 | .prepare = usbhsf_try_push, | |
385 | .try_run = usbhsf_try_push, | |
386 | }; | |
387 | ||
97664a20 | 388 | static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done) |
e8d548d5 | 389 | { |
dad67397 | 390 | struct usbhs_pipe *pipe = pkt->pipe; |
d77e3f4e KM |
391 | |
392 | if (usbhs_pipe_is_busy(pipe)) | |
393 | return 0; | |
e8d548d5 KM |
394 | |
395 | /* | |
d77e3f4e | 396 | * pipe enable to prepare packet receive |
e8d548d5 | 397 | */ |
e8d548d5 KM |
398 | |
399 | usbhs_pipe_enable(pipe); | |
659d4954 | 400 | usbhsf_rx_irq_ctrl(pipe, 1); |
e8d548d5 | 401 | |
d3af90a5 | 402 | return 0; |
e8d548d5 KM |
403 | } |
404 | ||
97664a20 | 405 | static int usbhsf_try_pop(struct usbhs_pkt *pkt, int *is_done) |
e8d548d5 | 406 | { |
4bd04811 | 407 | struct usbhs_pipe *pipe = pkt->pipe; |
e8d548d5 | 408 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
659d4954 | 409 | struct device *dev = usbhs_priv_to_dev(priv); |
d3af90a5 KM |
410 | struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ |
411 | void __iomem *addr = priv->base + fifo->port; | |
659d4954 KM |
412 | u8 *buf; |
413 | u32 data = 0; | |
414 | int maxp = usbhs_pipe_get_maxpacket(pipe); | |
4bd04811 | 415 | int rcv_len, len; |
e8d548d5 | 416 | int i, ret; |
4bd04811 | 417 | int total_len = 0; |
e8d548d5 | 418 | |
d3af90a5 | 419 | ret = usbhsf_fifo_select(pipe, fifo, 0); |
e8d548d5 | 420 | if (ret < 0) |
d77e3f4e | 421 | return 0; |
e8d548d5 | 422 | |
d3af90a5 | 423 | ret = usbhsf_fifo_barrier(priv, fifo); |
e8d548d5 | 424 | if (ret < 0) |
d77e3f4e | 425 | goto usbhs_fifo_read_busy; |
e8d548d5 | 426 | |
d3af90a5 | 427 | rcv_len = usbhsf_fifo_rcv_len(priv, fifo); |
e8d548d5 | 428 | |
659d4954 KM |
429 | buf = pkt->buf + pkt->actual; |
430 | len = pkt->length - pkt->actual; | |
431 | len = min(len, rcv_len); | |
432 | total_len = len; | |
433 | ||
e8d548d5 KM |
434 | /* |
435 | * Buffer clear if Zero-Length packet | |
436 | * | |
437 | * see | |
438 | * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function" | |
439 | */ | |
440 | if (0 == rcv_len) { | |
d3af90a5 | 441 | usbhsf_fifo_clear(pipe, fifo); |
4bd04811 | 442 | goto usbhs_fifo_read_end; |
e8d548d5 KM |
443 | } |
444 | ||
e8d548d5 KM |
445 | /* |
446 | * FIXME | |
447 | * | |
448 | * 32-bit access only | |
449 | */ | |
659d4954 | 450 | if (len >= 4 && !((unsigned long)buf & 0x03)) { |
e8d548d5 KM |
451 | ioread32_rep(addr, buf, len / 4); |
452 | len %= 4; | |
659d4954 | 453 | buf += total_len - len; |
e8d548d5 KM |
454 | } |
455 | ||
456 | /* the rest operation */ | |
457 | for (i = 0; i < len; i++) { | |
458 | if (!(i & 0x03)) | |
459 | data = ioread32(addr); | |
460 | ||
461 | buf[i] = (data >> ((i & 0x03) * 8)) & 0xff; | |
462 | } | |
463 | ||
659d4954 KM |
464 | pkt->actual += total_len; |
465 | ||
4bd04811 | 466 | usbhs_fifo_read_end: |
659d4954 | 467 | if ((pkt->actual == pkt->length) || /* receive all data */ |
97664a20 KM |
468 | (total_len < maxp)) { /* short packet */ |
469 | *is_done = 1; | |
659d4954 KM |
470 | usbhsf_rx_irq_ctrl(pipe, 0); |
471 | usbhs_pipe_disable(pipe); | |
4bd04811 KM |
472 | } |
473 | ||
97664a20 KM |
474 | dev_dbg(dev, " recv %d (%d/ %d/ %d/ %d)\n", |
475 | usbhs_pipe_number(pipe), | |
476 | pkt->length, pkt->actual, *is_done, pkt->zero); | |
477 | ||
d77e3f4e KM |
478 | usbhs_fifo_read_busy: |
479 | usbhsf_fifo_unselect(pipe, fifo); | |
480 | ||
481 | return ret; | |
e8d548d5 | 482 | } |
dad67397 KM |
483 | |
484 | struct usbhs_pkt_handle usbhs_fifo_pop_handler = { | |
485 | .prepare = usbhsf_prepare_pop, | |
486 | .try_run = usbhsf_try_pop, | |
487 | }; | |
488 | ||
489 | /* | |
490 | * handler function | |
491 | */ | |
97664a20 | 492 | static int usbhsf_ctrl_stage_end(struct usbhs_pkt *pkt, int *is_done) |
dad67397 | 493 | { |
97664a20 | 494 | usbhs_dcp_control_transfer_done(pkt->pipe); |
dad67397 | 495 | |
97664a20 | 496 | *is_done = 1; |
dad67397 KM |
497 | |
498 | return 0; | |
499 | } | |
500 | ||
501 | struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler = { | |
502 | .prepare = usbhsf_ctrl_stage_end, | |
503 | .try_run = usbhsf_ctrl_stage_end, | |
504 | }; | |
505 | ||
506 | /* | |
507 | * irq functions | |
508 | */ | |
509 | static int usbhsf_irq_empty(struct usbhs_priv *priv, | |
510 | struct usbhs_irq_state *irq_state) | |
511 | { | |
512 | struct usbhs_pipe *pipe; | |
dad67397 KM |
513 | struct device *dev = usbhs_priv_to_dev(priv); |
514 | int i, ret; | |
515 | ||
516 | if (!irq_state->bempsts) { | |
517 | dev_err(dev, "debug %s !!\n", __func__); | |
518 | return -EIO; | |
519 | } | |
520 | ||
521 | dev_dbg(dev, "irq empty [0x%04x]\n", irq_state->bempsts); | |
522 | ||
523 | /* | |
524 | * search interrupted "pipe" | |
525 | * not "uep". | |
526 | */ | |
527 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | |
528 | if (!(irq_state->bempsts & (1 << i))) | |
529 | continue; | |
530 | ||
97664a20 | 531 | ret = usbhs_pkt_run(pipe); |
dad67397 KM |
532 | if (ret < 0) |
533 | dev_err(dev, "irq_empty run_error %d : %d\n", i, ret); | |
534 | } | |
535 | ||
536 | return 0; | |
537 | } | |
538 | ||
539 | static int usbhsf_irq_ready(struct usbhs_priv *priv, | |
540 | struct usbhs_irq_state *irq_state) | |
541 | { | |
542 | struct usbhs_pipe *pipe; | |
dad67397 KM |
543 | struct device *dev = usbhs_priv_to_dev(priv); |
544 | int i, ret; | |
545 | ||
546 | if (!irq_state->brdysts) { | |
547 | dev_err(dev, "debug %s !!\n", __func__); | |
548 | return -EIO; | |
549 | } | |
550 | ||
551 | dev_dbg(dev, "irq ready [0x%04x]\n", irq_state->brdysts); | |
552 | ||
553 | /* | |
554 | * search interrupted "pipe" | |
555 | * not "uep". | |
556 | */ | |
557 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | |
558 | if (!(irq_state->brdysts & (1 << i))) | |
559 | continue; | |
560 | ||
97664a20 | 561 | ret = usbhs_pkt_run(pipe); |
dad67397 KM |
562 | if (ret < 0) |
563 | dev_err(dev, "irq_ready run_error %d : %d\n", i, ret); | |
564 | } | |
565 | ||
566 | return 0; | |
567 | } | |
568 | ||
569 | /* | |
570 | * fifo init | |
571 | */ | |
572 | void usbhs_fifo_init(struct usbhs_priv *priv) | |
573 | { | |
574 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | |
d77e3f4e | 575 | struct usbhs_fifo *cfifo = usbhsf_get_cfifo(priv); |
dad67397 KM |
576 | |
577 | mod->irq_empty = usbhsf_irq_empty; | |
578 | mod->irq_ready = usbhsf_irq_ready; | |
579 | mod->irq_bempsts = 0; | |
580 | mod->irq_brdysts = 0; | |
d77e3f4e KM |
581 | |
582 | cfifo->pipe = NULL; | |
dad67397 KM |
583 | } |
584 | ||
585 | void usbhs_fifo_quit(struct usbhs_priv *priv) | |
586 | { | |
587 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | |
588 | ||
589 | mod->irq_empty = NULL; | |
590 | mod->irq_ready = NULL; | |
591 | mod->irq_bempsts = 0; | |
592 | mod->irq_brdysts = 0; | |
593 | } | |
d3af90a5 KM |
594 | |
595 | int usbhs_fifo_probe(struct usbhs_priv *priv) | |
596 | { | |
597 | struct usbhs_fifo *fifo; | |
598 | ||
599 | /* CFIFO */ | |
600 | fifo = usbhsf_get_cfifo(priv); | |
601 | fifo->port = CFIFO; | |
602 | fifo->sel = CFIFOSEL; | |
603 | fifo->ctr = CFIFOCTR; | |
604 | ||
605 | return 0; | |
606 | } | |
607 | ||
608 | void usbhs_fifo_remove(struct usbhs_priv *priv) | |
609 | { | |
610 | } |