Message ID | 20190521112331.32424-1-alexandru.ardelean@analog.com (mailing list archive) |
---|---|
State | Changes Requested |
Headers | show |
Series | [1/2] dmaengine: axi-dmac: Discover length alignment requirement | expand |
On 21-05-19, 14:23, Alexandru Ardelean wrote: > From: Lars-Peter Clausen <lars@metafoo.de> > > Starting with version 4.1.a the AXI-DMAC is capable of reporting the > required length alignment. > > The LSBs that are required to be set for alignment will always read back as > set from the transfer length register. It is not possible to clear them by > writing a 0. This means the driver can discover the length alignment > requirement by writing 0 to that register and reading back the value. > > Since the DMA will support length alignment requirements that are different > from the address alignment requirement track both of them independently. > > For older versions of the peripheral assume that the length alignment > requirement is equal to the address alignment requirement. > > Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> You need to sign off the patch before sending. Please reread Documentation/process/submitting-patches.rst > axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, AXI_DMAC_FLAG_CYCLIC); > if (axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS) == AXI_DMAC_FLAG_CYCLIC) > @@ -670,6 +676,13 @@ static int axi_dmac_detect_caps(struct axi_dmac *dmac) > return -ENODEV; > } > > + if ((version & 0xff00) >= 0x0100) { magic numbers yaay
On Tue, 2019-05-21 at 14:30 +0530, Vinod Koul wrote: > [External] > > > On 21-05-19, 14:23, Alexandru Ardelean wrote: > > From: Lars-Peter Clausen <lars@metafoo.de> > > > > Starting with version 4.1.a the AXI-DMAC is capable of reporting the > > required length alignment. > > > > The LSBs that are required to be set for alignment will always read back as > > set from the transfer length register. It is not possible to clear them by > > writing a 0. This means the driver can discover the length alignment > > requirement by writing 0 to that register and reading back the value. > > > > Since the DMA will support length alignment requirements that are different > > from the address alignment requirement track both of them independently. > > > > For older versions of the peripheral assume that the length alignment > > requirement is equal to the address alignment requirement. > > > > Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> > > You need to sign off the patch before sending. Please reread Documentation/process/submitting-patches.rst Ack. Sorry for forgetting this one. > > > axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, AXI_DMAC_FLAG_CYCLIC); > > if (axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS) == AXI_DMAC_FLAG_CYCLIC) > > @@ -670,6 +676,13 @@ static int axi_dmac_detect_caps(struct axi_dmac *dmac) > > return -ENODEV; > > } > > > > + if ((version & 0xff00) >= 0x0100) { > > magic numbers yaay Good point. Will fix. > > -- > ~Vinod
diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c index 0984ae6eb155..edd81ceeeb33 100644 --- a/drivers/dma/dma-axi-dmac.c +++ b/drivers/dma/dma-axi-dmac.c @@ -44,6 +44,8 @@ * there is no address than can or needs to be configured for the device side. */ +#define AXI_DMAC_REG_VERSION 0x00 + #define AXI_DMAC_REG_IRQ_MASK 0x80 #define AXI_DMAC_REG_IRQ_PENDING 0x84 #define AXI_DMAC_REG_IRQ_SOURCE 0x88 @@ -110,7 +112,8 @@ struct axi_dmac_chan { unsigned int dest_type; unsigned int max_length; - unsigned int align_mask; + unsigned int address_align_mask; + unsigned int length_align_mask; bool hw_cyclic; bool hw_2d; @@ -169,14 +172,14 @@ static bool axi_dmac_check_len(struct axi_dmac_chan *chan, unsigned int len) { if (len == 0) return false; - if ((len & chan->align_mask) != 0) /* Not aligned */ + if ((len & chan->length_align_mask) != 0) /* Not aligned */ return false; return true; } static bool axi_dmac_check_addr(struct axi_dmac_chan *chan, dma_addr_t addr) { - if ((addr & chan->align_mask) != 0) /* Not aligned */ + if ((addr & chan->address_align_mask) != 0) /* Not aligned */ return false; return true; } @@ -394,7 +397,7 @@ static struct axi_dmac_sg *axi_dmac_fill_linear_sg(struct axi_dmac_chan *chan, num_segments = DIV_ROUND_UP(period_len, chan->max_length); segment_size = DIV_ROUND_UP(period_len, num_segments); /* Take care of alignment */ - segment_size = ((segment_size - 1) | chan->align_mask) + 1; + segment_size = ((segment_size - 1) | chan->length_align_mask) + 1; for (i = 0; i < num_periods; i++) { len = period_len; @@ -623,7 +626,7 @@ static int axi_dmac_parse_chan_dt(struct device_node *of_chan, return ret; chan->dest_width = val / 8; - chan->align_mask = max(chan->dest_width, chan->src_width) - 1; + chan->address_align_mask = max(chan->dest_width, chan->src_width) - 1; if (axi_dmac_dest_is_mem(chan) && axi_dmac_src_is_mem(chan)) chan->direction = DMA_MEM_TO_MEM; @@ -640,6 +643,9 @@ static int axi_dmac_parse_chan_dt(struct device_node *of_chan, static int axi_dmac_detect_caps(struct axi_dmac *dmac) { struct axi_dmac_chan *chan = &dmac->chan; + unsigned int version; + + version = axi_dmac_read(dmac, AXI_DMAC_REG_VERSION); axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, AXI_DMAC_FLAG_CYCLIC); if (axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS) == AXI_DMAC_FLAG_CYCLIC) @@ -670,6 +676,13 @@ static int axi_dmac_detect_caps(struct axi_dmac *dmac) return -ENODEV; } + if ((version & 0xff00) >= 0x0100) { + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, 0x00); + chan->length_align_mask = axi_dmac_read(dmac, AXI_DMAC_REG_X_LENGTH); + } else { + chan->length_align_mask = chan->address_align_mask; + } + return 0; }