dma: dw-axi-dmac: support per channel interrupt
authorBaruch Siach <baruch@tkos.co.il>
Tue, 26 Mar 2024 11:43:07 +0000 (13:43 +0200)
committerVinod Koul <vkoul@kernel.org>
Sun, 7 Apr 2024 11:48:14 +0000 (17:18 +0530)
Hardware might not support a single combined interrupt that covers all
channels. In that case we have to deal with interrupt per channel. Add
support for that configuration.

Signed-off-by: Baruch Siach <baruch@tkos.co.il>
Link: https://lore.kernel.org/r/ebab52e886ef1adc3c40e636aeb1ba3adfe2e578.1711453387.git.baruchs-c@neureality.ai
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
drivers/dma/dw-axi-dmac/dw-axi-dmac.h

index 8e4cfac6413719b7b596865447ca2d0b772ba88e..fffafa86d964e01be1cd0ea49429aebef0352a22 100644 (file)
@@ -1443,6 +1443,24 @@ static int parse_device_properties(struct axi_dma_chip *chip)
        return 0;
 }
 
+static int axi_req_irqs(struct platform_device *pdev, struct axi_dma_chip *chip)
+{
+       int irq_count = platform_irq_count(pdev);
+       int ret;
+
+       for (int i = 0; i < irq_count; i++) {
+               chip->irq[i] = platform_get_irq(pdev, i);
+               if (chip->irq[i] < 0)
+                       return chip->irq[i];
+               ret = devm_request_irq(chip->dev, chip->irq[i], dw_axi_dma_interrupt,
+                               IRQF_SHARED, KBUILD_MODNAME, chip);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static int dw_probe(struct platform_device *pdev)
 {
        struct axi_dma_chip *chip;
@@ -1469,10 +1487,6 @@ static int dw_probe(struct platform_device *pdev)
        chip->dev = &pdev->dev;
        chip->dw->hdata = hdata;
 
-       chip->irq = platform_get_irq(pdev, 0);
-       if (chip->irq < 0)
-               return chip->irq;
-
        chip->regs = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(chip->regs))
                return PTR_ERR(chip->regs);
@@ -1513,8 +1527,7 @@ static int dw_probe(struct platform_device *pdev)
        if (!dw->chan)
                return -ENOMEM;
 
-       ret = devm_request_irq(chip->dev, chip->irq, dw_axi_dma_interrupt,
-                              IRQF_SHARED, KBUILD_MODNAME, chip);
+       ret = axi_req_irqs(pdev, chip);
        if (ret)
                return ret;
 
@@ -1627,7 +1640,9 @@ static void dw_remove(struct platform_device *pdev)
        pm_runtime_disable(chip->dev);
        axi_dma_suspend(chip);
 
-       devm_free_irq(chip->dev, chip->irq, chip);
+       for (i = 0; i < DMAC_MAX_CHANNELS; i++)
+               if (chip->irq[i] > 0)
+                       devm_free_irq(chip->dev, chip->irq[i], chip);
 
        of_dma_controller_free(chip->dev->of_node);
 
index ac571b413b21ccbcc53bec28db9a16d3d0dd5a37..b842e6a8d90d3db82690b60f2d35fcaf52e7652d 100644 (file)
@@ -65,7 +65,7 @@ struct dw_axi_dma {
 
 struct axi_dma_chip {
        struct device           *dev;
-       int                     irq;
+       int                     irq[DMAC_MAX_CHANNELS];
        void __iomem            *regs;
        void __iomem            *apb_regs;
        struct clk              *core_clk;