Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

dmaengine: stm32-dma: add support to trigger STM32 MDMA

STM32 MDMA can be triggered by STM32 DMA channels transfer complete.
The "request line number" triggering STM32 MDMA is the STM32 DMAMUX channel
id set by stm32-dmamux driver in dma_spec->args[3].

stm32-dma driver fills the struct stm32_dma_mdma_config used to configure
the MDMA with struct dma_slave_config .peripheral_config/.peripheral_size.

Signed-off-by: Amelie Delaunay <amelie.delaunay@foss.st.com>
Link: https://lore.kernel.org/r/20220829154646.29867-6-amelie.delaunay@foss.st.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Amelie Delaunay and committed by
Vinod Koul
72379517 b9a22954

+46 -1
+46 -1
drivers/dma/stm32-dma.c
··· 140 140 #define STM32_DMA_THRESHOLD_FTR_MASK GENMASK(1, 0) 141 141 #define STM32_DMA_DIRECT_MODE_MASK BIT(2) 142 142 #define STM32_DMA_ALT_ACK_MODE_MASK BIT(4) 143 + #define STM32_DMA_MDMA_STREAM_ID_MASK GENMASK(19, 16) 143 144 144 145 enum stm32_dma_width { 145 146 STM32_DMA_BYTE, ··· 194 193 struct stm32_dma_sg_req sg_req[]; 195 194 }; 196 195 196 + /** 197 + * struct stm32_dma_mdma_config - STM32 DMA MDMA configuration 198 + * @stream_id: DMA request to trigger STM32 MDMA transfer 199 + * @ifcr: DMA interrupt flag clear register address, 200 + * used by STM32 MDMA to clear DMA Transfer Complete flag 201 + * @tcf: DMA Transfer Complete flag 202 + */ 203 + struct stm32_dma_mdma_config { 204 + u32 stream_id; 205 + u32 ifcr; 206 + u32 tcf; 207 + }; 208 + 197 209 struct stm32_dma_chan { 198 210 struct virt_dma_chan vchan; 199 211 bool config_init; ··· 221 207 u32 mem_burst; 222 208 u32 mem_width; 223 209 enum dma_status status; 210 + bool trig_mdma; 211 + struct stm32_dma_mdma_config mdma_config; 224 212 }; 225 213 226 214 struct stm32_dma_device { ··· 402 386 403 387 memcpy(&chan->dma_sconfig, config, sizeof(*config)); 404 388 389 + /* Check if user is requesting DMA to trigger STM32 MDMA */ 390 + if (config->peripheral_size) { 391 + config->peripheral_config = &chan->mdma_config; 392 + config->peripheral_size = sizeof(chan->mdma_config); 393 + chan->trig_mdma = true; 394 + } 395 + 405 396 chan->config_init = true; 406 397 407 398 return 0; ··· 584 561 sg_req = &chan->desc->sg_req[chan->next_sg]; 585 562 reg = &sg_req->chan_reg; 586 563 564 + /* When DMA triggers STM32 MDMA, DMA Transfer Complete is managed by STM32 MDMA */ 565 + if (chan->trig_mdma && chan->dma_sconfig.direction != DMA_MEM_TO_DEV) 566 + reg->dma_scr &= ~STM32_DMA_SCR_TCIE; 567 + 587 568 reg->dma_scr &= ~STM32_DMA_SCR_EN; 588 569 stm32_dma_write(dmadev, STM32_DMA_SCR(chan->id), reg->dma_scr); 589 570 stm32_dma_write(dmadev, STM32_DMA_SPAR(chan->id), reg->dma_spar); ··· 737 710 738 711 if (chan->desc->cyclic) { 739 712 vchan_cyclic_callback(&chan->desc->vdesc); 713 + if (chan->trig_mdma) 714 + return; 740 715 stm32_dma_sg_inc(chan); 741 716 /* cyclic while CIRC/DBM disable => post resume reconfiguration needed */ 742 717 if (!(scr & (STM32_DMA_SCR_CIRC | STM32_DMA_SCR_DBM))) ··· 1114 1085 else 1115 1086 chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_PFCTRL; 1116 1087 1088 + /* Activate Double Buffer Mode if DMA triggers STM32 MDMA and more than 1 sg */ 1089 + if (chan->trig_mdma && sg_len > 1) 1090 + chan->chan_reg.dma_scr |= STM32_DMA_SCR_DBM; 1091 + 1117 1092 for_each_sg(sgl, sg, sg_len, i) { 1118 1093 ret = stm32_dma_set_xfer_param(chan, direction, &buswidth, 1119 1094 sg_dma_len(sg), ··· 1139 1106 desc->sg_req[i].chan_reg.dma_spar = chan->chan_reg.dma_spar; 1140 1107 desc->sg_req[i].chan_reg.dma_sm0ar = sg_dma_address(sg); 1141 1108 desc->sg_req[i].chan_reg.dma_sm1ar = sg_dma_address(sg); 1109 + if (chan->trig_mdma) 1110 + desc->sg_req[i].chan_reg.dma_sm1ar += sg_dma_len(sg); 1142 1111 desc->sg_req[i].chan_reg.dma_sndtr = nb_data_items; 1143 1112 } 1144 1113 ··· 1228 1193 desc->sg_req[i].chan_reg.dma_spar = chan->chan_reg.dma_spar; 1229 1194 desc->sg_req[i].chan_reg.dma_sm0ar = buf_addr; 1230 1195 desc->sg_req[i].chan_reg.dma_sm1ar = buf_addr; 1196 + if (chan->trig_mdma) 1197 + desc->sg_req[i].chan_reg.dma_sm1ar += period_len; 1231 1198 desc->sg_req[i].chan_reg.dma_sndtr = nb_data_items; 1232 - buf_addr += period_len; 1199 + if (!chan->trig_mdma) 1200 + buf_addr += period_len; 1233 1201 } 1234 1202 1235 1203 desc->num_sgs = num_periods; ··· 1514 1476 chan->threshold = STM32_DMA_FIFO_THRESHOLD_NONE; 1515 1477 if (FIELD_GET(STM32_DMA_ALT_ACK_MODE_MASK, cfg->features)) 1516 1478 chan->chan_reg.dma_scr |= STM32_DMA_SCR_TRBUFF; 1479 + chan->mdma_config.stream_id = FIELD_GET(STM32_DMA_MDMA_STREAM_ID_MASK, cfg->features); 1517 1480 } 1518 1481 1519 1482 static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec, ··· 1654 1615 chan->id = i; 1655 1616 chan->vchan.desc_free = stm32_dma_desc_free; 1656 1617 vchan_init(&chan->vchan, dd); 1618 + 1619 + chan->mdma_config.ifcr = res->start; 1620 + chan->mdma_config.ifcr += STM32_DMA_IFCR(chan->id); 1621 + 1622 + chan->mdma_config.tcf = STM32_DMA_TCI; 1623 + chan->mdma_config.tcf <<= STM32_DMA_FLAGS_SHIFT(chan->id); 1657 1624 } 1658 1625 1659 1626 ret = dma_async_device_register(dd);