Merge tag 'for-v5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux...
[linux-2.6-microblaze.git] / drivers / spi / spi-stm32.c
index 05618a6..9bd3fd1 100644 (file)
 #define SPI_3WIRE_TX           3
 #define SPI_3WIRE_RX           4
 
+#define STM32_SPI_AUTOSUSPEND_DELAY            1       /* 1 ms */
+
 /*
  * use PIO for small transfers, avoiding DMA setup/teardown overhead for drivers
  * without fifo buffers.
@@ -568,29 +570,30 @@ static void stm32f4_spi_read_rx(struct stm32_spi *spi)
 /**
  * stm32h7_spi_read_rxfifo - Read bytes in Receive Data Register
  * @spi: pointer to the spi controller data structure
- * @flush: boolean indicating that FIFO should be flushed
  *
  * Write in rx_buf depends on remaining bytes to avoid to write beyond
  * rx_buf end.
  */
-static void stm32h7_spi_read_rxfifo(struct stm32_spi *spi, bool flush)
+static void stm32h7_spi_read_rxfifo(struct stm32_spi *spi)
 {
        u32 sr = readl_relaxed(spi->base + STM32H7_SPI_SR);
        u32 rxplvl = FIELD_GET(STM32H7_SPI_SR_RXPLVL, sr);
 
        while ((spi->rx_len > 0) &&
               ((sr & STM32H7_SPI_SR_RXP) ||
-               (flush && ((sr & STM32H7_SPI_SR_RXWNE) || (rxplvl > 0))))) {
+               ((sr & STM32H7_SPI_SR_EOT) &&
+                ((sr & STM32H7_SPI_SR_RXWNE) || (rxplvl > 0))))) {
                u32 offs = spi->cur_xferlen - spi->rx_len;
 
                if ((spi->rx_len >= sizeof(u32)) ||
-                   (flush && (sr & STM32H7_SPI_SR_RXWNE))) {
+                   (sr & STM32H7_SPI_SR_RXWNE)) {
                        u32 *rx_buf32 = (u32 *)(spi->rx_buf + offs);
 
                        *rx_buf32 = readl_relaxed(spi->base + STM32H7_SPI_RXDR);
                        spi->rx_len -= sizeof(u32);
                } else if ((spi->rx_len >= sizeof(u16)) ||
-                          (flush && (rxplvl >= 2 || spi->cur_bpw > 8))) {
+                          (!(sr & STM32H7_SPI_SR_RXWNE) &&
+                           (rxplvl >= 2 || spi->cur_bpw > 8))) {
                        u16 *rx_buf16 = (u16 *)(spi->rx_buf + offs);
 
                        *rx_buf16 = readw_relaxed(spi->base + STM32H7_SPI_RXDR);
@@ -606,8 +609,8 @@ static void stm32h7_spi_read_rxfifo(struct stm32_spi *spi, bool flush)
                rxplvl = FIELD_GET(STM32H7_SPI_SR_RXPLVL, sr);
        }
 
-       dev_dbg(spi->dev, "%s%s: %d bytes left\n", __func__,
-               flush ? "(flush)" : "", spi->rx_len);
+       dev_dbg(spi->dev, "%s: %d bytes left (sr=%08x)\n",
+               __func__, spi->rx_len, sr);
 }
 
 /**
@@ -674,18 +677,12 @@ static void stm32f4_spi_disable(struct stm32_spi *spi)
  * stm32h7_spi_disable - Disable SPI controller
  * @spi: pointer to the spi controller data structure
  *
- * RX-Fifo is flushed when SPI controller is disabled. To prevent any data
- * loss, use stm32h7_spi_read_rxfifo(flush) to read the remaining bytes in
- * RX-Fifo.
- * Normally, if TSIZE has been configured, we should relax the hardware at the
- * reception of the EOT interrupt. But in case of error, EOT will not be
- * raised. So the subsystem unprepare_message call allows us to properly
- * complete the transfer from an hardware point of view.
+ * RX-Fifo is flushed when SPI controller is disabled.
  */
 static void stm32h7_spi_disable(struct stm32_spi *spi)
 {
        unsigned long flags;
-       u32 cr1, sr;
+       u32 cr1;
 
        dev_dbg(spi->dev, "disable controller\n");
 
@@ -698,25 +695,6 @@ static void stm32h7_spi_disable(struct stm32_spi *spi)
                return;
        }
 
-       /* Wait on EOT or suspend the flow */
-       if (readl_relaxed_poll_timeout_atomic(spi->base + STM32H7_SPI_SR,
-                                             sr, !(sr & STM32H7_SPI_SR_EOT),
-                                             10, 100000) < 0) {
-               if (cr1 & STM32H7_SPI_CR1_CSTART) {
-                       writel_relaxed(cr1 | STM32H7_SPI_CR1_CSUSP,
-                                      spi->base + STM32H7_SPI_CR1);
-                       if (readl_relaxed_poll_timeout_atomic(
-                                               spi->base + STM32H7_SPI_SR,
-                                               sr, !(sr & STM32H7_SPI_SR_SUSP),
-                                               10, 100000) < 0)
-                               dev_warn(spi->dev,
-                                        "Suspend request timeout\n");
-               }
-       }
-
-       if (!spi->cur_usedma && spi->rx_buf && (spi->rx_len > 0))
-               stm32h7_spi_read_rxfifo(spi, true);
-
        if (spi->cur_usedma && spi->dma_tx)
                dmaengine_terminate_all(spi->dma_tx);
        if (spi->cur_usedma && spi->dma_rx)
@@ -911,7 +889,7 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id)
                if (__ratelimit(&rs))
                        dev_dbg_ratelimited(spi->dev, "Communication suspended\n");
                if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0)))
-                       stm32h7_spi_read_rxfifo(spi, false);
+                       stm32h7_spi_read_rxfifo(spi);
                /*
                 * If communication is suspended while using DMA, it means
                 * that something went wrong, so stop the current transfer
@@ -932,8 +910,10 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id)
 
        if (sr & STM32H7_SPI_SR_EOT) {
                if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0)))
-                       stm32h7_spi_read_rxfifo(spi, true);
-               end = true;
+                       stm32h7_spi_read_rxfifo(spi);
+               if (!spi->cur_usedma ||
+                   (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX))
+                       end = true;
        }
 
        if (sr & STM32H7_SPI_SR_TXP)
@@ -942,7 +922,7 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id)
 
        if (sr & STM32H7_SPI_SR_RXP)
                if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0)))
-                       stm32h7_spi_read_rxfifo(spi, false);
+                       stm32h7_spi_read_rxfifo(spi);
 
        writel_relaxed(sr & mask, spi->base + STM32H7_SPI_IFCR);
 
@@ -1041,42 +1021,17 @@ static void stm32f4_spi_dma_tx_cb(void *data)
 }
 
 /**
- * stm32f4_spi_dma_rx_cb - dma callback
+ * stm32_spi_dma_rx_cb - dma callback
  * @data: pointer to the spi controller data structure
  *
  * DMA callback is called when the transfer is complete for DMA RX channel.
  */
-static void stm32f4_spi_dma_rx_cb(void *data)
+static void stm32_spi_dma_rx_cb(void *data)
 {
        struct stm32_spi *spi = data;
 
        spi_finalize_current_transfer(spi->master);
-       stm32f4_spi_disable(spi);
-}
-
-/**
- * stm32h7_spi_dma_cb - dma callback
- * @data: pointer to the spi controller data structure
- *
- * DMA callback is called when the transfer is complete or when an error
- * occurs. If the transfer is complete, EOT flag is raised.
- */
-static void stm32h7_spi_dma_cb(void *data)
-{
-       struct stm32_spi *spi = data;
-       unsigned long flags;
-       u32 sr;
-
-       spin_lock_irqsave(&spi->lock, flags);
-
-       sr = readl_relaxed(spi->base + STM32H7_SPI_SR);
-
-       spin_unlock_irqrestore(&spi->lock, flags);
-
-       if (!(sr & STM32H7_SPI_SR_EOT))
-               dev_warn(spi->dev, "DMA error (sr=0x%08x)\n", sr);
-
-       /* Now wait for EOT, or SUSP or OVR in case of error */
+       spi->cfg->disable(spi);
 }
 
 /**
@@ -1242,11 +1197,13 @@ static void stm32f4_spi_transfer_one_dma_start(struct stm32_spi *spi)
  */
 static void stm32h7_spi_transfer_one_dma_start(struct stm32_spi *spi)
 {
-       /* Enable the interrupts relative to the end of transfer */
-       stm32_spi_set_bits(spi, STM32H7_SPI_IER, STM32H7_SPI_IER_EOTIE |
-                                                STM32H7_SPI_IER_TXTFIE |
-                                                STM32H7_SPI_IER_OVRIE |
-                                                STM32H7_SPI_IER_MODFIE);
+       uint32_t ier = STM32H7_SPI_IER_OVRIE | STM32H7_SPI_IER_MODFIE;
+
+       /* Enable the interrupts */
+       if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX)
+               ier |= STM32H7_SPI_IER_EOTIE | STM32H7_SPI_IER_TXTFIE;
+
+       stm32_spi_set_bits(spi, STM32H7_SPI_IER, ier);
 
        stm32_spi_enable(spi);
 
@@ -1645,10 +1602,6 @@ static int stm32_spi_transfer_one(struct spi_master *master,
        struct stm32_spi *spi = spi_master_get_devdata(master);
        int ret;
 
-       /* Don't do anything on 0 bytes transfers */
-       if (transfer->len == 0)
-               return 0;
-
        spi->tx_buf = transfer->tx_buf;
        spi->rx_buf = transfer->rx_buf;
        spi->tx_len = spi->tx_buf ? transfer->len : 0;
@@ -1762,7 +1715,7 @@ static const struct stm32_spi_cfg stm32f4_spi_cfg = {
        .set_mode = stm32f4_spi_set_mode,
        .transfer_one_dma_start = stm32f4_spi_transfer_one_dma_start,
        .dma_tx_cb = stm32f4_spi_dma_tx_cb,
-       .dma_rx_cb = stm32f4_spi_dma_rx_cb,
+       .dma_rx_cb = stm32_spi_dma_rx_cb,
        .transfer_one_irq = stm32f4_spi_transfer_one_irq,
        .irq_handler_event = stm32f4_spi_irq_event,
        .irq_handler_thread = stm32f4_spi_irq_thread,
@@ -1782,8 +1735,11 @@ static const struct stm32_spi_cfg stm32h7_spi_cfg = {
        .set_data_idleness = stm32h7_spi_data_idleness,
        .set_number_of_data = stm32h7_spi_number_of_data,
        .transfer_one_dma_start = stm32h7_spi_transfer_one_dma_start,
-       .dma_rx_cb = stm32h7_spi_dma_cb,
-       .dma_tx_cb = stm32h7_spi_dma_cb,
+       .dma_rx_cb = stm32_spi_dma_rx_cb,
+       /*
+        * dma_tx_cb is not necessary since in case of TX, dma is followed by
+        * SPI access hence handling is performed within the SPI interrupt
+        */
        .transfer_one_irq = stm32h7_spi_transfer_one_irq,
        .irq_handler_thread = stm32h7_spi_irq_thread,
        .baud_rate_div_min = STM32H7_SPI_MBR_DIV_MIN,
@@ -1927,6 +1883,9 @@ static int stm32_spi_probe(struct platform_device *pdev)
        if (spi->dma_tx || spi->dma_rx)
                master->can_dma = stm32_spi_can_dma;
 
+       pm_runtime_set_autosuspend_delay(&pdev->dev,
+                                        STM32_SPI_AUTOSUSPEND_DELAY);
+       pm_runtime_use_autosuspend(&pdev->dev);
        pm_runtime_set_active(&pdev->dev);
        pm_runtime_get_noresume(&pdev->dev);
        pm_runtime_enable(&pdev->dev);
@@ -1938,6 +1897,9 @@ static int stm32_spi_probe(struct platform_device *pdev)
                goto err_pm_disable;
        }
 
+       pm_runtime_mark_last_busy(&pdev->dev);
+       pm_runtime_put_autosuspend(&pdev->dev);
+
        dev_info(&pdev->dev, "driver initialized\n");
 
        return 0;
@@ -1946,6 +1908,7 @@ err_pm_disable:
        pm_runtime_disable(&pdev->dev);
        pm_runtime_put_noidle(&pdev->dev);
        pm_runtime_set_suspended(&pdev->dev);
+       pm_runtime_dont_use_autosuspend(&pdev->dev);
 err_dma_release:
        if (spi->dma_tx)
                dma_release_channel(spi->dma_tx);
@@ -1970,6 +1933,8 @@ static int stm32_spi_remove(struct platform_device *pdev)
        pm_runtime_disable(&pdev->dev);
        pm_runtime_put_noidle(&pdev->dev);
        pm_runtime_set_suspended(&pdev->dev);
+       pm_runtime_dont_use_autosuspend(&pdev->dev);
+
        if (master->dma_tx)
                dma_release_channel(master->dma_tx);
        if (master->dma_rx)