bcm53xx: backport Broadcom's iProc QSPI driver
[lede.git] / target / linux / bcm53xx / patches-4.4 / 083-0008-spi-iproc-qspi-Add-Broadcom-iProc-SoCs-support.patch
1 From cc20a38612dbc87dc7396affc9758e3bfbe92340 Mon Sep 17 00:00:00 2001
2 From: Kamal Dasu <kdasu.kdev@gmail.com>
3 Date: Wed, 24 Aug 2016 18:04:29 -0400
4 Subject: [PATCH] spi: iproc-qspi: Add Broadcom iProc SoCs support
5
6 This spi driver uses the common spi-bcm-qspi driver and implements iProc
7 SoCs specific interrupt controller. The common driver now calls the SoC
8 handlers when present. Adding support for both muxed l1 and unmuxed interrupt
9 sources.
10
11 Signed-off-by: Kamal Dasu <kdasu.kdev@gmail.com>
12 Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>
13 Signed-off-by: Mark Brown <broonie@kernel.org>
14 ---
15  drivers/spi/Makefile         |   2 +-
16  drivers/spi/spi-bcm-qspi.c   |  97 ++++++++++++++++++++++++-
17  drivers/spi/spi-bcm-qspi.h   |  34 ++++++++-
18  drivers/spi/spi-iproc-qspi.c | 163 +++++++++++++++++++++++++++++++++++++++++++
19  4 files changed, 291 insertions(+), 5 deletions(-)
20  create mode 100644 drivers/spi/spi-iproc-qspi.c
21
22 --- a/drivers/spi/Makefile
23 +++ b/drivers/spi/Makefile
24 @@ -19,7 +19,7 @@ obj-$(CONFIG_SPI_BCM2835AUX)          += spi-bcm
25  obj-$(CONFIG_SPI_BCM53XX)              += spi-bcm53xx.o
26  obj-$(CONFIG_SPI_BCM63XX)              += spi-bcm63xx.o
27  obj-$(CONFIG_SPI_BCM63XX_HSSPI)                += spi-bcm63xx-hsspi.o
28 -obj-$(CONFIG_SPI_BCM_QSPI)             += spi-brcmstb-qspi.o spi-bcm-qspi.o
29 +obj-$(CONFIG_SPI_BCM_QSPI)             += spi-iproc-qspi.o spi-brcmstb-qspi.o spi-bcm-qspi.o
30  obj-$(CONFIG_SPI_BFIN5XX)              += spi-bfin5xx.o
31  obj-$(CONFIG_SPI_ADI_V3)                += spi-adi-v3.o
32  obj-$(CONFIG_SPI_BFIN_SPORT)           += spi-bfin-sport.o
33 --- a/drivers/spi/spi-bcm-qspi.c
34 +++ b/drivers/spi/spi-bcm-qspi.c
35 @@ -175,9 +175,15 @@ enum base_type {
36         BASEMAX,
37  };
38  
39 +enum irq_source {
40 +       SINGLE_L2,
41 +       MUXED_L1,
42 +};
43 +
44  struct bcm_qspi_irq {
45         const char *irq_name;
46         const irq_handler_t irq_handler;
47 +       int irq_source;
48         u32 mask;
49  };
50  
51 @@ -198,6 +204,10 @@ struct bcm_qspi {
52         u32 base_clk;
53         u32 max_speed_hz;
54         void __iomem *base[BASEMAX];
55 +
56 +       /* Some SoCs provide custom interrupt status register(s) */
57 +       struct bcm_qspi_soc_intc        *soc_intc;
58 +
59         struct bcm_qspi_parms last_parms;
60         struct qspi_trans  trans_pos;
61         int curr_cs;
62 @@ -806,6 +816,7 @@ static int bcm_qspi_bspi_flash_read(stru
63         u32 addr = 0, len, len_words;
64         int ret = 0;
65         unsigned long timeo = msecs_to_jiffies(100);
66 +       struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc;
67  
68         if (bcm_qspi_bspi_ver_three(qspi))
69                 if (msg->addr_width == BSPI_ADDRLEN_4BYTES)
70 @@ -850,6 +861,15 @@ static int bcm_qspi_bspi_flash_read(stru
71         bcm_qspi_write(qspi, BSPI, BSPI_RAF_NUM_WORDS, len_words);
72         bcm_qspi_write(qspi, BSPI, BSPI_RAF_WATERMARK, 0);
73  
74 +       if (qspi->soc_intc) {
75 +               /*
76 +                * clear soc MSPI and BSPI interrupts and enable
77 +                * BSPI interrupts.
78 +                */
79 +               soc_intc->bcm_qspi_int_ack(soc_intc, MSPI_BSPI_DONE);
80 +               soc_intc->bcm_qspi_int_set(soc_intc, BSPI_DONE, true);
81 +       }
82 +
83         /* Must flush previous writes before starting BSPI operation */
84         mb();
85  
86 @@ -952,9 +972,12 @@ static irqreturn_t bcm_qspi_mspi_l2_isr(
87         u32 status = bcm_qspi_read(qspi, MSPI, MSPI_MSPI_STATUS);
88  
89         if (status & MSPI_MSPI_STATUS_SPIF) {
90 +               struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc;
91                 /* clear interrupt */
92                 status &= ~MSPI_MSPI_STATUS_SPIF;
93                 bcm_qspi_write(qspi, MSPI, MSPI_MSPI_STATUS, status);
94 +               if (qspi->soc_intc)
95 +                       soc_intc->bcm_qspi_int_ack(soc_intc, MSPI_DONE);
96                 complete(&qspi->mspi_done);
97                 return IRQ_HANDLED;
98         }
99 @@ -966,20 +989,33 @@ static irqreturn_t bcm_qspi_bspi_lr_l2_i
100  {
101         struct bcm_qspi_dev_id *qspi_dev_id = dev_id;
102         struct bcm_qspi *qspi = qspi_dev_id->dev;
103 -       u32 status;
104 +       struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc;
105 +       u32 status = qspi_dev_id->irqp->mask;
106  
107         if (qspi->bspi_enabled && qspi->bspi_rf_msg) {
108                 bcm_qspi_bspi_lr_data_read(qspi);
109                 if (qspi->bspi_rf_msg_len == 0) {
110                         qspi->bspi_rf_msg = NULL;
111 +                       if (qspi->soc_intc) {
112 +                               /* disable soc BSPI interrupt */
113 +                               soc_intc->bcm_qspi_int_set(soc_intc, BSPI_DONE,
114 +                                                          false);
115 +                               /* indicate done */
116 +                               status = INTR_BSPI_LR_SESSION_DONE_MASK;
117 +                       }
118 +
119                         if (qspi->bspi_rf_msg_status)
120                                 bcm_qspi_bspi_lr_clear(qspi);
121                         else
122                                 bcm_qspi_bspi_flush_prefetch_buffers(qspi);
123                 }
124 +
125 +               if (qspi->soc_intc)
126 +                       /* clear soc BSPI interrupt */
127 +                       soc_intc->bcm_qspi_int_ack(soc_intc, BSPI_DONE);
128         }
129  
130 -       status = (qspi_dev_id->irqp->mask & INTR_BSPI_LR_SESSION_DONE_MASK);
131 +       status &= INTR_BSPI_LR_SESSION_DONE_MASK;
132         if (qspi->bspi_enabled && status && qspi->bspi_rf_msg_len == 0)
133                 complete(&qspi->bspi_done);
134  
135 @@ -990,13 +1026,39 @@ static irqreturn_t bcm_qspi_bspi_lr_err_
136  {
137         struct bcm_qspi_dev_id *qspi_dev_id = dev_id;
138         struct bcm_qspi *qspi = qspi_dev_id->dev;
139 +       struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc;
140  
141         dev_err(&qspi->pdev->dev, "BSPI INT error\n");
142         qspi->bspi_rf_msg_status = -EIO;
143 +       if (qspi->soc_intc)
144 +               /* clear soc interrupt */
145 +               soc_intc->bcm_qspi_int_ack(soc_intc, BSPI_ERR);
146 +
147         complete(&qspi->bspi_done);
148         return IRQ_HANDLED;
149  }
150  
151 +static irqreturn_t bcm_qspi_l1_isr(int irq, void *dev_id)
152 +{
153 +       struct bcm_qspi_dev_id *qspi_dev_id = dev_id;
154 +       struct bcm_qspi *qspi = qspi_dev_id->dev;
155 +       struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc;
156 +       irqreturn_t ret = IRQ_NONE;
157 +
158 +       if (soc_intc) {
159 +               u32 status = soc_intc->bcm_qspi_get_int_status(soc_intc);
160 +
161 +               if (status & MSPI_DONE)
162 +                       ret = bcm_qspi_mspi_l2_isr(irq, dev_id);
163 +               else if (status & BSPI_DONE)
164 +                       ret = bcm_qspi_bspi_lr_l2_isr(irq, dev_id);
165 +               else if (status & BSPI_ERR)
166 +                       ret = bcm_qspi_bspi_lr_err_l2_isr(irq, dev_id);
167 +       }
168 +
169 +       return ret;
170 +}
171 +
172  static const struct bcm_qspi_irq qspi_irq_tab[] = {
173         {
174                 .irq_name = "spi_lr_fullness_reached",
175 @@ -1036,6 +1098,13 @@ static const struct bcm_qspi_irq qspi_ir
176                 .irq_handler = bcm_qspi_mspi_l2_isr,
177                 .mask = INTR_MSPI_HALTED_MASK,
178         },
179 +       {
180 +               /* single muxed L1 interrupt source */
181 +               .irq_name = "spi_l1_intr",
182 +               .irq_handler = bcm_qspi_l1_isr,
183 +               .irq_source = MUXED_L1,
184 +               .mask = QSPI_INTERRUPTS_ALL,
185 +       },
186  };
187  
188  static void bcm_qspi_bspi_init(struct bcm_qspi *qspi)
189 @@ -1182,7 +1251,13 @@ int bcm_qspi_probe(struct platform_devic
190         for (val = 0; val < num_irqs; val++) {
191                 irq = -1;
192                 name = qspi_irq_tab[val].irq_name;
193 -               irq = platform_get_irq_byname(pdev, name);
194 +               if (qspi_irq_tab[val].irq_source == SINGLE_L2) {
195 +                       /* get the l2 interrupts */
196 +                       irq = platform_get_irq_byname(pdev, name);
197 +               } else if (!num_ints && soc_intc) {
198 +                       /* all mspi, bspi intrs muxed to one L1 intr */
199 +                       irq = platform_get_irq(pdev, 0);
200 +               }
201  
202                 if (irq  >= 0) {
203                         ret = devm_request_irq(&pdev->dev, irq,
204 @@ -1209,6 +1284,17 @@ int bcm_qspi_probe(struct platform_devic
205                 goto qspi_probe_err;
206         }
207  
208 +       /*
209 +        * Some SoCs integrate spi controller (e.g., its interrupt bits)
210 +        * in specific ways
211 +        */
212 +       if (soc_intc) {
213 +               qspi->soc_intc = soc_intc;
214 +               soc_intc->bcm_qspi_int_set(soc_intc, MSPI_DONE, true);
215 +       } else {
216 +               qspi->soc_intc = NULL;
217 +       }
218 +
219         qspi->clk = devm_clk_get(&pdev->dev, NULL);
220         if (IS_ERR(qspi->clk)) {
221                 dev_warn(dev, "unable to get clock\n");
222 @@ -1288,6 +1374,11 @@ static int __maybe_unused bcm_qspi_resum
223  
224         bcm_qspi_hw_init(qspi);
225         bcm_qspi_chip_select(qspi, qspi->curr_cs);
226 +       if (qspi->soc_intc)
227 +               /* enable MSPI interrupt */
228 +               qspi->soc_intc->bcm_qspi_int_set(qspi->soc_intc, MSPI_DONE,
229 +                                                true);
230 +
231         ret = clk_enable(qspi->clk);
232         if (!ret)
233                 spi_master_resume(qspi->master);
234 --- a/drivers/spi/spi-bcm-qspi.h
235 +++ b/drivers/spi/spi-bcm-qspi.h
236 @@ -48,10 +48,26 @@
237         (INTR_MSPI_DONE_MASK |                 \
238          INTR_MSPI_HALTED_MASK)
239  
240 +#define QSPI_INTERRUPTS_ALL                    \
241 +       (MSPI_INTERRUPTS_ALL |                 \
242 +        BSPI_LR_INTERRUPTS_ALL)
243 +
244  struct platform_device;
245  struct dev_pm_ops;
246  
247 -struct bcm_qspi_soc_intc;
248 +enum {
249 +       MSPI_DONE = 0x1,
250 +       BSPI_DONE = 0x2,
251 +       BSPI_ERR = 0x4,
252 +       MSPI_BSPI_DONE = 0x7
253 +};
254 +
255 +struct bcm_qspi_soc_intc {
256 +       void (*bcm_qspi_int_ack)(struct bcm_qspi_soc_intc *soc_intc, int type);
257 +       void (*bcm_qspi_int_set)(struct bcm_qspi_soc_intc *soc_intc, int type,
258 +                                bool en);
259 +       u32 (*bcm_qspi_get_int_status)(struct bcm_qspi_soc_intc *soc_intc);
260 +};
261  
262  /* Read controller register*/
263  static inline u32 bcm_qspi_readl(bool be, void __iomem *addr)
264 @@ -72,6 +88,22 @@ static inline void bcm_qspi_writel(bool
265                 writel_relaxed(data, addr);
266  }
267  
268 +static inline u32 get_qspi_mask(int type)
269 +{
270 +       switch (type) {
271 +       case MSPI_DONE:
272 +               return INTR_MSPI_DONE_MASK;
273 +       case BSPI_DONE:
274 +               return BSPI_LR_INTERRUPTS_ALL;
275 +       case MSPI_BSPI_DONE:
276 +               return QSPI_INTERRUPTS_ALL;
277 +       case BSPI_ERR:
278 +               return BSPI_LR_INTERRUPTS_ERROR;
279 +       }
280 +
281 +       return 0;
282 +}
283 +
284  /* The common driver functions to be called by the SoC platform driver */
285  int bcm_qspi_probe(struct platform_device *pdev,
286                    struct bcm_qspi_soc_intc *soc_intc);
287 --- /dev/null
288 +++ b/drivers/spi/spi-iproc-qspi.c
289 @@ -0,0 +1,163 @@
290 +/*
291 + * Copyright 2016 Broadcom Limited
292 + *
293 + * This program is free software; you can redistribute it and/or modify
294 + * it under the terms of the GNU General Public License version 2 as
295 + * published by the Free Software Foundation.
296 + *
297 + * This program is distributed in the hope that it will be useful,
298 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
299 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
300 + * GNU General Public License for more details.
301 + */
302 +
303 +#include <linux/device.h>
304 +#include <linux/io.h>
305 +#include <linux/ioport.h>
306 +#include <linux/module.h>
307 +#include <linux/of.h>
308 +#include <linux/of_address.h>
309 +#include <linux/platform_device.h>
310 +#include <linux/slab.h>
311 +
312 +#include "spi-bcm-qspi.h"
313 +
314 +#define INTR_BASE_BIT_SHIFT                    0x02
315 +#define INTR_COUNT                             0x07
316 +
317 +struct bcm_iproc_intc {
318 +       struct bcm_qspi_soc_intc soc_intc;
319 +       struct platform_device *pdev;
320 +       void __iomem *int_reg;
321 +       void __iomem *int_status_reg;
322 +       spinlock_t soclock;
323 +       bool big_endian;
324 +};
325 +
326 +static u32 bcm_iproc_qspi_get_l2_int_status(struct bcm_qspi_soc_intc *soc_intc)
327 +{
328 +       struct bcm_iproc_intc *priv =
329 +                       container_of(soc_intc, struct bcm_iproc_intc, soc_intc);
330 +       void __iomem *mmio = priv->int_status_reg;
331 +       int i;
332 +       u32 val = 0, sts = 0;
333 +
334 +       for (i = 0; i < INTR_COUNT; i++) {
335 +               if (bcm_qspi_readl(priv->big_endian, mmio + (i * 4)))
336 +                       val |= 1UL << i;
337 +       }
338 +
339 +       if (val & INTR_MSPI_DONE_MASK)
340 +               sts |= MSPI_DONE;
341 +
342 +       if (val & BSPI_LR_INTERRUPTS_ALL)
343 +               sts |= BSPI_DONE;
344 +
345 +       if (val & BSPI_LR_INTERRUPTS_ERROR)
346 +               sts |= BSPI_ERR;
347 +
348 +       return sts;
349 +}
350 +
351 +static void bcm_iproc_qspi_int_ack(struct bcm_qspi_soc_intc *soc_intc, int type)
352 +{
353 +       struct bcm_iproc_intc *priv =
354 +                       container_of(soc_intc, struct bcm_iproc_intc, soc_intc);
355 +       void __iomem *mmio = priv->int_status_reg;
356 +       u32 mask = get_qspi_mask(type);
357 +       int i;
358 +
359 +       for (i = 0; i < INTR_COUNT; i++) {
360 +               if (mask & (1UL << i))
361 +                       bcm_qspi_writel(priv->big_endian, 1, mmio + (i * 4));
362 +       }
363 +}
364 +
365 +static void bcm_iproc_qspi_int_set(struct bcm_qspi_soc_intc *soc_intc, int type,
366 +                                  bool en)
367 +{
368 +       struct bcm_iproc_intc *priv =
369 +                       container_of(soc_intc, struct bcm_iproc_intc, soc_intc);
370 +       void __iomem *mmio = priv->int_reg;
371 +       u32 mask = get_qspi_mask(type);
372 +       u32 val;
373 +       unsigned long flags;
374 +
375 +       spin_lock_irqsave(&priv->soclock, flags);
376 +
377 +       val = bcm_qspi_readl(priv->big_endian, mmio);
378 +
379 +       if (en)
380 +               val = val | (mask << INTR_BASE_BIT_SHIFT);
381 +       else
382 +               val = val & ~(mask << INTR_BASE_BIT_SHIFT);
383 +
384 +       bcm_qspi_writel(priv->big_endian, val, mmio);
385 +
386 +       spin_unlock_irqrestore(&priv->soclock, flags);
387 +}
388 +
389 +static int bcm_iproc_probe(struct platform_device *pdev)
390 +{
391 +       struct device *dev = &pdev->dev;
392 +       struct bcm_iproc_intc *priv;
393 +       struct bcm_qspi_soc_intc *soc_intc;
394 +       struct resource *res;
395 +
396 +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
397 +       if (!priv)
398 +               return -ENOMEM;
399 +       soc_intc = &priv->soc_intc;
400 +       priv->pdev = pdev;
401 +
402 +       spin_lock_init(&priv->soclock);
403 +
404 +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr_regs");
405 +       priv->int_reg = devm_ioremap_resource(dev, res);
406 +       if (IS_ERR(priv->int_reg))
407 +               return PTR_ERR(priv->int_reg);
408 +
409 +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
410 +                                          "intr_status_reg");
411 +       priv->int_status_reg = devm_ioremap_resource(dev, res);
412 +       if (IS_ERR(priv->int_status_reg))
413 +               return PTR_ERR(priv->int_status_reg);
414 +
415 +       priv->big_endian = of_device_is_big_endian(dev->of_node);
416 +
417 +       bcm_iproc_qspi_int_ack(soc_intc, MSPI_BSPI_DONE);
418 +       bcm_iproc_qspi_int_set(soc_intc, MSPI_BSPI_DONE, false);
419 +
420 +       soc_intc->bcm_qspi_int_ack = bcm_iproc_qspi_int_ack;
421 +       soc_intc->bcm_qspi_int_set = bcm_iproc_qspi_int_set;
422 +       soc_intc->bcm_qspi_get_int_status = bcm_iproc_qspi_get_l2_int_status;
423 +
424 +       return bcm_qspi_probe(pdev, soc_intc);
425 +}
426 +
427 +static int bcm_iproc_remove(struct platform_device *pdev)
428 +{
429 +       return bcm_qspi_remove(pdev);
430 +}
431 +
432 +static const struct of_device_id bcm_iproc_of_match[] = {
433 +       { .compatible = "brcm,spi-nsp-qspi" },
434 +       { .compatible = "brcm,spi-ns2-qspi" },
435 +       {},
436 +};
437 +MODULE_DEVICE_TABLE(of, bcm_iproc_of_match);
438 +
439 +static struct platform_driver bcm_iproc_driver = {
440 +       .probe                  = bcm_iproc_probe,
441 +       .remove                 = bcm_iproc_remove,
442 +       .driver = {
443 +               .name           = "bcm_iproc",
444 +               .pm             = &bcm_qspi_pm_ops,
445 +               .of_match_table = bcm_iproc_of_match,
446 +       }
447 +};
448 +module_platform_driver(bcm_iproc_driver);
449 +
450 +MODULE_LICENSE("GPL v2");
451 +MODULE_AUTHOR("Kamal Dasu");
452 +MODULE_DESCRIPTION("SPI flash driver for Broadcom iProc SoCs");