diff options
-rw-r--r-- | drivers/spi/spi-bitbang.c | 100 | ||||
-rw-r--r-- | include/linux/spi/spi_bitbang.h | 4 |
2 files changed, 30 insertions, 74 deletions
diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index 8b8487c9694e..c100875cfd42 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c | |||
@@ -255,6 +255,21 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) | |||
255 | * Drivers can provide word-at-a-time i/o primitives, or provide | 255 | * Drivers can provide word-at-a-time i/o primitives, or provide |
256 | * transfer-at-a-time ones to leverage dma or fifo hardware. | 256 | * transfer-at-a-time ones to leverage dma or fifo hardware. |
257 | */ | 257 | */ |
258 | |||
259 | static int spi_bitbang_prepare_hardware(struct spi_master *spi) | ||
260 | { | ||
261 | struct spi_bitbang *bitbang; | ||
262 | unsigned long flags; | ||
263 | |||
264 | bitbang = spi_master_get_devdata(spi); | ||
265 | |||
266 | spin_lock_irqsave(&bitbang->lock, flags); | ||
267 | bitbang->busy = 1; | ||
268 | spin_unlock_irqrestore(&bitbang->lock, flags); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
258 | static int spi_bitbang_transfer_one(struct spi_device *spi, | 273 | static int spi_bitbang_transfer_one(struct spi_device *spi, |
259 | struct spi_message *m) | 274 | struct spi_message *m) |
260 | { | 275 | { |
@@ -346,7 +361,6 @@ static int spi_bitbang_transfer_one(struct spi_device *spi, | |||
346 | } | 361 | } |
347 | 362 | ||
348 | m->status = status; | 363 | m->status = status; |
349 | m->complete(m->context); | ||
350 | 364 | ||
351 | /* normally deactivate chipselect ... unless no error and | 365 | /* normally deactivate chipselect ... unless no error and |
352 | * cs_change has hinted that the next message will probably | 366 | * cs_change has hinted that the next message will probably |
@@ -358,54 +372,23 @@ static int spi_bitbang_transfer_one(struct spi_device *spi, | |||
358 | ndelay(nsecs); | 372 | ndelay(nsecs); |
359 | } | 373 | } |
360 | 374 | ||
361 | return status; | 375 | spi_finalize_current_message(spi->master); |
362 | } | ||
363 | |||
364 | static void bitbang_work(struct work_struct *work) | ||
365 | { | ||
366 | struct spi_bitbang *bitbang = | ||
367 | container_of(work, struct spi_bitbang, work); | ||
368 | unsigned long flags; | ||
369 | struct spi_message *m, *_m; | ||
370 | |||
371 | spin_lock_irqsave(&bitbang->lock, flags); | ||
372 | bitbang->busy = 1; | ||
373 | list_for_each_entry_safe(m, _m, &bitbang->queue, queue) { | ||
374 | list_del(&m->queue); | ||
375 | spin_unlock_irqrestore(&bitbang->lock, flags); | ||
376 | |||
377 | spi_bitbang_transfer_one(m->spi, m); | ||
378 | 376 | ||
379 | spin_lock_irqsave(&bitbang->lock, flags); | 377 | return status; |
380 | } | ||
381 | bitbang->busy = 0; | ||
382 | spin_unlock_irqrestore(&bitbang->lock, flags); | ||
383 | } | 378 | } |
384 | 379 | ||
385 | /** | 380 | static int spi_bitbang_unprepare_hardware(struct spi_master *spi) |
386 | * spi_bitbang_transfer - default submit to transfer queue | ||
387 | */ | ||
388 | static int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) | ||
389 | { | 381 | { |
390 | struct spi_bitbang *bitbang; | 382 | struct spi_bitbang *bitbang; |
391 | unsigned long flags; | 383 | unsigned long flags; |
392 | int status = 0; | ||
393 | |||
394 | m->actual_length = 0; | ||
395 | m->status = -EINPROGRESS; | ||
396 | 384 | ||
397 | bitbang = spi_master_get_devdata(spi->master); | 385 | bitbang = spi_master_get_devdata(spi); |
398 | 386 | ||
399 | spin_lock_irqsave(&bitbang->lock, flags); | 387 | spin_lock_irqsave(&bitbang->lock, flags); |
400 | if (!spi->max_speed_hz) | 388 | bitbang->busy = 0; |
401 | status = -ENETDOWN; | ||
402 | else { | ||
403 | list_add_tail(&m->queue, &bitbang->queue); | ||
404 | queue_work(bitbang->workqueue, &bitbang->work); | ||
405 | } | ||
406 | spin_unlock_irqrestore(&bitbang->lock, flags); | 389 | spin_unlock_irqrestore(&bitbang->lock, flags); |
407 | 390 | ||
408 | return status; | 391 | return 0; |
409 | } | 392 | } |
410 | 393 | ||
411 | /*----------------------------------------------------------------------*/ | 394 | /*----------------------------------------------------------------------*/ |
@@ -436,20 +419,22 @@ static int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) | |||
436 | int spi_bitbang_start(struct spi_bitbang *bitbang) | 419 | int spi_bitbang_start(struct spi_bitbang *bitbang) |
437 | { | 420 | { |
438 | struct spi_master *master = bitbang->master; | 421 | struct spi_master *master = bitbang->master; |
439 | int status; | ||
440 | 422 | ||
441 | if (!master || !bitbang->chipselect) | 423 | if (!master || !bitbang->chipselect) |
442 | return -EINVAL; | 424 | return -EINVAL; |
443 | 425 | ||
444 | INIT_WORK(&bitbang->work, bitbang_work); | ||
445 | spin_lock_init(&bitbang->lock); | 426 | spin_lock_init(&bitbang->lock); |
446 | INIT_LIST_HEAD(&bitbang->queue); | ||
447 | 427 | ||
448 | if (!master->mode_bits) | 428 | if (!master->mode_bits) |
449 | master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; | 429 | master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; |
450 | 430 | ||
451 | if (!master->transfer) | 431 | if (master->transfer || master->transfer_one_message) |
452 | master->transfer = spi_bitbang_transfer; | 432 | return -EINVAL; |
433 | |||
434 | master->prepare_transfer_hardware = spi_bitbang_prepare_hardware; | ||
435 | master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware; | ||
436 | master->transfer_one_message = spi_bitbang_transfer_one; | ||
437 | |||
453 | if (!bitbang->txrx_bufs) { | 438 | if (!bitbang->txrx_bufs) { |
454 | bitbang->use_dma = 0; | 439 | bitbang->use_dma = 0; |
455 | bitbang->txrx_bufs = spi_bitbang_bufs; | 440 | bitbang->txrx_bufs = spi_bitbang_bufs; |
@@ -462,32 +447,11 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) | |||
462 | } | 447 | } |
463 | } else if (!master->setup) | 448 | } else if (!master->setup) |
464 | return -EINVAL; | 449 | return -EINVAL; |
465 | if (master->transfer == spi_bitbang_transfer && | ||
466 | !bitbang->setup_transfer) | ||
467 | return -EINVAL; | ||
468 | |||
469 | /* this task is the only thing to touch the SPI bits */ | ||
470 | bitbang->busy = 0; | ||
471 | bitbang->workqueue = create_singlethread_workqueue( | ||
472 | dev_name(master->dev.parent)); | ||
473 | if (bitbang->workqueue == NULL) { | ||
474 | status = -EBUSY; | ||
475 | goto err1; | ||
476 | } | ||
477 | 450 | ||
478 | /* driver may get busy before register() returns, especially | 451 | /* driver may get busy before register() returns, especially |
479 | * if someone registered boardinfo for devices | 452 | * if someone registered boardinfo for devices |
480 | */ | 453 | */ |
481 | status = spi_register_master(master); | 454 | return spi_register_master(master); |
482 | if (status < 0) | ||
483 | goto err2; | ||
484 | |||
485 | return status; | ||
486 | |||
487 | err2: | ||
488 | destroy_workqueue(bitbang->workqueue); | ||
489 | err1: | ||
490 | return status; | ||
491 | } | 455 | } |
492 | EXPORT_SYMBOL_GPL(spi_bitbang_start); | 456 | EXPORT_SYMBOL_GPL(spi_bitbang_start); |
493 | 457 | ||
@@ -498,10 +462,6 @@ int spi_bitbang_stop(struct spi_bitbang *bitbang) | |||
498 | { | 462 | { |
499 | spi_unregister_master(bitbang->master); | 463 | spi_unregister_master(bitbang->master); |
500 | 464 | ||
501 | WARN_ON(!list_empty(&bitbang->queue)); | ||
502 | |||
503 | destroy_workqueue(bitbang->workqueue); | ||
504 | |||
505 | return 0; | 465 | return 0; |
506 | } | 466 | } |
507 | EXPORT_SYMBOL_GPL(spi_bitbang_stop); | 467 | EXPORT_SYMBOL_GPL(spi_bitbang_stop); |
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h index b5aa215493f6..daebaba886aa 100644 --- a/include/linux/spi/spi_bitbang.h +++ b/include/linux/spi/spi_bitbang.h | |||
@@ -4,11 +4,7 @@ | |||
4 | #include <linux/workqueue.h> | 4 | #include <linux/workqueue.h> |
5 | 5 | ||
6 | struct spi_bitbang { | 6 | struct spi_bitbang { |
7 | struct workqueue_struct *workqueue; | ||
8 | struct work_struct work; | ||
9 | |||
10 | spinlock_t lock; | 7 | spinlock_t lock; |
11 | struct list_head queue; | ||
12 | u8 busy; | 8 | u8 busy; |
13 | u8 use_dma; | 9 | u8 use_dma; |
14 | u8 flags; /* extra spi->mode support */ | 10 | u8 flags; /* extra spi->mode support */ |