[PATCH 217/260] usb: gadget: renesas_usbhs: add data/status stage handler

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Kuninori Morimoto <kuninori.morimoto.gx@xxxxxxxxxxx>

mod_host needs data/status stage handler

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@xxxxxxxxxxx>
Signed-off-by: Felipe Balbi <balbi@xxxxxx>
---
 drivers/usb/renesas_usbhs/fifo.c |  145 ++++++++++++++++++++++++++++++++++++++
 drivers/usb/renesas_usbhs/fifo.h |    5 ++
 2 files changed, 150 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index 1a345c2..16b12b0 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,
 }
 
 /*
+ *		DCP status stage
+ */
+static int usbhs_dcp_dir_switch_to_write(struct usbhs_pkt *pkt, int *is_done)
+{
+	struct usbhs_pipe *pipe = pkt->pipe;
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+	struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */
+	struct device *dev = usbhs_priv_to_dev(priv);
+	int ret;
+
+	usbhs_pipe_disable(pipe);
+
+	ret = usbhsf_fifo_select(pipe, fifo, 1);
+	if (ret < 0) {
+		dev_err(dev, "%s() faile\n", __func__);
+		return ret;
+	}
+
+	usbhs_pipe_sequence_data1(pipe); /* DATA1 */
+
+	usbhsf_fifo_clear(pipe, fifo);
+	usbhsf_send_terminator(pipe, fifo);
+
+	usbhsf_fifo_unselect(pipe, fifo);
+
+	usbhsf_tx_irq_ctrl(pipe, 1);
+	usbhs_pipe_enable(pipe);
+
+	return ret;
+}
+
+static int usbhs_dcp_dir_switch_to_read(struct usbhs_pkt *pkt, int *is_done)
+{
+	struct usbhs_pipe *pipe = pkt->pipe;
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+	struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */
+	struct device *dev = usbhs_priv_to_dev(priv);
+	int ret;
+
+	usbhs_pipe_disable(pipe);
+
+	ret = usbhsf_fifo_select(pipe, fifo, 0);
+	if (ret < 0) {
+		dev_err(dev, "%s() fail\n", __func__);
+		return ret;
+	}
+
+	usbhs_pipe_sequence_data1(pipe); /* DATA1 */
+	usbhsf_fifo_clear(pipe, fifo);
+
+	usbhsf_fifo_unselect(pipe, fifo);
+
+	usbhsf_rx_irq_ctrl(pipe, 1);
+	usbhs_pipe_enable(pipe);
+
+	return ret;
+
+}
+
+static int usbhs_dcp_dir_switch_done(struct usbhs_pkt *pkt, int *is_done)
+{
+	struct usbhs_pipe *pipe = pkt->pipe;
+
+	if (pkt->handler == &usbhs_dcp_status_stage_in_handler)
+		usbhsf_tx_irq_ctrl(pipe, 0);
+	else
+		usbhsf_rx_irq_ctrl(pipe, 0);
+
+	pkt->actual = pkt->length;
+	*is_done = 1;
+
+	return 0;
+}
+
+struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler = {
+	.prepare = usbhs_dcp_dir_switch_to_write,
+	.try_run = usbhs_dcp_dir_switch_done,
+};
+
+struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler = {
+	.prepare = usbhs_dcp_dir_switch_to_read,
+	.try_run = usbhs_dcp_dir_switch_done,
+};
+
+/*
+ *		DCP data stage (push)
+ */
+static int usbhsf_dcp_data_stage_try_push(struct usbhs_pkt *pkt, int *is_done)
+{
+	struct usbhs_pipe *pipe = pkt->pipe;
+
+	usbhs_pipe_sequence_data1(pipe); /* DATA1 */
+
+	/*
+	 * change handler to PIO push
+	 */
+	pkt->handler = &usbhs_fifo_pio_push_handler;
+
+	return pkt->handler->prepare(pkt, is_done);
+}
+
+struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler = {
+	.prepare = usbhsf_dcp_data_stage_try_push,
+};
+
+/*
+ *		DCP data stage (pop)
+ */
+static int usbhsf_dcp_data_stage_prepare_pop(struct usbhs_pkt *pkt,
+					     int *is_done)
+{
+	struct usbhs_pipe *pipe = pkt->pipe;
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+	struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv);
+
+	if (usbhs_pipe_is_busy(pipe))
+		return 0;
+
+	/*
+	 * prepare pop for DCP should
+	 *  - change DCP direction,
+	 *  - clear fifo
+	 *  - DATA1
+	 */
+	usbhs_pipe_disable(pipe);
+
+	usbhs_pipe_sequence_data1(pipe); /* DATA1 */
+
+	usbhsf_fifo_select(pipe, fifo, 0);
+	usbhsf_fifo_clear(pipe, fifo);
+	usbhsf_fifo_unselect(pipe, fifo);
+
+	/*
+	 * change handler to PIO pop
+	 */
+	pkt->handler = &usbhs_fifo_pio_pop_handler;
+
+	return pkt->handler->prepare(pkt, is_done);
+}
+
+struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler = {
+	.prepare = usbhsf_dcp_data_stage_prepare_pop,
+};
+
+/*
  *		PIO push handler
  */
 static 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 0e82d67..32a7b24 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;
 extern struct usbhs_pkt_handle usbhs_fifo_dma_push_handler;
 extern struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler;
 
+extern struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler;
+extern struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler;
+
+extern struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler;
+extern struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler;
 
 void usbhs_pkt_init(struct usbhs_pkt *pkt);
 void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
-- 
1.7.7

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux