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

dmaengine: apple-admac: Keep upper bits of REG_BUS_WIDTH

For RX channels, REG_BUS_WIDTH seems to default to a value of 0xf00, and
macOS preserves the upper bits when setting the configuration in the
lower ones. If we reset the upper bits to 0, this causes framing errors
on suspend/resume (the data stream "tears" and channels get swapped
around). Keeping the upper bits untouched, like the macOS driver does,
fixes this issue.

Signed-off-by: Hector Martin <marcan@marcan.st>
Reviewed-by: Martin Povišer <povik+lin@cutebit.org>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
Link: https://lore.kernel.org/r/20231029170704.82238-1-povik+lin@cutebit.org
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Hector Martin and committed by
Vinod Koul
306f5df8 375ff42c

+4 -1
+4 -1
drivers/dma/apple-admac.c
··· 57 57 58 58 #define REG_BUS_WIDTH(ch) (0x8040 + (ch) * 0x200) 59 59 60 + #define BUS_WIDTH_WORD_SIZE GENMASK(3, 0) 61 + #define BUS_WIDTH_FRAME_SIZE GENMASK(7, 4) 60 62 #define BUS_WIDTH_8BIT 0x00 61 63 #define BUS_WIDTH_16BIT 0x01 62 64 #define BUS_WIDTH_32BIT 0x02 ··· 742 740 struct admac_data *ad = adchan->host; 743 741 bool is_tx = admac_chan_direction(adchan->no) == DMA_MEM_TO_DEV; 744 742 int wordsize = 0; 745 - u32 bus_width = 0; 743 + u32 bus_width = readl_relaxed(ad->base + REG_BUS_WIDTH(adchan->no)) & 744 + ~(BUS_WIDTH_WORD_SIZE | BUS_WIDTH_FRAME_SIZE); 746 745 747 746 switch (is_tx ? config->dst_addr_width : config->src_addr_width) { 748 747 case DMA_SLAVE_BUSWIDTH_1_BYTE: