From: Robin Gong Date: Wed, 24 Mar 2021 16:50:10 +0000 (+0800) Subject: dmaengine: imx-sdma: move dma parameters from imx_dma_data to slave_config X-Git-Tag: rel_imx_5.10.35_2.0.0-somdevices.0~242 X-Git-Url: https://git.somdevices.com/?a=commitdiff_plain;h=e33374afd3f735d2e2a93afb3286c5fc8cac0992;p=linux.git dmaengine: imx-sdma: move dma parameters from imx_dma_data to slave_config use 'peripheral_config' to pass our special sdma parameters from dma_request_slave_channel() to dmaengine_slave_config(), thus could make upper driver much cleaner, besides could make binding docs much cleaner too and easier to upstreaming. Signed-off-by: Robin Gong Reviewed-by: Shengjiu Wang (cherry picked from commit 6f52f8e232017df86fa50270c206f99b21a37ac2) --- diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 298fb5b1d3ce..92d23730032c 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -377,8 +377,9 @@ struct sdma_channel { struct sdma_desc *desc; struct sdma_engine *sdma; unsigned int channel; - enum dma_transfer_direction direction; + enum dma_transfer_direction direction; struct dma_slave_config slave_config; + struct sdma_audio_config *audio_config; enum sdma_peripheral_type peripheral_type; unsigned int event_id0; unsigned int event_id1; @@ -395,11 +396,6 @@ struct sdma_channel { struct imx_dma_data data; struct work_struct terminate_worker; 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) @@ -829,12 +825,13 @@ static void sdma_event_enable(struct sdma_channel *sdmac, unsigned int event) 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; + if (sdmac->audio_config && sdmac->audio_config->sw_done_sel & BIT(31)) { + u32 sw_done_sel = sdmac->audio_config->sw_done_sel & 0xff; + u32 offset = SDMA_DONE0_CONFIG + sw_done_sel / 4; u32 done_sel = SDMA_DONE0_CONFIG_DONE_SEL + - ((sdmac->sw_done_sel % 4) << 3); + ((sw_done_sel % 4) << 3); u32 sw_done_dis = SDMA_DONE0_CONFIG_DONE_DIS + - ((sdmac->sw_done_sel % 4) << 3); + ((sw_done_sel % 4) << 3); val = readl_relaxed(sdma->regs + offset); __set_bit(done_sel, &val); @@ -1306,30 +1303,35 @@ static void sdma_set_watermarklevel_for_p2p(struct sdma_channel *sdmac) sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_CONT; - if (sdmac->src_dualfifo) + if (sdmac->audio_config->src_fifo_num > 1) sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_SD; - if (sdmac->dst_dualfifo) + if (sdmac->audio_config->dst_fifo_num > 1) sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_DD; } static void sdma_set_watermarklevel_for_sais(struct sdma_channel *sdmac) { + u8 fifo_num = sdmac->audio_config->src_fifo_num | + sdmac->audio_config->dst_fifo_num; + 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) + if (sdmac->audio_config->sw_done_sel & BIT(31)) sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_SW_DONE | - sdmac->sw_done_sel << - SDMA_WATERMARK_LEVEL_SW_DONE_SEL_OFF; + (sdmac->audio_config->sw_done_sel & 0xff) << + SDMA_WATERMARK_LEVEL_SW_DONE_SEL_OFF; /* For fifo_num * bit 12-15 is the fifo number; * bit 16-19 is the fifo offset, + * bit 28-31 is the channels per fifo. * 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; + if (fifo_num) + sdmac->watermark_level |= fifo_num << + SDMA_WATERMARK_LEVEL_FIFOS_OFF; } static int sdma_config_channel(struct dma_chan *chan) @@ -1603,13 +1605,6 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan) sdmac->peripheral_type = data->peripheral_type; sdmac->event_id0 = data->dma_request; 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; - } pm_runtime_get_sync(sdmac->sdma->dev); @@ -1638,6 +1633,9 @@ static void sdma_free_chan_resources(struct dma_chan *chan) sdma_set_channel_priority(sdmac, 0); + kfree(sdmac->audio_config); + sdmac->audio_config = NULL; + pm_runtime_put_sync(sdma->dev); } @@ -1918,7 +1916,6 @@ static int sdma_config_write(struct dma_chan *chan, 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; @@ -1936,7 +1933,6 @@ 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); @@ -1946,9 +1942,23 @@ static int sdma_config(struct dma_chan *chan, struct dma_slave_config *dmaengine_cfg) { struct sdma_channel *sdmac = to_sdma_chan(chan); + void *tmp; memcpy(&sdmac->slave_config, dmaengine_cfg, sizeof(*dmaengine_cfg)); + /* Allocate special sdma_audio_config if it's used */ + if (dmaengine_cfg->peripheral_config) { + tmp = krealloc(sdmac->audio_config, + dmaengine_cfg->peripheral_size, GFP_NOWAIT); + if (!tmp) + return -ENOMEM; + + sdmac->audio_config = (struct sdma_audio_config *)tmp; + + memcpy(tmp, dmaengine_cfg->peripheral_config, + dmaengine_cfg->peripheral_size); + } + /* Set ENBLn earlier to make sure dma request triggered after that */ if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events) return -EINVAL; @@ -2267,9 +2277,6 @@ 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]; - /* 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. diff --git a/include/linux/platform_data/dma-imx.h b/include/linux/platform_data/dma-imx.h index f10d76759109..2a88d5aaad93 100644 --- a/include/linux/platform_data/dma-imx.h +++ b/include/linux/platform_data/dma-imx.h @@ -51,14 +51,44 @@ enum imx_dma_prio { DMA_PRIO_LOW = 2 }; +/** + * struct sdma_audio_config - special sdma config for audio case + * @src_fifo_num: source fifo number for mcu_2_sai/sai_2_mcu script + * For example, if there are 4 fifos, sdma will fetch + * fifos one by one and roll back to the first fifo after + * the 4th fifo fetch. + * @dst_fifo_num: similar as src_fifo_num, but dest fifo instead. + * @src_fifo_off: source fifo offset, 0 means all fifos are continuous, 1 + * means 1 word offset between fifos. All offset between + * fifos should be same. + * @dst_fifo_off: dst fifo offset, similar as @src_fifo_off. + * @words_per_fifo: numbers of words per fifo fetch/fill, 0 means + * one channel per fifo, 1 means 2 channels per fifo.. + * If 'src_fifo_num = 4' and 'chans_per_fifo = 1', it + * means the first two words(channels) fetch from fifo1 + * and then jump to fifo2 for next two words, and so on + * after the last fifo4 fetched, roll back to fifo1. + * @sw_done_sel: software done selector, PDM need enable software done feature + * in mcu_2_sai/sai_2_mcu script. + * Bit31: sw_done eanbled or not + * Bit16~Bit0: selector + * For example: 0x80000000 means sw_done enabled for done0 + * sector which is for PDM on i.mx8mm. + */ +struct sdma_audio_config { + u8 src_fifo_num; + u8 dst_fifo_num; + u8 src_fifo_off; + u8 dst_fifo_off; + u8 words_per_fifo; + u32 sw_done_sel; +}; + struct imx_dma_data { int dma_request; /* DMA request line */ int dma_request2; /* secondary DMA request line */ enum sdma_peripheral_type peripheral_type; int priority; - bool src_dualfifo; - bool dst_dualfifo; - int done_sel; }; static inline int imx_dma_is_ipu(struct dma_chan *chan)