aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorCory Maccarrone <darkstar6262@gmail.com>2009-12-13 03:02:11 -0500
committerGrant Likely <grant.likely@secretlab.ca>2009-12-13 03:02:11 -0500
commit35c9049b27040d09461bc90928ad770be7ddf661 (patch)
tree5f982bb68be90e834f8213e47a41dd442c6e679d /drivers/spi
parent980f3beeb68fd3b383908bac8a017b121df8ee29 (diff)
Add OMAP spi100k driver
This change adds the OMAP SPI 100k driver created by Fabrice Crohas <fcrohas@gmail.com>. This SPI bus is found on OMAP7xx-series smartphones, and for many, the touchscreen is attached to this bus. The lion's share of the work was done by Fabrice on this driver -- I am merely porting it from the Linwizard project on his behalf. Signed-off-by: Cory Maccarrone <darkstar6262@gmail.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/Kconfig6
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/omap_spi_100k.c635
3 files changed, 642 insertions, 0 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index b9908e9a9954..07e5453f7b18 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -172,6 +172,12 @@ config SPI_OMAP24XX
172 SPI master controller for OMAP24xx/OMAP34xx Multichannel SPI 172 SPI master controller for OMAP24xx/OMAP34xx Multichannel SPI
173 (McSPI) modules. 173 (McSPI) modules.
174 174
175config SPI_OMAP_100K
176 tristate "OMAP SPI 100K"
177 depends on SPI_MASTER && (ARCH_OMAP850 || ARCH_OMAP730)
178 help
179 OMAP SPI 100K master controller for omap7xx boards.
180
175config SPI_ORION 181config SPI_ORION
176 tristate "Orion SPI master (EXPERIMENTAL)" 182 tristate "Orion SPI master (EXPERIMENTAL)"
177 depends on PLAT_ORION && EXPERIMENTAL 183 depends on PLAT_ORION && EXPERIMENTAL
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index be6e8a50468e..ed8c1675b52f 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o
22obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o 22obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
23obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o 23obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o
24obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o 24obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o
25obj-$(CONFIG_SPI_OMAP_100K) += omap_spi_100k.o
25obj-$(CONFIG_SPI_ORION) += orion_spi.o 26obj-$(CONFIG_SPI_ORION) += orion_spi.o
26obj-$(CONFIG_SPI_PL022) += amba-pl022.o 27obj-$(CONFIG_SPI_PL022) += amba-pl022.o
27obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o 28obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o
diff --git a/drivers/spi/omap_spi_100k.c b/drivers/spi/omap_spi_100k.c
new file mode 100644
index 000000000000..5355d90d1bee
--- /dev/null
+++ b/drivers/spi/omap_spi_100k.c
@@ -0,0 +1,635 @@
1/*
2 * OMAP7xx SPI 100k controller driver
3 * Author: Fabrice Crohas <fcrohas@gmail.com>
4 * from original omap1_mcspi driver
5 *
6 * Copyright (C) 2005, 2006 Nokia Corporation
7 * Author: Samuel Ortiz <samuel.ortiz@nokia.com> and
8 * Juha Yrj�l� <juha.yrjola@nokia.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
25#include <linux/kernel.h>
26#include <linux/init.h>
27#include <linux/interrupt.h>
28#include <linux/module.h>
29#include <linux/device.h>
30#include <linux/delay.h>
31#include <linux/platform_device.h>
32#include <linux/err.h>
33#include <linux/clk.h>
34#include <linux/io.h>
35#include <linux/gpio.h>
36
37#include <linux/spi/spi.h>
38
39#include <plat/clock.h>
40
41#define OMAP1_SPI100K_MAX_FREQ 48000000
42
43#define ICR_SPITAS (OMAP7XX_ICR_BASE + 0x12)
44
45#define SPI_SETUP1 0x00
46#define SPI_SETUP2 0x02
47#define SPI_CTRL 0x04
48#define SPI_STATUS 0x06
49#define SPI_TX_LSB 0x08
50#define SPI_TX_MSB 0x0a
51#define SPI_RX_LSB 0x0c
52#define SPI_RX_MSB 0x0e
53
54#define SPI_SETUP1_INT_READ_ENABLE (1UL << 5)
55#define SPI_SETUP1_INT_WRITE_ENABLE (1UL << 4)
56#define SPI_SETUP1_CLOCK_DIVISOR(x) ((x) << 1)
57#define SPI_SETUP1_CLOCK_ENABLE (1UL << 0)
58
59#define SPI_SETUP2_ACTIVE_EDGE_FALLING (0UL << 0)
60#define SPI_SETUP2_ACTIVE_EDGE_RISING (1UL << 0)
61#define SPI_SETUP2_NEGATIVE_LEVEL (0UL << 5)
62#define SPI_SETUP2_POSITIVE_LEVEL (1UL << 5)
63#define SPI_SETUP2_LEVEL_TRIGGER (0UL << 10)
64#define SPI_SETUP2_EDGE_TRIGGER (1UL << 10)
65
66#define SPI_CTRL_SEN(x) ((x) << 7)
67#define SPI_CTRL_WORD_SIZE(x) (((x) - 1) << 2)
68#define SPI_CTRL_WR (1UL << 1)
69#define SPI_CTRL_RD (1UL << 0)
70
71#define SPI_STATUS_WE (1UL << 1)
72#define SPI_STATUS_RD (1UL << 0)
73
74#define WRITE 0
75#define READ 1
76
77
78/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
79 * cache operations; better heuristics consider wordsize and bitrate.
80 */
81#define DMA_MIN_BYTES 8
82
83#define SPI_RUNNING 0
84#define SPI_SHUTDOWN 1
85
86struct omap1_spi100k {
87 struct work_struct work;
88
89 /* lock protects queue and registers */
90 spinlock_t lock;
91 struct list_head msg_queue;
92 struct spi_master *master;
93 struct clk *ick;
94 struct clk *fck;
95
96 /* Virtual base address of the controller */
97 void __iomem *base;
98
99 /* State of the SPI */
100 unsigned int state;
101};
102
103struct omap1_spi100k_cs {
104 void __iomem *base;
105 int word_len;
106};
107
108static struct workqueue_struct *omap1_spi100k_wq;
109
110#define MOD_REG_BIT(val, mask, set) do { \
111 if (set) \
112 val |= mask; \
113 else \
114 val &= ~mask; \
115} while (0)
116
117static void spi100k_enable_clock(struct spi_master *master)
118{
119 unsigned int val;
120 struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
121
122 /* enable SPI */
123 val = readw(spi100k->base + SPI_SETUP1);
124 val |= SPI_SETUP1_CLOCK_ENABLE;
125 writew(val, spi100k->base + SPI_SETUP1);
126}
127
128static void spi100k_disable_clock(struct spi_master *master)
129{
130 unsigned int val;
131 struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
132
133 /* disable SPI */
134 val = readw(spi100k->base + SPI_SETUP1);
135 val &= ~SPI_SETUP1_CLOCK_ENABLE;
136 writew(val, spi100k->base + SPI_SETUP1);
137}
138
139static void spi100k_write_data(struct spi_master *master, int len, int data)
140{
141 struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
142
143 /* write 16-bit word */
144 spi100k_enable_clock(master);
145 writew( data , spi100k->base + SPI_TX_MSB);
146
147 writew(SPI_CTRL_SEN(0) |
148 SPI_CTRL_WORD_SIZE(len) |
149 SPI_CTRL_WR,
150 spi100k->base + SPI_CTRL);
151
152 /* Wait for bit ack send change */
153 while((readw(spi100k->base + SPI_STATUS) & SPI_STATUS_WE) != SPI_STATUS_WE);
154 udelay(1000);
155
156 spi100k_disable_clock(master);
157}
158
159static int spi100k_read_data(struct spi_master *master, int len)
160{
161 int dataH,dataL;
162 struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
163
164 spi100k_enable_clock(master);
165 writew(SPI_CTRL_SEN(0) |
166 SPI_CTRL_WORD_SIZE(len) |
167 SPI_CTRL_RD,
168 spi100k->base + SPI_CTRL);
169
170 while((readw(spi100k->base + SPI_STATUS) & SPI_STATUS_RD) != SPI_STATUS_RD);
171 udelay(1000);
172
173 dataL = readw(spi100k->base + SPI_RX_LSB);
174 dataH = readw(spi100k->base + SPI_RX_MSB);
175 spi100k_disable_clock(master);
176
177 return dataL;
178}
179
180static void spi100k_open(struct spi_master *master)
181{
182 /* get control of SPI */
183 struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
184
185 writew(SPI_SETUP1_INT_READ_ENABLE |
186 SPI_SETUP1_INT_WRITE_ENABLE |
187 SPI_SETUP1_CLOCK_DIVISOR(0), spi100k->base + SPI_SETUP1);
188
189 /* configure clock and interrupts */
190 writew(SPI_SETUP2_ACTIVE_EDGE_FALLING |
191 SPI_SETUP2_NEGATIVE_LEVEL |
192 SPI_SETUP2_LEVEL_TRIGGER, spi100k->base + SPI_SETUP2);
193}
194
195static void omap1_spi100k_force_cs(struct omap1_spi100k *spi100k, int enable)
196{
197 if (enable)
198 writew(0x05fc, spi100k->base + SPI_CTRL);
199 else
200 writew(0x05fd, spi100k->base + SPI_CTRL);
201}
202
203static unsigned
204omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
205{
206 struct omap1_spi100k *spi100k;
207 struct omap1_spi100k_cs *cs = spi->controller_state;
208 unsigned int count, c;
209 int word_len;
210
211 spi100k = spi_master_get_devdata(spi->master);
212 count = xfer->len;
213 c = count;
214 word_len = cs->word_len;
215
216 /* RX_ONLY mode needs dummy data in TX reg */
217 if (xfer->tx_buf == NULL)
218 spi100k_write_data(spi->master,word_len, 0);
219
220 if (word_len <= 8) {
221 u8 *rx;
222 const u8 *tx;
223
224 rx = xfer->rx_buf;
225 tx = xfer->tx_buf;
226 do {
227 c-=1;
228 if (xfer->tx_buf != NULL)
229 spi100k_write_data(spi->master,word_len, *tx);
230 if (xfer->rx_buf != NULL)
231 *rx = spi100k_read_data(spi->master,word_len);
232 } while(c);
233 } else if (word_len <= 16) {
234 u16 *rx;
235 const u16 *tx;
236
237 rx = xfer->rx_buf;
238 tx = xfer->tx_buf;
239 do {
240 c-=2;
241 if (xfer->tx_buf != NULL)
242 spi100k_write_data(spi->master,word_len, *tx++);
243 if (xfer->rx_buf != NULL)
244 *rx++ = spi100k_read_data(spi->master,word_len);
245 } while(c);
246 } else if (word_len <= 32) {
247 u32 *rx;
248 const u32 *tx;
249
250 rx = xfer->rx_buf;
251 tx = xfer->tx_buf;
252 do {
253 c-=4;
254 if (xfer->tx_buf != NULL)
255 spi100k_write_data(spi->master,word_len, *tx);
256 if (xfer->rx_buf != NULL)
257 *rx = spi100k_read_data(spi->master,word_len);
258 } while(c);
259 }
260 return count - c;
261}
262
263/* called only when no transfer is active to this device */
264static int omap1_spi100k_setup_transfer(struct spi_device *spi,
265 struct spi_transfer *t)
266{
267 struct omap1_spi100k *spi100k = spi_master_get_devdata(spi->master);
268 struct omap1_spi100k_cs *cs = spi->controller_state;
269 u8 word_len = spi->bits_per_word;
270
271 if (t != NULL && t->bits_per_word)
272 word_len = t->bits_per_word;
273 if (!word_len)
274 word_len = 8;
275
276 if (spi->bits_per_word > 32)
277 return -EINVAL;
278 cs->word_len = word_len;
279
280 /* SPI init before transfer */
281 writew(0x3e , spi100k->base + SPI_SETUP1);
282 writew(0x00 , spi100k->base + SPI_STATUS);
283 writew(0x3e , spi100k->base + SPI_CTRL);
284
285 return 0;
286}
287
288/* the spi->mode bits understood by this driver: */
289#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
290
291static int omap1_spi100k_setup(struct spi_device *spi)
292{
293 int ret;
294 struct omap1_spi100k *spi100k;
295 struct omap1_spi100k_cs *cs = spi->controller_state;
296
297 if (spi->bits_per_word < 4 || spi->bits_per_word > 32) {
298 dev_dbg(&spi->dev, "setup: unsupported %d bit words\n",
299 spi->bits_per_word);
300 return -EINVAL;
301 }
302
303 spi100k = spi_master_get_devdata(spi->master);
304
305 if (!cs) {
306 cs = kzalloc(sizeof *cs, GFP_KERNEL);
307 if (!cs)
308 return -ENOMEM;
309 cs->base = spi100k->base + spi->chip_select * 0x14;
310 spi->controller_state = cs;
311 }
312
313 spi100k_open(spi->master);
314
315 clk_enable(spi100k->ick);
316 clk_enable(spi100k->fck);
317
318 ret = omap1_spi100k_setup_transfer(spi, NULL);
319
320 clk_disable(spi100k->ick);
321 clk_disable(spi100k->fck);
322
323 return ret;
324}
325
326static void omap1_spi100k_work(struct work_struct *work)
327{
328 struct omap1_spi100k *spi100k;
329 int status = 0;
330
331 spi100k = container_of(work, struct omap1_spi100k, work);
332 spin_lock_irq(&spi100k->lock);
333
334 clk_enable(spi100k->ick);
335 clk_enable(spi100k->fck);
336
337 /* We only enable one channel at a time -- the one whose message is
338 * at the head of the queue -- although this controller would gladly
339 * arbitrate among multiple channels. This corresponds to "single
340 * channel" master mode. As a side effect, we need to manage the
341 * chipselect with the FORCE bit ... CS != channel enable.
342 */
343 while (!list_empty(&spi100k->msg_queue)) {
344 struct spi_message *m;
345 struct spi_device *spi;
346 struct spi_transfer *t = NULL;
347 int cs_active = 0;
348 struct omap1_spi100k_cs *cs;
349 int par_override = 0;
350
351 m = container_of(spi100k->msg_queue.next, struct spi_message,
352 queue);
353
354 list_del_init(&m->queue);
355 spin_unlock_irq(&spi100k->lock);
356
357 spi = m->spi;
358 cs = spi->controller_state;
359
360 list_for_each_entry(t, &m->transfers, transfer_list) {
361 if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
362 status = -EINVAL;
363 break;
364 }
365 if (par_override || t->speed_hz || t->bits_per_word) {
366 par_override = 1;
367 status = omap1_spi100k_setup_transfer(spi, t);
368 if (status < 0)
369 break;
370 if (!t->speed_hz && !t->bits_per_word)
371 par_override = 0;
372 }
373
374 if (!cs_active) {
375 omap1_spi100k_force_cs(spi100k, 1);
376 cs_active = 1;
377 }
378
379 if (t->len) {
380 unsigned count;
381
382 /* RX_ONLY mode needs dummy data in TX reg */
383 if (t->tx_buf == NULL)
384 spi100k_write_data(spi->master, 8, 0);
385
386 count = omap1_spi100k_txrx_pio(spi, t);
387 m->actual_length += count;
388
389 if (count != t->len) {
390 status = -EIO;
391 break;
392 }
393 }
394
395 if (t->delay_usecs)
396 udelay(t->delay_usecs);
397
398 /* ignore the "leave it on after last xfer" hint */
399
400 if (t->cs_change) {
401 omap1_spi100k_force_cs(spi100k, 0);
402 cs_active = 0;
403 }
404 }
405
406 /* Restore defaults if they were overriden */
407 if (par_override) {
408 par_override = 0;
409 status = omap1_spi100k_setup_transfer(spi, NULL);
410 }
411
412 if (cs_active)
413 omap1_spi100k_force_cs(spi100k, 0);
414
415 m->status = status;
416 m->complete(m->context);
417
418 spin_lock_irq(&spi100k->lock);
419 }
420
421 clk_disable(spi100k->ick);
422 clk_disable(spi100k->fck);
423 spin_unlock_irq(&spi100k->lock);
424
425 if (status < 0)
426 printk(KERN_WARNING "spi transfer failed with %d\n", status);
427}
428
429static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m)
430{
431 struct omap1_spi100k *spi100k;
432 unsigned long flags;
433 struct spi_transfer *t;
434
435 m->actual_length = 0;
436 m->status = -EINPROGRESS;
437
438 spi100k = spi_master_get_devdata(spi->master);
439
440 /* Don't accept new work if we're shutting down */
441 if (spi100k->state == SPI_SHUTDOWN)
442 return -ESHUTDOWN;
443
444 /* reject invalid messages and transfers */
445 if (list_empty(&m->transfers) || !m->complete)
446 return -EINVAL;
447
448 list_for_each_entry(t, &m->transfers, transfer_list) {
449 const void *tx_buf = t->tx_buf;
450 void *rx_buf = t->rx_buf;
451 unsigned len = t->len;
452
453 if (t->speed_hz > OMAP1_SPI100K_MAX_FREQ
454 || (len && !(rx_buf || tx_buf))
455 || (t->bits_per_word &&
456 ( t->bits_per_word < 4
457 || t->bits_per_word > 32))) {
458 dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
459 t->speed_hz,
460 len,
461 tx_buf ? "tx" : "",
462 rx_buf ? "rx" : "",
463 t->bits_per_word);
464 return -EINVAL;
465 }
466
467 if (t->speed_hz && t->speed_hz < OMAP1_SPI100K_MAX_FREQ/(1<<16)) {
468 dev_dbg(&spi->dev, "%d Hz max exceeds %d\n",
469 t->speed_hz,
470 OMAP1_SPI100K_MAX_FREQ/(1<<16));
471 return -EINVAL;
472 }
473
474 }
475
476 spin_lock_irqsave(&spi100k->lock, flags);
477 list_add_tail(&m->queue, &spi100k->msg_queue);
478 queue_work(omap1_spi100k_wq, &spi100k->work);
479 spin_unlock_irqrestore(&spi100k->lock, flags);
480
481 return 0;
482}
483
484static int __init omap1_spi100k_reset(struct omap1_spi100k *spi100k)
485{
486 return 0;
487}
488
489static int __devinit omap1_spi100k_probe(struct platform_device *pdev)
490{
491 struct spi_master *master;
492 struct omap1_spi100k *spi100k;
493 int status = 0;
494
495 if (!pdev->id)
496 return -EINVAL;
497
498 master = spi_alloc_master(&pdev->dev, sizeof *spi100k);
499 if (master == NULL) {
500 dev_dbg(&pdev->dev, "master allocation failed\n");
501 return -ENOMEM;
502 }
503
504 if (pdev->id != -1)
505 master->bus_num = pdev->id;
506
507 master->setup = omap1_spi100k_setup;
508 master->transfer = omap1_spi100k_transfer;
509 master->cleanup = NULL;
510 master->num_chipselect = 2;
511 master->mode_bits = MODEBITS;
512
513 dev_set_drvdata(&pdev->dev, master);
514
515 spi100k = spi_master_get_devdata(master);
516 spi100k->master = master;
517
518 /*
519 * The memory region base address is taken as the platform_data.
520 * You should allocate this with ioremap() before initializing
521 * the SPI.
522 */
523 spi100k->base = (void __iomem *) pdev->dev.platform_data;
524
525 INIT_WORK(&spi100k->work, omap1_spi100k_work);
526
527 spin_lock_init(&spi100k->lock);
528 INIT_LIST_HEAD(&spi100k->msg_queue);
529 spi100k->ick = clk_get(&pdev->dev, "ick");
530 if (IS_ERR(spi100k->ick)) {
531 dev_dbg(&pdev->dev, "can't get spi100k_ick\n");
532 status = PTR_ERR(spi100k->ick);
533 goto err1;
534 }
535
536 spi100k->fck = clk_get(&pdev->dev, "fck");
537 if (IS_ERR(spi100k->fck)) {
538 dev_dbg(&pdev->dev, "can't get spi100k_fck\n");
539 status = PTR_ERR(spi100k->fck);
540 goto err2;
541 }
542
543 if (omap1_spi100k_reset(spi100k) < 0)
544 goto err3;
545
546 status = spi_register_master(master);
547 if (status < 0)
548 goto err3;
549
550 spi100k->state = SPI_RUNNING;
551
552 return status;
553
554err3:
555 clk_put(spi100k->fck);
556err2:
557 clk_put(spi100k->ick);
558err1:
559 spi_master_put(master);
560 return status;
561}
562
563static int __exit omap1_spi100k_remove(struct platform_device *pdev)
564{
565 struct spi_master *master;
566 struct omap1_spi100k *spi100k;
567 struct resource *r;
568 unsigned limit = 500;
569 unsigned long flags;
570 int status = 0;
571
572 master = dev_get_drvdata(&pdev->dev);
573 spi100k = spi_master_get_devdata(master);
574
575 spin_lock_irqsave(&spi100k->lock, flags);
576
577 spi100k->state = SPI_SHUTDOWN;
578 while (!list_empty(&spi100k->msg_queue) && limit--) {
579 spin_unlock_irqrestore(&spi100k->lock, flags);
580 msleep(10);
581 spin_lock_irqsave(&spi100k->lock, flags);
582 }
583
584 if (!list_empty(&spi100k->msg_queue))
585 status = -EBUSY;
586
587 spin_unlock_irqrestore(&spi100k->lock, flags);
588
589 if (status != 0)
590 return status;
591
592 clk_put(spi100k->fck);
593 clk_put(spi100k->ick);
594
595 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
596
597 spi_unregister_master(master);
598
599 return 0;
600}
601
602static struct platform_driver omap1_spi100k_driver = {
603 .driver = {
604 .name = "omap1_spi100k",
605 .owner = THIS_MODULE,
606 },
607 .remove = __exit_p(omap1_spi100k_remove),
608};
609
610
611static int __init omap1_spi100k_init(void)
612{
613 omap1_spi100k_wq = create_singlethread_workqueue(
614 omap1_spi100k_driver.driver.name);
615
616 if (omap1_spi100k_wq == NULL)
617 return -1;
618
619 return platform_driver_probe(&omap1_spi100k_driver, omap1_spi100k_probe);
620}
621
622static void __exit omap1_spi100k_exit(void)
623{
624 platform_driver_unregister(&omap1_spi100k_driver);
625
626 destroy_workqueue(omap1_spi100k_wq);
627}
628
629module_init(omap1_spi100k_init);
630module_exit(omap1_spi100k_exit);
631
632MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver");
633MODULE_AUTHOR("Fabrice Crohas <fcrohas@gmail.com>");
634MODULE_LICENSE("GPL");
635