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
parent
40373109c4
commit
b9416dfe21
|
@ -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.
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue