Skip to content

Commit 4a63a8b

Browse files
andy-shevVinod Koul
authored andcommitted
dw_dmac: autoconfigure block_size or use platform data
The maximum block size is a configurable parameter for the chip. So, driver will try to get it from the encoded component parameters. Otherwise it will come from the platform data. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
1 parent 482c67e commit 4a63a8b

File tree

5 files changed

+28
-16
lines changed

5 files changed

+28
-16
lines changed

arch/arm/mach-spear13xx/spear13xx.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ struct dw_dma_platform_data dmac_plat_data = {
7878
.nr_channels = 8,
7979
.chan_allocation_order = CHAN_ALLOCATION_DESCENDING,
8080
.chan_priority = CHAN_PRIORITY_DESCENDING,
81+
.block_size = 4095U,
8182
};
8283

8384
void __init spear13xx_l2x0_init(void)

arch/avr32/mach-at32ap/at32ap700x.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,7 @@ static void __init genclk_init_parent(struct clk *clk)
605605

606606
static struct dw_dma_platform_data dw_dmac0_data = {
607607
.nr_channels = 3,
608+
.block_size = 4095U,
608609
};
609610

610611
static struct resource dw_dmac0_resource[] = {

drivers/dma/dw_dmac.c

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,6 @@
5555
| DWC_CTLL_SMS(_sms)); \
5656
})
5757

58-
/*
59-
* This is configuration-dependent and usually a funny size like 4095.
60-
*
61-
* Note that this is a transfer count, i.e. if we transfer 32-bit
62-
* words, we can do 16380 bytes per descriptor.
63-
*
64-
* This parameter is also system-specific.
65-
*/
66-
#define DWC_MAX_COUNT 4095U
67-
6858
/*
6959
* Number of descriptors to allocate for each channel. This should be
7060
* made configurable somehow; preferably, the clients (at least the
@@ -672,7 +662,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
672662

673663
for (offset = 0; offset < len; offset += xfer_count << src_width) {
674664
xfer_count = min_t(size_t, (len - offset) >> src_width,
675-
DWC_MAX_COUNT);
665+
dwc->block_size);
676666

677667
desc = dwc_desc_get(dwc);
678668
if (!desc)
@@ -773,8 +763,8 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
773763
desc->lli.sar = mem;
774764
desc->lli.dar = reg;
775765
desc->lli.ctllo = ctllo | DWC_CTLL_SRC_WIDTH(mem_width);
776-
if ((len >> mem_width) > DWC_MAX_COUNT) {
777-
dlen = DWC_MAX_COUNT << mem_width;
766+
if ((len >> mem_width) > dwc->block_size) {
767+
dlen = dwc->block_size << mem_width;
778768
mem += dlen;
779769
len -= dlen;
780770
} else {
@@ -833,8 +823,8 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
833823
desc->lli.sar = reg;
834824
desc->lli.dar = mem;
835825
desc->lli.ctllo = ctllo | DWC_CTLL_DST_WIDTH(mem_width);
836-
if ((len >> reg_width) > DWC_MAX_COUNT) {
837-
dlen = DWC_MAX_COUNT << reg_width;
826+
if ((len >> reg_width) > dwc->block_size) {
827+
dlen = dwc->block_size << reg_width;
838828
mem += dlen;
839829
len -= dlen;
840830
} else {
@@ -1217,7 +1207,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
12171207
periods = buf_len / period_len;
12181208

12191209
/* Check for too big/unaligned periods and unaligned DMA buffer. */
1220-
if (period_len > (DWC_MAX_COUNT << reg_width))
1210+
if (period_len > (dwc->block_size << reg_width))
12211211
goto out_err;
12221212
if (unlikely(period_len & ((1 << reg_width) - 1)))
12231213
goto out_err;
@@ -1383,6 +1373,7 @@ static int __devinit dw_probe(struct platform_device *pdev)
13831373
bool autocfg;
13841374
unsigned int dw_params;
13851375
unsigned int nr_channels;
1376+
unsigned int max_blk_size = 0;
13861377
int irq;
13871378
int err;
13881379
int i;
@@ -1423,6 +1414,10 @@ static int __devinit dw_probe(struct platform_device *pdev)
14231414

14241415
dw->regs = regs;
14251416

1417+
/* get hardware configuration parameters */
1418+
if (autocfg)
1419+
max_blk_size = dma_readl(dw, MAX_BLK_SIZE);
1420+
14261421
/* Calculate all channel mask before DMA setup */
14271422
dw->all_chan_mask = (1 << nr_channels) - 1;
14281423

@@ -1468,6 +1463,16 @@ static int __devinit dw_probe(struct platform_device *pdev)
14681463
INIT_LIST_HEAD(&dwc->free_list);
14691464

14701465
channel_clear_bit(dw, CH_EN, dwc->mask);
1466+
1467+
/* hardware configuration */
1468+
if (autocfg)
1469+
/* Decode maximum block size for given channel. The
1470+
* stored 4 bit value represents blocks from 0x00 for 3
1471+
* up to 0x0a for 4095. */
1472+
dwc->block_size =
1473+
(4 << ((max_blk_size >> 4 * i) & 0xf)) - 1;
1474+
else
1475+
dwc->block_size = pdata->block_size;
14711476
}
14721477

14731478
/* Clear all interrupts on all channels. */

drivers/dma/dw_dmac_regs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@ struct dw_dma_chan {
193193

194194
unsigned int descs_allocated;
195195

196+
/* hardware configuration */
197+
unsigned int block_size;
198+
196199
/* configuration passed via DMA_SLAVE_CONFIG */
197200
struct dma_slave_config dma_sconfig;
198201
};

include/linux/dw_dmac.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
* @nr_channels: Number of channels supported by hardware (max 8)
2020
* @is_private: The device channels should be marked as private and not for
2121
* by the general purpose DMA channel allocator.
22+
* @block_size: Maximum block size supported by the controller
2223
*/
2324
struct dw_dma_platform_data {
2425
unsigned int nr_channels;
@@ -29,6 +30,7 @@ struct dw_dma_platform_data {
2930
#define CHAN_PRIORITY_ASCENDING 0 /* chan0 highest */
3031
#define CHAN_PRIORITY_DESCENDING 1 /* chan7 highest */
3132
unsigned char chan_priority;
33+
unsigned short block_size;
3234
};
3335

3436
/* bursts size */

0 commit comments

Comments
 (0)