1
0
Fork 0

dmaengine: imx-sdma: update sdma script for multi fifo on SAI

update sdma script for multi fifo SAI on i.mx8MQ. Besides,Add
new cell for sw_done/sw_done_selector, because PDM need enable
software done feature in sdma script(same multi fifo script).
The new fourth cell defined as below:
        Bit31: sw_done
        Bit15~bit0: selector
For example: 0x80000000 means sw_done enabled for done0 sector which
is for PDM on i.mx8mm.

Signed-off-by: Robin Gong <yibin.gong@nxp.com>
5.4-rM2-2.2.x-imx-squashed
Robin Gong 2018-01-16 17:52:49 +08:00 committed by Dong Aisheng
parent 40373109c4
commit b9416dfe21
3 changed files with 75 additions and 2 deletions

View File

@ -55,7 +55,12 @@ The full ID of peripheral types can be found below.
24 SAI
25 HDMI Audio
The third cell specifies the transfer priority as below.
The third cell specifies the transfer priority and software done
as below.
Bit31: sw_done
Bit15~Bit8: selector
Bit7~Bit0: priority level
ID transfer priority
-------------------------
@ -63,6 +68,9 @@ The third cell specifies the transfer priority as below.
1 Medium
2 Low
For example: 0x80000000 means sw_done enabled for done0 sector and
High priority for PDM on i.mx8mm.
Optional properties:
- gpr : The phandle to the General Purpose Register (GPR) node.

View File

@ -76,6 +76,9 @@
#define SDMA_CHNENBL0_IMX35 0x200
#define SDMA_CHNENBL0_IMX31 0x080
#define SDMA_CHNPRI_0 0x100
#define SDMA_DONE0_CONFIG 0x1000
#define SDMA_DONE0_CONFIG_DONE_SEL 0x7
#define SDMA_DONE0_CONFIG_DONE_DIS 0x6
/*
* Buffer descriptor status values.
@ -186,6 +189,10 @@
BIT(DMA_MEM_TO_DEV) | \
BIT(DMA_DEV_TO_DEV))
#define SDMA_WATERMARK_LEVEL_FIFOS_OFF 12
#define SDMA_WATERMARK_LEVEL_SW_DONE BIT(23)
#define SDMA_WATERMARK_LEVEL_SW_DONE_SEL_OFF 24
/*
* Mode/Count of data node descriptors - IPCv2
*/
@ -387,6 +394,9 @@ struct sdma_channel {
bool is_ram_script;
bool src_dualfifo;
bool dst_dualfifo;
unsigned int fifo_num;
bool sw_done;
u32 sw_done_sel;
};
#define IMX_DMA_SG_LOOP BIT(0)
@ -797,6 +807,21 @@ static void sdma_event_enable(struct sdma_channel *sdmac, unsigned int event)
val = readl_relaxed(sdma->regs + chnenbl);
__set_bit(channel, &val);
writel_relaxed(val, sdma->regs + chnenbl);
/* Set SDMA_DONEx_CONFIG is sw_done enabled */
if (sdmac->sw_done) {
u32 offset = SDMA_DONE0_CONFIG + sdmac->sw_done_sel / 4;
u32 done_sel = SDMA_DONE0_CONFIG_DONE_SEL +
((sdmac->sw_done_sel % 4) << 3);
u32 sw_done_dis = SDMA_DONE0_CONFIG_DONE_DIS +
((sdmac->sw_done_sel % 4) << 3);
val = readl_relaxed(sdma->regs + offset);
__set_bit(done_sel, &val);
__clear_bit(sw_done_dis, &val);
writel_relaxed(val, sdma->regs + offset);
}
}
static void sdma_event_disable(struct sdma_channel *sdmac, unsigned int event)
@ -1045,6 +1070,9 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
case IMX_DMATYPE_HDMI:
emi_2_per = sdma->script_addrs->hdmi_dma_addr;
break;
case IMX_DMATYPE_MULTI_SAI:
per_2_emi = sdma->script_addrs->sai_2_mcu_addr;
emi_2_per = sdma->script_addrs->mcu_2_sai_addr;
default:
break;
}
@ -1251,6 +1279,26 @@ static void sdma_set_watermarklevel_for_p2p(struct sdma_channel *sdmac)
sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_DD;
}
static void sdma_set_watermarklevel_for_sais(struct sdma_channel *sdmac)
{
sdmac->watermark_level &= ~(0xFF << SDMA_WATERMARK_LEVEL_FIFOS_OFF |
SDMA_WATERMARK_LEVEL_SW_DONE |
0xf << SDMA_WATERMARK_LEVEL_SW_DONE_SEL_OFF);
if (sdmac->sw_done)
sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_SW_DONE |
sdmac->sw_done_sel <<
SDMA_WATERMARK_LEVEL_SW_DONE_SEL_OFF;
/* For fifo_num
* bit 12-15 is the fifo number;
* bit 16-19 is the fifo offset,
* so here only need to shift left fifo_num 12 bit for watermake_level
*/
sdmac->watermark_level |= sdmac->fifo_num<<
SDMA_WATERMARK_LEVEL_FIFOS_OFF;
}
static int sdma_config_channel(struct dma_chan *chan)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
@ -1292,6 +1340,10 @@ static int sdma_config_channel(struct dma_chan *chan)
sdmac->direction == DMA_MEM_TO_DEV &&
sdmac->sdma->drvdata->ecspi_fixed)
__set_bit(31, &sdmac->watermark_level);
else if (sdmac->peripheral_type ==
IMX_DMATYPE_MULTI_SAI)
sdma_set_watermarklevel_for_sais(sdmac);
__set_bit(sdmac->event_id0, sdmac->event_mask);
}
@ -1433,6 +1485,11 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan)
sdmac->event_id1 = data->dma_request2;
sdmac->src_dualfifo = data->src_dualfifo;
sdmac->dst_dualfifo = data->dst_dualfifo;
/* Get software done selector if sw_done enabled */
if (data->done_sel & BIT(31)) {
sdmac->sw_done = true;
sdmac->sw_done_sel = (data->done_sel >> 8) & 0xff;
}
ret = clk_enable(sdmac->sdma->clk_ipg);
if (ret)
@ -1743,11 +1800,14 @@ static int sdma_config_write(struct dma_chan *chan,
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
sdmac->watermark_level = 0;
if (direction == DMA_DEV_TO_MEM) {
sdmac->per_address = dmaengine_cfg->src_addr;
sdmac->watermark_level = dmaengine_cfg->src_maxburst *
dmaengine_cfg->src_addr_width;
sdmac->word_size = dmaengine_cfg->src_addr_width;
sdmac->fifo_num = dmaengine_cfg->src_fifo_num;
} else if (direction == DMA_DEV_TO_DEV) {
sdmac->per_address2 = dmaengine_cfg->src_addr;
sdmac->per_address = dmaengine_cfg->dst_addr;
@ -1765,6 +1825,7 @@ static int sdma_config_write(struct dma_chan *chan,
sdmac->watermark_level = dmaengine_cfg->dst_maxburst *
dmaengine_cfg->dst_addr_width;
sdmac->word_size = dmaengine_cfg->dst_addr_width;
sdmac->fifo_num = dmaengine_cfg->dst_fifo_num;
}
sdmac->direction = direction;
return sdma_config_channel(chan);
@ -2118,7 +2179,10 @@ static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec,
data.dma_request = dma_spec->args[0];
data.peripheral_type = dma_spec->args[1];
data.priority = dma_spec->args[2];
/* Get sw_done setting if sw_done enabled */
if (dma_spec->args[2] & BIT(31))
data.done_sel = dma_spec->args[2];
data.priority = dma_spec->args[2] & 0xff;
/*
* init dma_request2 to zero, which is not used by the dts.
* For P2P, dma_request2 is init from dma_request_channel(),

View File

@ -57,6 +57,7 @@ struct imx_dma_data {
int priority;
bool src_dualfifo;
bool dst_dualfifo;
int done_sel;
};
static inline int imx_dma_is_ipu(struct dma_chan *chan)