brcm2708: switch to linux 4.4 and update patches
[openwrt.git] / target / linux / brcm2708 / patches-4.1 / 0163-bcm2708-dmaengine-Use-more-DMA-channels-but-not-12.patch
1 From 08746a98cb4867e704bb799506301ca7200d78fa Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.org>
3 Date: Thu, 20 Aug 2015 13:50:18 +0100
4 Subject: [PATCH 163/222] bcm2708-dmaengine: Use more DMA channels (but not 12)
5
6 1) Only the bcm2708_fb drivers uses the legacy DMA API, and
7 it requires a BULK-capable channel, so all other types
8 (FAST, NORMAL and LITE) can be made available to the regular
9 DMA API.
10
11 2) DMA channels 11-14 share an interrupt. The driver can't
12 handle this, so don't use channels 12-14 (12 was used, probably
13 because it appears to have an interrupt, but in reality that
14 interrupt is for activity on ANY channel). This may explain
15 a lockup encountered when running out of DMA channels.
16
17 The combined effect of this patch is to leave 7 DMA channels
18 available + channel 0 for bcm2708_fb via the legacy API.
19
20 See: https://github.com/raspberrypi/linux/issues/1110
21      https://github.com/raspberrypi/linux/issues/1108
22 ---
23  arch/arm/boot/dts/bcm2708_common.dtsi |  5 ++--
24  drivers/dma/bcm2708-dmaengine.c       | 43 +++++++++++++++++++++++------------
25  2 files changed, 31 insertions(+), 17 deletions(-)
26
27 --- a/arch/arm/boot/dts/bcm2708_common.dtsi
28 +++ b/arch/arm/boot/dts/bcm2708_common.dtsi
29 @@ -59,11 +59,10 @@
30                                      <1 24>,
31                                      <1 25>,
32                                      <1 26>,
33 -                                    <1 27>,
34 -                                    <1 28>;
35 +                                    <1 27>;
36  
37                         #dma-cells = <1>;
38 -                       brcm,dma-channel-mask = <0x7f35>;
39 +                       brcm,dma-channel-mask = <0x0f35>;
40                 };
41  
42                 intc: interrupt-controller {
43 --- a/drivers/dma/bcm2708-dmaengine.c
44 +++ b/drivers/dma/bcm2708-dmaengine.c
45 @@ -184,7 +184,7 @@ static void vc_dmaman_init(struct vc_dma
46  }
47  
48  static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman,
49 -                               unsigned preferred_feature_set)
50 +                               unsigned required_feature_set)
51  {
52         u32 chans;
53         int chan = 0;
54 @@ -193,10 +193,8 @@ static int vc_dmaman_chan_alloc(struct v
55         chans = dmaman->chan_available;
56         for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++)
57                 /* select the subset of available channels with the desired
58 -                  feature so long as some of the candidate channels have that
59 -                  feature */
60 -               if ((preferred_feature_set & (1 << feature)) &&
61 -                   (chans & dmaman->has_feature[feature]))
62 +                  features */
63 +               if (required_feature_set & (1 << feature))
64                         chans &= dmaman->has_feature[feature];
65  
66         if (!chans)
67 @@ -228,7 +226,7 @@ static int vc_dmaman_chan_free(struct vc
68  
69  /* DMA Manager Monitor */
70  
71 -extern int bcm_dma_chan_alloc(unsigned preferred_feature_set,
72 +extern int bcm_dma_chan_alloc(unsigned required_feature_set,
73                               void __iomem **out_dma_base, int *out_dma_irq)
74  {
75         struct vc_dmaman *dmaman = g_dmaman;
76 @@ -240,7 +238,7 @@ extern int bcm_dma_chan_alloc(unsigned p
77                 return -ENODEV;
78  
79         mutex_lock(&dmaman->lock);
80 -       chan = vc_dmaman_chan_alloc(dmaman, preferred_feature_set);
81 +       chan = vc_dmaman_chan_alloc(dmaman, required_feature_set);
82         if (chan < 0)
83                 goto out;
84  
85 @@ -442,6 +440,7 @@ static inline struct bcm2835_desc *to_bc
86         return container_of(t, struct bcm2835_desc, vd.tx);
87  }
88  
89 +#if 0
90  static void dma_dumpregs(struct bcm2835_chan *c)
91  {
92         pr_debug("-------------DMA DUMPREGS-------------\n");
93 @@ -457,6 +456,7 @@ static void dma_dumpregs(struct bcm2835_
94                 readl(c->chan_base + BCM2835_DMA_NEXTCB));
95         pr_debug("--------------------------------------\n");
96  }
97 +#endif
98  
99  static void bcm2835_dma_desc_free(struct virt_dma_desc *vd)
100  {
101 @@ -862,6 +862,7 @@ static struct dma_async_tx_descriptor *b
102                 uint32_t len = sg_dma_len(sgent);
103  
104                 for (j = 0; j < len; j += max_size) {
105 +                       u32 waits;
106                         struct bcm2835_dma_cb *control_block =
107                                 &d->control_block_base[i+splitct];
108  
109 @@ -879,7 +880,7 @@ static struct dma_async_tx_descriptor *b
110                         }
111  
112                         /* Common part */
113 -                       u32 waits = SDHCI_BCM_DMA_WAITS;
114 +                       waits = SDHCI_BCM_DMA_WAITS;
115                         if ((dma_debug >> 0) & 0x1f)
116                                 waits = (dma_debug >> 0) & 0x1f;
117                         control_block->info |= BCM2835_DMA_WAITS(waits);
118 @@ -1074,6 +1075,14 @@ static int bcm2835_dma_probe(struct plat
119         int rc;
120         int i;
121         int irq;
122 +#ifdef CONFIG_DMA_BCM2708_LEGACY
123 +       static const u32 wanted_features[] = {
124 +               BCM_DMA_FEATURE_FAST,
125 +               BCM_DMA_FEATURE_NORMAL,
126 +               BCM_DMA_FEATURE_LITE
127 +       };
128 +       int j;
129 +#endif
130  
131  
132         if (!pdev->dev.dma_mask)
133 @@ -1120,20 +1129,24 @@ static int bcm2835_dma_probe(struct plat
134  
135         platform_set_drvdata(pdev, od);
136  
137 -       for (i = 0; i < 5; i++) {
138 +       for (i = 0, j = 0; j < ARRAY_SIZE(wanted_features);) {
139 +
140                 void __iomem *chan_base;
141                 int chan_id;
142  
143 -               chan_id = bcm_dma_chan_alloc(BCM_DMA_FEATURE_LITE,
144 -                       &chan_base,
145 -                       &irq);
146 -
147 -               if (chan_id < 0)
148 -                       break;
149 +               chan_id = bcm_dma_chan_alloc(wanted_features[j],
150 +                                            &chan_base,
151 +                                            &irq);
152 +
153 +               if (chan_id < 0) {
154 +                       j++;
155 +                       continue;
156 +               }
157  
158                 rc = bcm2708_dma_chan_init(od, chan_base, chan_id, irq);
159                 if (rc)
160                         goto err_no_dma;
161 +               i++;
162         }
163  
164         if (pdev->dev.of_node) {
165 @@ -1146,6 +1159,8 @@ static int bcm2835_dma_probe(struct plat
166                 }
167         }
168  
169 +       dev_info(&pdev->dev, "Initialized %i DMA channels (+ 1 legacy)\n", i);
170 +
171  #else
172         rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
173         if (rc)