dmaengine: tegra210-adma: add support for Tegra186/Tegra194

Add Tegra186 specific macro defines and chip_data structure for chip
specific information. New compatibility is added to select relevant
chip details. There is no major change for Tegra194 and hence it can
use the same chip data.

The bits in the BURST_SIZE field of the ADMA CH_CONFIG register are
encoded differently on Tegra186 and Tegra194 compared with Tegra210.
On Tegra210 the bits are encoded as follows ...

 1 = WORD_1
 2 = WORDS_2
 3 = WORDS_4
 4 = WORDS_8
 5 = WORDS_16

Where as on Tegra186 and Tegra194 the bits are encoded as ...

 0 = WORD_1
 1 = WORDS_2
 2 = WORDS_3
 3 = WORDS_4
 4 = WORDS_5
 ...
 15 = WORDS_16

Add helper functions for generating the correct burst size.

Signed-off-by: Sameer Pujar <spujar@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
Sameer Pujar 2019-05-02 18:25:14 +05:30 committed by Vinod Koul
parent c0e74dd254
commit 433de642a7
1 changed files with 37 additions and 8 deletions

View File

@ -45,8 +45,8 @@
#define ADMA_CH_CONFIG 0x28 #define ADMA_CH_CONFIG 0x28
#define ADMA_CH_CONFIG_SRC_BUF(val) (((val) & 0x7) << 28) #define ADMA_CH_CONFIG_SRC_BUF(val) (((val) & 0x7) << 28)
#define ADMA_CH_CONFIG_TRG_BUF(val) (((val) & 0x7) << 24) #define ADMA_CH_CONFIG_TRG_BUF(val) (((val) & 0x7) << 24)
#define ADMA_CH_CONFIG_BURST_SIZE(val) (((val) & 0x7) << 20) #define ADMA_CH_CONFIG_BURST_SIZE_SHIFT 20
#define ADMA_CH_CONFIG_BURST_16 5 #define ADMA_CH_CONFIG_MAX_BURST_SIZE 16
#define ADMA_CH_CONFIG_WEIGHT_FOR_WRR(val) ((val) & 0xf) #define ADMA_CH_CONFIG_WEIGHT_FOR_WRR(val) ((val) & 0xf)
#define ADMA_CH_CONFIG_MAX_BUFS 8 #define ADMA_CH_CONFIG_MAX_BUFS 8
@ -87,6 +87,7 @@ struct tegra_adma;
* @nr_channels: Number of DMA channels available. * @nr_channels: Number of DMA channels available.
*/ */
struct tegra_adma_chip_data { struct tegra_adma_chip_data {
unsigned int (*adma_get_burst_config)(unsigned int burst_size);
unsigned int global_reg_offset; unsigned int global_reg_offset;
unsigned int global_int_clear; unsigned int global_int_clear;
unsigned int ch_req_tx_shift; unsigned int ch_req_tx_shift;
@ -489,6 +490,22 @@ static enum dma_status tegra_adma_tx_status(struct dma_chan *dc,
return ret; return ret;
} }
static unsigned int tegra210_adma_get_burst_config(unsigned int burst_size)
{
if (!burst_size || burst_size > ADMA_CH_CONFIG_MAX_BURST_SIZE)
burst_size = ADMA_CH_CONFIG_MAX_BURST_SIZE;
return fls(burst_size) << ADMA_CH_CONFIG_BURST_SIZE_SHIFT;
}
static unsigned int tegra186_adma_get_burst_config(unsigned int burst_size)
{
if (!burst_size || burst_size > ADMA_CH_CONFIG_MAX_BURST_SIZE)
burst_size = ADMA_CH_CONFIG_MAX_BURST_SIZE;
return (burst_size - 1) << ADMA_CH_CONFIG_BURST_SIZE_SHIFT;
}
static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc, static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
struct tegra_adma_desc *desc, struct tegra_adma_desc *desc,
dma_addr_t buf_addr, dma_addr_t buf_addr,
@ -504,7 +521,7 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
switch (direction) { switch (direction) {
case DMA_MEM_TO_DEV: case DMA_MEM_TO_DEV:
adma_dir = ADMA_CH_CTRL_DIR_MEM2AHUB; adma_dir = ADMA_CH_CTRL_DIR_MEM2AHUB;
burst_size = fls(tdc->sconfig.dst_maxburst); burst_size = 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_REG_FIELD_VAL(tdc->sreq_index, ch_regs->ctrl = ADMA_CH_REG_FIELD_VAL(tdc->sreq_index,
cdata->ch_req_mask, cdata->ch_req_mask,
@ -514,7 +531,7 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
case DMA_DEV_TO_MEM: case DMA_DEV_TO_MEM:
adma_dir = ADMA_CH_CTRL_DIR_AHUB2MEM; adma_dir = ADMA_CH_CTRL_DIR_AHUB2MEM;
burst_size = fls(tdc->sconfig.src_maxburst); burst_size = 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_REG_FIELD_VAL(tdc->sreq_index, ch_regs->ctrl = ADMA_CH_REG_FIELD_VAL(tdc->sreq_index,
cdata->ch_req_mask, cdata->ch_req_mask,
@ -527,13 +544,10 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
return -EINVAL; return -EINVAL;
} }
if (!burst_size || burst_size > ADMA_CH_CONFIG_BURST_16)
burst_size = ADMA_CH_CONFIG_BURST_16;
ch_regs->ctrl |= ADMA_CH_CTRL_DIR(adma_dir) | ch_regs->ctrl |= ADMA_CH_CTRL_DIR(adma_dir) |
ADMA_CH_CTRL_MODE_CONTINUOUS | ADMA_CH_CTRL_MODE_CONTINUOUS |
ADMA_CH_CTRL_FLOWCTRL_EN; ADMA_CH_CTRL_FLOWCTRL_EN;
ch_regs->config |= ADMA_CH_CONFIG_BURST_SIZE(burst_size); ch_regs->config |= cdata->adma_get_burst_config(burst_size);
ch_regs->config |= ADMA_CH_CONFIG_WEIGHT_FOR_WRR(1); ch_regs->config |= ADMA_CH_CONFIG_WEIGHT_FOR_WRR(1);
ch_regs->fifo_ctrl = ADMA_CH_FIFO_CTRL_DEFAULT; ch_regs->fifo_ctrl = ADMA_CH_FIFO_CTRL_DEFAULT;
ch_regs->tc = desc->period_len & ADMA_CH_TC_COUNT_MASK; ch_regs->tc = desc->period_len & ADMA_CH_TC_COUNT_MASK;
@ -671,6 +685,7 @@ 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 = {
.adma_get_burst_config = tegra210_adma_get_burst_config,
.global_reg_offset = 0xc00, .global_reg_offset = 0xc00,
.global_int_clear = 0x20, .global_int_clear = 0x20,
.ch_req_tx_shift = 28, .ch_req_tx_shift = 28,
@ -682,8 +697,22 @@ static const struct tegra_adma_chip_data tegra210_chip_data = {
.nr_channels = 22, .nr_channels = 22,
}; };
static const struct tegra_adma_chip_data tegra186_chip_data = {
.adma_get_burst_config = tegra186_adma_get_burst_config,
.global_reg_offset = 0,
.global_int_clear = 0x402c,
.ch_req_tx_shift = 27,
.ch_req_rx_shift = 22,
.ch_base_offset = 0x10000,
.ch_req_mask = 0x1f,
.ch_req_max = 20,
.ch_reg_size = 0x100,
.nr_channels = 32,
};
static const struct of_device_id tegra_adma_of_match[] = { static const struct of_device_id tegra_adma_of_match[] = {
{ .compatible = "nvidia,tegra210-adma", .data = &tegra210_chip_data }, { .compatible = "nvidia,tegra210-adma", .data = &tegra210_chip_data },
{ .compatible = "nvidia,tegra186-adma", .data = &tegra186_chip_data },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, tegra_adma_of_match); MODULE_DEVICE_TABLE(of, tegra_adma_of_match);