Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 332883
b: refs/heads/master
c: a098200
h: refs/heads/master
i:
  332881: 32cab45
  332879: f143770
v: v3
  • Loading branch information
Andy Shevchenko authored and Vinod Koul committed Sep 27, 2012
1 parent a2228f8 commit c1a8a40
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4a63a8b3e8d2e4f56174deb728085010aa3ac2a1
refs/heads/master: a09820043c9e11149145a1ec221eed4a7b42dcce
2 changes: 2 additions & 0 deletions trunk/arch/arm/mach-spear13xx/spear13xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ struct dw_dma_platform_data dmac_plat_data = {
.chan_allocation_order = CHAN_ALLOCATION_DESCENDING,
.chan_priority = CHAN_PRIORITY_DESCENDING,
.block_size = 4095U,
.nr_masters = 2,
.data_width = { 3, 3, 0, 0 },
};

void __init spear13xx_l2x0_init(void)
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/avr32/mach-at32ap/at32ap700x.c
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,8 @@ static void __init genclk_init_parent(struct clk *clk)
static struct dw_dma_platform_data dw_dmac0_data = {
.nr_channels = 3,
.block_size = 4095U,
.nr_masters = 2,
.data_width = { 2, 2, 0, 0 },
};

static struct resource dw_dmac0_resource[] = {
Expand Down
46 changes: 40 additions & 6 deletions trunk/drivers/dma/dw_dmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,22 @@
* which does not support descriptor writeback.
*/

static inline unsigned int dwc_get_dms(struct dw_dma_slave *slave)
{
return slave ? slave->dst_master : 0;
}

static inline unsigned int dwc_get_sms(struct dw_dma_slave *slave)
{
return slave ? slave->src_master : 1;
}

#define DWC_DEFAULT_CTLLO(_chan) ({ \
struct dw_dma_slave *__slave = (_chan->private); \
struct dw_dma_chan *_dwc = to_dw_dma_chan(_chan); \
struct dma_slave_config *_sconfig = &_dwc->dma_sconfig; \
int _dms = __slave ? __slave->dst_master : 0; \
int _sms = __slave ? __slave->src_master : 1; \
int _dms = dwc_get_dms(__slave); \
int _sms = dwc_get_sms(__slave); \
u8 _smsize = __slave ? _sconfig->src_maxburst : \
DW_DMA_MSIZE_16; \
u8 _dmsize = __slave ? _sconfig->dst_maxburst : \
Expand Down Expand Up @@ -631,6 +641,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
size_t len, unsigned long flags)
{
struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
struct dw_dma_slave *dws = chan->private;
struct dw_desc *desc;
struct dw_desc *first;
struct dw_desc *prev;
Expand All @@ -650,7 +661,11 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
return NULL;
}

src_width = dst_width = dwc_fast_fls(src | dest | len);
src_width = min_t(unsigned int, dwc->dw->data_width[dwc_get_sms(dws)],
dwc_fast_fls(src | len));

dst_width = min_t(unsigned int, dwc->dw->data_width[dwc_get_dms(dws)],
dwc_fast_fls(dest | len));

ctllo = DWC_DEFAULT_CTLLO(chan)
| DWC_CTLL_DST_WIDTH(dst_width)
Expand Down Expand Up @@ -720,6 +735,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
dma_addr_t reg;
unsigned int reg_width;
unsigned int mem_width;
unsigned int data_width;
unsigned int i;
struct scatterlist *sg;
size_t total_len = 0;
Expand All @@ -743,14 +759,17 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) :
DWC_CTLL_FC(DW_DMA_FC_D_M2P);

data_width = dwc->dw->data_width[dwc_get_sms(dws)];

for_each_sg(sgl, sg, sg_len, i) {
struct dw_desc *desc;
u32 len, dlen, mem;

mem = sg_dma_address(sg);
len = sg_dma_len(sg);

mem_width = dwc_fast_fls(mem | len);
mem_width = min_t(unsigned int,
data_width, dwc_fast_fls(mem | len));

slave_sg_todev_fill_desc:
desc = dwc_desc_get(dwc);
Expand Down Expand Up @@ -803,14 +822,17 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) :
DWC_CTLL_FC(DW_DMA_FC_D_P2M);

data_width = dwc->dw->data_width[dwc_get_dms(dws)];

for_each_sg(sgl, sg, sg_len, i) {
struct dw_desc *desc;
u32 len, dlen, mem;

mem = sg_dma_address(sg);
len = sg_dma_len(sg);

mem_width = dwc_fast_fls(mem | len);
mem_width = min_t(unsigned int,
data_width, dwc_fast_fls(mem | len));

slave_sg_fromdev_fill_desc:
desc = dwc_desc_get(dwc);
Expand Down Expand Up @@ -1415,9 +1437,19 @@ static int __devinit dw_probe(struct platform_device *pdev)
dw->regs = regs;

/* get hardware configuration parameters */
if (autocfg)
if (autocfg) {
max_blk_size = dma_readl(dw, MAX_BLK_SIZE);

dw->nr_masters = (dw_params >> DW_PARAMS_NR_MASTER & 3) + 1;
for (i = 0; i < dw->nr_masters; i++) {
dw->data_width[i] =
(dw_params >> DW_PARAMS_DATA_WIDTH(i) & 3) + 2;
}
} else {
dw->nr_masters = pdata->nr_masters;
memcpy(dw->data_width, pdata->data_width, 4);
}

/* Calculate all channel mask before DMA setup */
dw->all_chan_mask = (1 << nr_channels) - 1;

Expand Down Expand Up @@ -1464,6 +1496,8 @@ static int __devinit dw_probe(struct platform_device *pdev)

channel_clear_bit(dw, CH_EN, dwc->mask);

dwc->dw = dw;

/* hardware configuration */
if (autocfg)
/* Decode maximum block size for given channel. The
Expand Down
7 changes: 7 additions & 0 deletions trunk/drivers/dma/dw_dmac_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ struct dw_dma_chan {

/* configuration passed via DMA_SLAVE_CONFIG */
struct dma_slave_config dma_sconfig;

/* backlink to dw_dma */
struct dw_dma *dw;
};

static inline struct dw_dma_chan_regs __iomem *
Expand All @@ -224,6 +227,10 @@ struct dw_dma {

u8 all_chan_mask;

/* hardware configuration */
unsigned char nr_masters;
unsigned char data_width[4];

struct dw_dma_chan chan[0];
};

Expand Down
5 changes: 5 additions & 0 deletions trunk/include/linux/dw_dmac.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
* @is_private: The device channels should be marked as private and not for
* by the general purpose DMA channel allocator.
* @block_size: Maximum block size supported by the controller
* @nr_masters: Number of AHB masters supported by the controller
* @data_width: Maximum data width supported by hardware per AHB master
* (0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
*/
struct dw_dma_platform_data {
unsigned int nr_channels;
Expand All @@ -31,6 +34,8 @@ struct dw_dma_platform_data {
#define CHAN_PRIORITY_DESCENDING 1 /* chan7 highest */
unsigned char chan_priority;
unsigned short block_size;
unsigned char nr_masters;
unsigned char data_width[4];
};

/* bursts size */
Expand Down

0 comments on commit c1a8a40

Please sign in to comment.