diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2011-06-06 01:18:28 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-06-07 12:10:08 -0400 |
commit | dad67397f2090b29cd1f169e6a4ac6f3532c6858 (patch) | |
tree | 02f3fe42ef7307b5c70a901b59598478897baa1b /drivers/usb/renesas_usbhs/fifo.c | |
parent | 659d495404d20ff8f96644fca82c772455f1226c (diff) |
usb: renesas_usbhs: modify data transfer interrupt
On current driver, overall data transfer method was implemented in fifo.c,
but its interrupt which is member of packet queue control
was still in mod_gadget.c.
This patch move it into fifo.c.
By this patch, the packet/fifo control is independent from mod_gadget.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/renesas_usbhs/fifo.c')
-rw-r--r-- | drivers/usb/renesas_usbhs/fifo.c | 168 |
1 files changed, 154 insertions, 14 deletions
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index b5031e3a1569..e9c4d3d8ef6e 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c | |||
@@ -22,19 +22,44 @@ | |||
22 | /* | 22 | /* |
23 | * packet info function | 23 | * packet info function |
24 | */ | 24 | */ |
25 | static int usbhsf_null_handle(struct usbhs_pkt *pkt) | ||
26 | { | ||
27 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pkt->pipe); | ||
28 | struct device *dev = usbhs_priv_to_dev(priv); | ||
29 | |||
30 | dev_err(dev, "null handler\n"); | ||
31 | |||
32 | return -EINVAL; | ||
33 | } | ||
34 | |||
35 | static struct usbhs_pkt_handle usbhsf_null_handler = { | ||
36 | .prepare = usbhsf_null_handle, | ||
37 | .try_run = usbhsf_null_handle, | ||
38 | }; | ||
39 | |||
25 | void usbhs_pkt_init(struct usbhs_pkt *pkt) | 40 | void usbhs_pkt_init(struct usbhs_pkt *pkt) |
26 | { | 41 | { |
27 | INIT_LIST_HEAD(&pkt->node); | 42 | INIT_LIST_HEAD(&pkt->node); |
28 | } | 43 | } |
29 | 44 | ||
30 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, | 45 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, |
46 | struct usbhs_pkt_handle *handler, | ||
31 | void *buf, int len, int zero) | 47 | void *buf, int len, int zero) |
32 | { | 48 | { |
49 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
50 | struct device *dev = usbhs_priv_to_dev(priv); | ||
51 | |||
52 | if (!handler) { | ||
53 | dev_err(dev, "no handler function\n"); | ||
54 | handler = &usbhsf_null_handler; | ||
55 | } | ||
56 | |||
33 | list_del_init(&pkt->node); | 57 | list_del_init(&pkt->node); |
34 | list_add_tail(&pkt->node, &pipe->list); | 58 | list_add_tail(&pkt->node, &pipe->list); |
35 | 59 | ||
36 | pkt->pipe = pipe; | 60 | pkt->pipe = pipe; |
37 | pkt->buf = buf; | 61 | pkt->buf = buf; |
62 | pkt->handler = handler; | ||
38 | pkt->length = len; | 63 | pkt->length = len; |
39 | pkt->zero = zero; | 64 | pkt->zero = zero; |
40 | pkt->actual = 0; | 65 | pkt->actual = 0; |
@@ -163,12 +188,7 @@ static int usbhsf_fifo_select(struct usbhs_pipe *pipe, int write) | |||
163 | /* | 188 | /* |
164 | * PIO fifo functions | 189 | * PIO fifo functions |
165 | */ | 190 | */ |
166 | int usbhs_fifo_prepare_write(struct usbhs_pipe *pipe) | 191 | static int usbhsf_try_push(struct usbhs_pkt *pkt) |
167 | { | ||
168 | return usbhsf_fifo_select(pipe, 1); | ||
169 | } | ||
170 | |||
171 | int usbhs_fifo_write(struct usbhs_pkt *pkt) | ||
172 | { | 192 | { |
173 | struct usbhs_pipe *pipe = pkt->pipe; | 193 | struct usbhs_pipe *pipe = pkt->pipe; |
174 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 194 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
@@ -181,11 +201,11 @@ int usbhs_fifo_write(struct usbhs_pkt *pkt) | |||
181 | int i, ret, len; | 201 | int i, ret, len; |
182 | int is_short, is_done; | 202 | int is_short, is_done; |
183 | 203 | ||
184 | ret = usbhs_pipe_is_accessible(pipe); | 204 | ret = usbhsf_fifo_select(pipe, 1); |
185 | if (ret < 0) | 205 | if (ret < 0) |
186 | goto usbhs_fifo_write_busy; | 206 | goto usbhs_fifo_write_busy; |
187 | 207 | ||
188 | ret = usbhsf_fifo_select(pipe, 1); | 208 | ret = usbhs_pipe_is_accessible(pipe); |
189 | if (ret < 0) | 209 | if (ret < 0) |
190 | goto usbhs_fifo_write_busy; | 210 | goto usbhs_fifo_write_busy; |
191 | 211 | ||
@@ -246,8 +266,7 @@ int usbhs_fifo_write(struct usbhs_pkt *pkt) | |||
246 | if (usbhs_pipe_is_dcp(pipe)) | 266 | if (usbhs_pipe_is_dcp(pipe)) |
247 | usbhs_dcp_control_transfer_done(pipe); | 267 | usbhs_dcp_control_transfer_done(pipe); |
248 | 268 | ||
249 | if (info->tx_done) | 269 | info->done(pkt); |
250 | info->tx_done(pkt); | ||
251 | } | 270 | } |
252 | 271 | ||
253 | return 0; | 272 | return 0; |
@@ -262,8 +281,14 @@ usbhs_fifo_write_busy: | |||
262 | return ret; | 281 | return ret; |
263 | } | 282 | } |
264 | 283 | ||
265 | int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe) | 284 | struct usbhs_pkt_handle usbhs_fifo_push_handler = { |
285 | .prepare = usbhsf_try_push, | ||
286 | .try_run = usbhsf_try_push, | ||
287 | }; | ||
288 | |||
289 | static int usbhsf_prepare_pop(struct usbhs_pkt *pkt) | ||
266 | { | 290 | { |
291 | struct usbhs_pipe *pipe = pkt->pipe; | ||
267 | int ret; | 292 | int ret; |
268 | 293 | ||
269 | /* | 294 | /* |
@@ -279,7 +304,7 @@ int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe) | |||
279 | return ret; | 304 | return ret; |
280 | } | 305 | } |
281 | 306 | ||
282 | int usbhs_fifo_read(struct usbhs_pkt *pkt) | 307 | static int usbhsf_try_pop(struct usbhs_pkt *pkt) |
283 | { | 308 | { |
284 | struct usbhs_pipe *pipe = pkt->pipe; | 309 | struct usbhs_pipe *pipe = pkt->pipe; |
285 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 310 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
@@ -355,9 +380,124 @@ usbhs_fifo_read_end: | |||
355 | usbhsf_rx_irq_ctrl(pipe, 0); | 380 | usbhsf_rx_irq_ctrl(pipe, 0); |
356 | usbhs_pipe_disable(pipe); | 381 | usbhs_pipe_disable(pipe); |
357 | 382 | ||
358 | if (info->rx_done) | 383 | info->done(pkt); |
359 | info->rx_done(pkt); | ||
360 | } | 384 | } |
361 | 385 | ||
362 | return 0; | 386 | return 0; |
363 | } | 387 | } |
388 | |||
389 | struct usbhs_pkt_handle usbhs_fifo_pop_handler = { | ||
390 | .prepare = usbhsf_prepare_pop, | ||
391 | .try_run = usbhsf_try_pop, | ||
392 | }; | ||
393 | |||
394 | /* | ||
395 | * handler function | ||
396 | */ | ||
397 | static int usbhsf_ctrl_stage_end(struct usbhs_pkt *pkt) | ||
398 | { | ||
399 | struct usbhs_pipe *pipe = pkt->pipe; | ||
400 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
401 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); | ||
402 | |||
403 | usbhs_dcp_control_transfer_done(pipe); | ||
404 | |||
405 | info->done(pkt); | ||
406 | |||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler = { | ||
411 | .prepare = usbhsf_ctrl_stage_end, | ||
412 | .try_run = usbhsf_ctrl_stage_end, | ||
413 | }; | ||
414 | |||
415 | /* | ||
416 | * irq functions | ||
417 | */ | ||
418 | static int usbhsf_irq_empty(struct usbhs_priv *priv, | ||
419 | struct usbhs_irq_state *irq_state) | ||
420 | { | ||
421 | struct usbhs_pipe *pipe; | ||
422 | struct usbhs_pkt *pkt; | ||
423 | struct device *dev = usbhs_priv_to_dev(priv); | ||
424 | int i, ret; | ||
425 | |||
426 | if (!irq_state->bempsts) { | ||
427 | dev_err(dev, "debug %s !!\n", __func__); | ||
428 | return -EIO; | ||
429 | } | ||
430 | |||
431 | dev_dbg(dev, "irq empty [0x%04x]\n", irq_state->bempsts); | ||
432 | |||
433 | /* | ||
434 | * search interrupted "pipe" | ||
435 | * not "uep". | ||
436 | */ | ||
437 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | ||
438 | if (!(irq_state->bempsts & (1 << i))) | ||
439 | continue; | ||
440 | |||
441 | pkt = usbhs_pkt_get(pipe); | ||
442 | ret = usbhs_pkt_run(pkt); | ||
443 | if (ret < 0) | ||
444 | dev_err(dev, "irq_empty run_error %d : %d\n", i, ret); | ||
445 | } | ||
446 | |||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | static int usbhsf_irq_ready(struct usbhs_priv *priv, | ||
451 | struct usbhs_irq_state *irq_state) | ||
452 | { | ||
453 | struct usbhs_pipe *pipe; | ||
454 | struct usbhs_pkt *pkt; | ||
455 | struct device *dev = usbhs_priv_to_dev(priv); | ||
456 | int i, ret; | ||
457 | |||
458 | if (!irq_state->brdysts) { | ||
459 | dev_err(dev, "debug %s !!\n", __func__); | ||
460 | return -EIO; | ||
461 | } | ||
462 | |||
463 | dev_dbg(dev, "irq ready [0x%04x]\n", irq_state->brdysts); | ||
464 | |||
465 | /* | ||
466 | * search interrupted "pipe" | ||
467 | * not "uep". | ||
468 | */ | ||
469 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | ||
470 | if (!(irq_state->brdysts & (1 << i))) | ||
471 | continue; | ||
472 | |||
473 | pkt = usbhs_pkt_get(pipe); | ||
474 | ret = usbhs_pkt_run(pkt); | ||
475 | if (ret < 0) | ||
476 | dev_err(dev, "irq_ready run_error %d : %d\n", i, ret); | ||
477 | } | ||
478 | |||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | /* | ||
483 | * fifo init | ||
484 | */ | ||
485 | void usbhs_fifo_init(struct usbhs_priv *priv) | ||
486 | { | ||
487 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | ||
488 | |||
489 | mod->irq_empty = usbhsf_irq_empty; | ||
490 | mod->irq_ready = usbhsf_irq_ready; | ||
491 | mod->irq_bempsts = 0; | ||
492 | mod->irq_brdysts = 0; | ||
493 | } | ||
494 | |||
495 | void usbhs_fifo_quit(struct usbhs_priv *priv) | ||
496 | { | ||
497 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | ||
498 | |||
499 | mod->irq_empty = NULL; | ||
500 | mod->irq_ready = NULL; | ||
501 | mod->irq_bempsts = 0; | ||
502 | mod->irq_brdysts = 0; | ||
503 | } | ||