diff options
Diffstat (limited to 'drivers/dma/imx-sdma.c')
-rw-r--r-- | drivers/dma/imx-sdma.c | 150 |
1 files changed, 59 insertions, 91 deletions
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index d0df198f62e9..18c0a131e4e4 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c | |||
@@ -830,20 +830,29 @@ static int sdma_load_context(struct sdma_channel *sdmac) | |||
830 | return ret; | 830 | return ret; |
831 | } | 831 | } |
832 | 832 | ||
833 | static void sdma_disable_channel(struct sdma_channel *sdmac) | 833 | static struct sdma_channel *to_sdma_chan(struct dma_chan *chan) |
834 | { | ||
835 | return container_of(chan, struct sdma_channel, chan); | ||
836 | } | ||
837 | |||
838 | static int sdma_disable_channel(struct dma_chan *chan) | ||
834 | { | 839 | { |
840 | struct sdma_channel *sdmac = to_sdma_chan(chan); | ||
835 | struct sdma_engine *sdma = sdmac->sdma; | 841 | struct sdma_engine *sdma = sdmac->sdma; |
836 | int channel = sdmac->channel; | 842 | int channel = sdmac->channel; |
837 | 843 | ||
838 | writel_relaxed(BIT(channel), sdma->regs + SDMA_H_STATSTOP); | 844 | writel_relaxed(BIT(channel), sdma->regs + SDMA_H_STATSTOP); |
839 | sdmac->status = DMA_ERROR; | 845 | sdmac->status = DMA_ERROR; |
846 | |||
847 | return 0; | ||
840 | } | 848 | } |
841 | 849 | ||
842 | static int sdma_config_channel(struct sdma_channel *sdmac) | 850 | static int sdma_config_channel(struct dma_chan *chan) |
843 | { | 851 | { |
852 | struct sdma_channel *sdmac = to_sdma_chan(chan); | ||
844 | int ret; | 853 | int ret; |
845 | 854 | ||
846 | sdma_disable_channel(sdmac); | 855 | sdma_disable_channel(chan); |
847 | 856 | ||
848 | sdmac->event_mask[0] = 0; | 857 | sdmac->event_mask[0] = 0; |
849 | sdmac->event_mask[1] = 0; | 858 | sdmac->event_mask[1] = 0; |
@@ -935,11 +944,6 @@ out: | |||
935 | return ret; | 944 | return ret; |
936 | } | 945 | } |
937 | 946 | ||
938 | static struct sdma_channel *to_sdma_chan(struct dma_chan *chan) | ||
939 | { | ||
940 | return container_of(chan, struct sdma_channel, chan); | ||
941 | } | ||
942 | |||
943 | static dma_cookie_t sdma_tx_submit(struct dma_async_tx_descriptor *tx) | 947 | static dma_cookie_t sdma_tx_submit(struct dma_async_tx_descriptor *tx) |
944 | { | 948 | { |
945 | unsigned long flags; | 949 | unsigned long flags; |
@@ -1004,7 +1008,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan) | |||
1004 | struct sdma_channel *sdmac = to_sdma_chan(chan); | 1008 | struct sdma_channel *sdmac = to_sdma_chan(chan); |
1005 | struct sdma_engine *sdma = sdmac->sdma; | 1009 | struct sdma_engine *sdma = sdmac->sdma; |
1006 | 1010 | ||
1007 | sdma_disable_channel(sdmac); | 1011 | sdma_disable_channel(chan); |
1008 | 1012 | ||
1009 | if (sdmac->event_id0) | 1013 | if (sdmac->event_id0) |
1010 | sdma_event_disable(sdmac, sdmac->event_id0); | 1014 | sdma_event_disable(sdmac, sdmac->event_id0); |
@@ -1203,35 +1207,24 @@ err_out: | |||
1203 | return NULL; | 1207 | return NULL; |
1204 | } | 1208 | } |
1205 | 1209 | ||
1206 | static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | 1210 | static int sdma_config(struct dma_chan *chan, |
1207 | unsigned long arg) | 1211 | struct dma_slave_config *dmaengine_cfg) |
1208 | { | 1212 | { |
1209 | struct sdma_channel *sdmac = to_sdma_chan(chan); | 1213 | struct sdma_channel *sdmac = to_sdma_chan(chan); |
1210 | struct dma_slave_config *dmaengine_cfg = (void *)arg; | ||
1211 | |||
1212 | switch (cmd) { | ||
1213 | case DMA_TERMINATE_ALL: | ||
1214 | sdma_disable_channel(sdmac); | ||
1215 | return 0; | ||
1216 | case DMA_SLAVE_CONFIG: | ||
1217 | if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) { | ||
1218 | sdmac->per_address = dmaengine_cfg->src_addr; | ||
1219 | sdmac->watermark_level = dmaengine_cfg->src_maxburst * | ||
1220 | dmaengine_cfg->src_addr_width; | ||
1221 | sdmac->word_size = dmaengine_cfg->src_addr_width; | ||
1222 | } else { | ||
1223 | sdmac->per_address = dmaengine_cfg->dst_addr; | ||
1224 | sdmac->watermark_level = dmaengine_cfg->dst_maxburst * | ||
1225 | dmaengine_cfg->dst_addr_width; | ||
1226 | sdmac->word_size = dmaengine_cfg->dst_addr_width; | ||
1227 | } | ||
1228 | sdmac->direction = dmaengine_cfg->direction; | ||
1229 | return sdma_config_channel(sdmac); | ||
1230 | default: | ||
1231 | return -ENOSYS; | ||
1232 | } | ||
1233 | 1214 | ||
1234 | return -EINVAL; | 1215 | if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) { |
1216 | sdmac->per_address = dmaengine_cfg->src_addr; | ||
1217 | sdmac->watermark_level = dmaengine_cfg->src_maxburst * | ||
1218 | dmaengine_cfg->src_addr_width; | ||
1219 | sdmac->word_size = dmaengine_cfg->src_addr_width; | ||
1220 | } else { | ||
1221 | sdmac->per_address = dmaengine_cfg->dst_addr; | ||
1222 | sdmac->watermark_level = dmaengine_cfg->dst_maxburst * | ||
1223 | dmaengine_cfg->dst_addr_width; | ||
1224 | sdmac->word_size = dmaengine_cfg->dst_addr_width; | ||
1225 | } | ||
1226 | sdmac->direction = dmaengine_cfg->direction; | ||
1227 | return sdma_config_channel(chan); | ||
1235 | } | 1228 | } |
1236 | 1229 | ||
1237 | static enum dma_status sdma_tx_status(struct dma_chan *chan, | 1230 | static enum dma_status sdma_tx_status(struct dma_chan *chan, |
@@ -1303,15 +1296,15 @@ static void sdma_load_firmware(const struct firmware *fw, void *context) | |||
1303 | if (header->ram_code_start + header->ram_code_size > fw->size) | 1296 | if (header->ram_code_start + header->ram_code_size > fw->size) |
1304 | goto err_firmware; | 1297 | goto err_firmware; |
1305 | switch (header->version_major) { | 1298 | switch (header->version_major) { |
1306 | case 1: | 1299 | case 1: |
1307 | sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; | 1300 | sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; |
1308 | break; | 1301 | break; |
1309 | case 2: | 1302 | case 2: |
1310 | sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2; | 1303 | sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2; |
1311 | break; | 1304 | break; |
1312 | default: | 1305 | default: |
1313 | dev_err(sdma->dev, "unknown firmware version\n"); | 1306 | dev_err(sdma->dev, "unknown firmware version\n"); |
1314 | goto err_firmware; | 1307 | goto err_firmware; |
1315 | } | 1308 | } |
1316 | 1309 | ||
1317 | addr = (void *)header + header->script_addrs_start; | 1310 | addr = (void *)header + header->script_addrs_start; |
@@ -1479,7 +1472,7 @@ static int sdma_probe(struct platform_device *pdev) | |||
1479 | if (ret) | 1472 | if (ret) |
1480 | return ret; | 1473 | return ret; |
1481 | 1474 | ||
1482 | sdma = kzalloc(sizeof(*sdma), GFP_KERNEL); | 1475 | sdma = devm_kzalloc(&pdev->dev, sizeof(*sdma), GFP_KERNEL); |
1483 | if (!sdma) | 1476 | if (!sdma) |
1484 | return -ENOMEM; | 1477 | return -ENOMEM; |
1485 | 1478 | ||
@@ -1488,48 +1481,34 @@ static int sdma_probe(struct platform_device *pdev) | |||
1488 | sdma->dev = &pdev->dev; | 1481 | sdma->dev = &pdev->dev; |
1489 | sdma->drvdata = drvdata; | 1482 | sdma->drvdata = drvdata; |
1490 | 1483 | ||
1491 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1492 | irq = platform_get_irq(pdev, 0); | 1484 | irq = platform_get_irq(pdev, 0); |
1493 | if (!iores || irq < 0) { | 1485 | if (irq < 0) |
1494 | ret = -EINVAL; | 1486 | return irq; |
1495 | goto err_irq; | ||
1496 | } | ||
1497 | 1487 | ||
1498 | if (!request_mem_region(iores->start, resource_size(iores), pdev->name)) { | 1488 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1499 | ret = -EBUSY; | 1489 | sdma->regs = devm_ioremap_resource(&pdev->dev, iores); |
1500 | goto err_request_region; | 1490 | if (IS_ERR(sdma->regs)) |
1501 | } | 1491 | return PTR_ERR(sdma->regs); |
1502 | 1492 | ||
1503 | sdma->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); | 1493 | sdma->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); |
1504 | if (IS_ERR(sdma->clk_ipg)) { | 1494 | if (IS_ERR(sdma->clk_ipg)) |
1505 | ret = PTR_ERR(sdma->clk_ipg); | 1495 | return PTR_ERR(sdma->clk_ipg); |
1506 | goto err_clk; | ||
1507 | } | ||
1508 | 1496 | ||
1509 | sdma->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); | 1497 | sdma->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); |
1510 | if (IS_ERR(sdma->clk_ahb)) { | 1498 | if (IS_ERR(sdma->clk_ahb)) |
1511 | ret = PTR_ERR(sdma->clk_ahb); | 1499 | return PTR_ERR(sdma->clk_ahb); |
1512 | goto err_clk; | ||
1513 | } | ||
1514 | 1500 | ||
1515 | clk_prepare(sdma->clk_ipg); | 1501 | clk_prepare(sdma->clk_ipg); |
1516 | clk_prepare(sdma->clk_ahb); | 1502 | clk_prepare(sdma->clk_ahb); |
1517 | 1503 | ||
1518 | sdma->regs = ioremap(iores->start, resource_size(iores)); | 1504 | ret = devm_request_irq(&pdev->dev, irq, sdma_int_handler, 0, "sdma", |
1519 | if (!sdma->regs) { | 1505 | sdma); |
1520 | ret = -ENOMEM; | ||
1521 | goto err_ioremap; | ||
1522 | } | ||
1523 | |||
1524 | ret = request_irq(irq, sdma_int_handler, 0, "sdma", sdma); | ||
1525 | if (ret) | 1506 | if (ret) |
1526 | goto err_request_irq; | 1507 | return ret; |
1527 | 1508 | ||
1528 | sdma->script_addrs = kzalloc(sizeof(*sdma->script_addrs), GFP_KERNEL); | 1509 | sdma->script_addrs = kzalloc(sizeof(*sdma->script_addrs), GFP_KERNEL); |
1529 | if (!sdma->script_addrs) { | 1510 | if (!sdma->script_addrs) |
1530 | ret = -ENOMEM; | 1511 | return -ENOMEM; |
1531 | goto err_alloc; | ||
1532 | } | ||
1533 | 1512 | ||
1534 | /* initially no scripts available */ | 1513 | /* initially no scripts available */ |
1535 | saddr_arr = (s32 *)sdma->script_addrs; | 1514 | saddr_arr = (s32 *)sdma->script_addrs; |
@@ -1600,7 +1579,12 @@ static int sdma_probe(struct platform_device *pdev) | |||
1600 | sdma->dma_device.device_tx_status = sdma_tx_status; | 1579 | sdma->dma_device.device_tx_status = sdma_tx_status; |
1601 | sdma->dma_device.device_prep_slave_sg = sdma_prep_slave_sg; | 1580 | sdma->dma_device.device_prep_slave_sg = sdma_prep_slave_sg; |
1602 | sdma->dma_device.device_prep_dma_cyclic = sdma_prep_dma_cyclic; | 1581 | sdma->dma_device.device_prep_dma_cyclic = sdma_prep_dma_cyclic; |
1603 | sdma->dma_device.device_control = sdma_control; | 1582 | sdma->dma_device.device_config = sdma_config; |
1583 | sdma->dma_device.device_terminate_all = sdma_disable_channel; | ||
1584 | sdma->dma_device.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); | ||
1585 | sdma->dma_device.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); | ||
1586 | sdma->dma_device.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); | ||
1587 | sdma->dma_device.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; | ||
1604 | sdma->dma_device.device_issue_pending = sdma_issue_pending; | 1588 | sdma->dma_device.device_issue_pending = sdma_issue_pending; |
1605 | sdma->dma_device.dev->dma_parms = &sdma->dma_parms; | 1589 | sdma->dma_device.dev->dma_parms = &sdma->dma_parms; |
1606 | dma_set_max_seg_size(sdma->dma_device.dev, 65535); | 1590 | dma_set_max_seg_size(sdma->dma_device.dev, 65535); |
@@ -1629,38 +1613,22 @@ err_register: | |||
1629 | dma_async_device_unregister(&sdma->dma_device); | 1613 | dma_async_device_unregister(&sdma->dma_device); |
1630 | err_init: | 1614 | err_init: |
1631 | kfree(sdma->script_addrs); | 1615 | kfree(sdma->script_addrs); |
1632 | err_alloc: | ||
1633 | free_irq(irq, sdma); | ||
1634 | err_request_irq: | ||
1635 | iounmap(sdma->regs); | ||
1636 | err_ioremap: | ||
1637 | err_clk: | ||
1638 | release_mem_region(iores->start, resource_size(iores)); | ||
1639 | err_request_region: | ||
1640 | err_irq: | ||
1641 | kfree(sdma); | ||
1642 | return ret; | 1616 | return ret; |
1643 | } | 1617 | } |
1644 | 1618 | ||
1645 | static int sdma_remove(struct platform_device *pdev) | 1619 | static int sdma_remove(struct platform_device *pdev) |
1646 | { | 1620 | { |
1647 | struct sdma_engine *sdma = platform_get_drvdata(pdev); | 1621 | struct sdma_engine *sdma = platform_get_drvdata(pdev); |
1648 | struct resource *iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1649 | int irq = platform_get_irq(pdev, 0); | ||
1650 | int i; | 1622 | int i; |
1651 | 1623 | ||
1652 | dma_async_device_unregister(&sdma->dma_device); | 1624 | dma_async_device_unregister(&sdma->dma_device); |
1653 | kfree(sdma->script_addrs); | 1625 | kfree(sdma->script_addrs); |
1654 | free_irq(irq, sdma); | ||
1655 | iounmap(sdma->regs); | ||
1656 | release_mem_region(iores->start, resource_size(iores)); | ||
1657 | /* Kill the tasklet */ | 1626 | /* Kill the tasklet */ |
1658 | for (i = 0; i < MAX_DMA_CHANNELS; i++) { | 1627 | for (i = 0; i < MAX_DMA_CHANNELS; i++) { |
1659 | struct sdma_channel *sdmac = &sdma->channel[i]; | 1628 | struct sdma_channel *sdmac = &sdma->channel[i]; |
1660 | 1629 | ||
1661 | tasklet_kill(&sdmac->tasklet); | 1630 | tasklet_kill(&sdmac->tasklet); |
1662 | } | 1631 | } |
1663 | kfree(sdma); | ||
1664 | 1632 | ||
1665 | platform_set_drvdata(pdev, NULL); | 1633 | platform_set_drvdata(pdev, NULL); |
1666 | dev_info(&pdev->dev, "Removed...\n"); | 1634 | dev_info(&pdev->dev, "Removed...\n"); |