usb: renesas_usbhs: add support for requesting DT DMA
[deliverable/linux.git] / drivers / usb / renesas_usbhs / fifo.c
index b0c97a3f1bfed74e262c3aa818817259f31e987e..4c086b1cda0495daa110ffb741f1ba8865015046 100644 (file)
@@ -21,8 +21,6 @@
 #include "pipe.h"
 
 #define usbhsf_get_cfifo(p)    (&((p)->fifo_info.cfifo))
-#define usbhsf_get_d0fifo(p)   (&((p)->fifo_info.d0fifo))
-#define usbhsf_get_d1fifo(p)   (&((p)->fifo_info.d1fifo))
 #define usbhsf_is_cfifo(p, f)  (usbhsf_get_cfifo(p) == f)
 
 #define usbhsf_fifo_is_busy(f) ((f)->pipe) /* see usbhs_pipe_select_fifo */
@@ -577,14 +575,6 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done)
                usbhs_pipe_number(pipe),
                pkt->length, pkt->actual, *is_done, pkt->zero);
 
-       /*
-        * Transmission end
-        */
-       if (*is_done) {
-               if (usbhs_pipe_is_dcp(pipe))
-                       usbhs_dcp_control_transfer_done(pipe);
-       }
-
        usbhsf_fifo_unselect(pipe, fifo);
 
        return 0;
@@ -722,14 +712,6 @@ usbhs_fifo_read_end:
                usbhs_pipe_number(pipe),
                pkt->length, pkt->actual, *is_done, pkt->zero);
 
-       /*
-        * Transmission end
-        */
-       if (*is_done) {
-               if (usbhs_pipe_is_dcp(pipe))
-                       usbhs_dcp_control_transfer_done(pipe);
-       }
-
 usbhs_fifo_read_busy:
        usbhsf_fifo_unselect(pipe, fifo);
 
@@ -777,18 +759,13 @@ static struct usbhs_fifo *usbhsf_get_dma_fifo(struct usbhs_priv *priv,
                                              struct usbhs_pkt *pkt)
 {
        struct usbhs_fifo *fifo;
+       int i;
 
-       /* DMA :: D0FIFO */
-       fifo = usbhsf_get_d0fifo(priv);
-       if (usbhsf_dma_chan_get(fifo, pkt) &&
-           !usbhsf_fifo_is_busy(fifo))
-               return fifo;
-
-       /* DMA :: D1FIFO */
-       fifo = usbhsf_get_d1fifo(priv);
-       if (usbhsf_dma_chan_get(fifo, pkt) &&
-           !usbhsf_fifo_is_busy(fifo))
-               return fifo;
+       usbhs_for_each_dfifo(priv, fifo, i) {
+               if (usbhsf_dma_chan_get(fifo, pkt) &&
+                   !usbhsf_fifo_is_busy(fifo))
+                       return fifo;
+       }
 
        return NULL;
 }
@@ -1077,10 +1054,8 @@ static void usbhsf_dma_quit(struct usbhs_priv *priv, struct usbhs_fifo *fifo)
        fifo->rx_chan = NULL;
 }
 
-static void usbhsf_dma_init(struct usbhs_priv *priv,
-                           struct usbhs_fifo *fifo)
+static void usbhsf_dma_init_pdev(struct usbhs_fifo *fifo)
 {
-       struct device *dev = usbhs_priv_to_dev(priv);
        dma_cap_mask_t mask;
 
        dma_cap_zero(mask);
@@ -1092,6 +1067,23 @@ static void usbhsf_dma_init(struct usbhs_priv *priv,
        dma_cap_set(DMA_SLAVE, mask);
        fifo->rx_chan = dma_request_channel(mask, usbhsf_dma_filter,
                                            &fifo->rx_slave);
+}
+
+static void usbhsf_dma_init_dt(struct device *dev, struct usbhs_fifo *fifo)
+{
+       fifo->tx_chan = dma_request_slave_channel_reason(dev, "tx");
+       fifo->rx_chan = dma_request_slave_channel_reason(dev, "rx");
+}
+
+static void usbhsf_dma_init(struct usbhs_priv *priv,
+                           struct usbhs_fifo *fifo)
+{
+       struct device *dev = usbhs_priv_to_dev(priv);
+
+       if (dev->of_node)
+               usbhsf_dma_init_dt(dev, fifo);
+       else
+               usbhsf_dma_init_pdev(fifo);
 
        if (fifo->tx_chan || fifo->rx_chan)
                dev_dbg(dev, "enable DMAEngine (%s%s%s)\n",
@@ -1176,6 +1168,24 @@ static void usbhsf_dma_complete(void *arg)
                        usbhs_pipe_number(pipe), ret);
 }
 
+void usbhs_fifo_clear_dcp(struct usbhs_pipe *pipe)
+{
+       struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+       struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */
+
+       /* clear DCP FIFO of transmission */
+       if (usbhsf_fifo_select(pipe, fifo, 1) < 0)
+               return;
+       usbhsf_fifo_clear(pipe, fifo);
+       usbhsf_fifo_unselect(pipe, fifo);
+
+       /* clear DCP FIFO of reception */
+       if (usbhsf_fifo_select(pipe, fifo, 0) < 0)
+               return;
+       usbhsf_fifo_clear(pipe, fifo);
+       usbhsf_fifo_unselect(pipe, fifo);
+}
+
 /*
  *             fifo init
  */
@@ -1183,8 +1193,8 @@ 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);
-       struct usbhs_fifo *d0fifo = usbhsf_get_d0fifo(priv);
-       struct usbhs_fifo *d1fifo = usbhsf_get_d1fifo(priv);
+       struct usbhs_fifo *dfifo;
+       int i;
 
        mod->irq_empty          = usbhsf_irq_empty;
        mod->irq_ready          = usbhsf_irq_ready;
@@ -1192,8 +1202,8 @@ void usbhs_fifo_init(struct usbhs_priv *priv)
        mod->irq_brdysts        = 0;
 
        cfifo->pipe     = NULL;
-       d0fifo->pipe    = NULL;
-       d1fifo->pipe    = NULL;
+       usbhs_for_each_dfifo(priv, dfifo, i)
+               dfifo->pipe     = NULL;
 }
 
 void usbhs_fifo_quit(struct usbhs_priv *priv)
@@ -1206,6 +1216,25 @@ void usbhs_fifo_quit(struct usbhs_priv *priv)
        mod->irq_brdysts        = 0;
 }
 
+#define __USBHS_DFIFO_INIT(priv, fifo, channel, fifo_port)             \
+do {                                                                   \
+       fifo = usbhsf_get_dnfifo(priv, channel);                        \
+       fifo->name      = "D"#channel"FIFO";                            \
+       fifo->port      = fifo_port;                                    \
+       fifo->sel       = D##channel##FIFOSEL;                          \
+       fifo->ctr       = D##channel##FIFOCTR;                          \
+       fifo->tx_slave.shdma_slave.slave_id =                           \
+                       usbhs_get_dparam(priv, d##channel##_tx_id);     \
+       fifo->rx_slave.shdma_slave.slave_id =                           \
+                       usbhs_get_dparam(priv, d##channel##_rx_id);     \
+       usbhsf_dma_init(priv, fifo);                                    \
+} while (0)
+
+#define USBHS_DFIFO_INIT(priv, fifo, channel)                          \
+               __USBHS_DFIFO_INIT(priv, fifo, channel, D##channel##FIFO)
+#define USBHS_DFIFO_INIT_NO_PORT(priv, fifo, channel)                  \
+               __USBHS_DFIFO_INIT(priv, fifo, channel, 0)
+
 int usbhs_fifo_probe(struct usbhs_priv *priv)
 {
        struct usbhs_fifo *fifo;
@@ -1217,31 +1246,20 @@ int usbhs_fifo_probe(struct usbhs_priv *priv)
        fifo->sel       = CFIFOSEL;
        fifo->ctr       = CFIFOCTR;
 
-       /* D0FIFO */
-       fifo = usbhsf_get_d0fifo(priv);
-       fifo->name      = "D0FIFO";
-       fifo->port      = D0FIFO;
-       fifo->sel       = D0FIFOSEL;
-       fifo->ctr       = D0FIFOCTR;
-       fifo->tx_slave.shdma_slave.slave_id     = usbhs_get_dparam(priv, d0_tx_id);
-       fifo->rx_slave.shdma_slave.slave_id     = usbhs_get_dparam(priv, d0_rx_id);
-       usbhsf_dma_init(priv, fifo);
-
-       /* D1FIFO */
-       fifo = usbhsf_get_d1fifo(priv);
-       fifo->name      = "D1FIFO";
-       fifo->port      = D1FIFO;
-       fifo->sel       = D1FIFOSEL;
-       fifo->ctr       = D1FIFOCTR;
-       fifo->tx_slave.shdma_slave.slave_id     = usbhs_get_dparam(priv, d1_tx_id);
-       fifo->rx_slave.shdma_slave.slave_id     = usbhs_get_dparam(priv, d1_rx_id);
-       usbhsf_dma_init(priv, fifo);
+       /* DFIFO */
+       USBHS_DFIFO_INIT(priv, fifo, 0);
+       USBHS_DFIFO_INIT(priv, fifo, 1);
+       USBHS_DFIFO_INIT_NO_PORT(priv, fifo, 2);
+       USBHS_DFIFO_INIT_NO_PORT(priv, fifo, 3);
 
        return 0;
 }
 
 void usbhs_fifo_remove(struct usbhs_priv *priv)
 {
-       usbhsf_dma_quit(priv, usbhsf_get_d0fifo(priv));
-       usbhsf_dma_quit(priv, usbhsf_get_d1fifo(priv));
+       struct usbhs_fifo *fifo;
+       int i;
+
+       usbhs_for_each_dfifo(priv, fifo, i)
+               usbhsf_dma_quit(priv, fifo);
 }
This page took 0.02732 seconds and 5 git commands to generate.