1 From 5a3b6667524d9164140077cfadf61b165f0950ec 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/174] 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 --- a/arch/arm/configs/bcmrpi_cutdown_defconfig
23 +++ b/arch/arm/configs/bcmrpi_cutdown_defconfig
24 @@ -492,3 +492,13 @@ CONFIG_CRYPTO_DEFLATE=m
25 # CONFIG_CRYPTO_HW is not set
29 +CONFIG_I2C_BOARDINFO=y
32 +CONFIG_I2C_HELPER_AUTO=y
38 --- a/arch/arm/configs/bcmrpi_defconfig
39 +++ b/arch/arm/configs/bcmrpi_defconfig
40 @@ -214,6 +214,11 @@ CONFIG_SERIAL_AMBA_PL011=y
41 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
42 # CONFIG_HW_RANDOM is not set
50 # CONFIG_HWMON is not set
52 --- a/arch/arm/mach-bcm2708/Kconfig
53 +++ b/arch/arm/mach-bcm2708/Kconfig
54 @@ -31,4 +31,11 @@ config BCM2708_NOL2CACHE
56 Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt.
58 +config BCM2708_SPIDEV
59 + bool "Bind spidev to SPI0 master"
60 + depends on MACH_BCM2708
64 + Binds spidev driver to the SPI0 master
66 --- a/arch/arm/mach-bcm2708/bcm2708.c
67 +++ b/arch/arm/mach-bcm2708/bcm2708.c
69 #include <linux/cnt32_to_63.h>
71 #include <linux/module.h>
72 +#include <linux/spi/spi.h>
74 #include <linux/version.h>
75 #include <linux/clkdev.h>
76 @@ -198,7 +199,6 @@ static struct clk osc_clk = {
78 /* warning - the USB needs a clock > 34MHz */
80 -#ifdef CONFIG_MMC_BCM2708
81 static struct clk sdhost_clk = {
82 #ifdef CONFIG_ARCH_BCM2708_CHIPIT
83 .rate = 4000000, /* 4MHz */
84 @@ -206,7 +206,6 @@ static struct clk sdhost_clk = {
85 .rate = 250000000, /* 250MHz */
90 static struct clk_lookup lookups[] = {
92 @@ -216,6 +215,15 @@ static struct clk_lookup lookups[] = {
94 .dev_id = "bcm2708_usb",
97 + .dev_id = "bcm2708_spi.0",
100 + .dev_id = "bcm2708_i2c.0",
101 + .clk = &sdhost_clk,
103 + .dev_id = "bcm2708_i2c.1",
104 + .clk = &sdhost_clk,
108 @@ -434,6 +442,89 @@ static struct platform_device bcm2708_al
112 +static struct resource bcm2708_spi_resources[] = {
114 + .start = SPI0_BASE,
115 + .end = SPI0_BASE + SZ_256 - 1,
116 + .flags = IORESOURCE_MEM,
120 + .flags = IORESOURCE_IRQ,
125 +static u64 bcm2708_spi_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
126 +static struct platform_device bcm2708_spi_device = {
127 + .name = "bcm2708_spi",
129 + .num_resources = ARRAY_SIZE(bcm2708_spi_resources),
130 + .resource = bcm2708_spi_resources,
132 + .dma_mask = &bcm2708_spi_dmamask,
133 + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON)},
136 +#ifdef CONFIG_BCM2708_SPIDEV
137 +static struct spi_board_info bcm2708_spi_devices[] = {
138 +#ifdef CONFIG_SPI_SPIDEV
140 + .modalias = "spidev",
141 + .max_speed_hz = 500000,
144 + .mode = SPI_MODE_0,
146 + .modalias = "spidev",
147 + .max_speed_hz = 500000,
150 + .mode = SPI_MODE_0,
156 +static struct resource bcm2708_bsc0_resources[] = {
158 + .start = BSC0_BASE,
159 + .end = BSC0_BASE + SZ_256 - 1,
160 + .flags = IORESOURCE_MEM,
162 + .start = INTERRUPT_I2C,
163 + .end = INTERRUPT_I2C,
164 + .flags = IORESOURCE_IRQ,
168 +static struct platform_device bcm2708_bsc0_device = {
169 + .name = "bcm2708_i2c",
171 + .num_resources = ARRAY_SIZE(bcm2708_bsc0_resources),
172 + .resource = bcm2708_bsc0_resources,
176 +static struct resource bcm2708_bsc1_resources[] = {
178 + .start = BSC1_BASE,
179 + .end = BSC1_BASE + SZ_256 - 1,
180 + .flags = IORESOURCE_MEM,
182 + .start = INTERRUPT_I2C,
183 + .end = INTERRUPT_I2C,
184 + .flags = IORESOURCE_IRQ,
188 +static struct platform_device bcm2708_bsc1_device = {
189 + .name = "bcm2708_i2c",
191 + .num_resources = ARRAY_SIZE(bcm2708_bsc1_resources),
192 + .resource = bcm2708_bsc1_resources,
195 int __init bcm_register_device(struct platform_device *pdev)
198 @@ -542,12 +633,21 @@ void __init bcm2708_init(void)
199 for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++)
200 bcm_register_device(&bcm2708_alsa_devices[i]);
202 + bcm_register_device(&bcm2708_spi_device);
203 + bcm_register_device(&bcm2708_bsc0_device);
204 + bcm_register_device(&bcm2708_bsc1_device);
206 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
207 struct amba_device *d = amba_devs[i];
208 amba_device_register(d, &iomem_resource);
210 system_rev = boardrev;
211 system_serial_low = serial;
213 +#ifdef CONFIG_BCM2708_SPIDEV
214 + spi_register_board_info(bcm2708_spi_devices,
215 + ARRAY_SIZE(bcm2708_spi_devices));
219 static void timer_set_mode(enum clock_event_mode mode,
220 --- a/arch/arm/mach-bcm2708/include/mach/platform.h
221 +++ b/arch/arm/mach-bcm2708/include/mach/platform.h
223 #define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */
224 #define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */
225 #define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */
226 +#define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) /* SPI0 */
227 +#define BSC0_BASE (BCM2708_PERI_BASE + 0x205000) /* BSC0 I2C/TWI */
228 #define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */
229 #define EMMC_BASE (BCM2708_PERI_BASE + 0x300000) /* eMMC interface */
230 #define SMI_BASE (BCM2708_PERI_BASE + 0x600000) /* SMI */
231 +#define BSC1_BASE (BCM2708_PERI_BASE + 0x804000) /* BSC1 I2C/TWI */
232 #define USB_BASE (BCM2708_PERI_BASE + 0x980000) /* DTC_OTG USB controller */
233 #define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/
235 --- a/drivers/i2c/busses/Kconfig
236 +++ b/drivers/i2c/busses/Kconfig
237 @@ -345,6 +345,14 @@ config I2C_BCM2835
238 This support is also available as a module. If so, the module
239 will be called i2c-bcm2835.
242 + tristate "BCM2708 BSC"
243 + depends on MACH_BCM2708
245 + Enabling this option will add BSC (Broadcom Serial Controller)
246 + support for the BCM2708. BSC is a Broadcom proprietary bus compatible
247 + with I2C/TWI/SMBus.
249 config I2C_BLACKFIN_TWI
250 tristate "Blackfin TWI I2C support"
252 --- a/drivers/i2c/busses/Makefile
253 +++ b/drivers/i2c/busses/Makefile
254 @@ -32,6 +32,7 @@ obj-$(CONFIG_I2C_POWERMAC) += i2c-powerm
255 obj-$(CONFIG_I2C_AT91) += i2c-at91.o
256 obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
257 obj-$(CONFIG_I2C_BCM2835) += i2c-bcm2835.o
258 +obj-$(CONFIG_I2C_BCM2708) += i2c-bcm2708.o
259 obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
260 obj-$(CONFIG_I2C_CBUS_GPIO) += i2c-cbus-gpio.o
261 obj-$(CONFIG_I2C_CPM) += i2c-cpm.o
263 +++ b/drivers/i2c/busses/i2c-bcm2708.c
266 + * Driver for Broadcom BCM2708 BSC Controllers
268 + * Copyright (C) 2012 Chris Boot & Frank Buss
270 + * This driver is inspired by:
271 + * i2c-ocores.c, by Peter Korsgaard <jacmet@sunsite.dk>
273 + * This program is free software; you can redistribute it and/or modify
274 + * it under the terms of the GNU General Public License as published by
275 + * the Free Software Foundation; either version 2 of the License, or
276 + * (at your option) any later version.
278 + * This program is distributed in the hope that it will be useful,
279 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
280 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
281 + * GNU General Public License for more details.
283 + * You should have received a copy of the GNU General Public License
284 + * along with this program; if not, write to the Free Software
285 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
288 +#include <linux/kernel.h>
289 +#include <linux/module.h>
290 +#include <linux/spinlock.h>
291 +#include <linux/clk.h>
292 +#include <linux/err.h>
293 +#include <linux/platform_device.h>
294 +#include <linux/io.h>
295 +#include <linux/slab.h>
296 +#include <linux/i2c.h>
297 +#include <linux/interrupt.h>
298 +#include <linux/sched.h>
299 +#include <linux/wait.h>
301 +/* BSC register offsets */
304 +#define BSC_DLEN 0x08
306 +#define BSC_FIFO 0x10
307 +#define BSC_DIV 0x14
308 +#define BSC_DEL 0x18
309 +#define BSC_CLKT 0x1c
311 +/* Bitfields in BSC_C */
312 +#define BSC_C_I2CEN 0x00008000
313 +#define BSC_C_INTR 0x00000400
314 +#define BSC_C_INTT 0x00000200
315 +#define BSC_C_INTD 0x00000100
316 +#define BSC_C_ST 0x00000080
317 +#define BSC_C_CLEAR_1 0x00000020
318 +#define BSC_C_CLEAR_2 0x00000010
319 +#define BSC_C_READ 0x00000001
321 +/* Bitfields in BSC_S */
322 +#define BSC_S_CLKT 0x00000200
323 +#define BSC_S_ERR 0x00000100
324 +#define BSC_S_RXF 0x00000080
325 +#define BSC_S_TXE 0x00000040
326 +#define BSC_S_RXD 0x00000020
327 +#define BSC_S_TXD 0x00000010
328 +#define BSC_S_RXR 0x00000008
329 +#define BSC_S_TXW 0x00000004
330 +#define BSC_S_DONE 0x00000002
331 +#define BSC_S_TA 0x00000001
333 +#define I2C_CLOCK_HZ 100000 /* FIXME: get from DT */
334 +#define I2C_TIMEOUT_MS 150
336 +#define DRV_NAME "bcm2708_i2c"
338 +struct bcm2708_i2c {
339 + struct i2c_adapter adapter;
342 + void __iomem *base;
346 + struct completion done;
348 + struct i2c_msg *msg;
355 + * This function sets the ALT mode on the I2C pins so that we can use them with
356 + * the BSC hardware.
358 + * FIXME: This is a hack. Use pinmux / pinctrl.
360 +static void bcm2708_i2c_init_pinmode(void)
362 +#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
363 +#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
366 + u32 *gpio = ioremap(0x20200000, SZ_16K);
368 + /* BSC0 is on GPIO 0 & 1, BSC1 is on GPIO 2 & 3 */
369 + for (pin = 0; pin <= 3; pin++) {
370 + INP_GPIO(pin); /* set mode to GPIO input first */
371 + SET_GPIO_ALT(pin, 0); /* set mode to ALT 0 */
380 +static inline u32 bcm2708_rd(struct bcm2708_i2c *bi, unsigned reg)
382 + return readl(bi->base + reg);
385 +static inline void bcm2708_wr(struct bcm2708_i2c *bi, unsigned reg, u32 val)
387 + writel(val, bi->base + reg);
390 +static inline void bcm2708_bsc_reset(struct bcm2708_i2c *bi)
392 + bcm2708_wr(bi, BSC_C, 0);
393 + bcm2708_wr(bi, BSC_S, BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE);
396 +static inline void bcm2708_bsc_fifo_drain(struct bcm2708_i2c *bi)
398 + while ((bcm2708_rd(bi, BSC_S) & BSC_S_RXD) && (bi->pos < bi->msg->len))
399 + bi->msg->buf[bi->pos++] = bcm2708_rd(bi, BSC_FIFO);
402 +static inline void bcm2708_bsc_fifo_fill(struct bcm2708_i2c *bi)
404 + while ((bcm2708_rd(bi, BSC_S) & BSC_S_TXD) && (bi->pos < bi->msg->len))
405 + bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]);
408 +static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi)
410 + unsigned long bus_hz;
412 + u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1;
414 + bus_hz = clk_get_rate(bi->clk);
415 + cdiv = bus_hz / I2C_CLOCK_HZ;
417 + if (bi->msg->flags & I2C_M_RD)
418 + c |= BSC_C_INTR | BSC_C_READ;
422 + bcm2708_wr(bi, BSC_DIV, cdiv);
423 + bcm2708_wr(bi, BSC_A, bi->msg->addr);
424 + bcm2708_wr(bi, BSC_DLEN, bi->msg->len);
425 + bcm2708_wr(bi, BSC_C, c);
428 +static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id)
430 + struct bcm2708_i2c *bi = dev_id;
431 + bool handled = true;
434 + spin_lock(&bi->lock);
436 + s = bcm2708_rd(bi, BSC_S);
438 + if (s & (BSC_S_CLKT | BSC_S_ERR)) {
439 + bcm2708_bsc_reset(bi);
442 + /* wake up our bh */
443 + complete(&bi->done);
444 + } else if (s & BSC_S_DONE) {
447 + if (bi->msg->flags & I2C_M_RD)
448 + bcm2708_bsc_fifo_drain(bi);
450 + bcm2708_bsc_reset(bi);
453 + /* advance to next message */
456 + bcm2708_bsc_setup(bi);
458 + /* wake up our bh */
459 + complete(&bi->done);
461 + } else if (s & BSC_S_TXW) {
462 + bcm2708_bsc_fifo_fill(bi);
463 + } else if (s & BSC_S_RXR) {
464 + bcm2708_bsc_fifo_drain(bi);
469 + spin_unlock(&bi->lock);
471 + return handled ? IRQ_HANDLED : IRQ_NONE;
474 +static int bcm2708_i2c_master_xfer(struct i2c_adapter *adap,
475 + struct i2c_msg *msgs, int num)
477 + struct bcm2708_i2c *bi = adap->algo_data;
478 + unsigned long flags;
481 + spin_lock_irqsave(&bi->lock, flags);
483 + INIT_COMPLETION(bi->done);
489 + spin_unlock_irqrestore(&bi->lock, flags);
491 + bcm2708_bsc_setup(bi);
493 + ret = wait_for_completion_timeout(&bi->done,
494 + msecs_to_jiffies(I2C_TIMEOUT_MS));
496 + dev_err(&adap->dev, "transfer timed out\n");
497 + spin_lock_irqsave(&bi->lock, flags);
498 + bcm2708_bsc_reset(bi);
499 + spin_unlock_irqrestore(&bi->lock, flags);
503 + return bi->error ? -EIO : num;
506 +static u32 bcm2708_i2c_functionality(struct i2c_adapter *adap)
508 + return I2C_FUNC_I2C | /*I2C_FUNC_10BIT_ADDR |*/ I2C_FUNC_SMBUS_EMUL;
511 +static struct i2c_algorithm bcm2708_i2c_algorithm = {
512 + .master_xfer = bcm2708_i2c_master_xfer,
513 + .functionality = bcm2708_i2c_functionality,
516 +static int bcm2708_i2c_probe(struct platform_device *pdev)
518 + struct resource *regs;
519 + int irq, err = -ENOMEM;
521 + struct bcm2708_i2c *bi;
522 + struct i2c_adapter *adap;
524 + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
526 + dev_err(&pdev->dev, "could not get IO memory\n");
530 + irq = platform_get_irq(pdev, 0);
532 + dev_err(&pdev->dev, "could not get IRQ\n");
536 + clk = clk_get(&pdev->dev, NULL);
538 + dev_err(&pdev->dev, "could not find clk: %ld\n", PTR_ERR(clk));
539 + return PTR_ERR(clk);
542 + bcm2708_i2c_init_pinmode();
544 + bi = kzalloc(sizeof(*bi), GFP_KERNEL);
548 + platform_set_drvdata(pdev, bi);
550 + adap = &bi->adapter;
551 + adap->class = I2C_CLASS_HWMON | I2C_CLASS_DDC;
552 + adap->algo = &bcm2708_i2c_algorithm;
553 + adap->algo_data = bi;
554 + adap->dev.parent = &pdev->dev;
555 + adap->nr = pdev->id;
556 + strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));
558 + switch (pdev->id) {
560 + adap->class = I2C_CLASS_HWMON;
563 + adap->class = I2C_CLASS_DDC;
566 + dev_err(&pdev->dev, "can only bind to BSC 0 or 1\n");
571 + spin_lock_init(&bi->lock);
572 + init_completion(&bi->done);
574 + bi->base = ioremap(regs->start, resource_size(regs));
576 + dev_err(&pdev->dev, "could not remap memory\n");
583 + err = request_irq(irq, bcm2708_i2c_interrupt, IRQF_SHARED,
584 + dev_name(&pdev->dev), bi);
586 + dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
590 + bcm2708_bsc_reset(bi);
592 + err = i2c_add_numbered_adapter(adap);
594 + dev_err(&pdev->dev, "could not add I2C adapter: %d\n", err);
598 + dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d)\n",
599 + pdev->id, (unsigned long)regs->start, irq);
604 + free_irq(bi->irq, bi);
614 +static int bcm2708_i2c_remove(struct platform_device *pdev)
616 + struct bcm2708_i2c *bi = platform_get_drvdata(pdev);
618 + platform_set_drvdata(pdev, NULL);
620 + i2c_del_adapter(&bi->adapter);
621 + free_irq(bi->irq, bi);
623 + clk_disable(bi->clk);
630 +static struct platform_driver bcm2708_i2c_driver = {
633 + .owner = THIS_MODULE,
635 + .probe = bcm2708_i2c_probe,
636 + .remove = bcm2708_i2c_remove,
639 +// module_platform_driver(bcm2708_i2c_driver);
642 +static int __init bcm2708_i2c_init(void)
644 + return platform_driver_register(&bcm2708_i2c_driver);
647 +static void __exit bcm2708_i2c_exit(void)
649 + platform_driver_unregister(&bcm2708_i2c_driver);
652 +module_init(bcm2708_i2c_init);
653 +module_exit(bcm2708_i2c_exit);
657 +MODULE_DESCRIPTION("BSC controller driver for Broadcom BCM2708");
658 +MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");
659 +MODULE_LICENSE("GPL v2");
660 +MODULE_ALIAS("platform:" DRV_NAME);
661 --- a/drivers/spi/Kconfig
662 +++ b/drivers/spi/Kconfig
663 @@ -86,6 +86,14 @@ config SPI_BCM2835
664 is for the regular SPI controller. Slave mode operation is not also
668 + tristate "BCM2708 SPI controller driver (SPI0)"
669 + depends on MACH_BCM2708
671 + This selects a driver for the Broadcom BCM2708 SPI master (SPI0). This
672 + driver is not compatible with the "Universal SPI Master" or the SPI slave
676 tristate "SPI controller driver for ADI Blackfin5xx"
678 --- a/drivers/spi/Makefile
679 +++ b/drivers/spi/Makefile
680 @@ -17,6 +17,7 @@ obj-$(CONFIG_SPI_AU1550) += spi-au1550.
681 obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o
682 obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
683 obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o
684 +obj-$(CONFIG_SPI_BCM2708) += spi-bcm2708.o
685 obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
686 obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
687 obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
689 +++ b/drivers/spi/spi-bcm2708.c
692 + * Driver for Broadcom BCM2708 SPI Controllers
694 + * Copyright (C) 2012 Chris Boot
696 + * This driver is inspired by:
697 + * spi-ath79.c, Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
698 + * spi-atmel.c, Copyright (C) 2006 Atmel Corporation
700 + * This program is free software; you can redistribute it and/or modify
701 + * it under the terms of the GNU General Public License as published by
702 + * the Free Software Foundation; either version 2 of the License, or
703 + * (at your option) any later version.
705 + * This program is distributed in the hope that it will be useful,
706 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
707 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
708 + * GNU General Public License for more details.
710 + * You should have received a copy of the GNU General Public License
711 + * along with this program; if not, write to the Free Software
712 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
715 +#include <linux/kernel.h>
716 +#include <linux/module.h>
717 +#include <linux/spinlock.h>
718 +#include <linux/clk.h>
719 +#include <linux/err.h>
720 +#include <linux/platform_device.h>
721 +#include <linux/io.h>
722 +#include <linux/spi/spi.h>
723 +#include <linux/interrupt.h>
724 +#include <linux/delay.h>
725 +#include <linux/log2.h>
726 +#include <linux/sched.h>
727 +#include <linux/wait.h>
729 +/* SPI register offsets */
731 +#define SPI_FIFO 0x04
732 +#define SPI_CLK 0x08
733 +#define SPI_DLEN 0x0c
734 +#define SPI_LTOH 0x10
737 +/* Bitfields in CS */
738 +#define SPI_CS_LEN_LONG 0x02000000
739 +#define SPI_CS_DMA_LEN 0x01000000
740 +#define SPI_CS_CSPOL2 0x00800000
741 +#define SPI_CS_CSPOL1 0x00400000
742 +#define SPI_CS_CSPOL0 0x00200000
743 +#define SPI_CS_RXF 0x00100000
744 +#define SPI_CS_RXR 0x00080000
745 +#define SPI_CS_TXD 0x00040000
746 +#define SPI_CS_RXD 0x00020000
747 +#define SPI_CS_DONE 0x00010000
748 +#define SPI_CS_LEN 0x00002000
749 +#define SPI_CS_REN 0x00001000
750 +#define SPI_CS_ADCS 0x00000800
751 +#define SPI_CS_INTR 0x00000400
752 +#define SPI_CS_INTD 0x00000200
753 +#define SPI_CS_DMAEN 0x00000100
754 +#define SPI_CS_TA 0x00000080
755 +#define SPI_CS_CSPOL 0x00000040
756 +#define SPI_CS_CLEAR_RX 0x00000020
757 +#define SPI_CS_CLEAR_TX 0x00000010
758 +#define SPI_CS_CPOL 0x00000008
759 +#define SPI_CS_CPHA 0x00000004
760 +#define SPI_CS_CS_10 0x00000002
761 +#define SPI_CS_CS_01 0x00000001
763 +#define SPI_TIMEOUT_MS 150
765 +#define DRV_NAME "bcm2708_spi"
767 +struct bcm2708_spi {
769 + void __iomem *base;
774 + struct list_head queue;
775 + struct workqueue_struct *workq;
776 + struct work_struct work;
777 + struct completion done;
784 +struct bcm2708_spi_state {
790 + * This function sets the ALT mode on the SPI pins so that we can use them with
791 + * the SPI hardware.
793 + * FIXME: This is a hack. Use pinmux / pinctrl.
795 +static void bcm2708_init_pinmode(void)
797 +#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
798 +#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
801 + u32 *gpio = ioremap(0x20200000, SZ_16K);
803 + /* SPI is on GPIO 7..11 */
804 + for (pin = 7; pin <= 11; pin++) {
805 + INP_GPIO(pin); /* set mode to GPIO input first */
806 + SET_GPIO_ALT(pin, 0); /* set mode to ALT 0 */
815 +static inline u32 bcm2708_rd(struct bcm2708_spi *bs, unsigned reg)
817 + return readl(bs->base + reg);
820 +static inline void bcm2708_wr(struct bcm2708_spi *bs, unsigned reg, u32 val)
822 + writel(val, bs->base + reg);
825 +static inline void bcm2708_rd_fifo(struct bcm2708_spi *bs, int len)
830 + byte = bcm2708_rd(bs, SPI_FIFO);
832 + *bs->rx_buf++ = byte;
836 +static inline void bcm2708_wr_fifo(struct bcm2708_spi *bs, int len)
844 + byte = bs->tx_buf ? *bs->tx_buf++ : 0;
845 + bcm2708_wr(bs, SPI_FIFO, byte);
850 +static irqreturn_t bcm2708_spi_interrupt(int irq, void *dev_id)
852 + struct spi_master *master = dev_id;
853 + struct bcm2708_spi *bs = spi_master_get_devdata(master);
856 + spin_lock(&bs->lock);
858 + cs = bcm2708_rd(bs, SPI_CS);
860 + if (cs & SPI_CS_DONE) {
861 + if (bs->len) { /* first interrupt in a transfer */
862 + /* fill the TX fifo with up to 16 bytes */
863 + bcm2708_wr_fifo(bs, 16);
864 + } else { /* transfer complete */
865 + /* disable interrupts */
866 + cs &= ~(SPI_CS_INTR | SPI_CS_INTD);
867 + bcm2708_wr(bs, SPI_CS, cs);
869 + /* drain RX FIFO */
870 + while (cs & SPI_CS_RXD) {
871 + bcm2708_rd_fifo(bs, 1);
872 + cs = bcm2708_rd(bs, SPI_CS);
875 + /* wake up our bh */
876 + complete(&bs->done);
878 + } else if (cs & SPI_CS_RXR) {
879 + /* read 12 bytes of data */
880 + bcm2708_rd_fifo(bs, 12);
882 + /* write up to 12 bytes */
883 + bcm2708_wr_fifo(bs, 12);
886 + spin_unlock(&bs->lock);
888 + return IRQ_HANDLED;
891 +static int bcm2708_setup_state(struct spi_master *master,
892 + struct device *dev, struct bcm2708_spi_state *state,
893 + u32 hz, u8 csel, u8 mode, u8 bpw)
895 + struct bcm2708_spi *bs = spi_master_get_devdata(master);
897 + unsigned long bus_hz;
900 + bus_hz = clk_get_rate(bs->clk);
902 + if (hz >= bus_hz) {
903 + cdiv = 2; /* bus_hz / 2 is as fast as we can go */
905 + cdiv = DIV_ROUND_UP(bus_hz, hz);
907 + /* CDIV must be a power of 2, so round up */
908 + cdiv = roundup_pow_of_two(cdiv);
910 + if (cdiv > 65536) {
912 + "setup: %d Hz too slow, cdiv %u; min %ld Hz\n",
913 + hz, cdiv, bus_hz / 65536);
915 + } else if (cdiv == 65536) {
917 + } else if (cdiv == 1) {
918 + cdiv = 2; /* 1 gets rounded down to 0; == 65536 */
928 + dev_dbg(dev, "setup: invalid bits_per_word %u (must be 8)\n",
933 + if (mode & SPI_CPOL)
935 + if (mode & SPI_CPHA)
938 + if (!(mode & SPI_NO_CS)) {
939 + if (mode & SPI_CS_HIGH) {
940 + cs |= SPI_CS_CSPOL;
941 + cs |= SPI_CS_CSPOL0 << csel;
946 + cs |= SPI_CS_CS_10 | SPI_CS_CS_01;
951 + state->cdiv = cdiv;
957 +static int bcm2708_process_transfer(struct bcm2708_spi *bs,
958 + struct spi_message *msg, struct spi_transfer *xfer)
960 + struct spi_device *spi = msg->spi;
961 + struct bcm2708_spi_state state, *stp;
968 + if (xfer->bits_per_word || xfer->speed_hz) {
969 + ret = bcm2708_setup_state(spi->master, &spi->dev, &state,
970 + spi->max_speed_hz, spi->chip_select, spi->mode,
971 + spi->bits_per_word);
977 + stp = spi->controller_state;
980 + INIT_COMPLETION(bs->done);
981 + bs->tx_buf = xfer->tx_buf;
982 + bs->rx_buf = xfer->rx_buf;
983 + bs->len = xfer->len;
985 + cs = stp->cs | SPI_CS_INTR | SPI_CS_INTD | SPI_CS_TA;
987 + bcm2708_wr(bs, SPI_CLK, stp->cdiv);
988 + bcm2708_wr(bs, SPI_CS, cs);
990 + ret = wait_for_completion_timeout(&bs->done,
991 + msecs_to_jiffies(SPI_TIMEOUT_MS));
993 + dev_err(&spi->dev, "transfer timed out\n");
997 + if (xfer->delay_usecs)
998 + udelay(xfer->delay_usecs);
1000 + if (list_is_last(&xfer->transfer_list, &msg->transfers) ||
1001 + xfer->cs_change) {
1002 + /* clear TA and interrupt flags */
1003 + bcm2708_wr(bs, SPI_CS, stp->cs);
1006 + msg->actual_length += (xfer->len - bs->len);
1011 +static void bcm2708_work(struct work_struct *work)
1013 + struct bcm2708_spi *bs = container_of(work, struct bcm2708_spi, work);
1014 + unsigned long flags;
1015 + struct spi_message *msg;
1016 + struct spi_transfer *xfer;
1019 + spin_lock_irqsave(&bs->lock, flags);
1020 + while (!list_empty(&bs->queue)) {
1021 + msg = list_first_entry(&bs->queue, struct spi_message, queue);
1022 + list_del_init(&msg->queue);
1023 + spin_unlock_irqrestore(&bs->lock, flags);
1025 + list_for_each_entry(xfer, &msg->transfers, transfer_list) {
1026 + status = bcm2708_process_transfer(bs, msg, xfer);
1031 + msg->status = status;
1032 + msg->complete(msg->context);
1034 + spin_lock_irqsave(&bs->lock, flags);
1036 + spin_unlock_irqrestore(&bs->lock, flags);
1039 +static int bcm2708_spi_setup(struct spi_device *spi)
1041 + struct bcm2708_spi *bs = spi_master_get_devdata(spi->master);
1042 + struct bcm2708_spi_state *state;
1046 + return -ESHUTDOWN;
1048 + if (!(spi->mode & SPI_NO_CS) &&
1049 + (spi->chip_select > spi->master->num_chipselect)) {
1050 + dev_dbg(&spi->dev,
1051 + "setup: invalid chipselect %u (%u defined)\n",
1052 + spi->chip_select, spi->master->num_chipselect);
1056 + state = spi->controller_state;
1058 + state = kzalloc(sizeof(*state), GFP_KERNEL);
1062 + spi->controller_state = state;
1065 + ret = bcm2708_setup_state(spi->master, &spi->dev, state,
1066 + spi->max_speed_hz, spi->chip_select, spi->mode,
1067 + spi->bits_per_word);
1070 + spi->controller_state = NULL;
1073 + dev_dbg(&spi->dev,
1074 + "setup: cd %d: %d Hz, bpw %u, mode 0x%x -> CS=%08x CDIV=%04x\n",
1075 + spi->chip_select, spi->max_speed_hz, spi->bits_per_word,
1076 + spi->mode, state->cs, state->cdiv);
1081 +static int bcm2708_spi_transfer(struct spi_device *spi, struct spi_message *msg)
1083 + struct bcm2708_spi *bs = spi_master_get_devdata(spi->master);
1084 + struct spi_transfer *xfer;
1086 + unsigned long flags;
1088 + if (unlikely(list_empty(&msg->transfers)))
1092 + return -ESHUTDOWN;
1094 + list_for_each_entry(xfer, &msg->transfers, transfer_list) {
1095 + if (!(xfer->tx_buf || xfer->rx_buf) && xfer->len) {
1096 + dev_dbg(&spi->dev, "missing rx or tx buf\n");
1100 + if (!xfer->bits_per_word || xfer->speed_hz)
1103 + ret = bcm2708_setup_state(spi->master, &spi->dev, NULL,
1104 + xfer->speed_hz ? xfer->speed_hz : spi->max_speed_hz,
1105 + spi->chip_select, spi->mode,
1106 + xfer->bits_per_word ? xfer->bits_per_word :
1107 + spi->bits_per_word);
1112 + msg->status = -EINPROGRESS;
1113 + msg->actual_length = 0;
1115 + spin_lock_irqsave(&bs->lock, flags);
1116 + list_add_tail(&msg->queue, &bs->queue);
1117 + queue_work(bs->workq, &bs->work);
1118 + spin_unlock_irqrestore(&bs->lock, flags);
1123 +static void bcm2708_spi_cleanup(struct spi_device *spi)
1125 + if (spi->controller_state) {
1126 + kfree(spi->controller_state);
1127 + spi->controller_state = NULL;
1131 +static int bcm2708_spi_probe(struct platform_device *pdev)
1133 + struct resource *regs;
1134 + int irq, err = -ENOMEM;
1136 + struct spi_master *master;
1137 + struct bcm2708_spi *bs;
1139 + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1141 + dev_err(&pdev->dev, "could not get IO memory\n");
1145 + irq = platform_get_irq(pdev, 0);
1147 + dev_err(&pdev->dev, "could not get IRQ\n");
1151 + clk = clk_get(&pdev->dev, NULL);
1152 + if (IS_ERR(clk)) {
1153 + dev_err(&pdev->dev, "could not find clk: %ld\n", PTR_ERR(clk));
1154 + return PTR_ERR(clk);
1157 + bcm2708_init_pinmode();
1159 + master = spi_alloc_master(&pdev->dev, sizeof(*bs));
1161 + dev_err(&pdev->dev, "spi_alloc_master() failed\n");
1165 + /* the spi->mode bits understood by this driver: */
1166 + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
1168 + master->bus_num = pdev->id;
1169 + master->num_chipselect = 3;
1170 + master->setup = bcm2708_spi_setup;
1171 + master->transfer = bcm2708_spi_transfer;
1172 + master->cleanup = bcm2708_spi_cleanup;
1173 + platform_set_drvdata(pdev, master);
1175 + bs = spi_master_get_devdata(master);
1177 + spin_lock_init(&bs->lock);
1178 + INIT_LIST_HEAD(&bs->queue);
1179 + init_completion(&bs->done);
1180 + INIT_WORK(&bs->work, bcm2708_work);
1182 + bs->base = ioremap(regs->start, resource_size(regs));
1184 + dev_err(&pdev->dev, "could not remap memory\n");
1185 + goto out_master_put;
1188 + bs->workq = create_singlethread_workqueue(dev_name(&pdev->dev));
1190 + dev_err(&pdev->dev, "could not create workqueue\n");
1196 + bs->stopping = false;
1198 + err = request_irq(irq, bcm2708_spi_interrupt, 0, dev_name(&pdev->dev),
1201 + dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
1202 + goto out_workqueue;
1205 + /* initialise the hardware */
1207 + bcm2708_wr(bs, SPI_CS, SPI_CS_REN | SPI_CS_CLEAR_RX | SPI_CS_CLEAR_TX);
1209 + err = spi_register_master(master);
1211 + dev_err(&pdev->dev, "could not register SPI master: %d\n", err);
1212 + goto out_free_irq;
1215 + dev_info(&pdev->dev, "SPI Controller at 0x%08lx (irq %d)\n",
1216 + (unsigned long)regs->start, irq);
1221 + free_irq(bs->irq, master);
1223 + destroy_workqueue(bs->workq);
1225 + iounmap(bs->base);
1227 + spi_master_put(master);
1233 +static int bcm2708_spi_remove(struct platform_device *pdev)
1235 + struct spi_master *master = platform_get_drvdata(pdev);
1236 + struct bcm2708_spi *bs = spi_master_get_devdata(master);
1238 + /* reset the hardware and block queue progress */
1239 + spin_lock_irq(&bs->lock);
1240 + bs->stopping = true;
1241 + bcm2708_wr(bs, SPI_CS, SPI_CS_CLEAR_RX | SPI_CS_CLEAR_TX);
1242 + spin_unlock_irq(&bs->lock);
1244 + flush_work_sync(&bs->work);
1246 + clk_disable(bs->clk);
1248 + free_irq(bs->irq, master);
1249 + iounmap(bs->base);
1251 + spi_unregister_master(master);
1256 +static struct platform_driver bcm2708_spi_driver = {
1259 + .owner = THIS_MODULE,
1261 + .probe = bcm2708_spi_probe,
1262 + .remove = bcm2708_spi_remove,
1266 +static int __init bcm2708_spi_init(void)
1268 + return platform_driver_probe(&bcm2708_spi_driver, bcm2708_spi_probe);
1270 +module_init(bcm2708_spi_init);
1272 +static void __exit bcm2708_spi_exit(void)
1274 + platform_driver_unregister(&bcm2708_spi_driver);
1276 +module_exit(bcm2708_spi_exit);
1279 +//module_platform_driver(bcm2708_spi_driver);
1281 +MODULE_DESCRIPTION("SPI controller driver for Broadcom BCM2708");
1282 +MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");
1283 +MODULE_LICENSE("GPL v2");
1284 +MODULE_ALIAS("platform:" DRV_NAME);