brcm2708-gpu-fw: update to latest version
[oweals/openwrt.git] / target / linux / brcm2708 / patches-4.4 / 0400-dmaengine-bcm2835-use-platform_get_irq_byname.patch
1 From 27a895c19212e695f70bd4860d4420f70f915fe1 Mon Sep 17 00:00:00 2001
2 From: Martin Sperl <kernel@martin.sperl.org>
3 Date: Mon, 11 Apr 2016 13:29:08 +0000
4 Subject: [PATCH] dmaengine: bcm2835: use platform_get_irq_byname
5
6 Use platform_get_irq_byname to allow for correct mapping of
7 interrupts to dma channels.
8
9 The currently implemented device tree is unfortunately
10 implemented with the wrong assumption, that each dma-channel
11 has its own dma channel, but dma-irq 11 is handling
12 dma-channel 11-14 and dma-irq 12 is actually a "catch all"
13 interrupt.
14
15 So here we use the byname variant and require that interrupts
16 are explicitly named via the interrupts-name property in the
17 device tree.
18
19 The use of shared interrupts is also implemented.
20
21 As a side-effect this means we can now use dma channels 12, 13 and 14
22 in a correct manner - also testing shows that onl using
23 channels 11 to 14 for spi and i2s works perfectly (when playing
24 some video)
25
26 Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
27 Acked-by: Eric Anholt <eric@anholt.net>
28 Acked-by: Mark Rutland <mark.rutland@arm.com>
29 Signed-off-by: Vinod Koul <vinod.koul@intel.com>
30 ---
31  drivers/dma/bcm2835-dma.c | 77 ++++++++++++++++++++++++++++++++++++++---------
32  1 file changed, 63 insertions(+), 14 deletions(-)
33
34 --- a/drivers/dma/bcm2835-dma.c
35 +++ b/drivers/dma/bcm2835-dma.c
36 @@ -46,6 +46,9 @@
37  
38  #include "virt-dma.h"
39  
40 +#define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14
41 +#define BCM2835_DMA_CHAN_NAME_SIZE 8
42 +
43  struct bcm2835_dmadev {
44         struct dma_device ddev;
45         spinlock_t lock;
46 @@ -81,6 +84,7 @@ struct bcm2835_chan {
47  
48         void __iomem *chan_base;
49         int irq_number;
50 +       unsigned int irq_flags;
51  
52         bool is_lite_channel;
53  };
54 @@ -466,6 +470,15 @@ static irqreturn_t bcm2835_dma_callback(
55         struct bcm2835_desc *d;
56         unsigned long flags;
57  
58 +       /* check the shared interrupt */
59 +       if (c->irq_flags & IRQF_SHARED) {
60 +               /* check if the interrupt is enabled */
61 +               flags = readl(c->chan_base + BCM2835_DMA_CS);
62 +               /* if not set then we are not the reason for the irq */
63 +               if (!(flags & BCM2835_DMA_INT))
64 +                       return IRQ_NONE;
65 +       }
66 +
67         spin_lock_irqsave(&c->vc.lock, flags);
68  
69         /* Acknowledge interrupt */
70 @@ -506,8 +519,8 @@ static int bcm2835_dma_alloc_chan_resour
71                 return -ENOMEM;
72         }
73  
74 -       return request_irq(c->irq_number,
75 -                       bcm2835_dma_callback, 0, "DMA IRQ", c);
76 +       return request_irq(c->irq_number, bcm2835_dma_callback,
77 +                          c->irq_flags, "DMA IRQ", c);
78  }
79  
80  static void bcm2835_dma_free_chan_resources(struct dma_chan *chan)
81 @@ -819,7 +832,8 @@ static int bcm2835_dma_terminate_all(str
82         return 0;
83  }
84  
85 -static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq)
86 +static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id,
87 +                                int irq, unsigned int irq_flags)
88  {
89         struct bcm2835_chan *c;
90  
91 @@ -834,6 +848,7 @@ static int bcm2835_dma_chan_init(struct
92         c->chan_base = BCM2835_DMA_CHANIO(d->base, chan_id);
93         c->ch = chan_id;
94         c->irq_number = irq;
95 +       c->irq_flags = irq_flags;
96  
97         /* check in DEBUG register if this is a LITE channel */
98         if (readl(c->chan_base + BCM2835_DMA_DEBUG) &
99 @@ -882,9 +897,11 @@ static int bcm2835_dma_probe(struct plat
100         struct resource *res;
101         void __iomem *base;
102         int rc;
103 -       int i;
104 -       int irq;
105 +       int i, j;
106 +       int irq[BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED + 1];
107 +       int irq_flags;
108         uint32_t chans_available;
109 +       char chan_name[BCM2835_DMA_CHAN_NAME_SIZE];
110  
111         if (!pdev->dev.dma_mask)
112                 pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
113 @@ -941,16 +958,48 @@ static int bcm2835_dma_probe(struct plat
114                 goto err_no_dma;
115         }
116  
117 -       for (i = 0; i < pdev->num_resources; i++) {
118 -               irq = platform_get_irq(pdev, i);
119 -               if (irq < 0)
120 -                       break;
121 -
122 -               if (chans_available & (1 << i)) {
123 -                       rc = bcm2835_dma_chan_init(od, i, irq);
124 -                       if (rc)
125 -                               goto err_no_dma;
126 +       /* get irqs for each channel that we support */
127 +       for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
128 +               /* skip masked out channels */
129 +               if (!(chans_available & (1 << i))) {
130 +                       irq[i] = -1;
131 +                       continue;
132                 }
133 +
134 +               /* get the named irq */
135 +               snprintf(chan_name, sizeof(chan_name), "dma%i", i);
136 +               irq[i] = platform_get_irq_byname(pdev, chan_name);
137 +               if (irq[i] >= 0)
138 +                       continue;
139 +
140 +               /* legacy device tree case handling */
141 +               dev_warn_once(&pdev->dev,
142 +                             "missing interrupts-names property in device tree - legacy interpretation is used");
143 +               /*
144 +                * in case of channel >= 11
145 +                * use the 11th interrupt and that is shared
146 +                */
147 +               irq[i] = platform_get_irq(pdev, i < 11 ? i : 11);
148 +       }
149 +
150 +       /* get irqs for each channel */
151 +       for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
152 +               /* skip channels without irq */
153 +               if (irq[i] < 0)
154 +                       continue;
155 +
156 +               /* check if there are other channels that also use this irq */
157 +               irq_flags = 0;
158 +               for (j = 0; j <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; j++)
159 +                       if ((i != j) && (irq[j] == irq[i])) {
160 +                               irq_flags = IRQF_SHARED;
161 +                               break;
162 +                       }
163 +
164 +               /* initialize the channel */
165 +               rc = bcm2835_dma_chan_init(od, i, irq[i], irq_flags);
166 +               if (rc)
167 +                       goto err_no_dma;
168         }
169  
170         dev_dbg(&pdev->dev, "Initialized %i DMA channels\n", i);