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

dmaengine: stm32-dma: take address into account when computing max width

DMA_SxPAR or DMA_SxM0AR/M1AR registers have to be aligned on PSIZE or MSIZE
respectively. This means that bus width needs to be forced to 1 byte when
computed width is not aligned with address.

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

authored by

Amelie Delaunay and committed by
Vinod Koul
e0ebdbdc 5d4d4dfb

+14 -5
+14 -5
drivers/dma/stm32-dma.c
··· 264 264 } 265 265 266 266 static enum dma_slave_buswidth stm32_dma_get_max_width(u32 buf_len, 267 + dma_addr_t buf_addr, 267 268 u32 threshold) 268 269 { 269 270 enum dma_slave_buswidth max_width; 271 + u64 addr = buf_addr; 270 272 271 273 if (threshold == STM32_DMA_FIFO_THRESHOLD_FULL) 272 274 max_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ··· 278 276 while ((buf_len < max_width || buf_len % max_width) && 279 277 max_width > DMA_SLAVE_BUSWIDTH_1_BYTE) 280 278 max_width = max_width >> 1; 279 + 280 + if (do_div(addr, max_width)) 281 + max_width = DMA_SLAVE_BUSWIDTH_1_BYTE; 281 282 282 283 return max_width; 283 284 } ··· 712 707 static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, 713 708 enum dma_transfer_direction direction, 714 709 enum dma_slave_buswidth *buswidth, 715 - u32 buf_len) 710 + u32 buf_len, dma_addr_t buf_addr) 716 711 { 717 712 enum dma_slave_buswidth src_addr_width, dst_addr_width; 718 713 int src_bus_width, dst_bus_width; ··· 744 739 return dst_burst_size; 745 740 746 741 /* Set memory data size */ 747 - src_addr_width = stm32_dma_get_max_width(buf_len, fifoth); 742 + src_addr_width = stm32_dma_get_max_width(buf_len, buf_addr, 743 + fifoth); 748 744 chan->mem_width = src_addr_width; 749 745 src_bus_width = stm32_dma_get_width(chan, src_addr_width); 750 746 if (src_bus_width < 0) ··· 794 788 return src_burst_size; 795 789 796 790 /* Set memory data size */ 797 - dst_addr_width = stm32_dma_get_max_width(buf_len, fifoth); 791 + dst_addr_width = stm32_dma_get_max_width(buf_len, buf_addr, 792 + fifoth); 798 793 chan->mem_width = dst_addr_width; 799 794 dst_bus_width = stm32_dma_get_width(chan, dst_addr_width); 800 795 if (dst_bus_width < 0) ··· 883 876 884 877 for_each_sg(sgl, sg, sg_len, i) { 885 878 ret = stm32_dma_set_xfer_param(chan, direction, &buswidth, 886 - sg_dma_len(sg)); 879 + sg_dma_len(sg), 880 + sg_dma_address(sg)); 887 881 if (ret < 0) 888 882 goto err; 889 883 ··· 952 944 return NULL; 953 945 } 954 946 955 - ret = stm32_dma_set_xfer_param(chan, direction, &buswidth, period_len); 947 + ret = stm32_dma_set_xfer_param(chan, direction, &buswidth, period_len, 948 + buf_addr); 956 949 if (ret < 0) 957 950 return NULL; 958 951