1 --- a/drivers/spi/Kconfig
2 +++ b/drivers/spi/Kconfig
3 @@ -86,6 +86,14 @@ config SPI_BCM2835
4 is for the regular SPI controller. Slave mode operation is not also
8 + tristate "BCM2708 SPI controller driver (SPI0)"
9 + depends on MACH_BCM2708
11 + This selects a driver for the Broadcom BCM2708 SPI master (SPI0). This
12 + driver is not compatible with the "Universal SPI Master" or the SPI slave
16 tristate "SPI controller driver for ADI Blackfin5xx"
18 --- a/drivers/spi/Makefile
19 +++ b/drivers/spi/Makefile
20 @@ -17,6 +17,7 @@ obj-$(CONFIG_SPI_AU1550) += spi-au1550.
21 obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o
22 obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
23 obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o
24 +obj-$(CONFIG_SPI_BCM2708) += spi-bcm2708.o
25 obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
26 obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
27 obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
29 +++ b/drivers/spi/spi-bcm2708.c
32 + * Driver for Broadcom BCM2708 SPI Controllers
34 + * Copyright (C) 2012 Chris Boot
36 + * This driver is inspired by:
37 + * spi-ath79.c, Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
38 + * spi-atmel.c, Copyright (C) 2006 Atmel Corporation
40 + * This program is free software; you can redistribute it and/or modify
41 + * it under the terms of the GNU General Public License as published by
42 + * the Free Software Foundation; either version 2 of the License, or
43 + * (at your option) any later version.
45 + * This program is distributed in the hope that it will be useful,
46 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
47 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48 + * GNU General Public License for more details.
50 + * You should have received a copy of the GNU General Public License
51 + * along with this program; if not, write to the Free Software
52 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
55 +#include <linux/kernel.h>
56 +#include <linux/module.h>
57 +#include <linux/spinlock.h>
58 +#include <linux/clk.h>
59 +#include <linux/err.h>
60 +#include <linux/platform_device.h>
61 +#include <linux/io.h>
62 +#include <linux/spi/spi.h>
63 +#include <linux/interrupt.h>
64 +#include <linux/delay.h>
65 +#include <linux/log2.h>
66 +#include <linux/sched.h>
67 +#include <linux/wait.h>
69 +/* SPI register offsets */
71 +#define SPI_FIFO 0x04
73 +#define SPI_DLEN 0x0c
74 +#define SPI_LTOH 0x10
77 +/* Bitfields in CS */
78 +#define SPI_CS_LEN_LONG 0x02000000
79 +#define SPI_CS_DMA_LEN 0x01000000
80 +#define SPI_CS_CSPOL2 0x00800000
81 +#define SPI_CS_CSPOL1 0x00400000
82 +#define SPI_CS_CSPOL0 0x00200000
83 +#define SPI_CS_RXF 0x00100000
84 +#define SPI_CS_RXR 0x00080000
85 +#define SPI_CS_TXD 0x00040000
86 +#define SPI_CS_RXD 0x00020000
87 +#define SPI_CS_DONE 0x00010000
88 +#define SPI_CS_LEN 0x00002000
89 +#define SPI_CS_REN 0x00001000
90 +#define SPI_CS_ADCS 0x00000800
91 +#define SPI_CS_INTR 0x00000400
92 +#define SPI_CS_INTD 0x00000200
93 +#define SPI_CS_DMAEN 0x00000100
94 +#define SPI_CS_TA 0x00000080
95 +#define SPI_CS_CSPOL 0x00000040
96 +#define SPI_CS_CLEAR_RX 0x00000020
97 +#define SPI_CS_CLEAR_TX 0x00000010
98 +#define SPI_CS_CPOL 0x00000008
99 +#define SPI_CS_CPHA 0x00000004
100 +#define SPI_CS_CS_10 0x00000002
101 +#define SPI_CS_CS_01 0x00000001
103 +#define SPI_TIMEOUT_MS 150
105 +#define DRV_NAME "bcm2708_spi"
107 +struct bcm2708_spi {
109 + void __iomem *base;
114 + struct list_head queue;
115 + struct workqueue_struct *workq;
116 + struct work_struct work;
117 + struct completion done;
124 +struct bcm2708_spi_state {
130 + * This function sets the ALT mode on the SPI pins so that we can use them with
131 + * the SPI hardware.
133 + * FIXME: This is a hack. Use pinmux / pinctrl.
135 +static void bcm2708_init_pinmode(void)
137 +#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
138 +#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
141 + u32 *gpio = ioremap(0x20200000, SZ_16K);
143 + /* SPI is on GPIO 7..11 */
144 + for (pin = 7; pin <= 11; pin++) {
145 + INP_GPIO(pin); /* set mode to GPIO input first */
146 + SET_GPIO_ALT(pin, 0); /* set mode to ALT 0 */
155 +static inline u32 bcm2708_rd(struct bcm2708_spi *bs, unsigned reg)
157 + return readl(bs->base + reg);
160 +static inline void bcm2708_wr(struct bcm2708_spi *bs, unsigned reg, u32 val)
162 + writel(val, bs->base + reg);
165 +static inline void bcm2708_rd_fifo(struct bcm2708_spi *bs, int len)
170 + byte = bcm2708_rd(bs, SPI_FIFO);
172 + *bs->rx_buf++ = byte;
176 +static inline void bcm2708_wr_fifo(struct bcm2708_spi *bs, int len)
184 + if (unlikely(bcm2708_rd(bs, SPI_CS) & SPI_CS_LEN)) {
186 + if (unlikely(len % 2)) {
187 + printk(KERN_ERR"bcm2708_wr_fifo: length must be even, skipping.\n");
193 + val = *(const u16 *)bs->tx_buf;
197 + bcm2708_wr(bs, SPI_FIFO, val);
205 + byte = bs->tx_buf ? *bs->tx_buf++ : 0;
206 + bcm2708_wr(bs, SPI_FIFO, byte);
211 +static irqreturn_t bcm2708_spi_interrupt(int irq, void *dev_id)
213 + struct spi_master *master = dev_id;
214 + struct bcm2708_spi *bs = spi_master_get_devdata(master);
217 + spin_lock(&bs->lock);
219 + cs = bcm2708_rd(bs, SPI_CS);
221 + if (cs & SPI_CS_DONE) {
222 + if (bs->len) { /* first interrupt in a transfer */
223 + /* fill the TX fifo with up to 16 bytes */
224 + bcm2708_wr_fifo(bs, 16);
225 + } else { /* transfer complete */
226 + /* disable interrupts */
227 + cs &= ~(SPI_CS_INTR | SPI_CS_INTD);
228 + bcm2708_wr(bs, SPI_CS, cs);
230 + /* drain RX FIFO */
231 + while (cs & SPI_CS_RXD) {
232 + bcm2708_rd_fifo(bs, 1);
233 + cs = bcm2708_rd(bs, SPI_CS);
236 + /* wake up our bh */
237 + complete(&bs->done);
239 + } else if (cs & SPI_CS_RXR) {
240 + /* read 12 bytes of data */
241 + bcm2708_rd_fifo(bs, 12);
243 + /* write up to 12 bytes */
244 + bcm2708_wr_fifo(bs, 12);
247 + spin_unlock(&bs->lock);
249 + return IRQ_HANDLED;
252 +static int bcm2708_setup_state(struct spi_master *master,
253 + struct device *dev, struct bcm2708_spi_state *state,
254 + u32 hz, u8 csel, u8 mode, u8 bpw)
256 + struct bcm2708_spi *bs = spi_master_get_devdata(master);
258 + unsigned long bus_hz;
261 + bus_hz = clk_get_rate(bs->clk);
263 + if (hz >= bus_hz) {
264 + cdiv = 2; /* bus_hz / 2 is as fast as we can go */
266 + cdiv = DIV_ROUND_UP(bus_hz, hz);
268 + /* CDIV must be a power of 2, so round up */
269 + cdiv = roundup_pow_of_two(cdiv);
271 + if (cdiv > 65536) {
273 + "setup: %d Hz too slow, cdiv %u; min %ld Hz\n",
274 + hz, cdiv, bus_hz / 65536);
276 + } else if (cdiv == 65536) {
278 + } else if (cdiv == 1) {
279 + cdiv = 2; /* 1 gets rounded down to 0; == 65536 */
289 + /* Reading in LoSSI mode is a special case. See 'BCM2835 ARM Peripherals' datasheet */
293 + dev_dbg(dev, "setup: invalid bits_per_word %u (must be 8 or 9)\n",
298 + if (mode & SPI_CPOL)
300 + if (mode & SPI_CPHA)
303 + if (!(mode & SPI_NO_CS)) {
304 + if (mode & SPI_CS_HIGH) {
305 + cs |= SPI_CS_CSPOL;
306 + cs |= SPI_CS_CSPOL0 << csel;
311 + cs |= SPI_CS_CS_10 | SPI_CS_CS_01;
316 + state->cdiv = cdiv;
317 + dev_dbg(dev, "setup: want %d Hz; "
318 + "bus_hz=%lu / cdiv=%u == %lu Hz; "
319 + "mode %u: cs 0x%08X\n",
320 + hz, bus_hz, cdiv, bus_hz/cdiv, mode, cs);
326 +static int bcm2708_process_transfer(struct bcm2708_spi *bs,
327 + struct spi_message *msg, struct spi_transfer *xfer)
329 + struct spi_device *spi = msg->spi;
330 + struct bcm2708_spi_state state, *stp;
337 + if (xfer->bits_per_word || xfer->speed_hz) {
338 + ret = bcm2708_setup_state(spi->master, &spi->dev, &state,
339 + xfer->speed_hz ? xfer->speed_hz : spi->max_speed_hz,
340 + spi->chip_select, spi->mode,
341 + xfer->bits_per_word ? xfer->bits_per_word :
342 + spi->bits_per_word);
348 + stp = spi->controller_state;
351 + INIT_COMPLETION(bs->done);
352 + bs->tx_buf = xfer->tx_buf;
353 + bs->rx_buf = xfer->rx_buf;
354 + bs->len = xfer->len;
356 + cs = stp->cs | SPI_CS_INTR | SPI_CS_INTD | SPI_CS_TA;
358 + bcm2708_wr(bs, SPI_CLK, stp->cdiv);
359 + bcm2708_wr(bs, SPI_CS, cs);
361 + ret = wait_for_completion_timeout(&bs->done,
362 + msecs_to_jiffies(SPI_TIMEOUT_MS));
364 + dev_err(&spi->dev, "transfer timed out\n");
368 + if (xfer->delay_usecs)
369 + udelay(xfer->delay_usecs);
371 + if (list_is_last(&xfer->transfer_list, &msg->transfers) ||
373 + /* clear TA and interrupt flags */
374 + bcm2708_wr(bs, SPI_CS, stp->cs);
377 + msg->actual_length += (xfer->len - bs->len);
382 +static void bcm2708_work(struct work_struct *work)
384 + struct bcm2708_spi *bs = container_of(work, struct bcm2708_spi, work);
385 + unsigned long flags;
386 + struct spi_message *msg;
387 + struct spi_transfer *xfer;
390 + spin_lock_irqsave(&bs->lock, flags);
391 + while (!list_empty(&bs->queue)) {
392 + msg = list_first_entry(&bs->queue, struct spi_message, queue);
393 + list_del_init(&msg->queue);
394 + spin_unlock_irqrestore(&bs->lock, flags);
396 + list_for_each_entry(xfer, &msg->transfers, transfer_list) {
397 + status = bcm2708_process_transfer(bs, msg, xfer);
402 + msg->status = status;
403 + msg->complete(msg->context);
405 + spin_lock_irqsave(&bs->lock, flags);
407 + spin_unlock_irqrestore(&bs->lock, flags);
410 +static int bcm2708_spi_setup(struct spi_device *spi)
412 + struct bcm2708_spi *bs = spi_master_get_devdata(spi->master);
413 + struct bcm2708_spi_state *state;
419 + if (!(spi->mode & SPI_NO_CS) &&
420 + (spi->chip_select > spi->master->num_chipselect)) {
422 + "setup: invalid chipselect %u (%u defined)\n",
423 + spi->chip_select, spi->master->num_chipselect);
427 + state = spi->controller_state;
429 + state = kzalloc(sizeof(*state), GFP_KERNEL);
433 + spi->controller_state = state;
436 + ret = bcm2708_setup_state(spi->master, &spi->dev, state,
437 + spi->max_speed_hz, spi->chip_select, spi->mode,
438 + spi->bits_per_word);
441 + spi->controller_state = NULL;
446 + "setup: cd %d: %d Hz, bpw %u, mode 0x%x -> CS=%08x CDIV=%04x\n",
447 + spi->chip_select, spi->max_speed_hz, spi->bits_per_word,
448 + spi->mode, state->cs, state->cdiv);
453 +static int bcm2708_spi_transfer(struct spi_device *spi, struct spi_message *msg)
455 + struct bcm2708_spi *bs = spi_master_get_devdata(spi->master);
456 + struct spi_transfer *xfer;
458 + unsigned long flags;
460 + if (unlikely(list_empty(&msg->transfers)))
466 + list_for_each_entry(xfer, &msg->transfers, transfer_list) {
467 + if (!(xfer->tx_buf || xfer->rx_buf) && xfer->len) {
468 + dev_dbg(&spi->dev, "missing rx or tx buf\n");
472 + if (!xfer->bits_per_word || xfer->speed_hz)
475 + ret = bcm2708_setup_state(spi->master, &spi->dev, NULL,
476 + xfer->speed_hz ? xfer->speed_hz : spi->max_speed_hz,
477 + spi->chip_select, spi->mode,
478 + xfer->bits_per_word ? xfer->bits_per_word :
479 + spi->bits_per_word);
484 + msg->status = -EINPROGRESS;
485 + msg->actual_length = 0;
487 + spin_lock_irqsave(&bs->lock, flags);
488 + list_add_tail(&msg->queue, &bs->queue);
489 + queue_work(bs->workq, &bs->work);
490 + spin_unlock_irqrestore(&bs->lock, flags);
495 +static void bcm2708_spi_cleanup(struct spi_device *spi)
497 + if (spi->controller_state) {
498 + kfree(spi->controller_state);
499 + spi->controller_state = NULL;
503 +static int bcm2708_spi_probe(struct platform_device *pdev)
505 + struct resource *regs;
506 + int irq, err = -ENOMEM;
508 + struct spi_master *master;
509 + struct bcm2708_spi *bs;
511 + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
513 + dev_err(&pdev->dev, "could not get IO memory\n");
517 + irq = platform_get_irq(pdev, 0);
519 + dev_err(&pdev->dev, "could not get IRQ\n");
523 + clk = clk_get(&pdev->dev, NULL);
525 + dev_err(&pdev->dev, "could not find clk: %ld\n", PTR_ERR(clk));
526 + return PTR_ERR(clk);
529 + bcm2708_init_pinmode();
531 + master = spi_alloc_master(&pdev->dev, sizeof(*bs));
533 + dev_err(&pdev->dev, "spi_alloc_master() failed\n");
537 + /* the spi->mode bits understood by this driver: */
538 + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
540 + master->bus_num = pdev->id;
541 + master->num_chipselect = 3;
542 + master->setup = bcm2708_spi_setup;
543 + master->transfer = bcm2708_spi_transfer;
544 + master->cleanup = bcm2708_spi_cleanup;
545 + platform_set_drvdata(pdev, master);
547 + bs = spi_master_get_devdata(master);
549 + spin_lock_init(&bs->lock);
550 + INIT_LIST_HEAD(&bs->queue);
551 + init_completion(&bs->done);
552 + INIT_WORK(&bs->work, bcm2708_work);
554 + bs->base = ioremap(regs->start, resource_size(regs));
556 + dev_err(&pdev->dev, "could not remap memory\n");
557 + goto out_master_put;
560 + bs->workq = create_singlethread_workqueue(dev_name(&pdev->dev));
562 + dev_err(&pdev->dev, "could not create workqueue\n");
568 + bs->stopping = false;
570 + err = request_irq(irq, bcm2708_spi_interrupt, 0, dev_name(&pdev->dev),
573 + dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
574 + goto out_workqueue;
577 + /* initialise the hardware */
579 + bcm2708_wr(bs, SPI_CS, SPI_CS_REN | SPI_CS_CLEAR_RX | SPI_CS_CLEAR_TX);
581 + err = spi_register_master(master);
583 + dev_err(&pdev->dev, "could not register SPI master: %d\n", err);
587 + dev_info(&pdev->dev, "SPI Controller at 0x%08lx (irq %d)\n",
588 + (unsigned long)regs->start, irq);
593 + free_irq(bs->irq, master);
595 + destroy_workqueue(bs->workq);
599 + spi_master_put(master);
605 +static int bcm2708_spi_remove(struct platform_device *pdev)
607 + struct spi_master *master = platform_get_drvdata(pdev);
608 + struct bcm2708_spi *bs = spi_master_get_devdata(master);
610 + /* reset the hardware and block queue progress */
611 + spin_lock_irq(&bs->lock);
612 + bs->stopping = true;
613 + bcm2708_wr(bs, SPI_CS, SPI_CS_CLEAR_RX | SPI_CS_CLEAR_TX);
614 + spin_unlock_irq(&bs->lock);
616 + flush_work_sync(&bs->work);
618 + clk_disable(bs->clk);
620 + free_irq(bs->irq, master);
623 + spi_unregister_master(master);
628 +static struct platform_driver bcm2708_spi_driver = {
631 + .owner = THIS_MODULE,
633 + .probe = bcm2708_spi_probe,
634 + .remove = bcm2708_spi_remove,
638 +static int __init bcm2708_spi_init(void)
640 + return platform_driver_probe(&bcm2708_spi_driver, bcm2708_spi_probe);
642 +module_init(bcm2708_spi_init);
644 +static void __exit bcm2708_spi_exit(void)
646 + platform_driver_unregister(&bcm2708_spi_driver);
648 +module_exit(bcm2708_spi_exit);
651 +//module_platform_driver(bcm2708_spi_driver);
653 +MODULE_DESCRIPTION("SPI controller driver for Broadcom BCM2708");
654 +MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");
655 +MODULE_LICENSE("GPL v2");
656 +MODULE_ALIAS("platform:" DRV_NAME);