diff options
author | Vinod Koul <vkoul@kernel.org> | 2018-08-17 08:28:44 -0400 |
---|---|---|
committer | Vinod Koul <vkoul@kernel.org> | 2018-08-17 08:28:44 -0400 |
commit | 89b7e78fb22a59fe96f07b87afaec1d5b60f8484 (patch) | |
tree | 7b1500d5b42a889207ee6e3205e0b28599ea3655 | |
parent | 35e0db66a88de30a2d069248f6357cb9f125892f (diff) | |
parent | 218c21043d0037f616bd8af406de55a01e3fa381 (diff) |
Merge branch 'topic/renesas' into for-linus
-rw-r--r-- | Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt | 1 | ||||
-rw-r--r-- | drivers/dma/sh/rcar-dmac.c | 112 |
2 files changed, 47 insertions, 66 deletions
diff --git a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt index b1ba639554c0..946229c48657 100644 --- a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt +++ b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt | |||
@@ -29,6 +29,7 @@ Required Properties: | |||
29 | - "renesas,dmac-r8a77965" (R-Car M3-N) | 29 | - "renesas,dmac-r8a77965" (R-Car M3-N) |
30 | - "renesas,dmac-r8a77970" (R-Car V3M) | 30 | - "renesas,dmac-r8a77970" (R-Car V3M) |
31 | - "renesas,dmac-r8a77980" (R-Car V3H) | 31 | - "renesas,dmac-r8a77980" (R-Car V3H) |
32 | - "renesas,dmac-r8a77990" (R-Car E3) | ||
32 | - "renesas,dmac-r8a77995" (R-Car D3) | 33 | - "renesas,dmac-r8a77995" (R-Car D3) |
33 | 34 | ||
34 | - reg: base address and length of the registers block for the DMAC | 35 | - reg: base address and length of the registers block for the DMAC |
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c index 2a2ccd9c78e4..48ee35e2bce6 100644 --- a/drivers/dma/sh/rcar-dmac.c +++ b/drivers/dma/sh/rcar-dmac.c | |||
@@ -1,13 +1,10 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Renesas R-Car Gen2 DMA Controller Driver | 3 | * Renesas R-Car Gen2 DMA Controller Driver |
3 | * | 4 | * |
4 | * Copyright (C) 2014 Renesas Electronics Inc. | 5 | * Copyright (C) 2014 Renesas Electronics Inc. |
5 | * | 6 | * |
6 | * Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 7 | * Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com> |
7 | * | ||
8 | * This is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of version 2 of the GNU General Public License as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | 8 | */ |
12 | 9 | ||
13 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
@@ -431,7 +428,8 @@ static void rcar_dmac_chan_start_xfer(struct rcar_dmac_chan *chan) | |||
431 | chcr |= RCAR_DMACHCR_DPM_DISABLED | RCAR_DMACHCR_IE; | 428 | chcr |= RCAR_DMACHCR_DPM_DISABLED | RCAR_DMACHCR_IE; |
432 | } | 429 | } |
433 | 430 | ||
434 | rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr | RCAR_DMACHCR_DE); | 431 | rcar_dmac_chan_write(chan, RCAR_DMACHCR, |
432 | chcr | RCAR_DMACHCR_DE | RCAR_DMACHCR_CAIE); | ||
435 | } | 433 | } |
436 | 434 | ||
437 | static int rcar_dmac_init(struct rcar_dmac *dmac) | 435 | static int rcar_dmac_init(struct rcar_dmac *dmac) |
@@ -761,21 +759,15 @@ static void rcar_dmac_chcr_de_barrier(struct rcar_dmac_chan *chan) | |||
761 | dev_err(chan->chan.device->dev, "CHCR DE check error\n"); | 759 | dev_err(chan->chan.device->dev, "CHCR DE check error\n"); |
762 | } | 760 | } |
763 | 761 | ||
764 | static void rcar_dmac_sync_tcr(struct rcar_dmac_chan *chan) | 762 | static void rcar_dmac_clear_chcr_de(struct rcar_dmac_chan *chan) |
765 | { | 763 | { |
766 | u32 chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR); | 764 | u32 chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR); |
767 | 765 | ||
768 | if (!(chcr & RCAR_DMACHCR_DE)) | ||
769 | return; | ||
770 | |||
771 | /* set DE=0 and flush remaining data */ | 766 | /* set DE=0 and flush remaining data */ |
772 | rcar_dmac_chan_write(chan, RCAR_DMACHCR, (chcr & ~RCAR_DMACHCR_DE)); | 767 | rcar_dmac_chan_write(chan, RCAR_DMACHCR, (chcr & ~RCAR_DMACHCR_DE)); |
773 | 768 | ||
774 | /* make sure all remaining data was flushed */ | 769 | /* make sure all remaining data was flushed */ |
775 | rcar_dmac_chcr_de_barrier(chan); | 770 | rcar_dmac_chcr_de_barrier(chan); |
776 | |||
777 | /* back DE */ | ||
778 | rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr); | ||
779 | } | 771 | } |
780 | 772 | ||
781 | static void rcar_dmac_chan_halt(struct rcar_dmac_chan *chan) | 773 | static void rcar_dmac_chan_halt(struct rcar_dmac_chan *chan) |
@@ -783,7 +775,8 @@ static void rcar_dmac_chan_halt(struct rcar_dmac_chan *chan) | |||
783 | u32 chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR); | 775 | u32 chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR); |
784 | 776 | ||
785 | chcr &= ~(RCAR_DMACHCR_DSE | RCAR_DMACHCR_DSIE | RCAR_DMACHCR_IE | | 777 | chcr &= ~(RCAR_DMACHCR_DSE | RCAR_DMACHCR_DSIE | RCAR_DMACHCR_IE | |
786 | RCAR_DMACHCR_TE | RCAR_DMACHCR_DE); | 778 | RCAR_DMACHCR_TE | RCAR_DMACHCR_DE | |
779 | RCAR_DMACHCR_CAE | RCAR_DMACHCR_CAIE); | ||
787 | rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr); | 780 | rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr); |
788 | rcar_dmac_chcr_de_barrier(chan); | 781 | rcar_dmac_chcr_de_barrier(chan); |
789 | } | 782 | } |
@@ -812,12 +805,7 @@ static void rcar_dmac_chan_reinit(struct rcar_dmac_chan *chan) | |||
812 | } | 805 | } |
813 | } | 806 | } |
814 | 807 | ||
815 | static void rcar_dmac_stop(struct rcar_dmac *dmac) | 808 | static void rcar_dmac_stop_all_chan(struct rcar_dmac *dmac) |
816 | { | ||
817 | rcar_dmac_write(dmac, RCAR_DMAOR, 0); | ||
818 | } | ||
819 | |||
820 | static void rcar_dmac_abort(struct rcar_dmac *dmac) | ||
821 | { | 809 | { |
822 | unsigned int i; | 810 | unsigned int i; |
823 | 811 | ||
@@ -826,14 +814,24 @@ static void rcar_dmac_abort(struct rcar_dmac *dmac) | |||
826 | struct rcar_dmac_chan *chan = &dmac->channels[i]; | 814 | struct rcar_dmac_chan *chan = &dmac->channels[i]; |
827 | 815 | ||
828 | /* Stop and reinitialize the channel. */ | 816 | /* Stop and reinitialize the channel. */ |
829 | spin_lock(&chan->lock); | 817 | spin_lock_irq(&chan->lock); |
830 | rcar_dmac_chan_halt(chan); | 818 | rcar_dmac_chan_halt(chan); |
831 | spin_unlock(&chan->lock); | 819 | spin_unlock_irq(&chan->lock); |
832 | |||
833 | rcar_dmac_chan_reinit(chan); | ||
834 | } | 820 | } |
835 | } | 821 | } |
836 | 822 | ||
823 | static int rcar_dmac_chan_pause(struct dma_chan *chan) | ||
824 | { | ||
825 | unsigned long flags; | ||
826 | struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan); | ||
827 | |||
828 | spin_lock_irqsave(&rchan->lock, flags); | ||
829 | rcar_dmac_clear_chcr_de(rchan); | ||
830 | spin_unlock_irqrestore(&rchan->lock, flags); | ||
831 | |||
832 | return 0; | ||
833 | } | ||
834 | |||
837 | /* ----------------------------------------------------------------------------- | 835 | /* ----------------------------------------------------------------------------- |
838 | * Descriptors preparation | 836 | * Descriptors preparation |
839 | */ | 837 | */ |
@@ -1355,9 +1353,6 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan, | |||
1355 | residue += chunk->size; | 1353 | residue += chunk->size; |
1356 | } | 1354 | } |
1357 | 1355 | ||
1358 | if (desc->direction == DMA_DEV_TO_MEM) | ||
1359 | rcar_dmac_sync_tcr(chan); | ||
1360 | |||
1361 | /* Add the residue for the current chunk. */ | 1356 | /* Add the residue for the current chunk. */ |
1362 | residue += rcar_dmac_chan_read(chan, RCAR_DMATCRB) << desc->xfer_shift; | 1357 | residue += rcar_dmac_chan_read(chan, RCAR_DMATCRB) << desc->xfer_shift; |
1363 | 1358 | ||
@@ -1522,11 +1517,26 @@ static irqreturn_t rcar_dmac_isr_channel(int irq, void *dev) | |||
1522 | u32 mask = RCAR_DMACHCR_DSE | RCAR_DMACHCR_TE; | 1517 | u32 mask = RCAR_DMACHCR_DSE | RCAR_DMACHCR_TE; |
1523 | struct rcar_dmac_chan *chan = dev; | 1518 | struct rcar_dmac_chan *chan = dev; |
1524 | irqreturn_t ret = IRQ_NONE; | 1519 | irqreturn_t ret = IRQ_NONE; |
1520 | bool reinit = false; | ||
1525 | u32 chcr; | 1521 | u32 chcr; |
1526 | 1522 | ||
1527 | spin_lock(&chan->lock); | 1523 | spin_lock(&chan->lock); |
1528 | 1524 | ||
1529 | chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR); | 1525 | chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR); |
1526 | if (chcr & RCAR_DMACHCR_CAE) { | ||
1527 | struct rcar_dmac *dmac = to_rcar_dmac(chan->chan.device); | ||
1528 | |||
1529 | /* | ||
1530 | * We don't need to call rcar_dmac_chan_halt() | ||
1531 | * because channel is already stopped in error case. | ||
1532 | * We need to clear register and check DE bit as recovery. | ||
1533 | */ | ||
1534 | rcar_dmac_write(dmac, RCAR_DMACHCLR, 1 << chan->index); | ||
1535 | rcar_dmac_chcr_de_barrier(chan); | ||
1536 | reinit = true; | ||
1537 | goto spin_lock_end; | ||
1538 | } | ||
1539 | |||
1530 | if (chcr & RCAR_DMACHCR_TE) | 1540 | if (chcr & RCAR_DMACHCR_TE) |
1531 | mask |= RCAR_DMACHCR_DE; | 1541 | mask |= RCAR_DMACHCR_DE; |
1532 | rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr & ~mask); | 1542 | rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr & ~mask); |
@@ -1539,8 +1549,16 @@ static irqreturn_t rcar_dmac_isr_channel(int irq, void *dev) | |||
1539 | if (chcr & RCAR_DMACHCR_TE) | 1549 | if (chcr & RCAR_DMACHCR_TE) |
1540 | ret |= rcar_dmac_isr_transfer_end(chan); | 1550 | ret |= rcar_dmac_isr_transfer_end(chan); |
1541 | 1551 | ||
1552 | spin_lock_end: | ||
1542 | spin_unlock(&chan->lock); | 1553 | spin_unlock(&chan->lock); |
1543 | 1554 | ||
1555 | if (reinit) { | ||
1556 | dev_err(chan->chan.device->dev, "Channel Address Error\n"); | ||
1557 | |||
1558 | rcar_dmac_chan_reinit(chan); | ||
1559 | ret = IRQ_HANDLED; | ||
1560 | } | ||
1561 | |||
1544 | return ret; | 1562 | return ret; |
1545 | } | 1563 | } |
1546 | 1564 | ||
@@ -1597,24 +1615,6 @@ static irqreturn_t rcar_dmac_isr_channel_thread(int irq, void *dev) | |||
1597 | return IRQ_HANDLED; | 1615 | return IRQ_HANDLED; |
1598 | } | 1616 | } |
1599 | 1617 | ||
1600 | static irqreturn_t rcar_dmac_isr_error(int irq, void *data) | ||
1601 | { | ||
1602 | struct rcar_dmac *dmac = data; | ||
1603 | |||
1604 | if (!(rcar_dmac_read(dmac, RCAR_DMAOR) & RCAR_DMAOR_AE)) | ||
1605 | return IRQ_NONE; | ||
1606 | |||
1607 | /* | ||
1608 | * An unrecoverable error occurred on an unknown channel. Halt the DMAC, | ||
1609 | * abort transfers on all channels, and reinitialize the DMAC. | ||
1610 | */ | ||
1611 | rcar_dmac_stop(dmac); | ||
1612 | rcar_dmac_abort(dmac); | ||
1613 | rcar_dmac_init(dmac); | ||
1614 | |||
1615 | return IRQ_HANDLED; | ||
1616 | } | ||
1617 | |||
1618 | /* ----------------------------------------------------------------------------- | 1618 | /* ----------------------------------------------------------------------------- |
1619 | * OF xlate and channel filter | 1619 | * OF xlate and channel filter |
1620 | */ | 1620 | */ |
@@ -1784,8 +1784,6 @@ static int rcar_dmac_probe(struct platform_device *pdev) | |||
1784 | struct rcar_dmac *dmac; | 1784 | struct rcar_dmac *dmac; |
1785 | struct resource *mem; | 1785 | struct resource *mem; |
1786 | unsigned int i; | 1786 | unsigned int i; |
1787 | char *irqname; | ||
1788 | int irq; | ||
1789 | int ret; | 1787 | int ret; |
1790 | 1788 | ||
1791 | dmac = devm_kzalloc(&pdev->dev, sizeof(*dmac), GFP_KERNEL); | 1789 | dmac = devm_kzalloc(&pdev->dev, sizeof(*dmac), GFP_KERNEL); |
@@ -1824,17 +1822,6 @@ static int rcar_dmac_probe(struct platform_device *pdev) | |||
1824 | if (IS_ERR(dmac->iomem)) | 1822 | if (IS_ERR(dmac->iomem)) |
1825 | return PTR_ERR(dmac->iomem); | 1823 | return PTR_ERR(dmac->iomem); |
1826 | 1824 | ||
1827 | irq = platform_get_irq_byname(pdev, "error"); | ||
1828 | if (irq < 0) { | ||
1829 | dev_err(&pdev->dev, "no error IRQ specified\n"); | ||
1830 | return -ENODEV; | ||
1831 | } | ||
1832 | |||
1833 | irqname = devm_kasprintf(dmac->dev, GFP_KERNEL, "%s:error", | ||
1834 | dev_name(dmac->dev)); | ||
1835 | if (!irqname) | ||
1836 | return -ENOMEM; | ||
1837 | |||
1838 | /* Enable runtime PM and initialize the device. */ | 1825 | /* Enable runtime PM and initialize the device. */ |
1839 | pm_runtime_enable(&pdev->dev); | 1826 | pm_runtime_enable(&pdev->dev); |
1840 | ret = pm_runtime_get_sync(&pdev->dev); | 1827 | ret = pm_runtime_get_sync(&pdev->dev); |
@@ -1871,6 +1858,7 @@ static int rcar_dmac_probe(struct platform_device *pdev) | |||
1871 | engine->device_prep_slave_sg = rcar_dmac_prep_slave_sg; | 1858 | engine->device_prep_slave_sg = rcar_dmac_prep_slave_sg; |
1872 | engine->device_prep_dma_cyclic = rcar_dmac_prep_dma_cyclic; | 1859 | engine->device_prep_dma_cyclic = rcar_dmac_prep_dma_cyclic; |
1873 | engine->device_config = rcar_dmac_device_config; | 1860 | engine->device_config = rcar_dmac_device_config; |
1861 | engine->device_pause = rcar_dmac_chan_pause; | ||
1874 | engine->device_terminate_all = rcar_dmac_chan_terminate_all; | 1862 | engine->device_terminate_all = rcar_dmac_chan_terminate_all; |
1875 | engine->device_tx_status = rcar_dmac_tx_status; | 1863 | engine->device_tx_status = rcar_dmac_tx_status; |
1876 | engine->device_issue_pending = rcar_dmac_issue_pending; | 1864 | engine->device_issue_pending = rcar_dmac_issue_pending; |
@@ -1885,14 +1873,6 @@ static int rcar_dmac_probe(struct platform_device *pdev) | |||
1885 | goto error; | 1873 | goto error; |
1886 | } | 1874 | } |
1887 | 1875 | ||
1888 | ret = devm_request_irq(&pdev->dev, irq, rcar_dmac_isr_error, 0, | ||
1889 | irqname, dmac); | ||
1890 | if (ret) { | ||
1891 | dev_err(&pdev->dev, "failed to request IRQ %u (%d)\n", | ||
1892 | irq, ret); | ||
1893 | return ret; | ||
1894 | } | ||
1895 | |||
1896 | /* Register the DMAC as a DMA provider for DT. */ | 1876 | /* Register the DMAC as a DMA provider for DT. */ |
1897 | ret = of_dma_controller_register(pdev->dev.of_node, rcar_dmac_of_xlate, | 1877 | ret = of_dma_controller_register(pdev->dev.of_node, rcar_dmac_of_xlate, |
1898 | NULL); | 1878 | NULL); |
@@ -1932,7 +1912,7 @@ static void rcar_dmac_shutdown(struct platform_device *pdev) | |||
1932 | { | 1912 | { |
1933 | struct rcar_dmac *dmac = platform_get_drvdata(pdev); | 1913 | struct rcar_dmac *dmac = platform_get_drvdata(pdev); |
1934 | 1914 | ||
1935 | rcar_dmac_stop(dmac); | 1915 | rcar_dmac_stop_all_chan(dmac); |
1936 | } | 1916 | } |
1937 | 1917 | ||
1938 | static const struct of_device_id rcar_dmac_of_ids[] = { | 1918 | static const struct of_device_id rcar_dmac_of_ids[] = { |