1 From eb8655fe20ef40189e9cda1441d488c5a23c89f2 Mon Sep 17 00:00:00 2001
2 From: popcornmix <popcornmix@gmail.com>
3 Date: Wed, 3 Jul 2013 00:41:10 +0100
4 Subject: [PATCH 019/196] Backport of Chris Boot's i2c and spi drivers.
7 arch/arm/configs/bcmrpi_cutdown_defconfig | 10 +
8 arch/arm/configs/bcmrpi_defconfig | 5 +
9 arch/arm/mach-bcm2708/Kconfig | 7 +
10 arch/arm/mach-bcm2708/bcm2708.c | 104 ++++-
11 arch/arm/mach-bcm2708/include/mach/platform.h | 3 +
12 drivers/i2c/busses/Kconfig | 8 +
13 drivers/i2c/busses/Makefile | 1 +
14 drivers/i2c/busses/i2c-bcm2708.c | 396 +++++++++++++++++
15 drivers/spi/Kconfig | 8 +
16 drivers/spi/Makefile | 1 +
17 drivers/spi/spi-bcm2708.c | 594 ++++++++++++++++++++++++++
18 11 files changed, 1135 insertions(+), 2 deletions(-)
19 create mode 100644 drivers/i2c/busses/i2c-bcm2708.c
20 create mode 100644 drivers/spi/spi-bcm2708.c
22 diff --git a/arch/arm/configs/bcmrpi_cutdown_defconfig b/arch/arm/configs/bcmrpi_cutdown_defconfig
23 index e519412..a61a915 100644
24 --- a/arch/arm/configs/bcmrpi_cutdown_defconfig
25 +++ b/arch/arm/configs/bcmrpi_cutdown_defconfig
26 @@ -492,3 +492,13 @@ CONFIG_CRYPTO_DEFLATE=m
27 # CONFIG_CRYPTO_HW is not set
31 +CONFIG_I2C_BOARDINFO=y
34 +CONFIG_I2C_HELPER_AUTO=y
40 diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig
41 index df947e5..6219df3 100644
42 --- a/arch/arm/configs/bcmrpi_defconfig
43 +++ b/arch/arm/configs/bcmrpi_defconfig
44 @@ -214,6 +214,11 @@ CONFIG_SERIAL_AMBA_PL011=y
45 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
46 # CONFIG_HW_RANDOM is not set
54 # CONFIG_HWMON is not set
56 diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig
57 index 63bb76c..a35ff89 100644
58 --- a/arch/arm/mach-bcm2708/Kconfig
59 +++ b/arch/arm/mach-bcm2708/Kconfig
60 @@ -31,4 +31,11 @@ config BCM2708_NOL2CACHE
62 Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt.
64 +config BCM2708_SPIDEV
65 + bool "Bind spidev to SPI0 master"
66 + depends on MACH_BCM2708
70 + Binds spidev driver to the SPI0 master
72 diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c
73 index 67f3608..03b8ec5 100644
74 --- a/arch/arm/mach-bcm2708/bcm2708.c
75 +++ b/arch/arm/mach-bcm2708/bcm2708.c
77 #include <linux/cnt32_to_63.h>
79 #include <linux/module.h>
80 +#include <linux/spi/spi.h>
82 #include <linux/version.h>
83 #include <linux/clkdev.h>
84 @@ -198,7 +199,6 @@ static struct clk osc_clk = {
86 /* warning - the USB needs a clock > 34MHz */
88 -#ifdef CONFIG_MMC_BCM2708
89 static struct clk sdhost_clk = {
90 #ifdef CONFIG_ARCH_BCM2708_CHIPIT
91 .rate = 4000000, /* 4MHz */
92 @@ -206,7 +206,6 @@ static struct clk sdhost_clk = {
93 .rate = 250000000, /* 250MHz */
98 static struct clk_lookup lookups[] = {
100 @@ -216,6 +215,15 @@ static struct clk_lookup lookups[] = {
102 .dev_id = "bcm2708_usb",
105 + .dev_id = "bcm2708_spi.0",
106 + .clk = &sdhost_clk,
108 + .dev_id = "bcm2708_i2c.0",
109 + .clk = &sdhost_clk,
111 + .dev_id = "bcm2708_i2c.1",
112 + .clk = &sdhost_clk,
116 @@ -434,6 +442,89 @@ static struct platform_device bcm2708_alsa_devices[] = {
120 +static struct resource bcm2708_spi_resources[] = {
122 + .start = SPI0_BASE,
123 + .end = SPI0_BASE + SZ_256 - 1,
124 + .flags = IORESOURCE_MEM,
128 + .flags = IORESOURCE_IRQ,
133 +static u64 bcm2708_spi_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
134 +static struct platform_device bcm2708_spi_device = {
135 + .name = "bcm2708_spi",
137 + .num_resources = ARRAY_SIZE(bcm2708_spi_resources),
138 + .resource = bcm2708_spi_resources,
140 + .dma_mask = &bcm2708_spi_dmamask,
141 + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON)},
144 +#ifdef CONFIG_BCM2708_SPIDEV
145 +static struct spi_board_info bcm2708_spi_devices[] = {
146 +#ifdef CONFIG_SPI_SPIDEV
148 + .modalias = "spidev",
149 + .max_speed_hz = 500000,
152 + .mode = SPI_MODE_0,
154 + .modalias = "spidev",
155 + .max_speed_hz = 500000,
158 + .mode = SPI_MODE_0,
164 +static struct resource bcm2708_bsc0_resources[] = {
166 + .start = BSC0_BASE,
167 + .end = BSC0_BASE + SZ_256 - 1,
168 + .flags = IORESOURCE_MEM,
170 + .start = INTERRUPT_I2C,
171 + .end = INTERRUPT_I2C,
172 + .flags = IORESOURCE_IRQ,
176 +static struct platform_device bcm2708_bsc0_device = {
177 + .name = "bcm2708_i2c",
179 + .num_resources = ARRAY_SIZE(bcm2708_bsc0_resources),
180 + .resource = bcm2708_bsc0_resources,
184 +static struct resource bcm2708_bsc1_resources[] = {
186 + .start = BSC1_BASE,
187 + .end = BSC1_BASE + SZ_256 - 1,
188 + .flags = IORESOURCE_MEM,
190 + .start = INTERRUPT_I2C,
191 + .end = INTERRUPT_I2C,
192 + .flags = IORESOURCE_IRQ,
196 +static struct platform_device bcm2708_bsc1_device = {
197 + .name = "bcm2708_i2c",
199 + .num_resources = ARRAY_SIZE(bcm2708_bsc1_resources),
200 + .resource = bcm2708_bsc1_resources,
203 int __init bcm_register_device(struct platform_device *pdev)
206 @@ -542,12 +633,21 @@ void __init bcm2708_init(void)
207 for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++)
208 bcm_register_device(&bcm2708_alsa_devices[i]);
210 + bcm_register_device(&bcm2708_spi_device);
211 + bcm_register_device(&bcm2708_bsc0_device);
212 + bcm_register_device(&bcm2708_bsc1_device);
214 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
215 struct amba_device *d = amba_devs[i];
216 amba_device_register(d, &iomem_resource);
218 system_rev = boardrev;
219 system_serial_low = serial;
221 +#ifdef CONFIG_BCM2708_SPIDEV
222 + spi_register_board_info(bcm2708_spi_devices,
223 + ARRAY_SIZE(bcm2708_spi_devices));
227 static void timer_set_mode(enum clock_event_mode mode,
228 diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h
229 index 110ce07..4d3c15d 100644
230 --- a/arch/arm/mach-bcm2708/include/mach/platform.h
231 +++ b/arch/arm/mach-bcm2708/include/mach/platform.h
233 #define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */
234 #define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */
235 #define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */
236 +#define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) /* SPI0 */
237 +#define BSC0_BASE (BCM2708_PERI_BASE + 0x205000) /* BSC0 I2C/TWI */
238 #define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */
239 #define EMMC_BASE (BCM2708_PERI_BASE + 0x300000) /* eMMC interface */
240 #define SMI_BASE (BCM2708_PERI_BASE + 0x600000) /* SMI */
241 +#define BSC1_BASE (BCM2708_PERI_BASE + 0x804000) /* BSC1 I2C/TWI */
242 #define USB_BASE (BCM2708_PERI_BASE + 0x980000) /* DTC_OTG USB controller */
243 #define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/
245 diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
246 index d4fe13e..290aee4 100644
247 --- a/drivers/i2c/busses/Kconfig
248 +++ b/drivers/i2c/busses/Kconfig
249 @@ -347,6 +347,14 @@ config I2C_BCM2835
250 This support is also available as a module. If so, the module
251 will be called i2c-bcm2835.
254 + tristate "BCM2708 BSC"
255 + depends on MACH_BCM2708
257 + Enabling this option will add BSC (Broadcom Serial Controller)
258 + support for the BCM2708. BSC is a Broadcom proprietary bus compatible
259 + with I2C/TWI/SMBus.
261 config I2C_BLACKFIN_TWI
262 tristate "Blackfin TWI I2C support"
264 diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
265 index 8f4fc23..ef26c38 100644
266 --- a/drivers/i2c/busses/Makefile
267 +++ b/drivers/i2c/busses/Makefile
268 @@ -32,6 +32,7 @@ obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
269 obj-$(CONFIG_I2C_AT91) += i2c-at91.o
270 obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
271 obj-$(CONFIG_I2C_BCM2835) += i2c-bcm2835.o
272 +obj-$(CONFIG_I2C_BCM2708) += i2c-bcm2708.o
273 obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
274 obj-$(CONFIG_I2C_CBUS_GPIO) += i2c-cbus-gpio.o
275 obj-$(CONFIG_I2C_CPM) += i2c-cpm.o
276 diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c
278 index 0000000..7cae615
280 +++ b/drivers/i2c/busses/i2c-bcm2708.c
283 + * Driver for Broadcom BCM2708 BSC Controllers
285 + * Copyright (C) 2012 Chris Boot & Frank Buss
287 + * This driver is inspired by:
288 + * i2c-ocores.c, by Peter Korsgaard <jacmet@sunsite.dk>
290 + * This program is free software; you can redistribute it and/or modify
291 + * it under the terms of the GNU General Public License as published by
292 + * the Free Software Foundation; either version 2 of the License, or
293 + * (at your option) any later version.
295 + * This program is distributed in the hope that it will be useful,
296 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
297 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
298 + * GNU General Public License for more details.
300 + * You should have received a copy of the GNU General Public License
301 + * along with this program; if not, write to the Free Software
302 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
305 +#include <linux/kernel.h>
306 +#include <linux/module.h>
307 +#include <linux/spinlock.h>
308 +#include <linux/clk.h>
309 +#include <linux/err.h>
310 +#include <linux/platform_device.h>
311 +#include <linux/io.h>
312 +#include <linux/slab.h>
313 +#include <linux/i2c.h>
314 +#include <linux/interrupt.h>
315 +#include <linux/sched.h>
316 +#include <linux/wait.h>
318 +/* BSC register offsets */
321 +#define BSC_DLEN 0x08
323 +#define BSC_FIFO 0x10
324 +#define BSC_DIV 0x14
325 +#define BSC_DEL 0x18
326 +#define BSC_CLKT 0x1c
328 +/* Bitfields in BSC_C */
329 +#define BSC_C_I2CEN 0x00008000
330 +#define BSC_C_INTR 0x00000400
331 +#define BSC_C_INTT 0x00000200
332 +#define BSC_C_INTD 0x00000100
333 +#define BSC_C_ST 0x00000080
334 +#define BSC_C_CLEAR_1 0x00000020
335 +#define BSC_C_CLEAR_2 0x00000010
336 +#define BSC_C_READ 0x00000001
338 +/* Bitfields in BSC_S */
339 +#define BSC_S_CLKT 0x00000200
340 +#define BSC_S_ERR 0x00000100
341 +#define BSC_S_RXF 0x00000080
342 +#define BSC_S_TXE 0x00000040
343 +#define BSC_S_RXD 0x00000020
344 +#define BSC_S_TXD 0x00000010
345 +#define BSC_S_RXR 0x00000008
346 +#define BSC_S_TXW 0x00000004
347 +#define BSC_S_DONE 0x00000002
348 +#define BSC_S_TA 0x00000001
350 +#define I2C_CLOCK_HZ 100000 /* FIXME: get from DT */
351 +#define I2C_TIMEOUT_MS 150
353 +#define DRV_NAME "bcm2708_i2c"
355 +struct bcm2708_i2c {
356 + struct i2c_adapter adapter;
359 + void __iomem *base;
363 + struct completion done;
365 + struct i2c_msg *msg;
372 + * This function sets the ALT mode on the I2C pins so that we can use them with
373 + * the BSC hardware.
375 + * FIXME: This is a hack. Use pinmux / pinctrl.
377 +static void bcm2708_i2c_init_pinmode(void)
379 +#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
380 +#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
383 + u32 *gpio = ioremap(0x20200000, SZ_16K);
385 + /* BSC0 is on GPIO 0 & 1, BSC1 is on GPIO 2 & 3 */
386 + for (pin = 0; pin <= 3; pin++) {
387 + INP_GPIO(pin); /* set mode to GPIO input first */
388 + SET_GPIO_ALT(pin, 0); /* set mode to ALT 0 */
397 +static inline u32 bcm2708_rd(struct bcm2708_i2c *bi, unsigned reg)
399 + return readl(bi->base + reg);
402 +static inline void bcm2708_wr(struct bcm2708_i2c *bi, unsigned reg, u32 val)
404 + writel(val, bi->base + reg);
407 +static inline void bcm2708_bsc_reset(struct bcm2708_i2c *bi)
409 + bcm2708_wr(bi, BSC_C, 0);
410 + bcm2708_wr(bi, BSC_S, BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE);
413 +static inline void bcm2708_bsc_fifo_drain(struct bcm2708_i2c *bi)
415 + while ((bcm2708_rd(bi, BSC_S) & BSC_S_RXD) && (bi->pos < bi->msg->len))
416 + bi->msg->buf[bi->pos++] = bcm2708_rd(bi, BSC_FIFO);
419 +static inline void bcm2708_bsc_fifo_fill(struct bcm2708_i2c *bi)
421 + while ((bcm2708_rd(bi, BSC_S) & BSC_S_TXD) && (bi->pos < bi->msg->len))
422 + bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]);
425 +static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi)
427 + unsigned long bus_hz;
429 + u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1;
431 + bus_hz = clk_get_rate(bi->clk);
432 + cdiv = bus_hz / I2C_CLOCK_HZ;
434 + if (bi->msg->flags & I2C_M_RD)
435 + c |= BSC_C_INTR | BSC_C_READ;
439 + bcm2708_wr(bi, BSC_DIV, cdiv);
440 + bcm2708_wr(bi, BSC_A, bi->msg->addr);
441 + bcm2708_wr(bi, BSC_DLEN, bi->msg->len);
442 + bcm2708_wr(bi, BSC_C, c);
445 +static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id)
447 + struct bcm2708_i2c *bi = dev_id;
448 + bool handled = true;
451 + spin_lock(&bi->lock);
453 + s = bcm2708_rd(bi, BSC_S);
455 + if (s & (BSC_S_CLKT | BSC_S_ERR)) {
456 + bcm2708_bsc_reset(bi);
459 + /* wake up our bh */
460 + complete(&bi->done);
461 + } else if (s & BSC_S_DONE) {
464 + if (bi->msg->flags & I2C_M_RD)
465 + bcm2708_bsc_fifo_drain(bi);
467 + bcm2708_bsc_reset(bi);
470 + /* advance to next message */
473 + bcm2708_bsc_setup(bi);
475 + /* wake up our bh */
476 + complete(&bi->done);
478 + } else if (s & BSC_S_TXW) {
479 + bcm2708_bsc_fifo_fill(bi);
480 + } else if (s & BSC_S_RXR) {
481 + bcm2708_bsc_fifo_drain(bi);
486 + spin_unlock(&bi->lock);
488 + return handled ? IRQ_HANDLED : IRQ_NONE;
491 +static int bcm2708_i2c_master_xfer(struct i2c_adapter *adap,
492 + struct i2c_msg *msgs, int num)
494 + struct bcm2708_i2c *bi = adap->algo_data;
495 + unsigned long flags;
498 + spin_lock_irqsave(&bi->lock, flags);
500 + INIT_COMPLETION(bi->done);
506 + spin_unlock_irqrestore(&bi->lock, flags);
508 + bcm2708_bsc_setup(bi);
510 + ret = wait_for_completion_timeout(&bi->done,
511 + msecs_to_jiffies(I2C_TIMEOUT_MS));
513 + dev_err(&adap->dev, "transfer timed out\n");
514 + spin_lock_irqsave(&bi->lock, flags);
515 + bcm2708_bsc_reset(bi);
516 + spin_unlock_irqrestore(&bi->lock, flags);
520 + return bi->error ? -EIO : num;
523 +static u32 bcm2708_i2c_functionality(struct i2c_adapter *adap)
525 + return I2C_FUNC_I2C | /*I2C_FUNC_10BIT_ADDR |*/ I2C_FUNC_SMBUS_EMUL;
528 +static struct i2c_algorithm bcm2708_i2c_algorithm = {
529 + .master_xfer = bcm2708_i2c_master_xfer,
530 + .functionality = bcm2708_i2c_functionality,
533 +static int bcm2708_i2c_probe(struct platform_device *pdev)
535 + struct resource *regs;
536 + int irq, err = -ENOMEM;
538 + struct bcm2708_i2c *bi;
539 + struct i2c_adapter *adap;
541 + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
543 + dev_err(&pdev->dev, "could not get IO memory\n");
547 + irq = platform_get_irq(pdev, 0);
549 + dev_err(&pdev->dev, "could not get IRQ\n");
553 + clk = clk_get(&pdev->dev, NULL);
555 + dev_err(&pdev->dev, "could not find clk: %ld\n", PTR_ERR(clk));
556 + return PTR_ERR(clk);
559 + bcm2708_i2c_init_pinmode();
561 + bi = kzalloc(sizeof(*bi), GFP_KERNEL);
565 + platform_set_drvdata(pdev, bi);
567 + adap = &bi->adapter;
568 + adap->class = I2C_CLASS_HWMON | I2C_CLASS_DDC;
569 + adap->algo = &bcm2708_i2c_algorithm;
570 + adap->algo_data = bi;
571 + adap->dev.parent = &pdev->dev;
572 + adap->nr = pdev->id;
573 + strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));
575 + switch (pdev->id) {
577 + adap->class = I2C_CLASS_HWMON;
580 + adap->class = I2C_CLASS_DDC;
583 + dev_err(&pdev->dev, "can only bind to BSC 0 or 1\n");
588 + spin_lock_init(&bi->lock);
589 + init_completion(&bi->done);
591 + bi->base = ioremap(regs->start, resource_size(regs));
593 + dev_err(&pdev->dev, "could not remap memory\n");
600 + err = request_irq(irq, bcm2708_i2c_interrupt, IRQF_SHARED,
601 + dev_name(&pdev->dev), bi);
603 + dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
607 + bcm2708_bsc_reset(bi);
609 + err = i2c_add_numbered_adapter(adap);
611 + dev_err(&pdev->dev, "could not add I2C adapter: %d\n", err);
615 + dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d)\n",
616 + pdev->id, (unsigned long)regs->start, irq);
621 + free_irq(bi->irq, bi);
631 +static int bcm2708_i2c_remove(struct platform_device *pdev)
633 + struct bcm2708_i2c *bi = platform_get_drvdata(pdev);
635 + platform_set_drvdata(pdev, NULL);
637 + i2c_del_adapter(&bi->adapter);
638 + free_irq(bi->irq, bi);
640 + clk_disable(bi->clk);
647 +static struct platform_driver bcm2708_i2c_driver = {
650 + .owner = THIS_MODULE,
652 + .probe = bcm2708_i2c_probe,
653 + .remove = bcm2708_i2c_remove,
656 +// module_platform_driver(bcm2708_i2c_driver);
659 +static int __init bcm2708_i2c_init(void)
661 + return platform_driver_register(&bcm2708_i2c_driver);
664 +static void __exit bcm2708_i2c_exit(void)
666 + platform_driver_unregister(&bcm2708_i2c_driver);
669 +module_init(bcm2708_i2c_init);
670 +module_exit(bcm2708_i2c_exit);
674 +MODULE_DESCRIPTION("BSC controller driver for Broadcom BCM2708");
675 +MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");
676 +MODULE_LICENSE("GPL v2");
677 +MODULE_ALIAS("platform:" DRV_NAME);
678 diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
679 index 92a9345..f0a2a9f 100644
680 --- a/drivers/spi/Kconfig
681 +++ b/drivers/spi/Kconfig
682 @@ -86,6 +86,14 @@ config SPI_BCM2835
683 is for the regular SPI controller. Slave mode operation is not also
687 + tristate "BCM2708 SPI controller driver (SPI0)"
688 + depends on MACH_BCM2708
690 + This selects a driver for the Broadcom BCM2708 SPI master (SPI0). This
691 + driver is not compatible with the "Universal SPI Master" or the SPI slave
695 tristate "SPI controller driver for ADI Blackfin5xx"
697 diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
698 index 33f9c09..17b4737 100644
699 --- a/drivers/spi/Makefile
700 +++ b/drivers/spi/Makefile
701 @@ -17,6 +17,7 @@ obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
702 obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o
703 obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
704 obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o
705 +obj-$(CONFIG_SPI_BCM2708) += spi-bcm2708.o
706 obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
707 obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
708 obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
709 diff --git a/drivers/spi/spi-bcm2708.c b/drivers/spi/spi-bcm2708.c
711 index 0000000..9f1580e
713 +++ b/drivers/spi/spi-bcm2708.c
716 + * Driver for Broadcom BCM2708 SPI Controllers
718 + * Copyright (C) 2012 Chris Boot
720 + * This driver is inspired by:
721 + * spi-ath79.c, Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
722 + * spi-atmel.c, Copyright (C) 2006 Atmel Corporation
724 + * This program is free software; you can redistribute it and/or modify
725 + * it under the terms of the GNU General Public License as published by
726 + * the Free Software Foundation; either version 2 of the License, or
727 + * (at your option) any later version.
729 + * This program is distributed in the hope that it will be useful,
730 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
731 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
732 + * GNU General Public License for more details.
734 + * You should have received a copy of the GNU General Public License
735 + * along with this program; if not, write to the Free Software
736 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
739 +#include <linux/kernel.h>
740 +#include <linux/module.h>
741 +#include <linux/spinlock.h>
742 +#include <linux/clk.h>
743 +#include <linux/err.h>
744 +#include <linux/platform_device.h>
745 +#include <linux/io.h>
746 +#include <linux/spi/spi.h>
747 +#include <linux/interrupt.h>
748 +#include <linux/delay.h>
749 +#include <linux/log2.h>
750 +#include <linux/sched.h>
751 +#include <linux/wait.h>
753 +/* SPI register offsets */
755 +#define SPI_FIFO 0x04
756 +#define SPI_CLK 0x08
757 +#define SPI_DLEN 0x0c
758 +#define SPI_LTOH 0x10
761 +/* Bitfields in CS */
762 +#define SPI_CS_LEN_LONG 0x02000000
763 +#define SPI_CS_DMA_LEN 0x01000000
764 +#define SPI_CS_CSPOL2 0x00800000
765 +#define SPI_CS_CSPOL1 0x00400000
766 +#define SPI_CS_CSPOL0 0x00200000
767 +#define SPI_CS_RXF 0x00100000
768 +#define SPI_CS_RXR 0x00080000
769 +#define SPI_CS_TXD 0x00040000
770 +#define SPI_CS_RXD 0x00020000
771 +#define SPI_CS_DONE 0x00010000
772 +#define SPI_CS_LEN 0x00002000
773 +#define SPI_CS_REN 0x00001000
774 +#define SPI_CS_ADCS 0x00000800
775 +#define SPI_CS_INTR 0x00000400
776 +#define SPI_CS_INTD 0x00000200
777 +#define SPI_CS_DMAEN 0x00000100
778 +#define SPI_CS_TA 0x00000080
779 +#define SPI_CS_CSPOL 0x00000040
780 +#define SPI_CS_CLEAR_RX 0x00000020
781 +#define SPI_CS_CLEAR_TX 0x00000010
782 +#define SPI_CS_CPOL 0x00000008
783 +#define SPI_CS_CPHA 0x00000004
784 +#define SPI_CS_CS_10 0x00000002
785 +#define SPI_CS_CS_01 0x00000001
787 +#define SPI_TIMEOUT_MS 150
789 +#define DRV_NAME "bcm2708_spi"
791 +struct bcm2708_spi {
793 + void __iomem *base;
798 + struct list_head queue;
799 + struct workqueue_struct *workq;
800 + struct work_struct work;
801 + struct completion done;
808 +struct bcm2708_spi_state {
814 + * This function sets the ALT mode on the SPI pins so that we can use them with
815 + * the SPI hardware.
817 + * FIXME: This is a hack. Use pinmux / pinctrl.
819 +static void bcm2708_init_pinmode(void)
821 +#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
822 +#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
825 + u32 *gpio = ioremap(0x20200000, SZ_16K);
827 + /* SPI is on GPIO 7..11 */
828 + for (pin = 7; pin <= 11; pin++) {
829 + INP_GPIO(pin); /* set mode to GPIO input first */
830 + SET_GPIO_ALT(pin, 0); /* set mode to ALT 0 */
839 +static inline u32 bcm2708_rd(struct bcm2708_spi *bs, unsigned reg)
841 + return readl(bs->base + reg);
844 +static inline void bcm2708_wr(struct bcm2708_spi *bs, unsigned reg, u32 val)
846 + writel(val, bs->base + reg);
849 +static inline void bcm2708_rd_fifo(struct bcm2708_spi *bs, int len)
854 + byte = bcm2708_rd(bs, SPI_FIFO);
856 + *bs->rx_buf++ = byte;
860 +static inline void bcm2708_wr_fifo(struct bcm2708_spi *bs, int len)
868 + byte = bs->tx_buf ? *bs->tx_buf++ : 0;
869 + bcm2708_wr(bs, SPI_FIFO, byte);
874 +static irqreturn_t bcm2708_spi_interrupt(int irq, void *dev_id)
876 + struct spi_master *master = dev_id;
877 + struct bcm2708_spi *bs = spi_master_get_devdata(master);
880 + spin_lock(&bs->lock);
882 + cs = bcm2708_rd(bs, SPI_CS);
884 + if (cs & SPI_CS_DONE) {
885 + if (bs->len) { /* first interrupt in a transfer */
886 + /* fill the TX fifo with up to 16 bytes */
887 + bcm2708_wr_fifo(bs, 16);
888 + } else { /* transfer complete */
889 + /* disable interrupts */
890 + cs &= ~(SPI_CS_INTR | SPI_CS_INTD);
891 + bcm2708_wr(bs, SPI_CS, cs);
893 + /* drain RX FIFO */
894 + while (cs & SPI_CS_RXD) {
895 + bcm2708_rd_fifo(bs, 1);
896 + cs = bcm2708_rd(bs, SPI_CS);
899 + /* wake up our bh */
900 + complete(&bs->done);
902 + } else if (cs & SPI_CS_RXR) {
903 + /* read 12 bytes of data */
904 + bcm2708_rd_fifo(bs, 12);
906 + /* write up to 12 bytes */
907 + bcm2708_wr_fifo(bs, 12);
910 + spin_unlock(&bs->lock);
912 + return IRQ_HANDLED;
915 +static int bcm2708_setup_state(struct spi_master *master,
916 + struct device *dev, struct bcm2708_spi_state *state,
917 + u32 hz, u8 csel, u8 mode, u8 bpw)
919 + struct bcm2708_spi *bs = spi_master_get_devdata(master);
921 + unsigned long bus_hz;
924 + bus_hz = clk_get_rate(bs->clk);
926 + if (hz >= bus_hz) {
927 + cdiv = 2; /* bus_hz / 2 is as fast as we can go */
929 + cdiv = DIV_ROUND_UP(bus_hz, hz);
931 + /* CDIV must be a power of 2, so round up */
932 + cdiv = roundup_pow_of_two(cdiv);
934 + if (cdiv > 65536) {
936 + "setup: %d Hz too slow, cdiv %u; min %ld Hz\n",
937 + hz, cdiv, bus_hz / 65536);
939 + } else if (cdiv == 65536) {
941 + } else if (cdiv == 1) {
942 + cdiv = 2; /* 1 gets rounded down to 0; == 65536 */
952 + dev_dbg(dev, "setup: invalid bits_per_word %u (must be 8)\n",
957 + if (mode & SPI_CPOL)
959 + if (mode & SPI_CPHA)
962 + if (!(mode & SPI_NO_CS)) {
963 + if (mode & SPI_CS_HIGH) {
964 + cs |= SPI_CS_CSPOL;
965 + cs |= SPI_CS_CSPOL0 << csel;
970 + cs |= SPI_CS_CS_10 | SPI_CS_CS_01;
975 + state->cdiv = cdiv;
981 +static int bcm2708_process_transfer(struct bcm2708_spi *bs,
982 + struct spi_message *msg, struct spi_transfer *xfer)
984 + struct spi_device *spi = msg->spi;
985 + struct bcm2708_spi_state state, *stp;
992 + if (xfer->bits_per_word || xfer->speed_hz) {
993 + ret = bcm2708_setup_state(spi->master, &spi->dev, &state,
994 + spi->max_speed_hz, spi->chip_select, spi->mode,
995 + spi->bits_per_word);
1001 + stp = spi->controller_state;
1004 + INIT_COMPLETION(bs->done);
1005 + bs->tx_buf = xfer->tx_buf;
1006 + bs->rx_buf = xfer->rx_buf;
1007 + bs->len = xfer->len;
1009 + cs = stp->cs | SPI_CS_INTR | SPI_CS_INTD | SPI_CS_TA;
1011 + bcm2708_wr(bs, SPI_CLK, stp->cdiv);
1012 + bcm2708_wr(bs, SPI_CS, cs);
1014 + ret = wait_for_completion_timeout(&bs->done,
1015 + msecs_to_jiffies(SPI_TIMEOUT_MS));
1017 + dev_err(&spi->dev, "transfer timed out\n");
1018 + return -ETIMEDOUT;
1021 + if (xfer->delay_usecs)
1022 + udelay(xfer->delay_usecs);
1024 + if (list_is_last(&xfer->transfer_list, &msg->transfers) ||
1025 + xfer->cs_change) {
1026 + /* clear TA and interrupt flags */
1027 + bcm2708_wr(bs, SPI_CS, stp->cs);
1030 + msg->actual_length += (xfer->len - bs->len);
1035 +static void bcm2708_work(struct work_struct *work)
1037 + struct bcm2708_spi *bs = container_of(work, struct bcm2708_spi, work);
1038 + unsigned long flags;
1039 + struct spi_message *msg;
1040 + struct spi_transfer *xfer;
1043 + spin_lock_irqsave(&bs->lock, flags);
1044 + while (!list_empty(&bs->queue)) {
1045 + msg = list_first_entry(&bs->queue, struct spi_message, queue);
1046 + list_del_init(&msg->queue);
1047 + spin_unlock_irqrestore(&bs->lock, flags);
1049 + list_for_each_entry(xfer, &msg->transfers, transfer_list) {
1050 + status = bcm2708_process_transfer(bs, msg, xfer);
1055 + msg->status = status;
1056 + msg->complete(msg->context);
1058 + spin_lock_irqsave(&bs->lock, flags);
1060 + spin_unlock_irqrestore(&bs->lock, flags);
1063 +static int bcm2708_spi_setup(struct spi_device *spi)
1065 + struct bcm2708_spi *bs = spi_master_get_devdata(spi->master);
1066 + struct bcm2708_spi_state *state;
1070 + return -ESHUTDOWN;
1072 + if (!(spi->mode & SPI_NO_CS) &&
1073 + (spi->chip_select > spi->master->num_chipselect)) {
1074 + dev_dbg(&spi->dev,
1075 + "setup: invalid chipselect %u (%u defined)\n",
1076 + spi->chip_select, spi->master->num_chipselect);
1080 + state = spi->controller_state;
1082 + state = kzalloc(sizeof(*state), GFP_KERNEL);
1086 + spi->controller_state = state;
1089 + ret = bcm2708_setup_state(spi->master, &spi->dev, state,
1090 + spi->max_speed_hz, spi->chip_select, spi->mode,
1091 + spi->bits_per_word);
1094 + spi->controller_state = NULL;
1097 + dev_dbg(&spi->dev,
1098 + "setup: cd %d: %d Hz, bpw %u, mode 0x%x -> CS=%08x CDIV=%04x\n",
1099 + spi->chip_select, spi->max_speed_hz, spi->bits_per_word,
1100 + spi->mode, state->cs, state->cdiv);
1105 +static int bcm2708_spi_transfer(struct spi_device *spi, struct spi_message *msg)
1107 + struct bcm2708_spi *bs = spi_master_get_devdata(spi->master);
1108 + struct spi_transfer *xfer;
1110 + unsigned long flags;
1112 + if (unlikely(list_empty(&msg->transfers)))
1116 + return -ESHUTDOWN;
1118 + list_for_each_entry(xfer, &msg->transfers, transfer_list) {
1119 + if (!(xfer->tx_buf || xfer->rx_buf) && xfer->len) {
1120 + dev_dbg(&spi->dev, "missing rx or tx buf\n");
1124 + if (!xfer->bits_per_word || xfer->speed_hz)
1127 + ret = bcm2708_setup_state(spi->master, &spi->dev, NULL,
1128 + xfer->speed_hz ? xfer->speed_hz : spi->max_speed_hz,
1129 + spi->chip_select, spi->mode,
1130 + xfer->bits_per_word ? xfer->bits_per_word :
1131 + spi->bits_per_word);
1136 + msg->status = -EINPROGRESS;
1137 + msg->actual_length = 0;
1139 + spin_lock_irqsave(&bs->lock, flags);
1140 + list_add_tail(&msg->queue, &bs->queue);
1141 + queue_work(bs->workq, &bs->work);
1142 + spin_unlock_irqrestore(&bs->lock, flags);
1147 +static void bcm2708_spi_cleanup(struct spi_device *spi)
1149 + if (spi->controller_state) {
1150 + kfree(spi->controller_state);
1151 + spi->controller_state = NULL;
1155 +static int bcm2708_spi_probe(struct platform_device *pdev)
1157 + struct resource *regs;
1158 + int irq, err = -ENOMEM;
1160 + struct spi_master *master;
1161 + struct bcm2708_spi *bs;
1163 + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1165 + dev_err(&pdev->dev, "could not get IO memory\n");
1169 + irq = platform_get_irq(pdev, 0);
1171 + dev_err(&pdev->dev, "could not get IRQ\n");
1175 + clk = clk_get(&pdev->dev, NULL);
1176 + if (IS_ERR(clk)) {
1177 + dev_err(&pdev->dev, "could not find clk: %ld\n", PTR_ERR(clk));
1178 + return PTR_ERR(clk);
1181 + bcm2708_init_pinmode();
1183 + master = spi_alloc_master(&pdev->dev, sizeof(*bs));
1185 + dev_err(&pdev->dev, "spi_alloc_master() failed\n");
1189 + /* the spi->mode bits understood by this driver: */
1190 + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
1192 + master->bus_num = pdev->id;
1193 + master->num_chipselect = 3;
1194 + master->setup = bcm2708_spi_setup;
1195 + master->transfer = bcm2708_spi_transfer;
1196 + master->cleanup = bcm2708_spi_cleanup;
1197 + platform_set_drvdata(pdev, master);
1199 + bs = spi_master_get_devdata(master);
1201 + spin_lock_init(&bs->lock);
1202 + INIT_LIST_HEAD(&bs->queue);
1203 + init_completion(&bs->done);
1204 + INIT_WORK(&bs->work, bcm2708_work);
1206 + bs->base = ioremap(regs->start, resource_size(regs));
1208 + dev_err(&pdev->dev, "could not remap memory\n");
1209 + goto out_master_put;
1212 + bs->workq = create_singlethread_workqueue(dev_name(&pdev->dev));
1214 + dev_err(&pdev->dev, "could not create workqueue\n");
1220 + bs->stopping = false;
1222 + err = request_irq(irq, bcm2708_spi_interrupt, 0, dev_name(&pdev->dev),
1225 + dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
1226 + goto out_workqueue;
1229 + /* initialise the hardware */
1231 + bcm2708_wr(bs, SPI_CS, SPI_CS_REN | SPI_CS_CLEAR_RX | SPI_CS_CLEAR_TX);
1233 + err = spi_register_master(master);
1235 + dev_err(&pdev->dev, "could not register SPI master: %d\n", err);
1236 + goto out_free_irq;
1239 + dev_info(&pdev->dev, "SPI Controller at 0x%08lx (irq %d)\n",
1240 + (unsigned long)regs->start, irq);
1245 + free_irq(bs->irq, master);
1247 + destroy_workqueue(bs->workq);
1249 + iounmap(bs->base);
1251 + spi_master_put(master);
1257 +static int bcm2708_spi_remove(struct platform_device *pdev)
1259 + struct spi_master *master = platform_get_drvdata(pdev);
1260 + struct bcm2708_spi *bs = spi_master_get_devdata(master);
1262 + /* reset the hardware and block queue progress */
1263 + spin_lock_irq(&bs->lock);
1264 + bs->stopping = true;
1265 + bcm2708_wr(bs, SPI_CS, SPI_CS_CLEAR_RX | SPI_CS_CLEAR_TX);
1266 + spin_unlock_irq(&bs->lock);
1268 + flush_work_sync(&bs->work);
1270 + clk_disable(bs->clk);
1272 + free_irq(bs->irq, master);
1273 + iounmap(bs->base);
1275 + spi_unregister_master(master);
1280 +static struct platform_driver bcm2708_spi_driver = {
1283 + .owner = THIS_MODULE,
1285 + .probe = bcm2708_spi_probe,
1286 + .remove = bcm2708_spi_remove,
1290 +static int __init bcm2708_spi_init(void)
1292 + return platform_driver_probe(&bcm2708_spi_driver, bcm2708_spi_probe);
1294 +module_init(bcm2708_spi_init);
1296 +static void __exit bcm2708_spi_exit(void)
1298 + platform_driver_unregister(&bcm2708_spi_driver);
1300 +module_exit(bcm2708_spi_exit);
1303 +//module_platform_driver(bcm2708_spi_driver);
1305 +MODULE_DESCRIPTION("SPI controller driver for Broadcom BCM2708");
1306 +MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");
1307 +MODULE_LICENSE("GPL v2");
1308 +MODULE_ALIAS("platform:" DRV_NAME);