diff options
| author | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2012-09-21 08:05:47 -0400 |
|---|---|---|
| committer | Vinod Koul <vinod.koul@linux.intel.com> | 2012-09-27 06:05:23 -0400 |
| commit | 4a63a8b3e8d2e4f56174deb728085010aa3ac2a1 (patch) | |
| tree | 0c6d4fb4cd88f9c7fff748909e5956ea55793ef0 | |
| parent | 482c67ea7bab80b956185a3e7553151820bc5876 (diff) | |
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>
| -rw-r--r-- | arch/arm/mach-spear13xx/spear13xx.c | 1 | ||||
| -rw-r--r-- | arch/avr32/mach-at32ap/at32ap700x.c | 1 | ||||
| -rw-r--r-- | drivers/dma/dw_dmac.c | 37 | ||||
| -rw-r--r-- | drivers/dma/dw_dmac_regs.h | 3 | ||||
| -rw-r--r-- | include/linux/dw_dmac.h | 2 |
5 files changed, 28 insertions, 16 deletions
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c index cf936b106e27..c64d8123518f 100644 --- a/arch/arm/mach-spear13xx/spear13xx.c +++ b/arch/arm/mach-spear13xx/spear13xx.c | |||
| @@ -78,6 +78,7 @@ struct dw_dma_platform_data dmac_plat_data = { | |||
| 78 | .nr_channels = 8, | 78 | .nr_channels = 8, |
| 79 | .chan_allocation_order = CHAN_ALLOCATION_DESCENDING, | 79 | .chan_allocation_order = CHAN_ALLOCATION_DESCENDING, |
| 80 | .chan_priority = CHAN_PRIORITY_DESCENDING, | 80 | .chan_priority = CHAN_PRIORITY_DESCENDING, |
| 81 | .block_size = 4095U, | ||
| 81 | }; | 82 | }; |
| 82 | 83 | ||
| 83 | void __init spear13xx_l2x0_init(void) | 84 | void __init spear13xx_l2x0_init(void) |
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index 0445c4fd67e3..2c4aefeb86b5 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c | |||
| @@ -605,6 +605,7 @@ static void __init genclk_init_parent(struct clk *clk) | |||
| 605 | 605 | ||
| 606 | static struct dw_dma_platform_data dw_dmac0_data = { | 606 | static struct dw_dma_platform_data dw_dmac0_data = { |
| 607 | .nr_channels = 3, | 607 | .nr_channels = 3, |
| 608 | .block_size = 4095U, | ||
| 608 | }; | 609 | }; |
| 609 | 610 | ||
| 610 | static struct resource dw_dmac0_resource[] = { | 611 | static struct resource dw_dmac0_resource[] = { |
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index d71bc7167891..c143b7e40716 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c | |||
| @@ -56,16 +56,6 @@ | |||
| 56 | }) | 56 | }) |
| 57 | 57 | ||
| 58 | /* | 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 | |||
| 68 | /* | ||
| 69 | * Number of descriptors to allocate for each channel. This should be | 59 | * Number of descriptors to allocate for each channel. This should be |
| 70 | * made configurable somehow; preferably, the clients (at least the | 60 | * made configurable somehow; preferably, the clients (at least the |
| 71 | * ones using slave transfers) should be able to give us a hint. | 61 | * ones using slave transfers) should be able to give us a hint. |
| @@ -672,7 +662,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, | |||
| 672 | 662 | ||
| 673 | for (offset = 0; offset < len; offset += xfer_count << src_width) { | 663 | for (offset = 0; offset < len; offset += xfer_count << src_width) { |
| 674 | xfer_count = min_t(size_t, (len - offset) >> src_width, | 664 | xfer_count = min_t(size_t, (len - offset) >> src_width, |
| 675 | DWC_MAX_COUNT); | 665 | dwc->block_size); |
| 676 | 666 | ||
| 677 | desc = dwc_desc_get(dwc); | 667 | desc = dwc_desc_get(dwc); |
| 678 | if (!desc) | 668 | if (!desc) |
| @@ -773,8 +763,8 @@ slave_sg_todev_fill_desc: | |||
| 773 | desc->lli.sar = mem; | 763 | desc->lli.sar = mem; |
| 774 | desc->lli.dar = reg; | 764 | desc->lli.dar = reg; |
| 775 | desc->lli.ctllo = ctllo | DWC_CTLL_SRC_WIDTH(mem_width); | 765 | desc->lli.ctllo = ctllo | DWC_CTLL_SRC_WIDTH(mem_width); |
| 776 | if ((len >> mem_width) > DWC_MAX_COUNT) { | 766 | if ((len >> mem_width) > dwc->block_size) { |
| 777 | dlen = DWC_MAX_COUNT << mem_width; | 767 | dlen = dwc->block_size << mem_width; |
| 778 | mem += dlen; | 768 | mem += dlen; |
| 779 | len -= dlen; | 769 | len -= dlen; |
| 780 | } else { | 770 | } else { |
| @@ -833,8 +823,8 @@ slave_sg_fromdev_fill_desc: | |||
| 833 | desc->lli.sar = reg; | 823 | desc->lli.sar = reg; |
| 834 | desc->lli.dar = mem; | 824 | desc->lli.dar = mem; |
| 835 | desc->lli.ctllo = ctllo | DWC_CTLL_DST_WIDTH(mem_width); | 825 | desc->lli.ctllo = ctllo | DWC_CTLL_DST_WIDTH(mem_width); |
| 836 | if ((len >> reg_width) > DWC_MAX_COUNT) { | 826 | if ((len >> reg_width) > dwc->block_size) { |
| 837 | dlen = DWC_MAX_COUNT << reg_width; | 827 | dlen = dwc->block_size << reg_width; |
| 838 | mem += dlen; | 828 | mem += dlen; |
| 839 | len -= dlen; | 829 | len -= dlen; |
| 840 | } else { | 830 | } else { |
| @@ -1217,7 +1207,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, | |||
| 1217 | periods = buf_len / period_len; | 1207 | periods = buf_len / period_len; |
| 1218 | 1208 | ||
| 1219 | /* Check for too big/unaligned periods and unaligned DMA buffer. */ | 1209 | /* 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)) |
| 1221 | goto out_err; | 1211 | goto out_err; |
| 1222 | if (unlikely(period_len & ((1 << reg_width) - 1))) | 1212 | if (unlikely(period_len & ((1 << reg_width) - 1))) |
| 1223 | goto out_err; | 1213 | goto out_err; |
| @@ -1383,6 +1373,7 @@ static int __devinit dw_probe(struct platform_device *pdev) | |||
| 1383 | bool autocfg; | 1373 | bool autocfg; |
| 1384 | unsigned int dw_params; | 1374 | unsigned int dw_params; |
| 1385 | unsigned int nr_channels; | 1375 | unsigned int nr_channels; |
| 1376 | unsigned int max_blk_size = 0; | ||
| 1386 | int irq; | 1377 | int irq; |
| 1387 | int err; | 1378 | int err; |
| 1388 | int i; | 1379 | int i; |
| @@ -1423,6 +1414,10 @@ static int __devinit dw_probe(struct platform_device *pdev) | |||
| 1423 | 1414 | ||
| 1424 | dw->regs = regs; | 1415 | dw->regs = regs; |
| 1425 | 1416 | ||
| 1417 | /* get hardware configuration parameters */ | ||
| 1418 | if (autocfg) | ||
| 1419 | max_blk_size = dma_readl(dw, MAX_BLK_SIZE); | ||
| 1420 | |||
| 1426 | /* Calculate all channel mask before DMA setup */ | 1421 | /* Calculate all channel mask before DMA setup */ |
| 1427 | dw->all_chan_mask = (1 << nr_channels) - 1; | 1422 | dw->all_chan_mask = (1 << nr_channels) - 1; |
| 1428 | 1423 | ||
| @@ -1468,6 +1463,16 @@ static int __devinit dw_probe(struct platform_device *pdev) | |||
| 1468 | INIT_LIST_HEAD(&dwc->free_list); | 1463 | INIT_LIST_HEAD(&dwc->free_list); |
| 1469 | 1464 | ||
| 1470 | channel_clear_bit(dw, CH_EN, dwc->mask); | 1465 | 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; | ||
| 1471 | } | 1476 | } |
| 1472 | 1477 | ||
| 1473 | /* Clear all interrupts on all channels. */ | 1478 | /* Clear all interrupts on all channels. */ |
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h index 8a3a81adbf78..2a1cc533f0c8 100644 --- a/drivers/dma/dw_dmac_regs.h +++ b/drivers/dma/dw_dmac_regs.h | |||
| @@ -193,6 +193,9 @@ struct dw_dma_chan { | |||
| 193 | 193 | ||
| 194 | unsigned int descs_allocated; | 194 | unsigned int descs_allocated; |
| 195 | 195 | ||
| 196 | /* hardware configuration */ | ||
| 197 | unsigned int block_size; | ||
| 198 | |||
| 196 | /* configuration passed via DMA_SLAVE_CONFIG */ | 199 | /* configuration passed via DMA_SLAVE_CONFIG */ |
| 197 | struct dma_slave_config dma_sconfig; | 200 | struct dma_slave_config dma_sconfig; |
| 198 | }; | 201 | }; |
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h index 2412e02d7c0f..3315ef9c785b 100644 --- a/include/linux/dw_dmac.h +++ b/include/linux/dw_dmac.h | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | * @nr_channels: Number of channels supported by hardware (max 8) | 19 | * @nr_channels: Number of channels supported by hardware (max 8) |
| 20 | * @is_private: The device channels should be marked as private and not for | 20 | * @is_private: The device channels should be marked as private and not for |
| 21 | * by the general purpose DMA channel allocator. | 21 | * by the general purpose DMA channel allocator. |
| 22 | * @block_size: Maximum block size supported by the controller | ||
| 22 | */ | 23 | */ |
| 23 | struct dw_dma_platform_data { | 24 | struct dw_dma_platform_data { |
| 24 | unsigned int nr_channels; | 25 | unsigned int nr_channels; |
| @@ -29,6 +30,7 @@ struct dw_dma_platform_data { | |||
| 29 | #define CHAN_PRIORITY_ASCENDING 0 /* chan0 highest */ | 30 | #define CHAN_PRIORITY_ASCENDING 0 /* chan0 highest */ |
| 30 | #define CHAN_PRIORITY_DESCENDING 1 /* chan7 highest */ | 31 | #define CHAN_PRIORITY_DESCENDING 1 /* chan7 highest */ |
| 31 | unsigned char chan_priority; | 32 | unsigned char chan_priority; |
| 33 | unsigned short block_size; | ||
| 32 | }; | 34 | }; |
| 33 | 35 | ||
| 34 | /* bursts size */ | 36 | /* bursts size */ |
