aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2011-10-11 01:07:08 -0400
committerFelipe Balbi <balbi@ti.com>2011-10-13 13:41:51 -0400
commit9e74d601de8adb0fe96e100e459ac52f2ddd47f3 (patch)
tree85fb10664987f1cebf3b13b76bb6e1422a7c320f /drivers/usb
parent89c1d2e7b5993db33805b42e3675289920812f6f (diff)
usb: gadget: renesas_usbhs: add data/status stage handler
mod_host needs data/status stage handler Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/renesas_usbhs/fifo.c145
-rw-r--r--drivers/usb/renesas_usbhs/fifo.h5
2 files changed, 150 insertions, 0 deletions
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index 1a345c20105f..16b12b09110a 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -321,6 +321,151 @@ static int usbhsf_fifo_select(struct usbhs_pipe *pipe,
321} 321}
322 322
323/* 323/*
324 * DCP status stage
325 */
326static int usbhs_dcp_dir_switch_to_write(struct usbhs_pkt *pkt, int *is_done)
327{
328 struct usbhs_pipe *pipe = pkt->pipe;
329 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
330 struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */
331 struct device *dev = usbhs_priv_to_dev(priv);
332 int ret;
333
334 usbhs_pipe_disable(pipe);
335
336 ret = usbhsf_fifo_select(pipe, fifo, 1);
337 if (ret < 0) {
338 dev_err(dev, "%s() faile\n", __func__);
339 return ret;
340 }
341
342 usbhs_pipe_sequence_data1(pipe); /* DATA1 */
343
344 usbhsf_fifo_clear(pipe, fifo);
345 usbhsf_send_terminator(pipe, fifo);
346
347 usbhsf_fifo_unselect(pipe, fifo);
348
349 usbhsf_tx_irq_ctrl(pipe, 1);
350 usbhs_pipe_enable(pipe);
351
352 return ret;
353}
354
355static int usbhs_dcp_dir_switch_to_read(struct usbhs_pkt *pkt, int *is_done)
356{
357 struct usbhs_pipe *pipe = pkt->pipe;
358 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
359 struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */
360 struct device *dev = usbhs_priv_to_dev(priv);
361 int ret;
362
363 usbhs_pipe_disable(pipe);
364
365 ret = usbhsf_fifo_select(pipe, fifo, 0);
366 if (ret < 0) {
367 dev_err(dev, "%s() fail\n", __func__);
368 return ret;
369 }
370
371 usbhs_pipe_sequence_data1(pipe); /* DATA1 */
372 usbhsf_fifo_clear(pipe, fifo);
373
374 usbhsf_fifo_unselect(pipe, fifo);
375
376 usbhsf_rx_irq_ctrl(pipe, 1);
377 usbhs_pipe_enable(pipe);
378
379 return ret;
380
381}
382
383static int usbhs_dcp_dir_switch_done(struct usbhs_pkt *pkt, int *is_done)
384{
385 struct usbhs_pipe *pipe = pkt->pipe;
386
387 if (pkt->handler == &usbhs_dcp_status_stage_in_handler)
388 usbhsf_tx_irq_ctrl(pipe, 0);
389 else
390 usbhsf_rx_irq_ctrl(pipe, 0);
391
392 pkt->actual = pkt->length;
393 *is_done = 1;
394
395 return 0;
396}
397
398struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler = {
399 .prepare = usbhs_dcp_dir_switch_to_write,
400 .try_run = usbhs_dcp_dir_switch_done,
401};
402
403struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler = {
404 .prepare = usbhs_dcp_dir_switch_to_read,
405 .try_run = usbhs_dcp_dir_switch_done,
406};
407
408/*
409 * DCP data stage (push)
410 */
411static int usbhsf_dcp_data_stage_try_push(struct usbhs_pkt *pkt, int *is_done)
412{
413 struct usbhs_pipe *pipe = pkt->pipe;
414
415 usbhs_pipe_sequence_data1(pipe); /* DATA1 */
416
417 /*
418 * change handler to PIO push
419 */
420 pkt->handler = &usbhs_fifo_pio_push_handler;
421
422 return pkt->handler->prepare(pkt, is_done);
423}
424
425struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler = {
426 .prepare = usbhsf_dcp_data_stage_try_push,
427};
428
429/*
430 * DCP data stage (pop)
431 */
432static int usbhsf_dcp_data_stage_prepare_pop(struct usbhs_pkt *pkt,
433 int *is_done)
434{
435 struct usbhs_pipe *pipe = pkt->pipe;
436 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
437 struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv);
438
439 if (usbhs_pipe_is_busy(pipe))
440 return 0;
441
442 /*
443 * prepare pop for DCP should
444 * - change DCP direction,
445 * - clear fifo
446 * - DATA1
447 */
448 usbhs_pipe_disable(pipe);
449
450 usbhs_pipe_sequence_data1(pipe); /* DATA1 */
451
452 usbhsf_fifo_select(pipe, fifo, 0);
453 usbhsf_fifo_clear(pipe, fifo);
454 usbhsf_fifo_unselect(pipe, fifo);
455
456 /*
457 * change handler to PIO pop
458 */
459 pkt->handler = &usbhs_fifo_pio_pop_handler;
460
461 return pkt->handler->prepare(pkt, is_done);
462}
463
464struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler = {
465 .prepare = usbhsf_dcp_data_stage_prepare_pop,
466};
467
468/*
324 * PIO push handler 469 * PIO push handler
325 */ 470 */
326static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done) 471static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done)
diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h
index 0e82d67a0257..32a7b246b28d 100644
--- a/drivers/usb/renesas_usbhs/fifo.h
+++ b/drivers/usb/renesas_usbhs/fifo.h
@@ -85,6 +85,11 @@ extern struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler;
85extern struct usbhs_pkt_handle usbhs_fifo_dma_push_handler; 85extern struct usbhs_pkt_handle usbhs_fifo_dma_push_handler;
86extern struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler; 86extern struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler;
87 87
88extern struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler;
89extern struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler;
90
91extern struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler;
92extern struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler;
88 93
89void usbhs_pkt_init(struct usbhs_pkt *pkt); 94void usbhs_pkt_init(struct usbhs_pkt *pkt);
90void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, 95void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,