summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHector Martin <marcan@marcan.st>2023-10-29 18:07:04 +0100
committerVinod Koul <vkoul@kernel.org>2023-11-24 18:57:56 +0530
commit306f5df81fcc89b462fbeb9dbe26d9a8ad7c7582 (patch)
tree6e44c1ca78926c92585b0d47193fbf346c3b8b83 /drivers
parent375ff42c4c9825c19a53b9095ae4b3337cc83442 (diff)
downloadlinux-stable-306f5df81fcc89b462fbeb9dbe26d9a8ad7c7582.tar.gz
linux-stable-306f5df81fcc89b462fbeb9dbe26d9a8ad7c7582.tar.bz2
linux-stable-306f5df81fcc89b462fbeb9dbe26d9a8ad7c7582.zip
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/dma/apple-admac.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c
index 5b63996640d9..9588773dd2eb 100644
--- a/drivers/dma/apple-admac.c
+++ b/drivers/dma/apple-admac.c
@@ -57,6 +57,8 @@
#define REG_BUS_WIDTH(ch) (0x8040 + (ch) * 0x200)
+#define BUS_WIDTH_WORD_SIZE GENMASK(3, 0)
+#define BUS_WIDTH_FRAME_SIZE GENMASK(7, 4)
#define BUS_WIDTH_8BIT 0x00
#define BUS_WIDTH_16BIT 0x01
#define BUS_WIDTH_32BIT 0x02
@@ -740,7 +742,8 @@ static int admac_device_config(struct dma_chan *chan,
struct admac_data *ad = adchan->host;
bool is_tx = admac_chan_direction(adchan->no) == DMA_MEM_TO_DEV;
int wordsize = 0;
- u32 bus_width = 0;
+ u32 bus_width = readl_relaxed(ad->base + REG_BUS_WIDTH(adchan->no)) &
+ ~(BUS_WIDTH_WORD_SIZE | BUS_WIDTH_FRAME_SIZE);
switch (is_tx ? config->dst_addr_width : config->src_addr_width) {
case DMA_SLAVE_BUSWIDTH_1_BYTE: