usb: renesas_usbhs: add pipe/fifo link

renesas_usbhs has CFIFO which is for PIO transfer,
and D0FIFO/D1FIFO which are for DMA transfer.
The pipe selects one of these fifo when it send/recv data.
But fifo must not be selected to different pipe in same time.
This patch add pipe/fifo link for each other,
and fifo is not selected by another pipe until it is unselected.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index 53e2b35..8852423 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -21,6 +21,8 @@
 
 #define usbhsf_get_cfifo(p)	(&((p)->fifo_info.cfifo))
 
+#define usbhsf_fifo_is_busy(f)	((f)->pipe) /* see usbhs_pipe_select_fifo */
+
 /*
  *		packet info function
  */
@@ -237,6 +239,15 @@
 	return usbhs_read(priv, fifo->ctr) & DTLN_MASK;
 }
 
+static void usbhsf_fifo_unselect(struct usbhs_pipe *pipe,
+				 struct usbhs_fifo *fifo)
+{
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+
+	usbhs_pipe_select_fifo(pipe, NULL);
+	usbhs_write(priv, fifo->sel, 0);
+}
+
 static int usbhsf_fifo_select(struct usbhs_pipe *pipe,
 			      struct usbhs_fifo *fifo,
 			      int write)
@@ -247,6 +258,10 @@
 	u16 mask = ((1 << 5) | 0xF);		/* mask of ISEL | CURPIPE */
 	u16 base = usbhs_pipe_number(pipe);	/* CURPIPE */
 
+	if (usbhs_pipe_is_busy(pipe) ||
+	    usbhsf_fifo_is_busy(fifo))
+		return -EBUSY;
+
 	if (usbhs_pipe_is_dcp(pipe))
 		base |= (1 == write) << 5;	/* ISEL */
 
@@ -255,8 +270,10 @@
 
 	/* check ISEL and CURPIPE value */
 	while (timeout--) {
-		if (base == (mask & usbhs_read(priv, fifo->sel)))
+		if (base == (mask & usbhs_read(priv, fifo->sel))) {
+			usbhs_pipe_select_fifo(pipe, fifo);
 			return 0;
+		}
 		udelay(10);
 	}
 
@@ -283,7 +300,7 @@
 
 	ret = usbhsf_fifo_select(pipe, fifo, 1);
 	if (ret < 0)
-		goto usbhs_fifo_write_busy;
+		return 0;
 
 	ret = usbhs_pipe_is_accessible(pipe);
 	if (ret < 0)
@@ -347,9 +364,13 @@
 			usbhs_dcp_control_transfer_done(pipe);
 	}
 
+	usbhsf_fifo_unselect(pipe, fifo);
+
 	return 0;
 
 usbhs_fifo_write_busy:
+	usbhsf_fifo_unselect(pipe, fifo);
+
 	/*
 	 * pipe is busy.
 	 * retry in interrupt
@@ -367,16 +388,13 @@
 static int usbhsf_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); /* CFIFO */
-	int ret;
+
+	if (usbhs_pipe_is_busy(pipe))
+		return 0;
 
 	/*
-	 * select pipe and enable it to prepare packet receive
+	 * pipe enable to prepare packet receive
 	 */
-	ret = usbhsf_fifo_select(pipe, fifo, 0);
-	if (ret < 0)
-		return ret;
 
 	usbhs_pipe_enable(pipe);
 	usbhsf_rx_irq_ctrl(pipe, 1);
@@ -400,11 +418,11 @@
 
 	ret = usbhsf_fifo_select(pipe, fifo, 0);
 	if (ret < 0)
-		return ret;
+		return 0;
 
 	ret = usbhsf_fifo_barrier(priv, fifo);
 	if (ret < 0)
-		return ret;
+		goto usbhs_fifo_read_busy;
 
 	rcv_len = usbhsf_fifo_rcv_len(priv, fifo);
 
@@ -457,7 +475,10 @@
 		usbhs_pipe_number(pipe),
 		pkt->length, pkt->actual, *is_done, pkt->zero);
 
-	return 0;
+usbhs_fifo_read_busy:
+	usbhsf_fifo_unselect(pipe, fifo);
+
+	return ret;
 }
 
 struct usbhs_pkt_handle usbhs_fifo_pop_handler = {
@@ -551,11 +572,14 @@
 void usbhs_fifo_init(struct usbhs_priv *priv)
 {
 	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
+	struct usbhs_fifo *cfifo = usbhsf_get_cfifo(priv);
 
 	mod->irq_empty		= usbhsf_irq_empty;
 	mod->irq_ready		= usbhsf_irq_ready;
 	mod->irq_bempsts	= 0;
 	mod->irq_brdysts	= 0;
+
+	cfifo->pipe	= NULL;
 }
 
 void usbhs_fifo_quit(struct usbhs_priv *priv)