blob: f92b4a69fffab6701e703c24c52700e88bbaa3f3 [file] [log] [blame]
Martin Sperl1ea29b32015-09-11 11:22:04 +00001/*
2 * Driver for Broadcom BCM2835 auxiliary SPI Controllers
3 *
4 * the driver does not rely on the native chipselects at all
5 * but only uses the gpio type chipselects
6 *
7 * Based on: spi-bcm2835.c
8 *
9 * Copyright (C) 2015 Martin Sperl
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 */
21
22#include <linux/clk.h>
23#include <linux/completion.h>
24#include <linux/delay.h>
25#include <linux/err.h>
26#include <linux/interrupt.h>
27#include <linux/io.h>
28#include <linux/kernel.h>
29#include <linux/module.h>
30#include <linux/of.h>
31#include <linux/of_address.h>
32#include <linux/of_device.h>
33#include <linux/of_gpio.h>
34#include <linux/of_irq.h>
35#include <linux/regmap.h>
36#include <linux/spi/spi.h>
37#include <linux/spinlock.h>
38
39/*
40 * spi register defines
41 *
42 * note there is garbage in the "official" documentation,
43 * so some data is taken from the file:
44 * brcm_usrlib/dag/vmcsx/vcinclude/bcm2708_chip/aux_io.h
45 * inside of:
46 * http://www.broadcom.com/docs/support/videocore/Brcm_Android_ICS_Graphics_Stack.tar.gz
47 */
48
49/* SPI register offsets */
50#define BCM2835_AUX_SPI_CNTL0 0x00
51#define BCM2835_AUX_SPI_CNTL1 0x04
52#define BCM2835_AUX_SPI_STAT 0x08
53#define BCM2835_AUX_SPI_PEEK 0x0C
54#define BCM2835_AUX_SPI_IO 0x20
55#define BCM2835_AUX_SPI_TXHOLD 0x30
56
57/* Bitfields in CNTL0 */
58#define BCM2835_AUX_SPI_CNTL0_SPEED 0xFFF00000
59#define BCM2835_AUX_SPI_CNTL0_SPEED_MAX 0xFFF
60#define BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT 20
61#define BCM2835_AUX_SPI_CNTL0_CS 0x000E0000
62#define BCM2835_AUX_SPI_CNTL0_POSTINPUT 0x00010000
63#define BCM2835_AUX_SPI_CNTL0_VAR_CS 0x00008000
64#define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH 0x00004000
65#define BCM2835_AUX_SPI_CNTL0_DOUTHOLD 0x00003000
66#define BCM2835_AUX_SPI_CNTL0_ENABLE 0x00000800
67#define BCM2835_AUX_SPI_CNTL0_CPHA_IN 0x00000400
68#define BCM2835_AUX_SPI_CNTL0_CLEARFIFO 0x00000200
69#define BCM2835_AUX_SPI_CNTL0_CPHA_OUT 0x00000100
70#define BCM2835_AUX_SPI_CNTL0_CPOL 0x00000080
71#define BCM2835_AUX_SPI_CNTL0_MSBF_OUT 0x00000040
72#define BCM2835_AUX_SPI_CNTL0_SHIFTLEN 0x0000003F
73
74/* Bitfields in CNTL1 */
75#define BCM2835_AUX_SPI_CNTL1_CSHIGH 0x00000700
76#define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000080
77#define BCM2835_AUX_SPI_CNTL1_TXEMPTY 0x00000040
78#define BCM2835_AUX_SPI_CNTL1_MSBF_IN 0x00000002
79#define BCM2835_AUX_SPI_CNTL1_KEEP_IN 0x00000001
80
81/* Bitfields in STAT */
82#define BCM2835_AUX_SPI_STAT_TX_LVL 0xFF000000
83#define BCM2835_AUX_SPI_STAT_RX_LVL 0x00FF0000
84#define BCM2835_AUX_SPI_STAT_TX_FULL 0x00000400
85#define BCM2835_AUX_SPI_STAT_TX_EMPTY 0x00000200
86#define BCM2835_AUX_SPI_STAT_RX_FULL 0x00000100
87#define BCM2835_AUX_SPI_STAT_RX_EMPTY 0x00000080
88#define BCM2835_AUX_SPI_STAT_BUSY 0x00000040
89#define BCM2835_AUX_SPI_STAT_BITCOUNT 0x0000003F
90
91/* timeout values */
92#define BCM2835_AUX_SPI_POLLING_LIMIT_US 30
93#define BCM2835_AUX_SPI_POLLING_JIFFIES 2
94
95#define BCM2835_AUX_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
96 | SPI_NO_CS)
97
98struct bcm2835aux_spi {
99 void __iomem *regs;
100 struct clk *clk;
101 int irq;
102 u32 cntl[2];
103 const u8 *tx_buf;
104 u8 *rx_buf;
105 int tx_len;
106 int rx_len;
107};
108
109static inline u32 bcm2835aux_rd(struct bcm2835aux_spi *bs, unsigned reg)
110{
111 return readl(bs->regs + reg);
112}
113
114static inline void bcm2835aux_wr(struct bcm2835aux_spi *bs, unsigned reg,
115 u32 val)
116{
117 writel(val, bs->regs + reg);
118}
119
120static inline void bcm2835aux_rd_fifo(struct bcm2835aux_spi *bs)
121{
122 u32 data;
123 int i;
124 int count = min(bs->rx_len, 3);
125
126 data = bcm2835aux_rd(bs, BCM2835_AUX_SPI_IO);
127 if (bs->rx_buf) {
128 for (i = 0; i < count; i++)
129 *bs->rx_buf++ = (data >> (8 * (2 - i))) & 0xff;
130 }
131 bs->rx_len -= count;
132}
133
134static inline void bcm2835aux_wr_fifo(struct bcm2835aux_spi *bs)
135{
136 u32 data;
137 u8 byte;
138 int count;
139 int i;
140
141 /* gather up to 3 bytes to write to the FIFO */
142 count = min(bs->tx_len, 3);
143 data = 0;
144 for (i = 0; i < count; i++) {
145 byte = bs->tx_buf ? *bs->tx_buf++ : 0;
146 data |= byte << (8 * (2 - i));
147 }
148
149 /* and set the variable bit-length */
150 data |= (count * 8) << 24;
151
152 /* and decrement length */
153 bs->tx_len -= count;
154
155 /* write to the correct TX-register */
156 if (bs->tx_len)
157 bcm2835aux_wr(bs, BCM2835_AUX_SPI_TXHOLD, data);
158 else
159 bcm2835aux_wr(bs, BCM2835_AUX_SPI_IO, data);
160}
161
162static void bcm2835aux_spi_reset_hw(struct bcm2835aux_spi *bs)
163{
164 /* disable spi clearing fifo and interrupts */
165 bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, 0);
166 bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0,
167 BCM2835_AUX_SPI_CNTL0_CLEARFIFO);
168}
169
170static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
171{
172 struct spi_master *master = dev_id;
173 struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
174 irqreturn_t ret = IRQ_NONE;
175
176 /* check if we have data to read */
177 while (bs->rx_len &&
178 (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
179 BCM2835_AUX_SPI_STAT_RX_EMPTY))) {
180 bcm2835aux_rd_fifo(bs);
181 ret = IRQ_HANDLED;
182 }
183
184 /* check if we have data to write */
185 while (bs->tx_len &&
186 (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
187 BCM2835_AUX_SPI_STAT_TX_FULL))) {
188 bcm2835aux_wr_fifo(bs);
189 ret = IRQ_HANDLED;
190 }
191
192 /* and check if we have reached "done" */
193 while (bs->rx_len &&
194 (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
195 BCM2835_AUX_SPI_STAT_BUSY))) {
196 bcm2835aux_rd_fifo(bs);
197 ret = IRQ_HANDLED;
198 }
199
200 /* and if rx_len is 0 then wake up completion and disable spi */
201 if (!bs->rx_len) {
202 bcm2835aux_spi_reset_hw(bs);
203 complete(&master->xfer_completion);
204 }
205
206 /* and return */
207 return ret;
208}
209
210static int __bcm2835aux_spi_transfer_one_irq(struct spi_master *master,
211 struct spi_device *spi,
212 struct spi_transfer *tfr)
213{
214 struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
215
216 /* enable interrupts */
217 bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1] |
218 BCM2835_AUX_SPI_CNTL1_TXEMPTY |
219 BCM2835_AUX_SPI_CNTL1_IDLE);
220
221 /* and wait for finish... */
222 return 1;
223}
224
225static int bcm2835aux_spi_transfer_one_irq(struct spi_master *master,
226 struct spi_device *spi,
227 struct spi_transfer *tfr)
228{
229 struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
230
231 /* fill in registers and fifos before enabling interrupts */
232 bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
233 bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
234
235 /* fill in tx fifo with data before enabling interrupts */
236 while ((bs->tx_len) &&
237 (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
238 BCM2835_AUX_SPI_STAT_TX_FULL))) {
239 bcm2835aux_wr_fifo(bs);
240 }
241
242 /* now run the interrupt mode */
243 return __bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
244}
245
246static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master,
247 struct spi_device *spi,
248 struct spi_transfer *tfr,
249 unsigned long xfer_time_us)
250{
251 struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
252 unsigned long timeout;
253 u32 stat;
254
255 /* configure spi */
256 bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
257 bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
258
259 /* set the timeout */
260 timeout = jiffies + BCM2835_AUX_SPI_POLLING_JIFFIES;
261
262 /* loop until finished the transfer */
263 while (bs->rx_len) {
264 /* read status */
265 stat = bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT);
266
267 /* fill in tx fifo with remaining data */
268 if ((bs->tx_len) && (!(stat & BCM2835_AUX_SPI_STAT_TX_FULL))) {
269 bcm2835aux_wr_fifo(bs);
270 continue;
271 }
272
273 /* read data from fifo for both cases */
274 if (!(stat & BCM2835_AUX_SPI_STAT_RX_EMPTY)) {
275 bcm2835aux_rd_fifo(bs);
276 continue;
277 }
278 if (!(stat & BCM2835_AUX_SPI_STAT_BUSY)) {
279 bcm2835aux_rd_fifo(bs);
280 continue;
281 }
282
283 /* there is still data pending to read check the timeout */
284 if (bs->rx_len && time_after(jiffies, timeout)) {
285 dev_dbg_ratelimited(&spi->dev,
286 "timeout period reached: jiffies: %lu remaining tx/rx: %d/%d - falling back to interrupt mode\n",
287 jiffies - timeout,
288 bs->tx_len, bs->rx_len);
289 /* forward to interrupt handler */
290 return __bcm2835aux_spi_transfer_one_irq(master,
291 spi, tfr);
292 }
293 }
294
295 /* Transfer complete - reset SPI HW */
296 bcm2835aux_spi_reset_hw(bs);
297
298 /* and return without waiting for completion */
299 return 0;
300}
301
302static int bcm2835aux_spi_transfer_one(struct spi_master *master,
303 struct spi_device *spi,
304 struct spi_transfer *tfr)
305{
306 struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
307 unsigned long spi_hz, clk_hz, speed;
308 unsigned long spi_used_hz, xfer_time_us;
309
310 /* calculate the registers to handle
311 *
312 * note that we use the variable data mode, which
313 * is not optimal for longer transfers as we waste registers
314 * resulting (potentially) in more interrupts when transferring
315 * more than 12 bytes
316 */
317 bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE |
318 BCM2835_AUX_SPI_CNTL0_VAR_WIDTH |
319 BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
320 bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN;
321
322 /* set clock */
323 spi_hz = tfr->speed_hz;
324 clk_hz = clk_get_rate(bs->clk);
325
326 if (spi_hz >= clk_hz / 2) {
327 speed = 0;
328 } else if (spi_hz) {
329 speed = DIV_ROUND_UP(clk_hz, 2 * spi_hz) - 1;
330 if (speed > BCM2835_AUX_SPI_CNTL0_SPEED_MAX)
331 speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
332 } else { /* the slowest we can go */
333 speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
334 }
335 bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT;
336
337 spi_used_hz = clk_hz / (2 * (speed + 1));
338
339 /* handle all the modes */
340 if (spi->mode & SPI_CPOL)
341 bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL;
342 if (spi->mode & SPI_CPHA)
343 bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPHA_OUT |
344 BCM2835_AUX_SPI_CNTL0_CPHA_IN;
345
346 /* set transmit buffers and length */
347 bs->tx_buf = tfr->tx_buf;
348 bs->rx_buf = tfr->rx_buf;
349 bs->tx_len = tfr->len;
350 bs->rx_len = tfr->len;
351
352 /* calculate the estimated time in us the transfer runs */
353 xfer_time_us = tfr->len
354 * 9 /* clocks/byte - SPI-HW waits 1 clock after each byte */
355 * 1000000 / spi_used_hz;
356
357 /* run in polling mode for short transfers */
358 if (xfer_time_us < BCM2835_AUX_SPI_POLLING_LIMIT_US)
359 return bcm2835aux_spi_transfer_one_poll(master, spi, tfr,
360 xfer_time_us);
361
362 /* run in interrupt mode for all others */
363 return bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
364}
365
366static void bcm2835aux_spi_handle_err(struct spi_master *master,
367 struct spi_message *msg)
368{
369 struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
370
371 bcm2835aux_spi_reset_hw(bs);
372}
373
374static int bcm2835aux_spi_probe(struct platform_device *pdev)
375{
376 struct spi_master *master;
377 struct bcm2835aux_spi *bs;
378 struct resource *res;
379 unsigned long clk_hz;
380 int err;
381
382 master = spi_alloc_master(&pdev->dev, sizeof(*bs));
383 if (!master) {
384 dev_err(&pdev->dev, "spi_alloc_master() failed\n");
385 return -ENOMEM;
386 }
387
388 platform_set_drvdata(pdev, master);
389 master->mode_bits = BCM2835_AUX_SPI_MODE_BITS;
390 master->bits_per_word_mask = SPI_BPW_MASK(8);
391 master->num_chipselect = -1;
392 master->transfer_one = bcm2835aux_spi_transfer_one;
393 master->handle_err = bcm2835aux_spi_handle_err;
394 master->dev.of_node = pdev->dev.of_node;
395
396 bs = spi_master_get_devdata(master);
397
398 /* the main area */
399 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
400 bs->regs = devm_ioremap_resource(&pdev->dev, res);
401 if (IS_ERR(bs->regs)) {
402 err = PTR_ERR(bs->regs);
403 goto out_master_put;
404 }
405
406 bs->clk = devm_clk_get(&pdev->dev, NULL);
407 if ((!bs->clk) || (IS_ERR(bs->clk))) {
408 err = PTR_ERR(bs->clk);
409 dev_err(&pdev->dev, "could not get clk: %d\n", err);
410 goto out_master_put;
411 }
412
413 bs->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
414 if (bs->irq <= 0) {
415 dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq);
416 err = bs->irq ? bs->irq : -ENODEV;
417 goto out_master_put;
418 }
419
420 /* this also enables the HW block */
421 err = clk_prepare_enable(bs->clk);
422 if (err) {
423 dev_err(&pdev->dev, "could not prepare clock: %d\n", err);
424 goto out_master_put;
425 }
426
427 /* just checking if the clock returns a sane value */
428 clk_hz = clk_get_rate(bs->clk);
429 if (!clk_hz) {
430 dev_err(&pdev->dev, "clock returns 0 Hz\n");
431 err = -ENODEV;
432 goto out_clk_disable;
433 }
434
435 err = devm_request_irq(&pdev->dev, bs->irq,
436 bcm2835aux_spi_interrupt,
437 IRQF_SHARED,
438 dev_name(&pdev->dev), master);
439 if (err) {
440 dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
441 goto out_clk_disable;
442 }
443
444 /* reset SPI-HW block */
445 bcm2835aux_spi_reset_hw(bs);
446
447 err = devm_spi_register_master(&pdev->dev, master);
448 if (err) {
449 dev_err(&pdev->dev, "could not register SPI master: %d\n", err);
450 goto out_clk_disable;
451 }
452
453 return 0;
454
455out_clk_disable:
456 clk_disable_unprepare(bs->clk);
457out_master_put:
458 spi_master_put(master);
459 return err;
460}
461
462static int bcm2835aux_spi_remove(struct platform_device *pdev)
463{
464 struct spi_master *master = platform_get_drvdata(pdev);
465 struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
466
467 bcm2835aux_spi_reset_hw(bs);
468
469 /* disable the HW block by releasing the clock */
470 clk_disable_unprepare(bs->clk);
471
472 return 0;
473}
474
475static const struct of_device_id bcm2835aux_spi_match[] = {
476 { .compatible = "brcm,bcm2835-aux-spi", },
477 {}
478};
479MODULE_DEVICE_TABLE(of, bcm2835aux_spi_match);
480
481static struct platform_driver bcm2835aux_spi_driver = {
482 .driver = {
483 .name = "spi-bcm2835aux",
484 .of_match_table = bcm2835aux_spi_match,
485 },
486 .probe = bcm2835aux_spi_probe,
487 .remove = bcm2835aux_spi_remove,
488};
489module_platform_driver(bcm2835aux_spi_driver);
490
491MODULE_DESCRIPTION("SPI controller driver for Broadcom BCM2835 aux");
492MODULE_AUTHOR("Martin Sperl <kernel@martin.sperl.org>");
493MODULE_LICENSE("GPL v2");