| From e24e6f7c2a5ce6be02608f445734223c0170ed93 Mon Sep 17 00:00:00 2001 |
| From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> |
| Date: Wed, 10 Jul 2013 12:09:47 +0200 |
| Subject: DMA: shdma: support the new CHCLR register layout |
| |
| On newer r-car SoCs the CHCLR register only contains one bit per channel, |
| to which a 1 has to be written to reset the channel. Older SoC versions had |
| one CHCLR register per channel, to which a 0 must be written to reset the |
| channel and clear its buffers. This patch adds support for the newer |
| layout. |
| |
| Signed-off-by: Guennadi Liakhovetski <g.liakhovetski+renesas@gmail.com> |
| Signed-off-by: Vinod Koul <vinod.koul@intel.com> |
| (cherry picked from commit ca8b387803072a16baf6d8090591b10bfdf4e253) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| drivers/dma/sh/shdma.c | 14 ++++++++++++-- |
| include/linux/sh_dma.h | 34 +++++++++++++++++++++++++++++++++- |
| 2 files changed, 45 insertions(+), 3 deletions(-) |
| |
| diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c |
| index 547a4ab69ca0..ba539d8cabee 100644 |
| --- a/drivers/dma/sh/shdma.c |
| +++ b/drivers/dma/sh/shdma.c |
| @@ -49,12 +49,22 @@ |
| static DEFINE_SPINLOCK(sh_dmae_lock); |
| static LIST_HEAD(sh_dmae_devices); |
| |
| +/* |
| + * Different DMAC implementations provide different ways to clear DMA channels: |
| + * (1) none - no CHCLR registers are available |
| + * (2) one CHCLR register per channel - 0 has to be written to it to clear |
| + * channel buffers |
| + * (3) one CHCLR per several channels - 1 has to be written to the bit, |
| + * corresponding to the specific channel to reset it |
| + */ |
| static void channel_clear(struct sh_dmae_chan *sh_dc) |
| { |
| struct sh_dmae_device *shdev = to_sh_dev(sh_dc); |
| + const struct sh_dmae_channel *chan_pdata = shdev->pdata->channel + |
| + sh_dc->shdma_chan.id; |
| + u32 val = shdev->pdata->chclr_bitwise ? 1 << chan_pdata->chclr_bit : 0; |
| |
| - __raw_writel(0, shdev->chan_reg + |
| - shdev->pdata->channel[sh_dc->shdma_chan.id].chclr_offset); |
| + __raw_writel(val, shdev->chan_reg + chan_pdata->chclr_offset); |
| } |
| |
| static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg) |
| diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h |
| index 4e83f3e034f3..776ed9d682f4 100644 |
| --- a/include/linux/sh_dma.h |
| +++ b/include/linux/sh_dma.h |
| @@ -33,13 +33,44 @@ struct sh_dmae_slave_config { |
| char mid_rid; |
| }; |
| |
| +/** |
| + * struct sh_dmae_channel - DMAC channel platform data |
| + * @offset: register offset within the main IOMEM resource |
| + * @dmars: channel DMARS register offset |
| + * @chclr_offset: channel CHCLR register offset |
| + * @dmars_bit: channel DMARS field offset within the register |
| + * @chclr_bit: bit position, to be set to reset the channel |
| + */ |
| struct sh_dmae_channel { |
| unsigned int offset; |
| unsigned int dmars; |
| - unsigned int dmars_bit; |
| unsigned int chclr_offset; |
| + unsigned char dmars_bit; |
| + unsigned char chclr_bit; |
| }; |
| |
| +/** |
| + * struct sh_dmae_pdata - DMAC platform data |
| + * @slave: array of slaves |
| + * @slave_num: number of slaves in the above array |
| + * @channel: array of DMA channels |
| + * @channel_num: number of channels in the above array |
| + * @ts_low_shift: shift of the low part of the TS field |
| + * @ts_low_mask: low TS field mask |
| + * @ts_high_shift: additional shift of the high part of the TS field |
| + * @ts_high_mask: high TS field mask |
| + * @ts_shift: array of Transfer Size shifts, indexed by TS value |
| + * @ts_shift_num: number of shifts in the above array |
| + * @dmaor_init: DMAOR initialisation value |
| + * @chcr_offset: CHCR address offset |
| + * @chcr_ie_bit: CHCR Interrupt Enable bit |
| + * @dmaor_is_32bit: DMAOR is a 32-bit register |
| + * @needs_tend_set: the TEND register has to be set |
| + * @no_dmars: DMAC has no DMARS registers |
| + * @chclr_present: DMAC has one or several CHCLR registers |
| + * @chclr_bitwise: channel CHCLR registers are bitwise |
| + * @slave_only: DMAC cannot be used for MEMCPY |
| + */ |
| struct sh_dmae_pdata { |
| const struct sh_dmae_slave_config *slave; |
| int slave_num; |
| @@ -59,6 +90,7 @@ struct sh_dmae_pdata { |
| unsigned int needs_tend_set:1; |
| unsigned int no_dmars:1; |
| unsigned int chclr_present:1; |
| + unsigned int chclr_bitwise:1; |
| unsigned int slave_only:1; |
| }; |
| |
| -- |
| 1.8.5.rc3 |
| |