Merge tag 'dmaengine-fix-5.2-rc4' of git://git.infradead.org/users/vkoul/slave-dma
[sfrench/cifs-2.6.git] / drivers / dma / tegra210-adma.c
index 21f6be16d013db042117a6581be6d7bed5fd584c..2805853e963fcf6f9076e8360ebd519585efa94e 100644 (file)
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * ADMA driver for Nvidia's Tegra210 ADMA controller.
  *
  * Copyright (c) 2016, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/clk.h>
 #define ADMA_CH_CONFIG_MAX_BUFS                                8
 
 #define ADMA_CH_FIFO_CTRL                              0x2c
-#define ADMA_CH_FIFO_CTRL_OVRFW_THRES(val)             (((val) & 0xf) << 24)
-#define ADMA_CH_FIFO_CTRL_STARV_THRES(val)             (((val) & 0xf) << 16)
-#define ADMA_CH_FIFO_CTRL_TX_FIFO_SIZE_SHIFT           8
-#define ADMA_CH_FIFO_CTRL_RX_FIFO_SIZE_SHIFT           0
+#define TEGRA210_ADMA_CH_FIFO_CTRL_OFLWTHRES(val)      (((val) & 0xf) << 24)
+#define TEGRA210_ADMA_CH_FIFO_CTRL_STRVTHRES(val)      (((val) & 0xf) << 16)
+#define TEGRA210_ADMA_CH_FIFO_CTRL_TXSIZE(val)         (((val) & 0xf) << 8)
+#define TEGRA210_ADMA_CH_FIFO_CTRL_RXSIZE(val)         ((val) & 0xf)
+#define TEGRA186_ADMA_CH_FIFO_CTRL_OFLWTHRES(val)      (((val) & 0x1f) << 24)
+#define TEGRA186_ADMA_CH_FIFO_CTRL_STRVTHRES(val)      (((val) & 0x1f) << 16)
+#define TEGRA186_ADMA_CH_FIFO_CTRL_TXSIZE(val)         (((val) & 0x1f) << 8)
+#define TEGRA186_ADMA_CH_FIFO_CTRL_RXSIZE(val)         ((val) & 0x1f)
 
 #define ADMA_CH_LOWER_SRC_ADDR                         0x34
 #define ADMA_CH_LOWER_TRG_ADDR                         0x3c
 
 #define TEGRA_ADMA_BURST_COMPLETE_TIME                 20
 
-#define ADMA_CH_FIFO_CTRL_DEFAULT      (ADMA_CH_FIFO_CTRL_OVRFW_THRES(1) | \
-                                        ADMA_CH_FIFO_CTRL_STARV_THRES(1))
+#define TEGRA210_FIFO_CTRL_DEFAULT (TEGRA210_ADMA_CH_FIFO_CTRL_OFLWTHRES(1) | \
+                                   TEGRA210_ADMA_CH_FIFO_CTRL_STRVTHRES(1) | \
+                                   TEGRA210_ADMA_CH_FIFO_CTRL_TXSIZE(3)    | \
+                                   TEGRA210_ADMA_CH_FIFO_CTRL_RXSIZE(3))
+
+#define TEGRA186_FIFO_CTRL_DEFAULT (TEGRA186_ADMA_CH_FIFO_CTRL_OFLWTHRES(1) | \
+                                   TEGRA186_ADMA_CH_FIFO_CTRL_STRVTHRES(1) | \
+                                   TEGRA186_ADMA_CH_FIFO_CTRL_TXSIZE(3)    | \
+                                   TEGRA186_ADMA_CH_FIFO_CTRL_RXSIZE(3))
 
 #define ADMA_CH_REG_FIELD_VAL(val, mask, shift)        (((val) & mask) << shift)
 
@@ -84,7 +84,8 @@ struct tegra_adma;
  * @global_int_clear: Register offset of DMA global interrupt clear.
  * @ch_req_tx_shift: Register offset for AHUB transmit channel select.
  * @ch_req_rx_shift: Register offset for AHUB receive channel select.
- * @ch_base_offset: Reister offset of DMA channel registers.
+ * @ch_base_offset: Register offset of DMA channel registers.
+ * @ch_fifo_ctrl: Default value for channel FIFO CTRL register.
  * @ch_req_mask: Mask for Tx or Rx channel select.
  * @ch_req_max: Maximum number of Tx or Rx channels available.
  * @ch_reg_size: Size of DMA channel register space.
@@ -97,6 +98,7 @@ struct tegra_adma_chip_data {
        unsigned int ch_req_tx_shift;
        unsigned int ch_req_rx_shift;
        unsigned int ch_base_offset;
+       unsigned int ch_fifo_ctrl;
        unsigned int ch_req_mask;
        unsigned int ch_req_max;
        unsigned int ch_reg_size;
@@ -600,7 +602,7 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
                         ADMA_CH_CTRL_FLOWCTRL_EN;
        ch_regs->config |= cdata->adma_get_burst_config(burst_size);
        ch_regs->config |= ADMA_CH_CONFIG_WEIGHT_FOR_WRR(1);
-       ch_regs->fifo_ctrl = ADMA_CH_FIFO_CTRL_DEFAULT;
+       ch_regs->fifo_ctrl = cdata->ch_fifo_ctrl;
        ch_regs->tc = desc->period_len & ADMA_CH_TC_COUNT_MASK;
 
        return tegra_adma_request_alloc(tdc, direction);
@@ -784,6 +786,7 @@ static const struct tegra_adma_chip_data tegra210_chip_data = {
        .ch_req_tx_shift        = 28,
        .ch_req_rx_shift        = 24,
        .ch_base_offset         = 0,
+       .ch_fifo_ctrl           = TEGRA210_FIFO_CTRL_DEFAULT,
        .ch_req_mask            = 0xf,
        .ch_req_max             = 10,
        .ch_reg_size            = 0x80,
@@ -797,6 +800,7 @@ static const struct tegra_adma_chip_data tegra186_chip_data = {
        .ch_req_tx_shift        = 27,
        .ch_req_rx_shift        = 22,
        .ch_base_offset         = 0x10000,
+       .ch_fifo_ctrl           = TEGRA186_FIFO_CTRL_DEFAULT,
        .ch_req_mask            = 0x1f,
        .ch_req_max             = 20,
        .ch_reg_size            = 0x100,
@@ -845,16 +849,6 @@ static int tegra_adma_probe(struct platform_device *pdev)
                return PTR_ERR(tdma->ahub_clk);
        }
 
-       pm_runtime_enable(&pdev->dev);
-
-       ret = pm_runtime_get_sync(&pdev->dev);
-       if (ret < 0)
-               goto rpm_disable;
-
-       ret = tegra_adma_init(tdma);
-       if (ret)
-               goto rpm_put;
-
        INIT_LIST_HEAD(&tdma->dma_dev.channels);
        for (i = 0; i < tdma->nr_channels; i++) {
                struct tegra_adma_chan *tdc = &tdma->channels[i];
@@ -873,6 +867,16 @@ static int tegra_adma_probe(struct platform_device *pdev)
                tdc->tdma = tdma;
        }
 
+       pm_runtime_enable(&pdev->dev);
+
+       ret = pm_runtime_get_sync(&pdev->dev);
+       if (ret < 0)
+               goto rpm_disable;
+
+       ret = tegra_adma_init(tdma);
+       if (ret)
+               goto rpm_put;
+
        dma_cap_set(DMA_SLAVE, tdma->dma_dev.cap_mask);
        dma_cap_set(DMA_PRIVATE, tdma->dma_dev.cap_mask);
        dma_cap_set(DMA_CYCLIC, tdma->dma_dev.cap_mask);
@@ -916,13 +920,13 @@ static int tegra_adma_probe(struct platform_device *pdev)
 
 dma_remove:
        dma_async_device_unregister(&tdma->dma_dev);
-irq_dispose:
-       while (--i >= 0)
-               irq_dispose_mapping(tdma->channels[i].irq);
 rpm_put:
        pm_runtime_put_sync(&pdev->dev);
 rpm_disable:
        pm_runtime_disable(&pdev->dev);
+irq_dispose:
+       while (--i >= 0)
+               irq_dispose_mapping(tdma->channels[i].irq);
 
        return ret;
 }