Commit 9e74d601de8adb0fe96e100e459ac52f2ddd47f3

Authored by Kuninori Morimoto
Committed by Felipe Balbi
1 parent 89c1d2e7b5

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>

Showing 2 changed files with 150 additions and 0 deletions Side-by-side Diff

drivers/usb/renesas_usbhs/fifo.c
... ... @@ -321,6 +321,151 @@
321 321 }
322 322  
323 323 /*
  324 + * DCP status stage
  325 + */
  326 +static 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 +
  355 +static 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 +
  383 +static 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 +
  398 +struct 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 +
  403 +struct 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 + */
  411 +static 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 +
  425 +struct 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 + */
  432 +static 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 +
  464 +struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler = {
  465 + .prepare = usbhsf_dcp_data_stage_prepare_pop,
  466 +};
  467 +
  468 +/*
324 469 * PIO push handler
325 470 */
326 471 static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done)
drivers/usb/renesas_usbhs/fifo.h
... ... @@ -85,6 +85,11 @@
85 85 extern struct usbhs_pkt_handle usbhs_fifo_dma_push_handler;
86 86 extern struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler;
87 87  
  88 +extern struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler;
  89 +extern struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler;
  90 +
  91 +extern struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler;
  92 +extern struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler;
88 93  
89 94 void usbhs_pkt_init(struct usbhs_pkt *pkt);
90 95 void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,