Merge tag 'wberr-v4.14-1' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayton...
[sfrench/cifs-2.6.git] / drivers / spi / spi-qup.c
index 3c2c2c0ed9ab433c144285395b79b1f38e7272eb..974a8ce58b68bc31e38d717ff16564aec398232e 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/spi/spi.h>
@@ -266,7 +267,7 @@ static void spi_qup_read_from_fifo(struct spi_qup *controller, u32 num_words)
        }
 }
 
-static void spi_qup_read(struct spi_qup *controller)
+static void spi_qup_read(struct spi_qup *controller, u32 *opflags)
 {
        u32 remainder, words_per_block, num_words;
        bool is_block_mode = controller->mode == QUP_IO_M_MODE_BLOCK;
@@ -305,10 +306,12 @@ static void spi_qup_read(struct spi_qup *controller)
 
        /*
         * Due to extra stickiness of the QUP_OP_IN_SERVICE_FLAG during block
-        * mode reads, it has to be cleared again at the very end
+        * reads, it has to be cleared again at the very end.  However, be sure
+        * to refresh opflags value because MAX_INPUT_DONE_FLAG may now be
+        * present and this is used to determine if transaction is complete
         */
-       if (is_block_mode && spi_qup_is_flag_set(controller,
-                               QUP_OP_MAX_INPUT_DONE_FLAG))
+       *opflags = readl_relaxed(controller->base + QUP_OPERATIONAL);
+       if (is_block_mode && *opflags & QUP_OP_MAX_INPUT_DONE_FLAG)
                writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
                               controller->base + QUP_OPERATIONAL);
 
@@ -424,8 +427,6 @@ static u32 spi_qup_sgl_get_nents_len(struct scatterlist *sgl, u32 max,
        struct scatterlist *sg;
        u32 total = 0;
 
-       *nents = 0;
-
        for (sg = sgl; sg; sg = sg_next(sg)) {
                unsigned int len = sg_dma_len(sg);
 
@@ -458,7 +459,7 @@ static int spi_qup_do_dma(struct spi_device *spi, struct spi_transfer *xfer,
        tx_sgl = xfer->tx_sg.sgl;
 
        do {
-               u32 rx_nents, tx_nents;
+               u32 rx_nents = 0, tx_nents = 0;
 
                if (rx_sgl)
                        qup->n_words = spi_qup_sgl_get_nents_len(rx_sgl,
@@ -613,7 +614,7 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
                writel_relaxed(opflags, controller->base + QUP_OPERATIONAL);
        } else {
                if (opflags & QUP_OP_IN_SERVICE_FLAG)
-                       spi_qup_read(controller);
+                       spi_qup_read(controller, &opflags);
 
                if (opflags & QUP_OP_OUT_SERVICE_FLAG)
                        spi_qup_write(controller);
@@ -1056,9 +1057,7 @@ static int spi_qup_probe(struct platform_device *pdev)
        else if (!ret)
                master->can_dma = spi_qup_can_dma;
 
-       /* set v1 flag if device is version 1 */
-       if (of_device_is_compatible(dev->of_node, "qcom,spi-qup-v1.1.1"))
-               controller->qup_v1 = 1;
+       controller->qup_v1 = (uintptr_t)of_device_get_match_data(dev);
 
        if (!controller->qup_v1)
                master->set_cs = spi_qup_set_cs;
@@ -1254,7 +1253,7 @@ static int spi_qup_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id spi_qup_dt_match[] = {
-       { .compatible = "qcom,spi-qup-v1.1.1", },
+       { .compatible = "qcom,spi-qup-v1.1.1", .data = (void *)1, },
        { .compatible = "qcom,spi-qup-v2.1.1", },
        { .compatible = "qcom,spi-qup-v2.2.1", },
        { }