Commit ded1f3db authored by Sameer Pujar's avatar Sameer Pujar Committed by Vinod Koul

dmaengine: tegra210-adma: prepare for supporting newer Tegra chips

This is a preparatory patch to add support for Tegra186 and Tegra194 chips.
Following changes are necessary to make driver code generic.
 * chip_data structure is enhanced to have chip specific details and
   following are the additions to the structure
   * Offset addresses for ADMA global and channel registers
   * Offset values for Tx and Rx channel selection
   * Maximum supported Tx and Rx channels
   * Tx and Rx channel request mask
   * ADMA channel register space size
 * Make use of above chip_data to generalise the driver code

Support for Tegra186 and Tegra194 will be added in subsequent patches of
the series.
Signed-off-by: default avatarSameer Pujar <spujar@nvidia.com>
Reviewed-by: default avatarJon Hunter <jonathanh@nvidia.com>
Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 0b515abb
...@@ -36,10 +36,6 @@ ...@@ -36,10 +36,6 @@
#define ADMA_CH_INT_CLEAR 0x1c #define ADMA_CH_INT_CLEAR 0x1c
#define ADMA_CH_CTRL 0x24 #define ADMA_CH_CTRL 0x24
#define ADMA_CH_CTRL_TX_REQ(val) (((val) & 0xf) << 28)
#define ADMA_CH_CTRL_TX_REQ_MAX 10
#define ADMA_CH_CTRL_RX_REQ(val) (((val) & 0xf) << 24)
#define ADMA_CH_CTRL_RX_REQ_MAX 10
#define ADMA_CH_CTRL_DIR(val) (((val) & 0xf) << 12) #define ADMA_CH_CTRL_DIR(val) (((val) & 0xf) << 12)
#define ADMA_CH_CTRL_DIR_AHUB2MEM 2 #define ADMA_CH_CTRL_DIR_AHUB2MEM 2
#define ADMA_CH_CTRL_DIR_MEM2AHUB 4 #define ADMA_CH_CTRL_DIR_MEM2AHUB 4
...@@ -57,8 +53,8 @@ ...@@ -57,8 +53,8 @@
#define ADMA_CH_FIFO_CTRL 0x2c #define ADMA_CH_FIFO_CTRL 0x2c
#define ADMA_CH_FIFO_CTRL_OVRFW_THRES(val) (((val) & 0xf) << 24) #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_STARV_THRES(val) (((val) & 0xf) << 16)
#define ADMA_CH_FIFO_CTRL_TX_SIZE(val) (((val) & 0xf) << 8) #define ADMA_CH_FIFO_CTRL_TX_FIFO_SIZE_SHIFT 8
#define ADMA_CH_FIFO_CTRL_RX_SIZE(val) ((val) & 0xf) #define ADMA_CH_FIFO_CTRL_RX_FIFO_SIZE_SHIFT 0
#define ADMA_CH_LOWER_SRC_ADDR 0x34 #define ADMA_CH_LOWER_SRC_ADDR 0x34
#define ADMA_CH_LOWER_TRG_ADDR 0x3c #define ADMA_CH_LOWER_TRG_ADDR 0x3c
...@@ -68,25 +64,38 @@ ...@@ -68,25 +64,38 @@
#define ADMA_CH_XFER_STATUS 0x54 #define ADMA_CH_XFER_STATUS 0x54
#define ADMA_CH_XFER_STATUS_COUNT_MASK 0xffff #define ADMA_CH_XFER_STATUS_COUNT_MASK 0xffff
#define ADMA_GLOBAL_CMD 0xc00 #define ADMA_GLOBAL_CMD 0x00
#define ADMA_GLOBAL_SOFT_RESET 0xc04 #define ADMA_GLOBAL_SOFT_RESET 0x04
#define ADMA_GLOBAL_INT_CLEAR 0xc20
#define ADMA_GLOBAL_CTRL 0xc24
#define ADMA_CH_REG_OFFSET(a) (a * 0x80)
#define ADMA_CH_FIFO_CTRL_DEFAULT (ADMA_CH_FIFO_CTRL_OVRFW_THRES(1) | \ #define ADMA_CH_FIFO_CTRL_DEFAULT (ADMA_CH_FIFO_CTRL_OVRFW_THRES(1) | \
ADMA_CH_FIFO_CTRL_STARV_THRES(1) | \ ADMA_CH_FIFO_CTRL_STARV_THRES(1))
ADMA_CH_FIFO_CTRL_TX_SIZE(3) | \
ADMA_CH_FIFO_CTRL_RX_SIZE(3)) #define ADMA_CH_REG_FIELD_VAL(val, mask, shift) (((val) & mask) << shift)
struct tegra_adma; struct tegra_adma;
/* /*
* struct tegra_adma_chip_data - Tegra chip specific data * struct tegra_adma_chip_data - Tegra chip specific data
* @global_reg_offset: Register offset of DMA global register.
* @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_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.
* @nr_channels: Number of DMA channels available. * @nr_channels: Number of DMA channels available.
*/ */
struct tegra_adma_chip_data { struct tegra_adma_chip_data {
int nr_channels; unsigned int global_reg_offset;
unsigned int global_int_clear;
unsigned int ch_req_tx_shift;
unsigned int ch_req_rx_shift;
unsigned int ch_base_offset;
unsigned int ch_req_mask;
unsigned int ch_req_max;
unsigned int ch_reg_size;
unsigned int nr_channels;
}; };
/* /*
...@@ -148,18 +157,20 @@ struct tegra_adma { ...@@ -148,18 +157,20 @@ struct tegra_adma {
/* Used to store global command register state when suspending */ /* Used to store global command register state when suspending */
unsigned int global_cmd; unsigned int global_cmd;
const struct tegra_adma_chip_data *cdata;
/* Last member of the structure */ /* Last member of the structure */
struct tegra_adma_chan channels[0]; struct tegra_adma_chan channels[0];
}; };
static inline void tdma_write(struct tegra_adma *tdma, u32 reg, u32 val) static inline void tdma_write(struct tegra_adma *tdma, u32 reg, u32 val)
{ {
writel(val, tdma->base_addr + reg); writel(val, tdma->base_addr + tdma->cdata->global_reg_offset + reg);
} }
static inline u32 tdma_read(struct tegra_adma *tdma, u32 reg) static inline u32 tdma_read(struct tegra_adma *tdma, u32 reg)
{ {
return readl(tdma->base_addr + reg); return readl(tdma->base_addr + tdma->cdata->global_reg_offset + reg);
} }
static inline void tdma_ch_write(struct tegra_adma_chan *tdc, u32 reg, u32 val) static inline void tdma_ch_write(struct tegra_adma_chan *tdc, u32 reg, u32 val)
...@@ -209,14 +220,16 @@ static int tegra_adma_init(struct tegra_adma *tdma) ...@@ -209,14 +220,16 @@ static int tegra_adma_init(struct tegra_adma *tdma)
int ret; int ret;
/* Clear any interrupts */ /* Clear any interrupts */
tdma_write(tdma, ADMA_GLOBAL_INT_CLEAR, 0x1); tdma_write(tdma, tdma->cdata->global_int_clear, 0x1);
/* Assert soft reset */ /* Assert soft reset */
tdma_write(tdma, ADMA_GLOBAL_SOFT_RESET, 0x1); tdma_write(tdma, ADMA_GLOBAL_SOFT_RESET, 0x1);
/* Wait for reset to clear */ /* Wait for reset to clear */
ret = readx_poll_timeout(readl, ret = readx_poll_timeout(readl,
tdma->base_addr + ADMA_GLOBAL_SOFT_RESET, tdma->base_addr +
tdma->cdata->global_reg_offset +
ADMA_GLOBAL_SOFT_RESET,
status, status == 0, 20, 10000); status, status == 0, 20, 10000);
if (ret) if (ret)
return ret; return ret;
...@@ -236,13 +249,13 @@ static int tegra_adma_request_alloc(struct tegra_adma_chan *tdc, ...@@ -236,13 +249,13 @@ static int tegra_adma_request_alloc(struct tegra_adma_chan *tdc,
if (tdc->sreq_reserved) if (tdc->sreq_reserved)
return tdc->sreq_dir == direction ? 0 : -EINVAL; return tdc->sreq_dir == direction ? 0 : -EINVAL;
if (sreq_index > tdma->cdata->ch_req_max) {
dev_err(tdma->dev, "invalid DMA request\n");
return -EINVAL;
}
switch (direction) { switch (direction) {
case DMA_MEM_TO_DEV: case DMA_MEM_TO_DEV:
if (sreq_index > ADMA_CH_CTRL_TX_REQ_MAX) {
dev_err(tdma->dev, "invalid DMA request\n");
return -EINVAL;
}
if (test_and_set_bit(sreq_index, &tdma->tx_requests_reserved)) { if (test_and_set_bit(sreq_index, &tdma->tx_requests_reserved)) {
dev_err(tdma->dev, "DMA request reserved\n"); dev_err(tdma->dev, "DMA request reserved\n");
return -EINVAL; return -EINVAL;
...@@ -250,11 +263,6 @@ static int tegra_adma_request_alloc(struct tegra_adma_chan *tdc, ...@@ -250,11 +263,6 @@ static int tegra_adma_request_alloc(struct tegra_adma_chan *tdc,
break; break;
case DMA_DEV_TO_MEM: case DMA_DEV_TO_MEM:
if (sreq_index > ADMA_CH_CTRL_RX_REQ_MAX) {
dev_err(tdma->dev, "invalid DMA request\n");
return -EINVAL;
}
if (test_and_set_bit(sreq_index, &tdma->rx_requests_reserved)) { if (test_and_set_bit(sreq_index, &tdma->rx_requests_reserved)) {
dev_err(tdma->dev, "DMA request reserved\n"); dev_err(tdma->dev, "DMA request reserved\n");
return -EINVAL; return -EINVAL;
...@@ -487,6 +495,7 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc, ...@@ -487,6 +495,7 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
enum dma_transfer_direction direction) enum dma_transfer_direction direction)
{ {
struct tegra_adma_chan_regs *ch_regs = &desc->ch_regs; struct tegra_adma_chan_regs *ch_regs = &desc->ch_regs;
const struct tegra_adma_chip_data *cdata = tdc->tdma->cdata;
unsigned int burst_size, adma_dir; unsigned int burst_size, adma_dir;
if (desc->num_periods > ADMA_CH_CONFIG_MAX_BUFS) if (desc->num_periods > ADMA_CH_CONFIG_MAX_BUFS)
...@@ -497,7 +506,9 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc, ...@@ -497,7 +506,9 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
adma_dir = ADMA_CH_CTRL_DIR_MEM2AHUB; adma_dir = ADMA_CH_CTRL_DIR_MEM2AHUB;
burst_size = fls(tdc->sconfig.dst_maxburst); burst_size = fls(tdc->sconfig.dst_maxburst);
ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(desc->num_periods - 1); ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(desc->num_periods - 1);
ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index); ch_regs->ctrl = ADMA_CH_REG_FIELD_VAL(tdc->sreq_index,
cdata->ch_req_mask,
cdata->ch_req_tx_shift);
ch_regs->src_addr = buf_addr; ch_regs->src_addr = buf_addr;
break; break;
...@@ -505,7 +516,9 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc, ...@@ -505,7 +516,9 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
adma_dir = ADMA_CH_CTRL_DIR_AHUB2MEM; adma_dir = ADMA_CH_CTRL_DIR_AHUB2MEM;
burst_size = fls(tdc->sconfig.src_maxburst); burst_size = fls(tdc->sconfig.src_maxburst);
ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(desc->num_periods - 1); ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(desc->num_periods - 1);
ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index); ch_regs->ctrl = ADMA_CH_REG_FIELD_VAL(tdc->sreq_index,
cdata->ch_req_mask,
cdata->ch_req_rx_shift);
ch_regs->trg_addr = buf_addr; ch_regs->trg_addr = buf_addr;
break; break;
...@@ -658,7 +671,15 @@ static int tegra_adma_runtime_resume(struct device *dev) ...@@ -658,7 +671,15 @@ static int tegra_adma_runtime_resume(struct device *dev)
} }
static const struct tegra_adma_chip_data tegra210_chip_data = { static const struct tegra_adma_chip_data tegra210_chip_data = {
.nr_channels = 22, .global_reg_offset = 0xc00,
.global_int_clear = 0x20,
.ch_req_tx_shift = 28,
.ch_req_rx_shift = 24,
.ch_base_offset = 0,
.ch_req_mask = 0xf,
.ch_req_max = 10,
.ch_reg_size = 0x80,
.nr_channels = 22,
}; };
static const struct of_device_id tegra_adma_of_match[] = { static const struct of_device_id tegra_adma_of_match[] = {
...@@ -687,6 +708,7 @@ static int tegra_adma_probe(struct platform_device *pdev) ...@@ -687,6 +708,7 @@ static int tegra_adma_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
tdma->dev = &pdev->dev; tdma->dev = &pdev->dev;
tdma->cdata = cdata;
tdma->nr_channels = cdata->nr_channels; tdma->nr_channels = cdata->nr_channels;
platform_set_drvdata(pdev, tdma); platform_set_drvdata(pdev, tdma);
...@@ -715,7 +737,8 @@ static int tegra_adma_probe(struct platform_device *pdev) ...@@ -715,7 +737,8 @@ static int tegra_adma_probe(struct platform_device *pdev)
for (i = 0; i < tdma->nr_channels; i++) { for (i = 0; i < tdma->nr_channels; i++) {
struct tegra_adma_chan *tdc = &tdma->channels[i]; struct tegra_adma_chan *tdc = &tdma->channels[i];
tdc->chan_addr = tdma->base_addr + ADMA_CH_REG_OFFSET(i); tdc->chan_addr = tdma->base_addr + cdata->ch_base_offset
+ (cdata->ch_reg_size * i);
tdc->irq = of_irq_get(pdev->dev.of_node, i); tdc->irq = of_irq_get(pdev->dev.of_node, i);
if (tdc->irq <= 0) { if (tdc->irq <= 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment