brcm2708: update 3.10 patches with raspberrypi/rpi-3.10.y of 27 Apr. 2014
[openwrt/openwrt.git] / target / linux / brcm2708 / patches-3.10 / 0019-Backport-of-Chris-Boot-s-i2c-and-spi-drivers.patch
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.
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 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
28 CONFIG_CRC_ITU_T=y
29 CONFIG_LIBCRC32C=y
30 +CONFIG_I2C=y
31 +CONFIG_I2C_BOARDINFO=y
32 +CONFIG_I2C_COMPAT=y
33 +CONFIG_I2C_CHARDEV=m
34 +CONFIG_I2C_HELPER_AUTO=y
35 +CONFIG_I2C_BCM2708=m
36 +CONFIG_SPI=y
37 +CONFIG_SPI_MASTER=y
38 +CONFIG_SPI_BCM2708=m
39 +
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
47 CONFIG_RAW_DRIVER=y
48 +CONFIG_I2C=y
49 +CONFIG_I2C_CHARDEV=m
50 +CONFIG_I2C_BCM2708=m
51 +CONFIG_SPI=y
52 +CONFIG_SPI_BCM2708=m
53 CONFIG_GPIO_SYSFS=y
54 # CONFIG_HWMON is not set
55 CONFIG_WATCHDOG=y
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
61 help
62 Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt.
63
64 +config BCM2708_SPIDEV
65 + bool "Bind spidev to SPI0 master"
66 + depends on MACH_BCM2708
67 + depends on SPI
68 + default y
69 + help
70 + Binds spidev driver to the SPI0 master
71 endmenu
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
76 @@ -31,6 +31,7 @@
77 #include <linux/cnt32_to_63.h>
78 #include <linux/io.h>
79 #include <linux/module.h>
80 +#include <linux/spi/spi.h>
81
82 #include <linux/version.h>
83 #include <linux/clkdev.h>
84 @@ -198,7 +199,6 @@ static struct clk osc_clk = {
85
86 /* warning - the USB needs a clock > 34MHz */
87
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 */
94 #endif
95 };
96 -#endif
97
98 static struct clk_lookup lookups[] = {
99 { /* UART0 */
100 @@ -216,6 +215,15 @@ static struct clk_lookup lookups[] = {
101 { /* USB */
102 .dev_id = "bcm2708_usb",
103 .clk = &osc_clk,
104 + }, { /* SPI */
105 + .dev_id = "bcm2708_spi.0",
106 + .clk = &sdhost_clk,
107 + }, { /* BSC0 */
108 + .dev_id = "bcm2708_i2c.0",
109 + .clk = &sdhost_clk,
110 + }, { /* BSC1 */
111 + .dev_id = "bcm2708_i2c.1",
112 + .clk = &sdhost_clk,
113 }
114 };
115
116 @@ -434,6 +442,89 @@ static struct platform_device bcm2708_alsa_devices[] = {
117 },
118 };
119
120 +static struct resource bcm2708_spi_resources[] = {
121 + {
122 + .start = SPI0_BASE,
123 + .end = SPI0_BASE + SZ_256 - 1,
124 + .flags = IORESOURCE_MEM,
125 + }, {
126 + .start = IRQ_SPI,
127 + .end = IRQ_SPI,
128 + .flags = IORESOURCE_IRQ,
129 + }
130 +};
131 +
132 +
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",
136 + .id = 0,
137 + .num_resources = ARRAY_SIZE(bcm2708_spi_resources),
138 + .resource = bcm2708_spi_resources,
139 + .dev = {
140 + .dma_mask = &bcm2708_spi_dmamask,
141 + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON)},
142 +};
143 +
144 +#ifdef CONFIG_BCM2708_SPIDEV
145 +static struct spi_board_info bcm2708_spi_devices[] = {
146 +#ifdef CONFIG_SPI_SPIDEV
147 + {
148 + .modalias = "spidev",
149 + .max_speed_hz = 500000,
150 + .bus_num = 0,
151 + .chip_select = 0,
152 + .mode = SPI_MODE_0,
153 + }, {
154 + .modalias = "spidev",
155 + .max_speed_hz = 500000,
156 + .bus_num = 0,
157 + .chip_select = 1,
158 + .mode = SPI_MODE_0,
159 + }
160 +#endif
161 +};
162 +#endif
163 +
164 +static struct resource bcm2708_bsc0_resources[] = {
165 + {
166 + .start = BSC0_BASE,
167 + .end = BSC0_BASE + SZ_256 - 1,
168 + .flags = IORESOURCE_MEM,
169 + }, {
170 + .start = INTERRUPT_I2C,
171 + .end = INTERRUPT_I2C,
172 + .flags = IORESOURCE_IRQ,
173 + }
174 +};
175 +
176 +static struct platform_device bcm2708_bsc0_device = {
177 + .name = "bcm2708_i2c",
178 + .id = 0,
179 + .num_resources = ARRAY_SIZE(bcm2708_bsc0_resources),
180 + .resource = bcm2708_bsc0_resources,
181 +};
182 +
183 +
184 +static struct resource bcm2708_bsc1_resources[] = {
185 + {
186 + .start = BSC1_BASE,
187 + .end = BSC1_BASE + SZ_256 - 1,
188 + .flags = IORESOURCE_MEM,
189 + }, {
190 + .start = INTERRUPT_I2C,
191 + .end = INTERRUPT_I2C,
192 + .flags = IORESOURCE_IRQ,
193 + }
194 +};
195 +
196 +static struct platform_device bcm2708_bsc1_device = {
197 + .name = "bcm2708_i2c",
198 + .id = 1,
199 + .num_resources = ARRAY_SIZE(bcm2708_bsc1_resources),
200 + .resource = bcm2708_bsc1_resources,
201 +};
202 +
203 int __init bcm_register_device(struct platform_device *pdev)
204 {
205 int ret;
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]);
209
210 + bcm_register_device(&bcm2708_spi_device);
211 + bcm_register_device(&bcm2708_bsc0_device);
212 + bcm_register_device(&bcm2708_bsc1_device);
213 +
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);
217 }
218 system_rev = boardrev;
219 system_serial_low = serial;
220 +
221 +#ifdef CONFIG_BCM2708_SPIDEV
222 + spi_register_board_info(bcm2708_spi_devices,
223 + ARRAY_SIZE(bcm2708_spi_devices));
224 +#endif
225 }
226
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
232 @@ -63,9 +63,12 @@
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*/
244
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.
252
253 +config I2C_BCM2708
254 + tristate "BCM2708 BSC"
255 + depends on MACH_BCM2708
256 + help
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.
260 +
261 config I2C_BLACKFIN_TWI
262 tristate "Blackfin TWI I2C support"
263 depends on BLACKFIN
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
277 new file mode 100644
278 index 0000000..7cae615
279 --- /dev/null
280 +++ b/drivers/i2c/busses/i2c-bcm2708.c
281 @@ -0,0 +1,396 @@
282 +/*
283 + * Driver for Broadcom BCM2708 BSC Controllers
284 + *
285 + * Copyright (C) 2012 Chris Boot & Frank Buss
286 + *
287 + * This driver is inspired by:
288 + * i2c-ocores.c, by Peter Korsgaard <jacmet@sunsite.dk>
289 + *
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.
294 + *
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.
299 + *
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.
303 + */
304 +
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>
317 +
318 +/* BSC register offsets */
319 +#define BSC_C 0x00
320 +#define BSC_S 0x04
321 +#define BSC_DLEN 0x08
322 +#define BSC_A 0x0c
323 +#define BSC_FIFO 0x10
324 +#define BSC_DIV 0x14
325 +#define BSC_DEL 0x18
326 +#define BSC_CLKT 0x1c
327 +
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
337 +
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
349 +
350 +#define I2C_CLOCK_HZ 100000 /* FIXME: get from DT */
351 +#define I2C_TIMEOUT_MS 150
352 +
353 +#define DRV_NAME "bcm2708_i2c"
354 +
355 +struct bcm2708_i2c {
356 + struct i2c_adapter adapter;
357 +
358 + spinlock_t lock;
359 + void __iomem *base;
360 + int irq;
361 + struct clk *clk;
362 +
363 + struct completion done;
364 +
365 + struct i2c_msg *msg;
366 + int pos;
367 + int nmsgs;
368 + bool error;
369 +};
370 +
371 +/*
372 + * This function sets the ALT mode on the I2C pins so that we can use them with
373 + * the BSC hardware.
374 + *
375 + * FIXME: This is a hack. Use pinmux / pinctrl.
376 + */
377 +static void bcm2708_i2c_init_pinmode(void)
378 +{
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))
381 +
382 + int pin;
383 + u32 *gpio = ioremap(0x20200000, SZ_16K);
384 +
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 */
389 + }
390 +
391 + iounmap(gpio);
392 +
393 +#undef INP_GPIO
394 +#undef SET_GPIO_ALT
395 +}
396 +
397 +static inline u32 bcm2708_rd(struct bcm2708_i2c *bi, unsigned reg)
398 +{
399 + return readl(bi->base + reg);
400 +}
401 +
402 +static inline void bcm2708_wr(struct bcm2708_i2c *bi, unsigned reg, u32 val)
403 +{
404 + writel(val, bi->base + reg);
405 +}
406 +
407 +static inline void bcm2708_bsc_reset(struct bcm2708_i2c *bi)
408 +{
409 + bcm2708_wr(bi, BSC_C, 0);
410 + bcm2708_wr(bi, BSC_S, BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE);
411 +}
412 +
413 +static inline void bcm2708_bsc_fifo_drain(struct bcm2708_i2c *bi)
414 +{
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);
417 +}
418 +
419 +static inline void bcm2708_bsc_fifo_fill(struct bcm2708_i2c *bi)
420 +{
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++]);
423 +}
424 +
425 +static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi)
426 +{
427 + unsigned long bus_hz;
428 + u32 cdiv;
429 + u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1;
430 +
431 + bus_hz = clk_get_rate(bi->clk);
432 + cdiv = bus_hz / I2C_CLOCK_HZ;
433 +
434 + if (bi->msg->flags & I2C_M_RD)
435 + c |= BSC_C_INTR | BSC_C_READ;
436 + else
437 + c |= BSC_C_INTT;
438 +
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);
443 +}
444 +
445 +static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id)
446 +{
447 + struct bcm2708_i2c *bi = dev_id;
448 + bool handled = true;
449 + u32 s;
450 +
451 + spin_lock(&bi->lock);
452 +
453 + s = bcm2708_rd(bi, BSC_S);
454 +
455 + if (s & (BSC_S_CLKT | BSC_S_ERR)) {
456 + bcm2708_bsc_reset(bi);
457 + bi->error = true;
458 +
459 + /* wake up our bh */
460 + complete(&bi->done);
461 + } else if (s & BSC_S_DONE) {
462 + bi->nmsgs--;
463 +
464 + if (bi->msg->flags & I2C_M_RD)
465 + bcm2708_bsc_fifo_drain(bi);
466 +
467 + bcm2708_bsc_reset(bi);
468 +
469 + if (bi->nmsgs) {
470 + /* advance to next message */
471 + bi->msg++;
472 + bi->pos = 0;
473 + bcm2708_bsc_setup(bi);
474 + } else {
475 + /* wake up our bh */
476 + complete(&bi->done);
477 + }
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);
482 + } else {
483 + handled = false;
484 + }
485 +
486 + spin_unlock(&bi->lock);
487 +
488 + return handled ? IRQ_HANDLED : IRQ_NONE;
489 +}
490 +
491 +static int bcm2708_i2c_master_xfer(struct i2c_adapter *adap,
492 + struct i2c_msg *msgs, int num)
493 +{
494 + struct bcm2708_i2c *bi = adap->algo_data;
495 + unsigned long flags;
496 + int ret;
497 +
498 + spin_lock_irqsave(&bi->lock, flags);
499 +
500 + INIT_COMPLETION(bi->done);
501 + bi->msg = msgs;
502 + bi->pos = 0;
503 + bi->nmsgs = num;
504 + bi->error = false;
505 +
506 + spin_unlock_irqrestore(&bi->lock, flags);
507 +
508 + bcm2708_bsc_setup(bi);
509 +
510 + ret = wait_for_completion_timeout(&bi->done,
511 + msecs_to_jiffies(I2C_TIMEOUT_MS));
512 + if (ret == 0) {
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);
517 + return -ETIMEDOUT;
518 + }
519 +
520 + return bi->error ? -EIO : num;
521 +}
522 +
523 +static u32 bcm2708_i2c_functionality(struct i2c_adapter *adap)
524 +{
525 + return I2C_FUNC_I2C | /*I2C_FUNC_10BIT_ADDR |*/ I2C_FUNC_SMBUS_EMUL;
526 +}
527 +
528 +static struct i2c_algorithm bcm2708_i2c_algorithm = {
529 + .master_xfer = bcm2708_i2c_master_xfer,
530 + .functionality = bcm2708_i2c_functionality,
531 +};
532 +
533 +static int bcm2708_i2c_probe(struct platform_device *pdev)
534 +{
535 + struct resource *regs;
536 + int irq, err = -ENOMEM;
537 + struct clk *clk;
538 + struct bcm2708_i2c *bi;
539 + struct i2c_adapter *adap;
540 +
541 + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
542 + if (!regs) {
543 + dev_err(&pdev->dev, "could not get IO memory\n");
544 + return -ENXIO;
545 + }
546 +
547 + irq = platform_get_irq(pdev, 0);
548 + if (irq < 0) {
549 + dev_err(&pdev->dev, "could not get IRQ\n");
550 + return irq;
551 + }
552 +
553 + clk = clk_get(&pdev->dev, NULL);
554 + if (IS_ERR(clk)) {
555 + dev_err(&pdev->dev, "could not find clk: %ld\n", PTR_ERR(clk));
556 + return PTR_ERR(clk);
557 + }
558 +
559 + bcm2708_i2c_init_pinmode();
560 +
561 + bi = kzalloc(sizeof(*bi), GFP_KERNEL);
562 + if (!bi)
563 + goto out_clk_put;
564 +
565 + platform_set_drvdata(pdev, bi);
566 +
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));
574 +
575 + switch (pdev->id) {
576 + case 0:
577 + adap->class = I2C_CLASS_HWMON;
578 + break;
579 + case 1:
580 + adap->class = I2C_CLASS_DDC;
581 + break;
582 + default:
583 + dev_err(&pdev->dev, "can only bind to BSC 0 or 1\n");
584 + err = -ENXIO;
585 + goto out_free_bi;
586 + }
587 +
588 + spin_lock_init(&bi->lock);
589 + init_completion(&bi->done);
590 +
591 + bi->base = ioremap(regs->start, resource_size(regs));
592 + if (!bi->base) {
593 + dev_err(&pdev->dev, "could not remap memory\n");
594 + goto out_free_bi;
595 + }
596 +
597 + bi->irq = irq;
598 + bi->clk = clk;
599 +
600 + err = request_irq(irq, bcm2708_i2c_interrupt, IRQF_SHARED,
601 + dev_name(&pdev->dev), bi);
602 + if (err) {
603 + dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
604 + goto out_iounmap;
605 + }
606 +
607 + bcm2708_bsc_reset(bi);
608 +
609 + err = i2c_add_numbered_adapter(adap);
610 + if (err < 0) {
611 + dev_err(&pdev->dev, "could not add I2C adapter: %d\n", err);
612 + goto out_free_irq;
613 + }
614 +
615 + dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d)\n",
616 + pdev->id, (unsigned long)regs->start, irq);
617 +
618 + return 0;
619 +
620 +out_free_irq:
621 + free_irq(bi->irq, bi);
622 +out_iounmap:
623 + iounmap(bi->base);
624 +out_free_bi:
625 + kfree(bi);
626 +out_clk_put:
627 + clk_put(clk);
628 + return err;
629 +}
630 +
631 +static int bcm2708_i2c_remove(struct platform_device *pdev)
632 +{
633 + struct bcm2708_i2c *bi = platform_get_drvdata(pdev);
634 +
635 + platform_set_drvdata(pdev, NULL);
636 +
637 + i2c_del_adapter(&bi->adapter);
638 + free_irq(bi->irq, bi);
639 + iounmap(bi->base);
640 + clk_disable(bi->clk);
641 + clk_put(bi->clk);
642 + kfree(bi);
643 +
644 + return 0;
645 +}
646 +
647 +static struct platform_driver bcm2708_i2c_driver = {
648 + .driver = {
649 + .name = DRV_NAME,
650 + .owner = THIS_MODULE,
651 + },
652 + .probe = bcm2708_i2c_probe,
653 + .remove = bcm2708_i2c_remove,
654 +};
655 +
656 +// module_platform_driver(bcm2708_i2c_driver);
657 +
658 +
659 +static int __init bcm2708_i2c_init(void)
660 +{
661 + return platform_driver_register(&bcm2708_i2c_driver);
662 +}
663 +
664 +static void __exit bcm2708_i2c_exit(void)
665 +{
666 + platform_driver_unregister(&bcm2708_i2c_driver);
667 +}
668 +
669 +module_init(bcm2708_i2c_init);
670 +module_exit(bcm2708_i2c_exit);
671 +
672 +
673 +
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
684 not supported.
685
686 +config SPI_BCM2708
687 + tristate "BCM2708 SPI controller driver (SPI0)"
688 + depends on MACH_BCM2708
689 + help
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
692 + device.
693 +
694 config SPI_BFIN5XX
695 tristate "SPI controller driver for ADI Blackfin5xx"
696 depends on BLACKFIN
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
710 new file mode 100644
711 index 0000000..9f1580e
712 --- /dev/null
713 +++ b/drivers/spi/spi-bcm2708.c
714 @@ -0,0 +1,594 @@
715 +/*
716 + * Driver for Broadcom BCM2708 SPI Controllers
717 + *
718 + * Copyright (C) 2012 Chris Boot
719 + *
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
723 + *
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.
728 + *
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.
733 + *
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.
737 + */
738 +
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>
752 +
753 +/* SPI register offsets */
754 +#define SPI_CS 0x00
755 +#define SPI_FIFO 0x04
756 +#define SPI_CLK 0x08
757 +#define SPI_DLEN 0x0c
758 +#define SPI_LTOH 0x10
759 +#define SPI_DC 0x14
760 +
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
786 +
787 +#define SPI_TIMEOUT_MS 150
788 +
789 +#define DRV_NAME "bcm2708_spi"
790 +
791 +struct bcm2708_spi {
792 + spinlock_t lock;
793 + void __iomem *base;
794 + int irq;
795 + struct clk *clk;
796 + bool stopping;
797 +
798 + struct list_head queue;
799 + struct workqueue_struct *workq;
800 + struct work_struct work;
801 + struct completion done;
802 +
803 + const u8 *tx_buf;
804 + u8 *rx_buf;
805 + int len;
806 +};
807 +
808 +struct bcm2708_spi_state {
809 + u32 cs;
810 + u16 cdiv;
811 +};
812 +
813 +/*
814 + * This function sets the ALT mode on the SPI pins so that we can use them with
815 + * the SPI hardware.
816 + *
817 + * FIXME: This is a hack. Use pinmux / pinctrl.
818 + */
819 +static void bcm2708_init_pinmode(void)
820 +{
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))
823 +
824 + int pin;
825 + u32 *gpio = ioremap(0x20200000, SZ_16K);
826 +
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 */
831 + }
832 +
833 + iounmap(gpio);
834 +
835 +#undef INP_GPIO
836 +#undef SET_GPIO_ALT
837 +}
838 +
839 +static inline u32 bcm2708_rd(struct bcm2708_spi *bs, unsigned reg)
840 +{
841 + return readl(bs->base + reg);
842 +}
843 +
844 +static inline void bcm2708_wr(struct bcm2708_spi *bs, unsigned reg, u32 val)
845 +{
846 + writel(val, bs->base + reg);
847 +}
848 +
849 +static inline void bcm2708_rd_fifo(struct bcm2708_spi *bs, int len)
850 +{
851 + u8 byte;
852 +
853 + while (len--) {
854 + byte = bcm2708_rd(bs, SPI_FIFO);
855 + if (bs->rx_buf)
856 + *bs->rx_buf++ = byte;
857 + }
858 +}
859 +
860 +static inline void bcm2708_wr_fifo(struct bcm2708_spi *bs, int len)
861 +{
862 + u8 byte;
863 +
864 + if (len > bs->len)
865 + len = bs->len;
866 +
867 + while (len--) {
868 + byte = bs->tx_buf ? *bs->tx_buf++ : 0;
869 + bcm2708_wr(bs, SPI_FIFO, byte);
870 + bs->len--;
871 + }
872 +}
873 +
874 +static irqreturn_t bcm2708_spi_interrupt(int irq, void *dev_id)
875 +{
876 + struct spi_master *master = dev_id;
877 + struct bcm2708_spi *bs = spi_master_get_devdata(master);
878 + u32 cs;
879 +
880 + spin_lock(&bs->lock);
881 +
882 + cs = bcm2708_rd(bs, SPI_CS);
883 +
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);
892 +
893 + /* drain RX FIFO */
894 + while (cs & SPI_CS_RXD) {
895 + bcm2708_rd_fifo(bs, 1);
896 + cs = bcm2708_rd(bs, SPI_CS);
897 + }
898 +
899 + /* wake up our bh */
900 + complete(&bs->done);
901 + }
902 + } else if (cs & SPI_CS_RXR) {
903 + /* read 12 bytes of data */
904 + bcm2708_rd_fifo(bs, 12);
905 +
906 + /* write up to 12 bytes */
907 + bcm2708_wr_fifo(bs, 12);
908 + }
909 +
910 + spin_unlock(&bs->lock);
911 +
912 + return IRQ_HANDLED;
913 +}
914 +
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)
918 +{
919 + struct bcm2708_spi *bs = spi_master_get_devdata(master);
920 + int cdiv;
921 + unsigned long bus_hz;
922 + u32 cs = 0;
923 +
924 + bus_hz = clk_get_rate(bs->clk);
925 +
926 + if (hz >= bus_hz) {
927 + cdiv = 2; /* bus_hz / 2 is as fast as we can go */
928 + } else if (hz) {
929 + cdiv = DIV_ROUND_UP(bus_hz, hz);
930 +
931 + /* CDIV must be a power of 2, so round up */
932 + cdiv = roundup_pow_of_two(cdiv);
933 +
934 + if (cdiv > 65536) {
935 + dev_dbg(dev,
936 + "setup: %d Hz too slow, cdiv %u; min %ld Hz\n",
937 + hz, cdiv, bus_hz / 65536);
938 + return -EINVAL;
939 + } else if (cdiv == 65536) {
940 + cdiv = 0;
941 + } else if (cdiv == 1) {
942 + cdiv = 2; /* 1 gets rounded down to 0; == 65536 */
943 + }
944 + } else {
945 + cdiv = 0;
946 + }
947 +
948 + switch (bpw) {
949 + case 8:
950 + break;
951 + default:
952 + dev_dbg(dev, "setup: invalid bits_per_word %u (must be 8)\n",
953 + bpw);
954 + return -EINVAL;
955 + }
956 +
957 + if (mode & SPI_CPOL)
958 + cs |= SPI_CS_CPOL;
959 + if (mode & SPI_CPHA)
960 + cs |= SPI_CS_CPHA;
961 +
962 + if (!(mode & SPI_NO_CS)) {
963 + if (mode & SPI_CS_HIGH) {
964 + cs |= SPI_CS_CSPOL;
965 + cs |= SPI_CS_CSPOL0 << csel;
966 + }
967 +
968 + cs |= csel;
969 + } else {
970 + cs |= SPI_CS_CS_10 | SPI_CS_CS_01;
971 + }
972 +
973 + if (state) {
974 + state->cs = cs;
975 + state->cdiv = cdiv;
976 + }
977 +
978 + return 0;
979 +}
980 +
981 +static int bcm2708_process_transfer(struct bcm2708_spi *bs,
982 + struct spi_message *msg, struct spi_transfer *xfer)
983 +{
984 + struct spi_device *spi = msg->spi;
985 + struct bcm2708_spi_state state, *stp;
986 + int ret;
987 + u32 cs;
988 +
989 + if (bs->stopping)
990 + return -ESHUTDOWN;
991 +
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);
996 + if (ret)
997 + return ret;
998 +
999 + stp = &state;
1000 + } else {
1001 + stp = spi->controller_state;
1002 + }
1003 +
1004 + INIT_COMPLETION(bs->done);
1005 + bs->tx_buf = xfer->tx_buf;
1006 + bs->rx_buf = xfer->rx_buf;
1007 + bs->len = xfer->len;
1008 +
1009 + cs = stp->cs | SPI_CS_INTR | SPI_CS_INTD | SPI_CS_TA;
1010 +
1011 + bcm2708_wr(bs, SPI_CLK, stp->cdiv);
1012 + bcm2708_wr(bs, SPI_CS, cs);
1013 +
1014 + ret = wait_for_completion_timeout(&bs->done,
1015 + msecs_to_jiffies(SPI_TIMEOUT_MS));
1016 + if (ret == 0) {
1017 + dev_err(&spi->dev, "transfer timed out\n");
1018 + return -ETIMEDOUT;
1019 + }
1020 +
1021 + if (xfer->delay_usecs)
1022 + udelay(xfer->delay_usecs);
1023 +
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);
1028 + }
1029 +
1030 + msg->actual_length += (xfer->len - bs->len);
1031 +
1032 + return 0;
1033 +}
1034 +
1035 +static void bcm2708_work(struct work_struct *work)
1036 +{
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;
1041 + int status = 0;
1042 +
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);
1048 +
1049 + list_for_each_entry(xfer, &msg->transfers, transfer_list) {
1050 + status = bcm2708_process_transfer(bs, msg, xfer);
1051 + if (status)
1052 + break;
1053 + }
1054 +
1055 + msg->status = status;
1056 + msg->complete(msg->context);
1057 +
1058 + spin_lock_irqsave(&bs->lock, flags);
1059 + }
1060 + spin_unlock_irqrestore(&bs->lock, flags);
1061 +}
1062 +
1063 +static int bcm2708_spi_setup(struct spi_device *spi)
1064 +{
1065 + struct bcm2708_spi *bs = spi_master_get_devdata(spi->master);
1066 + struct bcm2708_spi_state *state;
1067 + int ret;
1068 +
1069 + if (bs->stopping)
1070 + return -ESHUTDOWN;
1071 +
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);
1077 + return -EINVAL;
1078 + }
1079 +
1080 + state = spi->controller_state;
1081 + if (!state) {
1082 + state = kzalloc(sizeof(*state), GFP_KERNEL);
1083 + if (!state)
1084 + return -ENOMEM;
1085 +
1086 + spi->controller_state = state;
1087 + }
1088 +
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);
1092 + if (ret < 0) {
1093 + kfree(state);
1094 + spi->controller_state = NULL;
1095 + }
1096 +
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);
1101 +
1102 + return 0;
1103 +}
1104 +
1105 +static int bcm2708_spi_transfer(struct spi_device *spi, struct spi_message *msg)
1106 +{
1107 + struct bcm2708_spi *bs = spi_master_get_devdata(spi->master);
1108 + struct spi_transfer *xfer;
1109 + int ret;
1110 + unsigned long flags;
1111 +
1112 + if (unlikely(list_empty(&msg->transfers)))
1113 + return -EINVAL;
1114 +
1115 + if (bs->stopping)
1116 + return -ESHUTDOWN;
1117 +
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");
1121 + return -EINVAL;
1122 + }
1123 +
1124 + if (!xfer->bits_per_word || xfer->speed_hz)
1125 + continue;
1126 +
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);
1132 + if (ret)
1133 + return ret;
1134 + }
1135 +
1136 + msg->status = -EINPROGRESS;
1137 + msg->actual_length = 0;
1138 +
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);
1143 +
1144 + return 0;
1145 +}
1146 +
1147 +static void bcm2708_spi_cleanup(struct spi_device *spi)
1148 +{
1149 + if (spi->controller_state) {
1150 + kfree(spi->controller_state);
1151 + spi->controller_state = NULL;
1152 + }
1153 +}
1154 +
1155 +static int bcm2708_spi_probe(struct platform_device *pdev)
1156 +{
1157 + struct resource *regs;
1158 + int irq, err = -ENOMEM;
1159 + struct clk *clk;
1160 + struct spi_master *master;
1161 + struct bcm2708_spi *bs;
1162 +
1163 + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1164 + if (!regs) {
1165 + dev_err(&pdev->dev, "could not get IO memory\n");
1166 + return -ENXIO;
1167 + }
1168 +
1169 + irq = platform_get_irq(pdev, 0);
1170 + if (irq < 0) {
1171 + dev_err(&pdev->dev, "could not get IRQ\n");
1172 + return irq;
1173 + }
1174 +
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);
1179 + }
1180 +
1181 + bcm2708_init_pinmode();
1182 +
1183 + master = spi_alloc_master(&pdev->dev, sizeof(*bs));
1184 + if (!master) {
1185 + dev_err(&pdev->dev, "spi_alloc_master() failed\n");
1186 + goto out_clk_put;
1187 + }
1188 +
1189 + /* the spi->mode bits understood by this driver: */
1190 + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
1191 +
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);
1198 +
1199 + bs = spi_master_get_devdata(master);
1200 +
1201 + spin_lock_init(&bs->lock);
1202 + INIT_LIST_HEAD(&bs->queue);
1203 + init_completion(&bs->done);
1204 + INIT_WORK(&bs->work, bcm2708_work);
1205 +
1206 + bs->base = ioremap(regs->start, resource_size(regs));
1207 + if (!bs->base) {
1208 + dev_err(&pdev->dev, "could not remap memory\n");
1209 + goto out_master_put;
1210 + }
1211 +
1212 + bs->workq = create_singlethread_workqueue(dev_name(&pdev->dev));
1213 + if (!bs->workq) {
1214 + dev_err(&pdev->dev, "could not create workqueue\n");
1215 + goto out_iounmap;
1216 + }
1217 +
1218 + bs->irq = irq;
1219 + bs->clk = clk;
1220 + bs->stopping = false;
1221 +
1222 + err = request_irq(irq, bcm2708_spi_interrupt, 0, dev_name(&pdev->dev),
1223 + master);
1224 + if (err) {
1225 + dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
1226 + goto out_workqueue;
1227 + }
1228 +
1229 + /* initialise the hardware */
1230 + clk_enable(clk);
1231 + bcm2708_wr(bs, SPI_CS, SPI_CS_REN | SPI_CS_CLEAR_RX | SPI_CS_CLEAR_TX);
1232 +
1233 + err = spi_register_master(master);
1234 + if (err) {
1235 + dev_err(&pdev->dev, "could not register SPI master: %d\n", err);
1236 + goto out_free_irq;
1237 + }
1238 +
1239 + dev_info(&pdev->dev, "SPI Controller at 0x%08lx (irq %d)\n",
1240 + (unsigned long)regs->start, irq);
1241 +
1242 + return 0;
1243 +
1244 +out_free_irq:
1245 + free_irq(bs->irq, master);
1246 +out_workqueue:
1247 + destroy_workqueue(bs->workq);
1248 +out_iounmap:
1249 + iounmap(bs->base);
1250 +out_master_put:
1251 + spi_master_put(master);
1252 +out_clk_put:
1253 + clk_put(clk);
1254 + return err;
1255 +}
1256 +
1257 +static int bcm2708_spi_remove(struct platform_device *pdev)
1258 +{
1259 + struct spi_master *master = platform_get_drvdata(pdev);
1260 + struct bcm2708_spi *bs = spi_master_get_devdata(master);
1261 +
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);
1267 +
1268 + flush_work_sync(&bs->work);
1269 +
1270 + clk_disable(bs->clk);
1271 + clk_put(bs->clk);
1272 + free_irq(bs->irq, master);
1273 + iounmap(bs->base);
1274 +
1275 + spi_unregister_master(master);
1276 +
1277 + return 0;
1278 +}
1279 +
1280 +static struct platform_driver bcm2708_spi_driver = {
1281 + .driver = {
1282 + .name = DRV_NAME,
1283 + .owner = THIS_MODULE,
1284 + },
1285 + .probe = bcm2708_spi_probe,
1286 + .remove = bcm2708_spi_remove,
1287 +};
1288 +
1289 +
1290 +static int __init bcm2708_spi_init(void)
1291 +{
1292 + return platform_driver_probe(&bcm2708_spi_driver, bcm2708_spi_probe);
1293 +}
1294 +module_init(bcm2708_spi_init);
1295 +
1296 +static void __exit bcm2708_spi_exit(void)
1297 +{
1298 + platform_driver_unregister(&bcm2708_spi_driver);
1299 +}
1300 +module_exit(bcm2708_spi_exit);
1301 +
1302 +
1303 +//module_platform_driver(bcm2708_spi_driver);
1304 +
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);
1309 --
1310 1.9.1
1311