bcm53xx: sprom: extract for PCI host
[15.05/openwrt.git] / target / linux / bcm53xx / patches-3.14 / 180-spi-bcm53xx-driver-for-SPI-controller-on-Broadcom-bc.patch
1 From a59f3fa1dd4cb284171a53cb7a614ad947c544f6 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
3 Date: Wed, 13 Aug 2014 14:11:39 +0200
4 Subject: [PATCH V2] spi: bcm53xx: driver for SPI controller on Broadcom bcma
5  SoC
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
10 Broadcom 53xx ARM SoCs use bcma bus that contains various cores (AKA
11 devices). If board has a serial flash, it's connected over SPI and the
12 bcma bus includes a SPI controller. Example log from such a board:
13 bus0: Found chip with id 53010, rev 0x00 and package 0x02
14 (...)
15 bus0: Core 18 found: SPI flash controller (manuf 0x4BF, id 0x50A, rev 0x01, class 0x0)
16
17 This patch adds a bcma driver for SPI core, it registers SPI master
18 controller and "bcm53xxspiflash" SPI device.
19
20 Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
21 ---
22 Since RFC: Add Signed-off-by
23            Update to compile on top of for-next
24 V2: Use wait timeout
25     Describe bcm53xxspi_calc_timeout a bit
26     Use devm_spi_register_master
27
28 Thanks Mark for your comments!
29 ---
30  drivers/spi/Kconfig       |   6 +
31  drivers/spi/Makefile      |   1 +
32  drivers/spi/spi-bcm53xx.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++
33  drivers/spi/spi-bcm53xx.h |  72 +++++++++++
34  4 files changed, 374 insertions(+)
35  create mode 100644 drivers/spi/spi-bcm53xx.c
36  create mode 100644 drivers/spi/spi-bcm53xx.h
37
38 --- a/drivers/spi/Kconfig
39 +++ b/drivers/spi/Kconfig
40 @@ -112,6 +112,12 @@ config SPI_AU1550
41           If you say yes to this option, support will be included for the
42           PSC SPI controller found on Au1550, Au1200 and Au1300 series.
43  
44 +config SPI_BCM53XX
45 +       tristate "Broadcom BCM53xx SPI controller"
46 +       depends on ARCH_BCM_5301X
47 +       help
48 +          Enable support for the SPI controller on Broadcom BCM53xx ARM SoCs.
49 +
50  config SPI_BCM63XX
51         tristate "Broadcom BCM63xx SPI controller"
52         depends on BCM63XX
53 --- a/drivers/spi/Makefile
54 +++ b/drivers/spi/Makefile
55 @@ -15,6 +15,7 @@ obj-$(CONFIG_SPI_ATMEL)                       += spi-atmel.o
56  obj-$(CONFIG_SPI_ATH79)                        += spi-ath79.o
57  obj-$(CONFIG_SPI_AU1550)               += spi-au1550.o
58  obj-$(CONFIG_SPI_BCM2835)              += spi-bcm2835.o
59 +obj-$(CONFIG_SPI_BCM53XX)              += spi-bcm53xx.o
60  obj-$(CONFIG_SPI_BCM63XX)              += spi-bcm63xx.o
61  obj-$(CONFIG_SPI_BCM63XX_HSSPI)                += spi-bcm63xx-hsspi.o
62  obj-$(CONFIG_SPI_BFIN5XX)              += spi-bfin5xx.o
63 --- /dev/null
64 +++ b/drivers/spi/spi-bcm53xx.c
65 @@ -0,0 +1,295 @@
66 +#define pr_fmt(fmt)            KBUILD_MODNAME ": " fmt
67 +
68 +#include <linux/kernel.h>
69 +#include <linux/module.h>
70 +#include <linux/slab.h>
71 +#include <linux/delay.h>
72 +#include <linux/bcma/bcma.h>
73 +#include <linux/spi/spi.h>
74 +
75 +#include "spi-bcm53xx.h"
76 +
77 +#define BCM53XXSPI_MAX_SPI_BAUD        13500000        /* 216 MHz? */
78 +
79 +/* The longest observed required wait was 19 ms */
80 +#define BCM53XXSPI_SPE_TIMEOUT_MS      80
81 +
82 +struct bcm53xxspi {
83 +       struct bcma_device *core;
84 +       struct spi_master *master;
85 +
86 +       size_t read_offset;
87 +};
88 +
89 +static inline u32 bcm53xxspi_read(struct bcm53xxspi *b53spi, u16 offset)
90 +{
91 +       return bcma_read32(b53spi->core, offset);
92 +}
93 +
94 +static inline void bcm53xxspi_write(struct bcm53xxspi *b53spi, u16 offset,
95 +                                   u32 value)
96 +{
97 +       bcma_write32(b53spi->core, offset, value);
98 +}
99 +
100 +static inline unsigned int bcm53xxspi_calc_timeout(size_t len)
101 +{
102 +       /* Do some magic calculation based on length and buad. Add 10% and 1. */
103 +       return (len * 9000 / BCM53XXSPI_MAX_SPI_BAUD * 110 / 100) + 1;
104 +}
105 +
106 +static int bcm53xxspi_wait(struct bcm53xxspi *b53spi, unsigned int timeout_ms)
107 +{
108 +       unsigned long deadline;
109 +       u32 tmp;
110 +
111 +       /* SPE bit has to be 0 before we read MSPI STATUS */
112 +       deadline = jiffies + BCM53XXSPI_SPE_TIMEOUT_MS * HZ / 1000;
113 +       do {
114 +               tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_SPCR2);
115 +               if (!(tmp & B53SPI_MSPI_SPCR2_SPE))
116 +                       break;
117 +               udelay(5);
118 +       } while (!time_after_eq(jiffies, deadline));
119 +
120 +       if (tmp & B53SPI_MSPI_SPCR2_SPE)
121 +               goto spi_timeout;
122 +
123 +       /* Check status */
124 +       deadline = jiffies + timeout_ms * HZ / 1000;
125 +       do {
126 +               tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_MSPI_STATUS);
127 +               if (tmp & B53SPI_MSPI_MSPI_STATUS_SPIF) {
128 +                       bcm53xxspi_write(b53spi, B53SPI_MSPI_MSPI_STATUS, 0);
129 +                       return 0;
130 +               }
131 +
132 +               cpu_relax();
133 +               udelay(100);
134 +       } while (!time_after_eq(jiffies, deadline));
135 +
136 +spi_timeout:
137 +       bcm53xxspi_write(b53spi, B53SPI_MSPI_MSPI_STATUS, 0);
138 +
139 +       pr_err("Timeout waiting for SPI to be ready!\n");
140 +
141 +       return -EBUSY;
142 +}
143 +
144 +static void bcm53xxspi_buf_write(struct bcm53xxspi *b53spi, u8 *w_buf,
145 +                                size_t len, bool cont)
146 +{
147 +       u32 tmp;
148 +       int i;
149 +
150 +       for (i = 0; i < len; i++) {
151 +               /* Transmit Register File MSB */
152 +               bcm53xxspi_write(b53spi, B53SPI_MSPI_TXRAM + 4 * (i * 2),
153 +                                (unsigned int)w_buf[i]);
154 +       }
155 +
156 +       for (i = 0; i < len; i++) {
157 +               tmp = B53SPI_CDRAM_CONT | B53SPI_CDRAM_PCS_DISABLE_ALL |
158 +                     B53SPI_CDRAM_PCS_DSCK;
159 +               if (!cont && i == len - 1)
160 +                       tmp &= ~B53SPI_CDRAM_CONT;
161 +               tmp &= ~0x1;
162 +               /* Command Register File */
163 +               bcm53xxspi_write(b53spi, B53SPI_MSPI_CDRAM + 4 * i, tmp);
164 +       }
165 +
166 +       /* Set queue pointers */
167 +       bcm53xxspi_write(b53spi, B53SPI_MSPI_NEWQP, 0);
168 +       bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, len - 1);
169 +
170 +       if (cont)
171 +               bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 1);
172 +
173 +       /* Start SPI transfer */
174 +       tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_SPCR2);
175 +       tmp |= B53SPI_MSPI_SPCR2_SPE;
176 +       if (cont)
177 +               tmp |= B53SPI_MSPI_SPCR2_CONT_AFTER_CMD;
178 +       bcm53xxspi_write(b53spi, B53SPI_MSPI_SPCR2, tmp);
179 +
180 +       /* Wait for SPI to finish */
181 +       bcm53xxspi_wait(b53spi, bcm53xxspi_calc_timeout(len));
182 +
183 +       if (!cont)
184 +               bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0);
185 +
186 +       b53spi->read_offset = len;
187 +}
188 +
189 +static void bcm53xxspi_buf_read(struct bcm53xxspi *b53spi, u8 *r_buf,
190 +                               size_t len, bool cont)
191 +{
192 +       u32 tmp;
193 +       int i;
194 +
195 +       for (i = 0; i < b53spi->read_offset + len; i++) {
196 +               tmp = B53SPI_CDRAM_CONT | B53SPI_CDRAM_PCS_DISABLE_ALL |
197 +                     B53SPI_CDRAM_PCS_DSCK;
198 +               if (!cont && i == b53spi->read_offset + len - 1)
199 +                       tmp &= ~B53SPI_CDRAM_CONT;
200 +               tmp &= ~0x1;
201 +               /* Command Register File */
202 +               bcm53xxspi_write(b53spi, B53SPI_MSPI_CDRAM + 4 * i, tmp);
203 +       }
204 +
205 +       /* Set queue pointers */
206 +       bcm53xxspi_write(b53spi, B53SPI_MSPI_NEWQP, 0);
207 +       bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP,
208 +                        b53spi->read_offset + len - 1);
209 +
210 +       if (cont)
211 +               bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 1);
212 +
213 +       /* Start SPI transfer */
214 +       tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_SPCR2);
215 +       tmp |= B53SPI_MSPI_SPCR2_SPE;
216 +       if (cont)
217 +               tmp |= B53SPI_MSPI_SPCR2_CONT_AFTER_CMD;
218 +       bcm53xxspi_write(b53spi, B53SPI_MSPI_SPCR2, tmp);
219 +
220 +       /* Wait for SPI to finish */
221 +       bcm53xxspi_wait(b53spi, bcm53xxspi_calc_timeout(len));
222 +
223 +       if (!cont)
224 +               bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0);
225 +
226 +       for (i = 0; i < len; ++i) {
227 +               int offset = b53spi->read_offset + i;
228 +
229 +               /* Data stored in the transmit register file LSB */
230 +               r_buf[i] = (u8)bcm53xxspi_read(b53spi, B53SPI_MSPI_RXRAM + 4 * (1 + offset * 2));
231 +       }
232 +
233 +       b53spi->read_offset = 0;
234 +}
235 +
236 +static int bcm53xxspi_transfer_one(struct spi_master *master,
237 +                                  struct spi_device *spi,
238 +                                  struct spi_transfer *t)
239 +{
240 +       struct bcm53xxspi *b53spi = spi_master_get_devdata(master);
241 +       u8 *buf;
242 +       size_t left;
243 +
244 +       if (t->tx_buf) {
245 +               buf = (u8 *)t->tx_buf;
246 +               left = t->len;
247 +               while (left) {
248 +                       size_t to_write = min_t(size_t, 16, left);
249 +                       bool cont = left - to_write > 0;
250 +
251 +                       bcm53xxspi_buf_write(b53spi, buf, to_write, cont);
252 +                       left -= to_write;
253 +                       buf += to_write;
254 +               }
255 +       }
256 +
257 +       if (t->rx_buf) {
258 +               buf = (u8 *)t->rx_buf;
259 +               left = t->len;
260 +               while (left) {
261 +                       size_t to_read = min_t(size_t, 16 - b53spi->read_offset,
262 +                                              left);
263 +                       bool cont = left - to_read > 0;
264 +
265 +                       bcm53xxspi_buf_read(b53spi, buf, to_read, cont);
266 +                       left -= to_read;
267 +                       buf += to_read;
268 +               }
269 +       }
270 +
271 +       return 0;
272 +}
273 +
274 +/**************************************************
275 + * BCMA
276 + **************************************************/
277 +
278 +struct spi_board_info bcm53xx_info = {
279 +       .modalias       = "bcm53xxspiflash",
280 +};
281 +
282 +static const struct bcma_device_id bcm53xxspi_bcma_tbl[] = {
283 +       BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_QSPI, BCMA_ANY_REV, BCMA_ANY_CLASS),
284 +       BCMA_CORETABLE_END
285 +};
286 +MODULE_DEVICE_TABLE(bcma, bcm53xxspi_bcma_tbl);
287 +
288 +static int bcm53xxspi_bcma_probe(struct bcma_device *core)
289 +{
290 +       struct bcm53xxspi *b53spi;
291 +       struct spi_master *master;
292 +       int err;
293 +
294 +       if (core->bus->drv_cc.core->id.rev != 42) {
295 +               pr_err("SPI on SoC with unsupported ChipCommon rev\n");
296 +               return -ENOTSUPP;
297 +       }
298 +
299 +       master = spi_alloc_master(&core->dev, sizeof(*b53spi));
300 +       if (!master)
301 +               return -ENOMEM;
302 +
303 +       b53spi = spi_master_get_devdata(master);
304 +       b53spi->master = master;
305 +       b53spi->core = core;
306 +
307 +       master->transfer_one = bcm53xxspi_transfer_one;
308 +
309 +       bcma_set_drvdata(core, b53spi);
310 +
311 +       err = devm_spi_register_master(&core->dev, master);
312 +       if (err) {
313 +               spi_master_put(master);
314 +               bcma_set_drvdata(core, NULL);
315 +               goto out;
316 +       }
317 +
318 +       /* Broadcom SoCs (at least with the CC rev 42) use SPI for flash only */
319 +       spi_new_device(master, &bcm53xx_info);
320 +
321 +out:
322 +       return err;
323 +}
324 +
325 +static void bcm53xxspi_bcma_remove(struct bcma_device *core)
326 +{
327 +       struct bcm53xxspi *b53spi = bcma_get_drvdata(core);
328 +
329 +       spi_unregister_master(b53spi->master);
330 +}
331 +
332 +static struct bcma_driver bcm53xxspi_bcma_driver = {
333 +       .name           = KBUILD_MODNAME,
334 +       .id_table       = bcm53xxspi_bcma_tbl,
335 +       .probe          = bcm53xxspi_bcma_probe,
336 +       .remove         = bcm53xxspi_bcma_remove,
337 +};
338 +
339 +/**************************************************
340 + * Init & exit
341 + **************************************************/
342 +
343 +static int __init bcm53xxspi_module_init(void)
344 +{
345 +       int err = 0;
346 +
347 +       err = bcma_driver_register(&bcm53xxspi_bcma_driver);
348 +       if (err)
349 +               pr_err("Failed to register bcma driver: %d\n", err);
350 +
351 +       return err;
352 +}
353 +
354 +static void __exit bcm53xxspi_module_exit(void)
355 +{
356 +       bcma_driver_unregister(&bcm53xxspi_bcma_driver);
357 +}
358 +
359 +module_init(bcm53xxspi_module_init);
360 +module_exit(bcm53xxspi_module_exit);
361 --- /dev/null
362 +++ b/drivers/spi/spi-bcm53xx.h
363 @@ -0,0 +1,72 @@
364 +#ifndef SPI_BCM53XX_H
365 +#define SPI_BCM53XX_H
366 +
367 +#define B53SPI_BSPI_REVISION_ID                        0x000
368 +#define B53SPI_BSPI_SCRATCH                    0x004
369 +#define B53SPI_BSPI_MAST_N_BOOT_CTRL           0x008
370 +#define B53SPI_BSPI_BUSY_STATUS                        0x00c
371 +#define B53SPI_BSPI_INTR_STATUS                        0x010
372 +#define B53SPI_BSPI_B0_STATUS                  0x014
373 +#define B53SPI_BSPI_B0_CTRL                    0x018
374 +#define B53SPI_BSPI_B1_STATUS                  0x01c
375 +#define B53SPI_BSPI_B1_CTRL                    0x020
376 +#define B53SPI_BSPI_STRAP_OVERRIDE_CTRL                0x024
377 +#define B53SPI_BSPI_FLEX_MODE_ENABLE           0x028
378 +#define B53SPI_BSPI_BITS_PER_CYCLE             0x02c
379 +#define B53SPI_BSPI_BITS_PER_PHASE             0x030
380 +#define B53SPI_BSPI_CMD_AND_MODE_BYTE          0x034
381 +#define B53SPI_BSPI_BSPI_FLASH_UPPER_ADDR_BYTE 0x038
382 +#define B53SPI_BSPI_BSPI_XOR_VALUE             0x03c
383 +#define B53SPI_BSPI_BSPI_XOR_ENABLE            0x040
384 +#define B53SPI_BSPI_BSPI_PIO_MODE_ENABLE       0x044
385 +#define B53SPI_BSPI_BSPI_PIO_IODIR             0x048
386 +#define B53SPI_BSPI_BSPI_PIO_DATA              0x04c
387 +
388 +/* RAF */
389 +#define B53SPI_RAF_START_ADDR                  0x100
390 +#define B53SPI_RAF_NUM_WORDS                   0x104
391 +#define B53SPI_RAF_CTRL                                0x108
392 +#define B53SPI_RAF_FULLNESS                    0x10c
393 +#define B53SPI_RAF_WATERMARK                   0x110
394 +#define B53SPI_RAF_STATUS                      0x114
395 +#define B53SPI_RAF_READ_DATA                   0x118
396 +#define B53SPI_RAF_WORD_CNT                    0x11c
397 +#define B53SPI_RAF_CURR_ADDR                   0x120
398 +
399 +/* MSPI */
400 +#define B53SPI_MSPI_SPCR0_LSB                  0x200
401 +#define B53SPI_MSPI_SPCR0_MSB                  0x204
402 +#define B53SPI_MSPI_SPCR1_LSB                  0x208
403 +#define B53SPI_MSPI_SPCR1_MSB                  0x20c
404 +#define B53SPI_MSPI_NEWQP                      0x210
405 +#define B53SPI_MSPI_ENDQP                      0x214
406 +#define B53SPI_MSPI_SPCR2                      0x218
407 +#define  B53SPI_MSPI_SPCR2_SPE                 0x00000040
408 +#define  B53SPI_MSPI_SPCR2_CONT_AFTER_CMD      0x00000080
409 +#define B53SPI_MSPI_MSPI_STATUS                        0x220
410 +#define  B53SPI_MSPI_MSPI_STATUS_SPIF          0x00000001
411 +#define B53SPI_MSPI_CPTQP                      0x224
412 +#define B53SPI_MSPI_TXRAM                      0x240 /* 32 registers, up to 0x2b8 */
413 +#define B53SPI_MSPI_RXRAM                      0x2c0 /* 32 registers, up to 0x33c */
414 +#define B53SPI_MSPI_CDRAM                      0x340 /* 16 registers, up to 0x37c */
415 +#define  B53SPI_CDRAM_PCS_PCS0                 0x00000001
416 +#define  B53SPI_CDRAM_PCS_PCS1                 0x00000002
417 +#define  B53SPI_CDRAM_PCS_PCS2                 0x00000004
418 +#define  B53SPI_CDRAM_PCS_PCS3                 0x00000008
419 +#define  B53SPI_CDRAM_PCS_DISABLE_ALL          0x0000000f
420 +#define  B53SPI_CDRAM_PCS_DSCK                 0x00000010
421 +#define  B53SPI_CDRAM_BITSE                    0x00000040
422 +#define  B53SPI_CDRAM_CONT                     0x00000080
423 +#define B53SPI_MSPI_WRITE_LOCK                 0x380
424 +#define B53SPI_MSPI_DISABLE_FLUSH_GEN          0x384
425 +
426 +/* Interrupt */
427 +#define B53SPI_INTR_RAF_LR_FULLNESS_REACHED    0x3a0
428 +#define B53SPI_INTR_RAF_LR_TRUNCATED           0x3a4
429 +#define B53SPI_INTR_RAF_LR_IMPATIENT           0x3a8
430 +#define B53SPI_INTR_RAF_LR_SESSION_DONE                0x3ac
431 +#define B53SPI_INTR_RAF_LR_OVERREAD            0x3b0
432 +#define B53SPI_INTR_MSPI_DONE                  0x3b4
433 +#define B53SPI_INTR_MSPI_HALT_SET_TRANSACTION_DONE     0x3b8
434 +
435 +#endif /* SPI_BCM53XX_H */