diff options
author | Álvaro Fernández Rojas <noltari@gmail.com> | 2016-12-02 11:50:26 +0100 |
---|---|---|
committer | Álvaro Fernández Rojas <noltari@gmail.com> | 2016-12-04 12:32:04 +0100 |
commit | 011f2c26f1b62e309f2eac6a3101bfe0a3c76c7e (patch) | |
tree | be53d4f11f7625508ee3aea9889e854ab5b5f263 /target/linux/brcm2708/patches-4.4/0399-dmaengine-bcm2835-use-platform_get_irq_byname.patch | |
parent | 4257f6548b9480cdb436115b63d5c134c5e91303 (diff) | |
download | upstream-011f2c26f1b62e309f2eac6a3101bfe0a3c76c7e.tar.gz upstream-011f2c26f1b62e309f2eac6a3101bfe0a3c76c7e.tar.bz2 upstream-011f2c26f1b62e309f2eac6a3101bfe0a3c76c7e.zip |
brcm2708: update linux 4.4 patches to latest version
As usual these patches were extracted and rebased from the raspberry pi repo:
https://github.com/raspberrypi/linux/tree/rpi-4.4.y
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Diffstat (limited to 'target/linux/brcm2708/patches-4.4/0399-dmaengine-bcm2835-use-platform_get_irq_byname.patch')
-rw-r--r-- | target/linux/brcm2708/patches-4.4/0399-dmaengine-bcm2835-use-platform_get_irq_byname.patch | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-4.4/0399-dmaengine-bcm2835-use-platform_get_irq_byname.patch b/target/linux/brcm2708/patches-4.4/0399-dmaengine-bcm2835-use-platform_get_irq_byname.patch new file mode 100644 index 0000000000..247f6d89c6 --- /dev/null +++ b/target/linux/brcm2708/patches-4.4/0399-dmaengine-bcm2835-use-platform_get_irq_byname.patch @@ -0,0 +1,170 @@ +From 2913407433c67a96d02bc4b4c1e5111fdb6d356d Mon Sep 17 00:00:00 2001 +From: Martin Sperl <kernel@martin.sperl.org> +Date: Mon, 11 Apr 2016 13:29:08 +0000 +Subject: [PATCH] dmaengine: bcm2835: use platform_get_irq_byname + +Use platform_get_irq_byname to allow for correct mapping of +interrupts to dma channels. + +The currently implemented device tree is unfortunately +implemented with the wrong assumption, that each dma-channel +has its own dma channel, but dma-irq 11 is handling +dma-channel 11-14 and dma-irq 12 is actually a "catch all" +interrupt. + +So here we use the byname variant and require that interrupts +are explicitly named via the interrupts-name property in the +device tree. + +The use of shared interrupts is also implemented. + +As a side-effect this means we can now use dma channels 12, 13 and 14 +in a correct manner - also testing shows that onl using +channels 11 to 14 for spi and i2s works perfectly (when playing +some video) + +Signed-off-by: Martin Sperl <kernel@martin.sperl.org> +Acked-by: Eric Anholt <eric@anholt.net> +Acked-by: Mark Rutland <mark.rutland@arm.com> +Signed-off-by: Vinod Koul <vinod.koul@intel.com> +--- + drivers/dma/bcm2835-dma.c | 77 ++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 63 insertions(+), 14 deletions(-) + +--- a/drivers/dma/bcm2835-dma.c ++++ b/drivers/dma/bcm2835-dma.c +@@ -46,6 +46,9 @@ + + #include "virt-dma.h" + ++#define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14 ++#define BCM2835_DMA_CHAN_NAME_SIZE 8 ++ + struct bcm2835_dmadev { + struct dma_device ddev; + spinlock_t lock; +@@ -81,6 +84,7 @@ struct bcm2835_chan { + + void __iomem *chan_base; + int irq_number; ++ unsigned int irq_flags; + + bool is_lite_channel; + }; +@@ -466,6 +470,15 @@ static irqreturn_t bcm2835_dma_callback( + struct bcm2835_desc *d; + unsigned long flags; + ++ /* check the shared interrupt */ ++ if (c->irq_flags & IRQF_SHARED) { ++ /* check if the interrupt is enabled */ ++ flags = readl(c->chan_base + BCM2835_DMA_CS); ++ /* if not set then we are not the reason for the irq */ ++ if (!(flags & BCM2835_DMA_INT)) ++ return IRQ_NONE; ++ } ++ + spin_lock_irqsave(&c->vc.lock, flags); + + /* Acknowledge interrupt */ +@@ -506,8 +519,8 @@ static int bcm2835_dma_alloc_chan_resour + return -ENOMEM; + } + +- return request_irq(c->irq_number, +- bcm2835_dma_callback, 0, "DMA IRQ", c); ++ return request_irq(c->irq_number, bcm2835_dma_callback, ++ c->irq_flags, "DMA IRQ", c); + } + + static void bcm2835_dma_free_chan_resources(struct dma_chan *chan) +@@ -819,7 +832,8 @@ static int bcm2835_dma_terminate_all(str + return 0; + } + +-static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq) ++static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, ++ int irq, unsigned int irq_flags) + { + struct bcm2835_chan *c; + +@@ -834,6 +848,7 @@ static int bcm2835_dma_chan_init(struct + c->chan_base = BCM2835_DMA_CHANIO(d->base, chan_id); + c->ch = chan_id; + c->irq_number = irq; ++ c->irq_flags = irq_flags; + + /* check in DEBUG register if this is a LITE channel */ + if (readl(c->chan_base + BCM2835_DMA_DEBUG) & +@@ -882,9 +897,11 @@ static int bcm2835_dma_probe(struct plat + struct resource *res; + void __iomem *base; + int rc; +- int i; +- int irq; ++ int i, j; ++ int irq[BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED + 1]; ++ int irq_flags; + uint32_t chans_available; ++ char chan_name[BCM2835_DMA_CHAN_NAME_SIZE]; + + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; +@@ -941,16 +958,48 @@ static int bcm2835_dma_probe(struct plat + goto err_no_dma; + } + +- for (i = 0; i < pdev->num_resources; i++) { +- irq = platform_get_irq(pdev, i); +- if (irq < 0) +- break; +- +- if (chans_available & (1 << i)) { +- rc = bcm2835_dma_chan_init(od, i, irq); +- if (rc) +- goto err_no_dma; ++ /* get irqs for each channel that we support */ ++ for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) { ++ /* skip masked out channels */ ++ if (!(chans_available & (1 << i))) { ++ irq[i] = -1; ++ continue; + } ++ ++ /* get the named irq */ ++ snprintf(chan_name, sizeof(chan_name), "dma%i", i); ++ irq[i] = platform_get_irq_byname(pdev, chan_name); ++ if (irq[i] >= 0) ++ continue; ++ ++ /* legacy device tree case handling */ ++ dev_warn_once(&pdev->dev, ++ "missing interrupts-names property in device tree - legacy interpretation is used"); ++ /* ++ * in case of channel >= 11 ++ * use the 11th interrupt and that is shared ++ */ ++ irq[i] = platform_get_irq(pdev, i < 11 ? i : 11); ++ } ++ ++ /* get irqs for each channel */ ++ for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) { ++ /* skip channels without irq */ ++ if (irq[i] < 0) ++ continue; ++ ++ /* check if there are other channels that also use this irq */ ++ irq_flags = 0; ++ for (j = 0; j <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; j++) ++ if ((i != j) && (irq[j] == irq[i])) { ++ irq_flags = IRQF_SHARED; ++ break; ++ } ++ ++ /* initialize the channel */ ++ rc = bcm2835_dma_chan_init(od, i, irq[i], irq_flags); ++ if (rc) ++ goto err_no_dma; + } + + dev_dbg(&pdev->dev, "Initialized %i DMA channels\n", i); |