brcm2708: update against latest rpi-3.10.y branch
[openwrt/svn-archive/archive.git] / target / linux / brcm2708 / patches-3.10 / 0019-Backport-of-Chris-Boot-s-i2c-and-spi-drivers.patch
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.
5
6 ---
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
21
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
26 CONFIG_CRC_ITU_T=y
27 CONFIG_LIBCRC32C=y
28 +CONFIG_I2C=y
29 +CONFIG_I2C_BOARDINFO=y
30 +CONFIG_I2C_COMPAT=y
31 +CONFIG_I2C_CHARDEV=m
32 +CONFIG_I2C_HELPER_AUTO=y
33 +CONFIG_I2C_BCM2708=m
34 +CONFIG_SPI=y
35 +CONFIG_SPI_MASTER=y
36 +CONFIG_SPI_BCM2708=m
37 +
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
43 CONFIG_RAW_DRIVER=y
44 +CONFIG_I2C=y
45 +CONFIG_I2C_CHARDEV=m
46 +CONFIG_I2C_BCM2708=m
47 +CONFIG_SPI=y
48 +CONFIG_SPI_BCM2708=m
49 CONFIG_GPIO_SYSFS=y
50 # CONFIG_HWMON is not set
51 CONFIG_WATCHDOG=y
52 --- a/arch/arm/mach-bcm2708/Kconfig
53 +++ b/arch/arm/mach-bcm2708/Kconfig
54 @@ -31,4 +31,11 @@ config BCM2708_NOL2CACHE
55 help
56 Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt.
57
58 +config BCM2708_SPIDEV
59 + bool "Bind spidev to SPI0 master"
60 + depends on MACH_BCM2708
61 + depends on SPI
62 + default y
63 + help
64 + Binds spidev driver to the SPI0 master
65 endmenu
66 --- a/arch/arm/mach-bcm2708/bcm2708.c
67 +++ b/arch/arm/mach-bcm2708/bcm2708.c
68 @@ -31,6 +31,7 @@
69 #include <linux/cnt32_to_63.h>
70 #include <linux/io.h>
71 #include <linux/module.h>
72 +#include <linux/spi/spi.h>
73
74 #include <linux/version.h>
75 #include <linux/clkdev.h>
76 @@ -198,7 +199,6 @@ static struct clk osc_clk = {
77
78 /* warning - the USB needs a clock > 34MHz */
79
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 */
86 #endif
87 };
88 -#endif
89
90 static struct clk_lookup lookups[] = {
91 { /* UART0 */
92 @@ -216,6 +215,15 @@ static struct clk_lookup lookups[] = {
93 { /* USB */
94 .dev_id = "bcm2708_usb",
95 .clk = &osc_clk,
96 + }, { /* SPI */
97 + .dev_id = "bcm2708_spi.0",
98 + .clk = &sdhost_clk,
99 + }, { /* BSC0 */
100 + .dev_id = "bcm2708_i2c.0",
101 + .clk = &sdhost_clk,
102 + }, { /* BSC1 */
103 + .dev_id = "bcm2708_i2c.1",
104 + .clk = &sdhost_clk,
105 }
106 };
107
108 @@ -434,6 +442,89 @@ static struct platform_device bcm2708_al
109 },
110 };
111
112 +static struct resource bcm2708_spi_resources[] = {
113 + {
114 + .start = SPI0_BASE,
115 + .end = SPI0_BASE + SZ_256 - 1,
116 + .flags = IORESOURCE_MEM,
117 + }, {
118 + .start = IRQ_SPI,
119 + .end = IRQ_SPI,
120 + .flags = IORESOURCE_IRQ,
121 + }
122 +};
123 +
124 +
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",
128 + .id = 0,
129 + .num_resources = ARRAY_SIZE(bcm2708_spi_resources),
130 + .resource = bcm2708_spi_resources,
131 + .dev = {
132 + .dma_mask = &bcm2708_spi_dmamask,
133 + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON)},
134 +};
135 +
136 +#ifdef CONFIG_BCM2708_SPIDEV
137 +static struct spi_board_info bcm2708_spi_devices[] = {
138 +#ifdef CONFIG_SPI_SPIDEV
139 + {
140 + .modalias = "spidev",
141 + .max_speed_hz = 500000,
142 + .bus_num = 0,
143 + .chip_select = 0,
144 + .mode = SPI_MODE_0,
145 + }, {
146 + .modalias = "spidev",
147 + .max_speed_hz = 500000,
148 + .bus_num = 0,
149 + .chip_select = 1,
150 + .mode = SPI_MODE_0,
151 + }
152 +#endif
153 +};
154 +#endif
155 +
156 +static struct resource bcm2708_bsc0_resources[] = {
157 + {
158 + .start = BSC0_BASE,
159 + .end = BSC0_BASE + SZ_256 - 1,
160 + .flags = IORESOURCE_MEM,
161 + }, {
162 + .start = INTERRUPT_I2C,
163 + .end = INTERRUPT_I2C,
164 + .flags = IORESOURCE_IRQ,
165 + }
166 +};
167 +
168 +static struct platform_device bcm2708_bsc0_device = {
169 + .name = "bcm2708_i2c",
170 + .id = 0,
171 + .num_resources = ARRAY_SIZE(bcm2708_bsc0_resources),
172 + .resource = bcm2708_bsc0_resources,
173 +};
174 +
175 +
176 +static struct resource bcm2708_bsc1_resources[] = {
177 + {
178 + .start = BSC1_BASE,
179 + .end = BSC1_BASE + SZ_256 - 1,
180 + .flags = IORESOURCE_MEM,
181 + }, {
182 + .start = INTERRUPT_I2C,
183 + .end = INTERRUPT_I2C,
184 + .flags = IORESOURCE_IRQ,
185 + }
186 +};
187 +
188 +static struct platform_device bcm2708_bsc1_device = {
189 + .name = "bcm2708_i2c",
190 + .id = 1,
191 + .num_resources = ARRAY_SIZE(bcm2708_bsc1_resources),
192 + .resource = bcm2708_bsc1_resources,
193 +};
194 +
195 int __init bcm_register_device(struct platform_device *pdev)
196 {
197 int ret;
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]);
201
202 + bcm_register_device(&bcm2708_spi_device);
203 + bcm_register_device(&bcm2708_bsc0_device);
204 + bcm_register_device(&bcm2708_bsc1_device);
205 +
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);
209 }
210 system_rev = boardrev;
211 system_serial_low = serial;
212 +
213 +#ifdef CONFIG_BCM2708_SPIDEV
214 + spi_register_board_info(bcm2708_spi_devices,
215 + ARRAY_SIZE(bcm2708_spi_devices));
216 +#endif
217 }
218
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
222 @@ -63,9 +63,12 @@
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*/
234
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.
240
241 +config I2C_BCM2708
242 + tristate "BCM2708 BSC"
243 + depends on MACH_BCM2708
244 + help
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.
248 +
249 config I2C_BLACKFIN_TWI
250 tristate "Blackfin TWI I2C support"
251 depends on BLACKFIN
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
262 --- /dev/null
263 +++ b/drivers/i2c/busses/i2c-bcm2708.c
264 @@ -0,0 +1,396 @@
265 +/*
266 + * Driver for Broadcom BCM2708 BSC Controllers
267 + *
268 + * Copyright (C) 2012 Chris Boot & Frank Buss
269 + *
270 + * This driver is inspired by:
271 + * i2c-ocores.c, by Peter Korsgaard <jacmet@sunsite.dk>
272 + *
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.
277 + *
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.
282 + *
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.
286 + */
287 +
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>
300 +
301 +/* BSC register offsets */
302 +#define BSC_C 0x00
303 +#define BSC_S 0x04
304 +#define BSC_DLEN 0x08
305 +#define BSC_A 0x0c
306 +#define BSC_FIFO 0x10
307 +#define BSC_DIV 0x14
308 +#define BSC_DEL 0x18
309 +#define BSC_CLKT 0x1c
310 +
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
320 +
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
332 +
333 +#define I2C_CLOCK_HZ 100000 /* FIXME: get from DT */
334 +#define I2C_TIMEOUT_MS 150
335 +
336 +#define DRV_NAME "bcm2708_i2c"
337 +
338 +struct bcm2708_i2c {
339 + struct i2c_adapter adapter;
340 +
341 + spinlock_t lock;
342 + void __iomem *base;
343 + int irq;
344 + struct clk *clk;
345 +
346 + struct completion done;
347 +
348 + struct i2c_msg *msg;
349 + int pos;
350 + int nmsgs;
351 + bool error;
352 +};
353 +
354 +/*
355 + * This function sets the ALT mode on the I2C pins so that we can use them with
356 + * the BSC hardware.
357 + *
358 + * FIXME: This is a hack. Use pinmux / pinctrl.
359 + */
360 +static void bcm2708_i2c_init_pinmode(void)
361 +{
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))
364 +
365 + int pin;
366 + u32 *gpio = ioremap(0x20200000, SZ_16K);
367 +
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 */
372 + }
373 +
374 + iounmap(gpio);
375 +
376 +#undef INP_GPIO
377 +#undef SET_GPIO_ALT
378 +}
379 +
380 +static inline u32 bcm2708_rd(struct bcm2708_i2c *bi, unsigned reg)
381 +{
382 + return readl(bi->base + reg);
383 +}
384 +
385 +static inline void bcm2708_wr(struct bcm2708_i2c *bi, unsigned reg, u32 val)
386 +{
387 + writel(val, bi->base + reg);
388 +}
389 +
390 +static inline void bcm2708_bsc_reset(struct bcm2708_i2c *bi)
391 +{
392 + bcm2708_wr(bi, BSC_C, 0);
393 + bcm2708_wr(bi, BSC_S, BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE);
394 +}
395 +
396 +static inline void bcm2708_bsc_fifo_drain(struct bcm2708_i2c *bi)
397 +{
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);
400 +}
401 +
402 +static inline void bcm2708_bsc_fifo_fill(struct bcm2708_i2c *bi)
403 +{
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++]);
406 +}
407 +
408 +static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi)
409 +{
410 + unsigned long bus_hz;
411 + u32 cdiv;
412 + u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1;
413 +
414 + bus_hz = clk_get_rate(bi->clk);
415 + cdiv = bus_hz / I2C_CLOCK_HZ;
416 +
417 + if (bi->msg->flags & I2C_M_RD)
418 + c |= BSC_C_INTR | BSC_C_READ;
419 + else
420 + c |= BSC_C_INTT;
421 +
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);
426 +}
427 +
428 +static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id)
429 +{
430 + struct bcm2708_i2c *bi = dev_id;
431 + bool handled = true;
432 + u32 s;
433 +
434 + spin_lock(&bi->lock);
435 +
436 + s = bcm2708_rd(bi, BSC_S);
437 +
438 + if (s & (BSC_S_CLKT | BSC_S_ERR)) {
439 + bcm2708_bsc_reset(bi);
440 + bi->error = true;
441 +
442 + /* wake up our bh */
443 + complete(&bi->done);
444 + } else if (s & BSC_S_DONE) {
445 + bi->nmsgs--;
446 +
447 + if (bi->msg->flags & I2C_M_RD)
448 + bcm2708_bsc_fifo_drain(bi);
449 +
450 + bcm2708_bsc_reset(bi);
451 +
452 + if (bi->nmsgs) {
453 + /* advance to next message */
454 + bi->msg++;
455 + bi->pos = 0;
456 + bcm2708_bsc_setup(bi);
457 + } else {
458 + /* wake up our bh */
459 + complete(&bi->done);
460 + }
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);
465 + } else {
466 + handled = false;
467 + }
468 +
469 + spin_unlock(&bi->lock);
470 +
471 + return handled ? IRQ_HANDLED : IRQ_NONE;
472 +}
473 +
474 +static int bcm2708_i2c_master_xfer(struct i2c_adapter *adap,
475 + struct i2c_msg *msgs, int num)
476 +{
477 + struct bcm2708_i2c *bi = adap->algo_data;
478 + unsigned long flags;
479 + int ret;
480 +
481 + spin_lock_irqsave(&bi->lock, flags);
482 +
483 + INIT_COMPLETION(bi->done);
484 + bi->msg = msgs;
485 + bi->pos = 0;
486 + bi->nmsgs = num;
487 + bi->error = false;
488 +
489 + spin_unlock_irqrestore(&bi->lock, flags);
490 +
491 + bcm2708_bsc_setup(bi);
492 +
493 + ret = wait_for_completion_timeout(&bi->done,
494 + msecs_to_jiffies(I2C_TIMEOUT_MS));
495 + if (ret == 0) {
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);
500 + return -ETIMEDOUT;
501 + }
502 +
503 + return bi->error ? -EIO : num;
504 +}
505 +
506 +static u32 bcm2708_i2c_functionality(struct i2c_adapter *adap)
507 +{
508 + return I2C_FUNC_I2C | /*I2C_FUNC_10BIT_ADDR |*/ I2C_FUNC_SMBUS_EMUL;
509 +}
510 +
511 +static struct i2c_algorithm bcm2708_i2c_algorithm = {
512 + .master_xfer = bcm2708_i2c_master_xfer,
513 + .functionality = bcm2708_i2c_functionality,
514 +};
515 +
516 +static int bcm2708_i2c_probe(struct platform_device *pdev)
517 +{
518 + struct resource *regs;
519 + int irq, err = -ENOMEM;
520 + struct clk *clk;
521 + struct bcm2708_i2c *bi;
522 + struct i2c_adapter *adap;
523 +
524 + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
525 + if (!regs) {
526 + dev_err(&pdev->dev, "could not get IO memory\n");
527 + return -ENXIO;
528 + }
529 +
530 + irq = platform_get_irq(pdev, 0);
531 + if (irq < 0) {
532 + dev_err(&pdev->dev, "could not get IRQ\n");
533 + return irq;
534 + }
535 +
536 + clk = clk_get(&pdev->dev, NULL);
537 + if (IS_ERR(clk)) {
538 + dev_err(&pdev->dev, "could not find clk: %ld\n", PTR_ERR(clk));
539 + return PTR_ERR(clk);
540 + }
541 +
542 + bcm2708_i2c_init_pinmode();
543 +
544 + bi = kzalloc(sizeof(*bi), GFP_KERNEL);
545 + if (!bi)
546 + goto out_clk_put;
547 +
548 + platform_set_drvdata(pdev, bi);
549 +
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));
557 +
558 + switch (pdev->id) {
559 + case 0:
560 + adap->class = I2C_CLASS_HWMON;
561 + break;
562 + case 1:
563 + adap->class = I2C_CLASS_DDC;
564 + break;
565 + default:
566 + dev_err(&pdev->dev, "can only bind to BSC 0 or 1\n");
567 + err = -ENXIO;
568 + goto out_free_bi;
569 + }
570 +
571 + spin_lock_init(&bi->lock);
572 + init_completion(&bi->done);
573 +
574 + bi->base = ioremap(regs->start, resource_size(regs));
575 + if (!bi->base) {
576 + dev_err(&pdev->dev, "could not remap memory\n");
577 + goto out_free_bi;
578 + }
579 +
580 + bi->irq = irq;
581 + bi->clk = clk;
582 +
583 + err = request_irq(irq, bcm2708_i2c_interrupt, IRQF_SHARED,
584 + dev_name(&pdev->dev), bi);
585 + if (err) {
586 + dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
587 + goto out_iounmap;
588 + }
589 +
590 + bcm2708_bsc_reset(bi);
591 +
592 + err = i2c_add_numbered_adapter(adap);
593 + if (err < 0) {
594 + dev_err(&pdev->dev, "could not add I2C adapter: %d\n", err);
595 + goto out_free_irq;
596 + }
597 +
598 + dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d)\n",
599 + pdev->id, (unsigned long)regs->start, irq);
600 +
601 + return 0;
602 +
603 +out_free_irq:
604 + free_irq(bi->irq, bi);
605 +out_iounmap:
606 + iounmap(bi->base);
607 +out_free_bi:
608 + kfree(bi);
609 +out_clk_put:
610 + clk_put(clk);
611 + return err;
612 +}
613 +
614 +static int bcm2708_i2c_remove(struct platform_device *pdev)
615 +{
616 + struct bcm2708_i2c *bi = platform_get_drvdata(pdev);
617 +
618 + platform_set_drvdata(pdev, NULL);
619 +
620 + i2c_del_adapter(&bi->adapter);
621 + free_irq(bi->irq, bi);
622 + iounmap(bi->base);
623 + clk_disable(bi->clk);
624 + clk_put(bi->clk);
625 + kfree(bi);
626 +
627 + return 0;
628 +}
629 +
630 +static struct platform_driver bcm2708_i2c_driver = {
631 + .driver = {
632 + .name = DRV_NAME,
633 + .owner = THIS_MODULE,
634 + },
635 + .probe = bcm2708_i2c_probe,
636 + .remove = bcm2708_i2c_remove,
637 +};
638 +
639 +// module_platform_driver(bcm2708_i2c_driver);
640 +
641 +
642 +static int __init bcm2708_i2c_init(void)
643 +{
644 + return platform_driver_register(&bcm2708_i2c_driver);
645 +}
646 +
647 +static void __exit bcm2708_i2c_exit(void)
648 +{
649 + platform_driver_unregister(&bcm2708_i2c_driver);
650 +}
651 +
652 +module_init(bcm2708_i2c_init);
653 +module_exit(bcm2708_i2c_exit);
654 +
655 +
656 +
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
665 not supported.
666
667 +config SPI_BCM2708
668 + tristate "BCM2708 SPI controller driver (SPI0)"
669 + depends on MACH_BCM2708
670 + help
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
673 + device.
674 +
675 config SPI_BFIN5XX
676 tristate "SPI controller driver for ADI Blackfin5xx"
677 depends on BLACKFIN
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
688 --- /dev/null
689 +++ b/drivers/spi/spi-bcm2708.c
690 @@ -0,0 +1,594 @@
691 +/*
692 + * Driver for Broadcom BCM2708 SPI Controllers
693 + *
694 + * Copyright (C) 2012 Chris Boot
695 + *
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
699 + *
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.
704 + *
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.
709 + *
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.
713 + */
714 +
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>
728 +
729 +/* SPI register offsets */
730 +#define SPI_CS 0x00
731 +#define SPI_FIFO 0x04
732 +#define SPI_CLK 0x08
733 +#define SPI_DLEN 0x0c
734 +#define SPI_LTOH 0x10
735 +#define SPI_DC 0x14
736 +
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
762 +
763 +#define SPI_TIMEOUT_MS 150
764 +
765 +#define DRV_NAME "bcm2708_spi"
766 +
767 +struct bcm2708_spi {
768 + spinlock_t lock;
769 + void __iomem *base;
770 + int irq;
771 + struct clk *clk;
772 + bool stopping;
773 +
774 + struct list_head queue;
775 + struct workqueue_struct *workq;
776 + struct work_struct work;
777 + struct completion done;
778 +
779 + const u8 *tx_buf;
780 + u8 *rx_buf;
781 + int len;
782 +};
783 +
784 +struct bcm2708_spi_state {
785 + u32 cs;
786 + u16 cdiv;
787 +};
788 +
789 +/*
790 + * This function sets the ALT mode on the SPI pins so that we can use them with
791 + * the SPI hardware.
792 + *
793 + * FIXME: This is a hack. Use pinmux / pinctrl.
794 + */
795 +static void bcm2708_init_pinmode(void)
796 +{
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))
799 +
800 + int pin;
801 + u32 *gpio = ioremap(0x20200000, SZ_16K);
802 +
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 */
807 + }
808 +
809 + iounmap(gpio);
810 +
811 +#undef INP_GPIO
812 +#undef SET_GPIO_ALT
813 +}
814 +
815 +static inline u32 bcm2708_rd(struct bcm2708_spi *bs, unsigned reg)
816 +{
817 + return readl(bs->base + reg);
818 +}
819 +
820 +static inline void bcm2708_wr(struct bcm2708_spi *bs, unsigned reg, u32 val)
821 +{
822 + writel(val, bs->base + reg);
823 +}
824 +
825 +static inline void bcm2708_rd_fifo(struct bcm2708_spi *bs, int len)
826 +{
827 + u8 byte;
828 +
829 + while (len--) {
830 + byte = bcm2708_rd(bs, SPI_FIFO);
831 + if (bs->rx_buf)
832 + *bs->rx_buf++ = byte;
833 + }
834 +}
835 +
836 +static inline void bcm2708_wr_fifo(struct bcm2708_spi *bs, int len)
837 +{
838 + u8 byte;
839 +
840 + if (len > bs->len)
841 + len = bs->len;
842 +
843 + while (len--) {
844 + byte = bs->tx_buf ? *bs->tx_buf++ : 0;
845 + bcm2708_wr(bs, SPI_FIFO, byte);
846 + bs->len--;
847 + }
848 +}
849 +
850 +static irqreturn_t bcm2708_spi_interrupt(int irq, void *dev_id)
851 +{
852 + struct spi_master *master = dev_id;
853 + struct bcm2708_spi *bs = spi_master_get_devdata(master);
854 + u32 cs;
855 +
856 + spin_lock(&bs->lock);
857 +
858 + cs = bcm2708_rd(bs, SPI_CS);
859 +
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);
868 +
869 + /* drain RX FIFO */
870 + while (cs & SPI_CS_RXD) {
871 + bcm2708_rd_fifo(bs, 1);
872 + cs = bcm2708_rd(bs, SPI_CS);
873 + }
874 +
875 + /* wake up our bh */
876 + complete(&bs->done);
877 + }
878 + } else if (cs & SPI_CS_RXR) {
879 + /* read 12 bytes of data */
880 + bcm2708_rd_fifo(bs, 12);
881 +
882 + /* write up to 12 bytes */
883 + bcm2708_wr_fifo(bs, 12);
884 + }
885 +
886 + spin_unlock(&bs->lock);
887 +
888 + return IRQ_HANDLED;
889 +}
890 +
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)
894 +{
895 + struct bcm2708_spi *bs = spi_master_get_devdata(master);
896 + int cdiv;
897 + unsigned long bus_hz;
898 + u32 cs = 0;
899 +
900 + bus_hz = clk_get_rate(bs->clk);
901 +
902 + if (hz >= bus_hz) {
903 + cdiv = 2; /* bus_hz / 2 is as fast as we can go */
904 + } else if (hz) {
905 + cdiv = DIV_ROUND_UP(bus_hz, hz);
906 +
907 + /* CDIV must be a power of 2, so round up */
908 + cdiv = roundup_pow_of_two(cdiv);
909 +
910 + if (cdiv > 65536) {
911 + dev_dbg(dev,
912 + "setup: %d Hz too slow, cdiv %u; min %ld Hz\n",
913 + hz, cdiv, bus_hz / 65536);
914 + return -EINVAL;
915 + } else if (cdiv == 65536) {
916 + cdiv = 0;
917 + } else if (cdiv == 1) {
918 + cdiv = 2; /* 1 gets rounded down to 0; == 65536 */
919 + }
920 + } else {
921 + cdiv = 0;
922 + }
923 +
924 + switch (bpw) {
925 + case 8:
926 + break;
927 + default:
928 + dev_dbg(dev, "setup: invalid bits_per_word %u (must be 8)\n",
929 + bpw);
930 + return -EINVAL;
931 + }
932 +
933 + if (mode & SPI_CPOL)
934 + cs |= SPI_CS_CPOL;
935 + if (mode & SPI_CPHA)
936 + cs |= SPI_CS_CPHA;
937 +
938 + if (!(mode & SPI_NO_CS)) {
939 + if (mode & SPI_CS_HIGH) {
940 + cs |= SPI_CS_CSPOL;
941 + cs |= SPI_CS_CSPOL0 << csel;
942 + }
943 +
944 + cs |= csel;
945 + } else {
946 + cs |= SPI_CS_CS_10 | SPI_CS_CS_01;
947 + }
948 +
949 + if (state) {
950 + state->cs = cs;
951 + state->cdiv = cdiv;
952 + }
953 +
954 + return 0;
955 +}
956 +
957 +static int bcm2708_process_transfer(struct bcm2708_spi *bs,
958 + struct spi_message *msg, struct spi_transfer *xfer)
959 +{
960 + struct spi_device *spi = msg->spi;
961 + struct bcm2708_spi_state state, *stp;
962 + int ret;
963 + u32 cs;
964 +
965 + if (bs->stopping)
966 + return -ESHUTDOWN;
967 +
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);
972 + if (ret)
973 + return ret;
974 +
975 + stp = &state;
976 + } else {
977 + stp = spi->controller_state;
978 + }
979 +
980 + INIT_COMPLETION(bs->done);
981 + bs->tx_buf = xfer->tx_buf;
982 + bs->rx_buf = xfer->rx_buf;
983 + bs->len = xfer->len;
984 +
985 + cs = stp->cs | SPI_CS_INTR | SPI_CS_INTD | SPI_CS_TA;
986 +
987 + bcm2708_wr(bs, SPI_CLK, stp->cdiv);
988 + bcm2708_wr(bs, SPI_CS, cs);
989 +
990 + ret = wait_for_completion_timeout(&bs->done,
991 + msecs_to_jiffies(SPI_TIMEOUT_MS));
992 + if (ret == 0) {
993 + dev_err(&spi->dev, "transfer timed out\n");
994 + return -ETIMEDOUT;
995 + }
996 +
997 + if (xfer->delay_usecs)
998 + udelay(xfer->delay_usecs);
999 +
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);
1004 + }
1005 +
1006 + msg->actual_length += (xfer->len - bs->len);
1007 +
1008 + return 0;
1009 +}
1010 +
1011 +static void bcm2708_work(struct work_struct *work)
1012 +{
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;
1017 + int status = 0;
1018 +
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);
1024 +
1025 + list_for_each_entry(xfer, &msg->transfers, transfer_list) {
1026 + status = bcm2708_process_transfer(bs, msg, xfer);
1027 + if (status)
1028 + break;
1029 + }
1030 +
1031 + msg->status = status;
1032 + msg->complete(msg->context);
1033 +
1034 + spin_lock_irqsave(&bs->lock, flags);
1035 + }
1036 + spin_unlock_irqrestore(&bs->lock, flags);
1037 +}
1038 +
1039 +static int bcm2708_spi_setup(struct spi_device *spi)
1040 +{
1041 + struct bcm2708_spi *bs = spi_master_get_devdata(spi->master);
1042 + struct bcm2708_spi_state *state;
1043 + int ret;
1044 +
1045 + if (bs->stopping)
1046 + return -ESHUTDOWN;
1047 +
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);
1053 + return -EINVAL;
1054 + }
1055 +
1056 + state = spi->controller_state;
1057 + if (!state) {
1058 + state = kzalloc(sizeof(*state), GFP_KERNEL);
1059 + if (!state)
1060 + return -ENOMEM;
1061 +
1062 + spi->controller_state = state;
1063 + }
1064 +
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);
1068 + if (ret < 0) {
1069 + kfree(state);
1070 + spi->controller_state = NULL;
1071 + }
1072 +
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);
1077 +
1078 + return 0;
1079 +}
1080 +
1081 +static int bcm2708_spi_transfer(struct spi_device *spi, struct spi_message *msg)
1082 +{
1083 + struct bcm2708_spi *bs = spi_master_get_devdata(spi->master);
1084 + struct spi_transfer *xfer;
1085 + int ret;
1086 + unsigned long flags;
1087 +
1088 + if (unlikely(list_empty(&msg->transfers)))
1089 + return -EINVAL;
1090 +
1091 + if (bs->stopping)
1092 + return -ESHUTDOWN;
1093 +
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");
1097 + return -EINVAL;
1098 + }
1099 +
1100 + if (!xfer->bits_per_word || xfer->speed_hz)
1101 + continue;
1102 +
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);
1108 + if (ret)
1109 + return ret;
1110 + }
1111 +
1112 + msg->status = -EINPROGRESS;
1113 + msg->actual_length = 0;
1114 +
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);
1119 +
1120 + return 0;
1121 +}
1122 +
1123 +static void bcm2708_spi_cleanup(struct spi_device *spi)
1124 +{
1125 + if (spi->controller_state) {
1126 + kfree(spi->controller_state);
1127 + spi->controller_state = NULL;
1128 + }
1129 +}
1130 +
1131 +static int bcm2708_spi_probe(struct platform_device *pdev)
1132 +{
1133 + struct resource *regs;
1134 + int irq, err = -ENOMEM;
1135 + struct clk *clk;
1136 + struct spi_master *master;
1137 + struct bcm2708_spi *bs;
1138 +
1139 + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1140 + if (!regs) {
1141 + dev_err(&pdev->dev, "could not get IO memory\n");
1142 + return -ENXIO;
1143 + }
1144 +
1145 + irq = platform_get_irq(pdev, 0);
1146 + if (irq < 0) {
1147 + dev_err(&pdev->dev, "could not get IRQ\n");
1148 + return irq;
1149 + }
1150 +
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);
1155 + }
1156 +
1157 + bcm2708_init_pinmode();
1158 +
1159 + master = spi_alloc_master(&pdev->dev, sizeof(*bs));
1160 + if (!master) {
1161 + dev_err(&pdev->dev, "spi_alloc_master() failed\n");
1162 + goto out_clk_put;
1163 + }
1164 +
1165 + /* the spi->mode bits understood by this driver: */
1166 + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
1167 +
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);
1174 +
1175 + bs = spi_master_get_devdata(master);
1176 +
1177 + spin_lock_init(&bs->lock);
1178 + INIT_LIST_HEAD(&bs->queue);
1179 + init_completion(&bs->done);
1180 + INIT_WORK(&bs->work, bcm2708_work);
1181 +
1182 + bs->base = ioremap(regs->start, resource_size(regs));
1183 + if (!bs->base) {
1184 + dev_err(&pdev->dev, "could not remap memory\n");
1185 + goto out_master_put;
1186 + }
1187 +
1188 + bs->workq = create_singlethread_workqueue(dev_name(&pdev->dev));
1189 + if (!bs->workq) {
1190 + dev_err(&pdev->dev, "could not create workqueue\n");
1191 + goto out_iounmap;
1192 + }
1193 +
1194 + bs->irq = irq;
1195 + bs->clk = clk;
1196 + bs->stopping = false;
1197 +
1198 + err = request_irq(irq, bcm2708_spi_interrupt, 0, dev_name(&pdev->dev),
1199 + master);
1200 + if (err) {
1201 + dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
1202 + goto out_workqueue;
1203 + }
1204 +
1205 + /* initialise the hardware */
1206 + clk_enable(clk);
1207 + bcm2708_wr(bs, SPI_CS, SPI_CS_REN | SPI_CS_CLEAR_RX | SPI_CS_CLEAR_TX);
1208 +
1209 + err = spi_register_master(master);
1210 + if (err) {
1211 + dev_err(&pdev->dev, "could not register SPI master: %d\n", err);
1212 + goto out_free_irq;
1213 + }
1214 +
1215 + dev_info(&pdev->dev, "SPI Controller at 0x%08lx (irq %d)\n",
1216 + (unsigned long)regs->start, irq);
1217 +
1218 + return 0;
1219 +
1220 +out_free_irq:
1221 + free_irq(bs->irq, master);
1222 +out_workqueue:
1223 + destroy_workqueue(bs->workq);
1224 +out_iounmap:
1225 + iounmap(bs->base);
1226 +out_master_put:
1227 + spi_master_put(master);
1228 +out_clk_put:
1229 + clk_put(clk);
1230 + return err;
1231 +}
1232 +
1233 +static int bcm2708_spi_remove(struct platform_device *pdev)
1234 +{
1235 + struct spi_master *master = platform_get_drvdata(pdev);
1236 + struct bcm2708_spi *bs = spi_master_get_devdata(master);
1237 +
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);
1243 +
1244 + flush_work_sync(&bs->work);
1245 +
1246 + clk_disable(bs->clk);
1247 + clk_put(bs->clk);
1248 + free_irq(bs->irq, master);
1249 + iounmap(bs->base);
1250 +
1251 + spi_unregister_master(master);
1252 +
1253 + return 0;
1254 +}
1255 +
1256 +static struct platform_driver bcm2708_spi_driver = {
1257 + .driver = {
1258 + .name = DRV_NAME,
1259 + .owner = THIS_MODULE,
1260 + },
1261 + .probe = bcm2708_spi_probe,
1262 + .remove = bcm2708_spi_remove,
1263 +};
1264 +
1265 +
1266 +static int __init bcm2708_spi_init(void)
1267 +{
1268 + return platform_driver_probe(&bcm2708_spi_driver, bcm2708_spi_probe);
1269 +}
1270 +module_init(bcm2708_spi_init);
1271 +
1272 +static void __exit bcm2708_spi_exit(void)
1273 +{
1274 + platform_driver_unregister(&bcm2708_spi_driver);
1275 +}
1276 +module_exit(bcm2708_spi_exit);
1277 +
1278 +
1279 +//module_platform_driver(bcm2708_spi_driver);
1280 +
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);