diff options
author | Vinod Koul <vinod.koul@intel.com> | 2015-10-30 22:05:07 -0400 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2015-10-30 22:05:07 -0400 |
commit | 6df056d8e69a557ac76bc7a88960e4addbc98386 (patch) | |
tree | 6329893f9dc953d3a87a2a6a6a22356d99d0562c | |
parent | 67d25f0d4e24775418aae403610cae99e27cdc3c (diff) | |
parent | df5c7386f62d2db95ca48005087195e9a15e2b1f (diff) |
Merge branch 'topic/dw' into for-linus
-rw-r--r-- | drivers/dma/dw/core.c | 63 | ||||
-rw-r--r-- | drivers/dma/dw/platform.c | 17 | ||||
-rw-r--r-- | include/linux/platform_data/dma-dw.h | 2 |
3 files changed, 50 insertions, 32 deletions
diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 46859f738fcf..41e9554b884d 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c | |||
@@ -1499,9 +1499,8 @@ EXPORT_SYMBOL(dw_dma_cyclic_free); | |||
1499 | int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) | 1499 | int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) |
1500 | { | 1500 | { |
1501 | struct dw_dma *dw; | 1501 | struct dw_dma *dw; |
1502 | bool autocfg; | 1502 | bool autocfg = false; |
1503 | unsigned int dw_params; | 1503 | unsigned int dw_params; |
1504 | unsigned int nr_channels; | ||
1505 | unsigned int max_blk_size = 0; | 1504 | unsigned int max_blk_size = 0; |
1506 | int err; | 1505 | int err; |
1507 | int i; | 1506 | int i; |
@@ -1515,33 +1514,42 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) | |||
1515 | 1514 | ||
1516 | pm_runtime_get_sync(chip->dev); | 1515 | pm_runtime_get_sync(chip->dev); |
1517 | 1516 | ||
1518 | dw_params = dma_read_byaddr(chip->regs, DW_PARAMS); | 1517 | if (!pdata) { |
1519 | autocfg = dw_params >> DW_PARAMS_EN & 0x1; | 1518 | dw_params = dma_read_byaddr(chip->regs, DW_PARAMS); |
1519 | dev_dbg(chip->dev, "DW_PARAMS: 0x%08x\n", dw_params); | ||
1520 | 1520 | ||
1521 | dev_dbg(chip->dev, "DW_PARAMS: 0x%08x\n", dw_params); | 1521 | autocfg = dw_params >> DW_PARAMS_EN & 1; |
1522 | if (!autocfg) { | ||
1523 | err = -EINVAL; | ||
1524 | goto err_pdata; | ||
1525 | } | ||
1522 | 1526 | ||
1523 | if (!pdata && autocfg) { | ||
1524 | pdata = devm_kzalloc(chip->dev, sizeof(*pdata), GFP_KERNEL); | 1527 | pdata = devm_kzalloc(chip->dev, sizeof(*pdata), GFP_KERNEL); |
1525 | if (!pdata) { | 1528 | if (!pdata) { |
1526 | err = -ENOMEM; | 1529 | err = -ENOMEM; |
1527 | goto err_pdata; | 1530 | goto err_pdata; |
1528 | } | 1531 | } |
1529 | 1532 | ||
1533 | /* Get hardware configuration parameters */ | ||
1534 | pdata->nr_channels = (dw_params >> DW_PARAMS_NR_CHAN & 7) + 1; | ||
1535 | pdata->nr_masters = (dw_params >> DW_PARAMS_NR_MASTER & 3) + 1; | ||
1536 | for (i = 0; i < pdata->nr_masters; i++) { | ||
1537 | pdata->data_width[i] = | ||
1538 | (dw_params >> DW_PARAMS_DATA_WIDTH(i) & 3) + 2; | ||
1539 | } | ||
1540 | max_blk_size = dma_readl(dw, MAX_BLK_SIZE); | ||
1541 | |||
1530 | /* Fill platform data with the default values */ | 1542 | /* Fill platform data with the default values */ |
1531 | pdata->is_private = true; | 1543 | pdata->is_private = true; |
1544 | pdata->is_memcpy = true; | ||
1532 | pdata->chan_allocation_order = CHAN_ALLOCATION_ASCENDING; | 1545 | pdata->chan_allocation_order = CHAN_ALLOCATION_ASCENDING; |
1533 | pdata->chan_priority = CHAN_PRIORITY_ASCENDING; | 1546 | pdata->chan_priority = CHAN_PRIORITY_ASCENDING; |
1534 | } else if (!pdata || pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) { | 1547 | } else if (pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) { |
1535 | err = -EINVAL; | 1548 | err = -EINVAL; |
1536 | goto err_pdata; | 1549 | goto err_pdata; |
1537 | } | 1550 | } |
1538 | 1551 | ||
1539 | if (autocfg) | 1552 | dw->chan = devm_kcalloc(chip->dev, pdata->nr_channels, sizeof(*dw->chan), |
1540 | nr_channels = (dw_params >> DW_PARAMS_NR_CHAN & 0x7) + 1; | ||
1541 | else | ||
1542 | nr_channels = pdata->nr_channels; | ||
1543 | |||
1544 | dw->chan = devm_kcalloc(chip->dev, nr_channels, sizeof(*dw->chan), | ||
1545 | GFP_KERNEL); | 1553 | GFP_KERNEL); |
1546 | if (!dw->chan) { | 1554 | if (!dw->chan) { |
1547 | err = -ENOMEM; | 1555 | err = -ENOMEM; |
@@ -1549,22 +1557,12 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) | |||
1549 | } | 1557 | } |
1550 | 1558 | ||
1551 | /* Get hardware configuration parameters */ | 1559 | /* Get hardware configuration parameters */ |
1552 | if (autocfg) { | 1560 | dw->nr_masters = pdata->nr_masters; |
1553 | max_blk_size = dma_readl(dw, MAX_BLK_SIZE); | 1561 | for (i = 0; i < dw->nr_masters; i++) |
1554 | 1562 | dw->data_width[i] = pdata->data_width[i]; | |
1555 | dw->nr_masters = (dw_params >> DW_PARAMS_NR_MASTER & 3) + 1; | ||
1556 | for (i = 0; i < dw->nr_masters; i++) { | ||
1557 | dw->data_width[i] = | ||
1558 | (dw_params >> DW_PARAMS_DATA_WIDTH(i) & 3) + 2; | ||
1559 | } | ||
1560 | } else { | ||
1561 | dw->nr_masters = pdata->nr_masters; | ||
1562 | for (i = 0; i < dw->nr_masters; i++) | ||
1563 | dw->data_width[i] = pdata->data_width[i]; | ||
1564 | } | ||
1565 | 1563 | ||
1566 | /* Calculate all channel mask before DMA setup */ | 1564 | /* Calculate all channel mask before DMA setup */ |
1567 | dw->all_chan_mask = (1 << nr_channels) - 1; | 1565 | dw->all_chan_mask = (1 << pdata->nr_channels) - 1; |
1568 | 1566 | ||
1569 | /* Force dma off, just in case */ | 1567 | /* Force dma off, just in case */ |
1570 | dw_dma_off(dw); | 1568 | dw_dma_off(dw); |
@@ -1589,7 +1587,7 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) | |||
1589 | goto err_pdata; | 1587 | goto err_pdata; |
1590 | 1588 | ||
1591 | INIT_LIST_HEAD(&dw->dma.channels); | 1589 | INIT_LIST_HEAD(&dw->dma.channels); |
1592 | for (i = 0; i < nr_channels; i++) { | 1590 | for (i = 0; i < pdata->nr_channels; i++) { |
1593 | struct dw_dma_chan *dwc = &dw->chan[i]; | 1591 | struct dw_dma_chan *dwc = &dw->chan[i]; |
1594 | int r = nr_channels - i - 1; | 1592 | int r = nr_channels - i - 1; |
1595 | 1593 | ||
@@ -1603,7 +1601,7 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) | |||
1603 | 1601 | ||
1604 | /* 7 is highest priority & 0 is lowest. */ | 1602 | /* 7 is highest priority & 0 is lowest. */ |
1605 | if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING) | 1603 | if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING) |
1606 | dwc->priority = r; | 1604 | dwc->priority = pdata->nr_channels - i - 1; |
1607 | else | 1605 | else |
1608 | dwc->priority = i; | 1606 | dwc->priority = i; |
1609 | 1607 | ||
@@ -1656,10 +1654,13 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) | |||
1656 | dma_writel(dw, CLEAR.DST_TRAN, dw->all_chan_mask); | 1654 | dma_writel(dw, CLEAR.DST_TRAN, dw->all_chan_mask); |
1657 | dma_writel(dw, CLEAR.ERROR, dw->all_chan_mask); | 1655 | dma_writel(dw, CLEAR.ERROR, dw->all_chan_mask); |
1658 | 1656 | ||
1659 | dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask); | 1657 | /* Set capabilities */ |
1660 | dma_cap_set(DMA_SLAVE, dw->dma.cap_mask); | 1658 | dma_cap_set(DMA_SLAVE, dw->dma.cap_mask); |
1661 | if (pdata->is_private) | 1659 | if (pdata->is_private) |
1662 | dma_cap_set(DMA_PRIVATE, dw->dma.cap_mask); | 1660 | dma_cap_set(DMA_PRIVATE, dw->dma.cap_mask); |
1661 | if (pdata->is_memcpy) | ||
1662 | dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask); | ||
1663 | |||
1663 | dw->dma.dev = chip->dev; | 1664 | dw->dma.dev = chip->dev; |
1664 | dw->dma.device_alloc_chan_resources = dwc_alloc_chan_resources; | 1665 | dw->dma.device_alloc_chan_resources = dwc_alloc_chan_resources; |
1665 | dw->dma.device_free_chan_resources = dwc_free_chan_resources; | 1666 | dw->dma.device_free_chan_resources = dwc_free_chan_resources; |
@@ -1687,7 +1688,7 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) | |||
1687 | goto err_dma_register; | 1688 | goto err_dma_register; |
1688 | 1689 | ||
1689 | dev_info(chip->dev, "DesignWare DMA Controller, %d channels\n", | 1690 | dev_info(chip->dev, "DesignWare DMA Controller, %d channels\n", |
1690 | nr_channels); | 1691 | pdata->nr_channels); |
1691 | 1692 | ||
1692 | pm_runtime_put_sync_suspend(chip->dev); | 1693 | pm_runtime_put_sync_suspend(chip->dev); |
1693 | 1694 | ||
diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index b2c3ae071429..68a4815750b5 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c | |||
@@ -155,6 +155,7 @@ static int dw_probe(struct platform_device *pdev) | |||
155 | struct dw_dma_chip *chip; | 155 | struct dw_dma_chip *chip; |
156 | struct device *dev = &pdev->dev; | 156 | struct device *dev = &pdev->dev; |
157 | struct resource *mem; | 157 | struct resource *mem; |
158 | const struct acpi_device_id *id; | ||
158 | struct dw_dma_platform_data *pdata; | 159 | struct dw_dma_platform_data *pdata; |
159 | int err; | 160 | int err; |
160 | 161 | ||
@@ -178,6 +179,11 @@ static int dw_probe(struct platform_device *pdev) | |||
178 | pdata = dev_get_platdata(dev); | 179 | pdata = dev_get_platdata(dev); |
179 | if (!pdata) | 180 | if (!pdata) |
180 | pdata = dw_dma_parse_dt(pdev); | 181 | pdata = dw_dma_parse_dt(pdev); |
182 | if (!pdata && has_acpi_companion(dev)) { | ||
183 | id = acpi_match_device(dev->driver->acpi_match_table, dev); | ||
184 | if (id) | ||
185 | pdata = (struct dw_dma_platform_data *)id->driver_data; | ||
186 | } | ||
181 | 187 | ||
182 | chip->dev = dev; | 188 | chip->dev = dev; |
183 | 189 | ||
@@ -246,8 +252,17 @@ MODULE_DEVICE_TABLE(of, dw_dma_of_id_table); | |||
246 | #endif | 252 | #endif |
247 | 253 | ||
248 | #ifdef CONFIG_ACPI | 254 | #ifdef CONFIG_ACPI |
255 | static struct dw_dma_platform_data dw_dma_acpi_pdata = { | ||
256 | .nr_channels = 8, | ||
257 | .is_private = true, | ||
258 | .chan_allocation_order = CHAN_ALLOCATION_ASCENDING, | ||
259 | .chan_priority = CHAN_PRIORITY_ASCENDING, | ||
260 | .block_size = 4095, | ||
261 | .nr_masters = 2, | ||
262 | }; | ||
263 | |||
249 | static const struct acpi_device_id dw_dma_acpi_id_table[] = { | 264 | static const struct acpi_device_id dw_dma_acpi_id_table[] = { |
250 | { "INTL9C60", 0 }, | 265 | { "INTL9C60", (kernel_ulong_t)&dw_dma_acpi_pdata }, |
251 | { } | 266 | { } |
252 | }; | 267 | }; |
253 | MODULE_DEVICE_TABLE(acpi, dw_dma_acpi_id_table); | 268 | MODULE_DEVICE_TABLE(acpi, dw_dma_acpi_id_table); |
diff --git a/include/linux/platform_data/dma-dw.h b/include/linux/platform_data/dma-dw.h index 87ac14c584f2..03b6095d3b18 100644 --- a/include/linux/platform_data/dma-dw.h +++ b/include/linux/platform_data/dma-dw.h | |||
@@ -37,6 +37,7 @@ struct dw_dma_slave { | |||
37 | * @nr_channels: Number of channels supported by hardware (max 8) | 37 | * @nr_channels: Number of channels supported by hardware (max 8) |
38 | * @is_private: The device channels should be marked as private and not for | 38 | * @is_private: The device channels should be marked as private and not for |
39 | * by the general purpose DMA channel allocator. | 39 | * by the general purpose DMA channel allocator. |
40 | * @is_memcpy: The device channels do support memory-to-memory transfers. | ||
40 | * @chan_allocation_order: Allocate channels starting from 0 or 7 | 41 | * @chan_allocation_order: Allocate channels starting from 0 or 7 |
41 | * @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0. | 42 | * @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0. |
42 | * @block_size: Maximum block size supported by the controller | 43 | * @block_size: Maximum block size supported by the controller |
@@ -47,6 +48,7 @@ struct dw_dma_slave { | |||
47 | struct dw_dma_platform_data { | 48 | struct dw_dma_platform_data { |
48 | unsigned int nr_channels; | 49 | unsigned int nr_channels; |
49 | bool is_private; | 50 | bool is_private; |
51 | bool is_memcpy; | ||
50 | #define CHAN_ALLOCATION_ASCENDING 0 /* zero to seven */ | 52 | #define CHAN_ALLOCATION_ASCENDING 0 /* zero to seven */ |
51 | #define CHAN_ALLOCATION_DESCENDING 1 /* seven to zero */ | 53 | #define CHAN_ALLOCATION_DESCENDING 1 /* seven to zero */ |
52 | unsigned char chan_allocation_order; | 54 | unsigned char chan_allocation_order; |