pps: add kernel consumer support
[firefly-linux-kernel-4.4.55.git] / drivers / spi / dw_spi.c
index b50bf5ba873f65628f43f6b438903599921f5cf5..22af77f98816c5116a1e138f59dc169d0e52ff71 100644 (file)
@@ -288,8 +288,10 @@ static void *next_transfer(struct dw_spi *dws)
  */
 static int map_dma_buffers(struct dw_spi *dws)
 {
-       if (!dws->cur_msg->is_dma_mapped || !dws->dma_inited
-               || !dws->cur_chip->enable_dma)
+       if (!dws->cur_msg->is_dma_mapped
+               || !dws->dma_inited
+               || !dws->cur_chip->enable_dma
+               || !dws->dma_ops)
                return 0;
 
        if (dws->cur_transfer->tx_dma)
@@ -341,7 +343,7 @@ static void int_error_stop(struct dw_spi *dws, const char *msg)
        tasklet_schedule(&dws->pump_transfers);
 }
 
-static void transfer_complete(struct dw_spi *dws)
+void dw_spi_xfer_done(struct dw_spi *dws)
 {
        /* Update total byte transfered return count actual bytes read */
        dws->cur_msg->actual_length += dws->len;
@@ -356,6 +358,7 @@ static void transfer_complete(struct dw_spi *dws)
        } else
                tasklet_schedule(&dws->pump_transfers);
 }
+EXPORT_SYMBOL_GPL(dw_spi_xfer_done);
 
 static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 {
@@ -387,7 +390,7 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
                if (dws->tx_end > dws->tx)
                        spi_umask_intr(dws, SPI_INT_TXEI);
                else
-                       transfer_complete(dws);
+                       dw_spi_xfer_done(dws);
        }
 
        return IRQ_HANDLED;
@@ -422,11 +425,7 @@ static void poll_transfer(struct dw_spi *dws)
         */
        dws->read(dws);
 
-       transfer_complete(dws);
-}
-
-static void dma_transfer(struct dw_spi *dws, int cs_change)
-{
+       dw_spi_xfer_done(dws);
 }
 
 static void pump_transfers(unsigned long data)
@@ -595,7 +594,7 @@ static void pump_transfers(unsigned long data)
                spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);
                spi_chip_sel(dws, spi->chip_select);
 
-               /* Set the interrupt mask, for poll mode just diable all int */
+               /* Set the interrupt mask, for poll mode just disable all int */
                spi_mask_intr(dws, 0xff);
                if (imask)
                        spi_umask_intr(dws, imask);
@@ -608,7 +607,7 @@ static void pump_transfers(unsigned long data)
        }
 
        if (dws->dma_mapped)
-               dma_transfer(dws, cs_change);
+               dws->dma_ops->dma_transfer(dws, cs_change);
 
        if (chip->poll_mode)
                poll_transfer(dws);
@@ -904,11 +903,17 @@ int __devinit dw_spi_add_host(struct dw_spi *dws)
        master->setup = dw_spi_setup;
        master->transfer = dw_spi_transfer;
 
-       dws->dma_inited = 0;
-
        /* Basic HW init */
        spi_hw_init(dws);
 
+       if (dws->dma_ops && dws->dma_ops->dma_init) {
+               ret = dws->dma_ops->dma_init(dws);
+               if (ret) {
+                       dev_warn(&master->dev, "DMA init failed\n");
+                       dws->dma_inited = 0;
+               }
+       }
+
        /* Initial and start queue */
        ret = init_queue(dws);
        if (ret) {
@@ -933,6 +938,8 @@ int __devinit dw_spi_add_host(struct dw_spi *dws)
 
 err_queue_alloc:
        destroy_queue(dws);
+       if (dws->dma_ops && dws->dma_ops->dma_exit)
+               dws->dma_ops->dma_exit(dws);
 err_diable_hw:
        spi_enable_chip(dws, 0);
        free_irq(dws->irq, dws);
@@ -957,6 +964,8 @@ void __devexit dw_spi_remove_host(struct dw_spi *dws)
                dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not "
                        "complete, message memory not freed\n");
 
+       if (dws->dma_ops && dws->dma_ops->dma_exit)
+               dws->dma_ops->dma_exit(dws);
        spi_enable_chip(dws, 0);
        /* Disable clk */
        spi_set_clk(dws, 0);