Message ID | 20240524182702.1317935-5-dave.stevenson@raspberrypi.com |
---|---|
State | New |
Headers | show |
Series | BCM2835 DMA mapping cleanups and fixes | expand |
On Fri, May 24, 2024 at 07:26:48PM +0100, Dave Stevenson wrote: > From: Stefan Wahren <stefan.wahren@i2se.com> > > Actually the generation of the Control Block info follows some simple > rules. So handle this with a separate function to avoid open coding > for every DMA operation. Another advantage is that we can easier > introduce other platforms with different info bits. May simple said as: Introduce common help funtion to prepare Control Block Info to avoid dupicate code in every DMA operation. > > Signed-off-by: Stefan Wahren <wahrenst@gmx.net> > Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> > --- > drivers/dma/bcm2835-dma.c | 50 +++++++++++++++++++++++++-------------- > 1 file changed, 32 insertions(+), 18 deletions(-) > > diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c > index 528c4593b45a..7cef7ff89575 100644 > --- a/drivers/dma/bcm2835-dma.c > +++ b/drivers/dma/bcm2835-dma.c > @@ -201,6 +201,34 @@ static inline struct bcm2835_desc *to_bcm2835_dma_desc( > return container_of(t, struct bcm2835_desc, vd.tx); > } > > +static u32 bcm2835_dma_prepare_cb_info(struct bcm2835_chan *c, > + enum dma_transfer_direction direction, > + bool zero_page) > +{ > + u32 result; > + > + if (direction == DMA_MEM_TO_MEM) > + return BCM2835_DMA_D_INC | BCM2835_DMA_S_INC; > + > + result = BCM2835_DMA_WAIT_RESP; > + > + /* Setup DREQ channel */ > + if (c->dreq != 0) > + result |= BCM2835_DMA_PER_MAP(c->dreq); > + > + if (direction == DMA_DEV_TO_MEM) { > + result |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC; > + } else { > + result |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC; > + > + /* non-lite channels can write zeroes w/o accessing memory */ > + if (zero_page && !c->is_lite_channel) > + result |= BCM2835_DMA_S_IGNORE; > + } > + > + return result; > +} > + > static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc) > { > size_t i; > @@ -615,7 +643,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_memcpy( > { > struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); > struct bcm2835_desc *d; > - u32 info = BCM2835_DMA_D_INC | BCM2835_DMA_S_INC; > + u32 info = bcm2835_dma_prepare_cb_info(c, DMA_MEM_TO_MEM, false); > u32 extra = BCM2835_DMA_INT_EN | BCM2835_DMA_WAIT_RESP; > size_t max_len = bcm2835_dma_max_frame_length(c); > size_t frames; > @@ -646,7 +674,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( > struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); > struct bcm2835_desc *d; > dma_addr_t src = 0, dst = 0; > - u32 info = BCM2835_DMA_WAIT_RESP; > + u32 info = bcm2835_dma_prepare_cb_info(c, direction, false); > u32 extra = BCM2835_DMA_INT_EN; > size_t frames; > > @@ -656,19 +684,14 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( > return NULL; > } > > - if (c->dreq != 0) > - info |= BCM2835_DMA_PER_MAP(c->dreq); > - > if (direction == DMA_DEV_TO_MEM) { > if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) > return NULL; > src = c->cfg.src_addr; > - info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC; > } else { > if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) > return NULL; > dst = c->cfg.dst_addr; > - info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC; > } > > /* count frames in sg list */ > @@ -698,7 +721,8 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( > struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); > struct bcm2835_desc *d; > dma_addr_t src, dst; > - u32 info = BCM2835_DMA_WAIT_RESP; > + u32 info = bcm2835_dma_prepare_cb_info(c, direction, > + buf_addr == od->zero_page); > u32 extra = 0; > size_t max_len = bcm2835_dma_max_frame_length(c); > size_t frames; > @@ -729,26 +753,16 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( > "%s: buffer_length (%zd) is not a multiple of period_len (%zd)\n", > __func__, buf_len, period_len); > > - /* Setup DREQ channel */ > - if (c->dreq != 0) > - info |= BCM2835_DMA_PER_MAP(c->dreq); > - > if (direction == DMA_DEV_TO_MEM) { > if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) > return NULL; > src = c->cfg.src_addr; > dst = buf_addr; > - info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC; > } else { > if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) > return NULL; > dst = c->cfg.dst_addr; > src = buf_addr; > - info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC; > - > - /* non-lite channels can write zeroes w/o accessing memory */ > - if (buf_addr == od->zero_page && !c->is_lite_channel) > - info |= BCM2835_DMA_S_IGNORE; > } > > /* calculate number of frames */ > -- > 2.34.1 >
diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 528c4593b45a..7cef7ff89575 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -201,6 +201,34 @@ static inline struct bcm2835_desc *to_bcm2835_dma_desc( return container_of(t, struct bcm2835_desc, vd.tx); } +static u32 bcm2835_dma_prepare_cb_info(struct bcm2835_chan *c, + enum dma_transfer_direction direction, + bool zero_page) +{ + u32 result; + + if (direction == DMA_MEM_TO_MEM) + return BCM2835_DMA_D_INC | BCM2835_DMA_S_INC; + + result = BCM2835_DMA_WAIT_RESP; + + /* Setup DREQ channel */ + if (c->dreq != 0) + result |= BCM2835_DMA_PER_MAP(c->dreq); + + if (direction == DMA_DEV_TO_MEM) { + result |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC; + } else { + result |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC; + + /* non-lite channels can write zeroes w/o accessing memory */ + if (zero_page && !c->is_lite_channel) + result |= BCM2835_DMA_S_IGNORE; + } + + return result; +} + static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc) { size_t i; @@ -615,7 +643,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_memcpy( { struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_desc *d; - u32 info = BCM2835_DMA_D_INC | BCM2835_DMA_S_INC; + u32 info = bcm2835_dma_prepare_cb_info(c, DMA_MEM_TO_MEM, false); u32 extra = BCM2835_DMA_INT_EN | BCM2835_DMA_WAIT_RESP; size_t max_len = bcm2835_dma_max_frame_length(c); size_t frames; @@ -646,7 +674,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_desc *d; dma_addr_t src = 0, dst = 0; - u32 info = BCM2835_DMA_WAIT_RESP; + u32 info = bcm2835_dma_prepare_cb_info(c, direction, false); u32 extra = BCM2835_DMA_INT_EN; size_t frames; @@ -656,19 +684,14 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( return NULL; } - if (c->dreq != 0) - info |= BCM2835_DMA_PER_MAP(c->dreq); - if (direction == DMA_DEV_TO_MEM) { if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) return NULL; src = c->cfg.src_addr; - info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC; } else { if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) return NULL; dst = c->cfg.dst_addr; - info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC; } /* count frames in sg list */ @@ -698,7 +721,8 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_desc *d; dma_addr_t src, dst; - u32 info = BCM2835_DMA_WAIT_RESP; + u32 info = bcm2835_dma_prepare_cb_info(c, direction, + buf_addr == od->zero_page); u32 extra = 0; size_t max_len = bcm2835_dma_max_frame_length(c); size_t frames; @@ -729,26 +753,16 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( "%s: buffer_length (%zd) is not a multiple of period_len (%zd)\n", __func__, buf_len, period_len); - /* Setup DREQ channel */ - if (c->dreq != 0) - info |= BCM2835_DMA_PER_MAP(c->dreq); - if (direction == DMA_DEV_TO_MEM) { if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) return NULL; src = c->cfg.src_addr; dst = buf_addr; - info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC; } else { if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) return NULL; dst = c->cfg.dst_addr; src = buf_addr; - info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC; - - /* non-lite channels can write zeroes w/o accessing memory */ - if (buf_addr == od->zero_page && !c->is_lite_channel) - info |= BCM2835_DMA_S_IGNORE; } /* calculate number of frames */