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>
This commit is contained in:
Guennadi Liakhovetski 2013-07-10 12:09:47 +02:00 committed by Vinod Koul
parent 115357e977
commit ca8b387803
2 changed files with 45 additions and 3 deletions

View File

@ -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)

View File

@ -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;
};