diff options
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r-- | drivers/spi/spi.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 8a30c6b66a64..85c18d8a86b3 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -526,6 +526,95 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) | |||
526 | 526 | ||
527 | /*-------------------------------------------------------------------------*/ | 527 | /*-------------------------------------------------------------------------*/ |
528 | 528 | ||
529 | static void spi_set_cs(struct spi_device *spi, bool enable) | ||
530 | { | ||
531 | if (spi->mode & SPI_CS_HIGH) | ||
532 | enable = !enable; | ||
533 | |||
534 | if (spi->cs_gpio >= 0) | ||
535 | gpio_set_value(spi->cs_gpio, !enable); | ||
536 | else if (spi->master->set_cs) | ||
537 | spi->master->set_cs(spi, !enable); | ||
538 | } | ||
539 | |||
540 | /* | ||
541 | * spi_transfer_one_message - Default implementation of transfer_one_message() | ||
542 | * | ||
543 | * This is a standard implementation of transfer_one_message() for | ||
544 | * drivers which impelment a transfer_one() operation. It provides | ||
545 | * standard handling of delays and chip select management. | ||
546 | */ | ||
547 | static int spi_transfer_one_message(struct spi_master *master, | ||
548 | struct spi_message *msg) | ||
549 | { | ||
550 | struct spi_transfer *xfer; | ||
551 | bool cur_cs = true; | ||
552 | bool keep_cs = false; | ||
553 | int ret = 0; | ||
554 | |||
555 | spi_set_cs(msg->spi, true); | ||
556 | |||
557 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { | ||
558 | trace_spi_transfer_start(msg, xfer); | ||
559 | |||
560 | INIT_COMPLETION(master->xfer_completion); | ||
561 | |||
562 | ret = master->transfer_one(master, msg->spi, xfer); | ||
563 | if (ret < 0) { | ||
564 | dev_err(&msg->spi->dev, | ||
565 | "SPI transfer failed: %d\n", ret); | ||
566 | goto out; | ||
567 | } | ||
568 | |||
569 | if (ret > 0) | ||
570 | wait_for_completion(&master->xfer_completion); | ||
571 | |||
572 | trace_spi_transfer_stop(msg, xfer); | ||
573 | |||
574 | if (msg->status != -EINPROGRESS) | ||
575 | goto out; | ||
576 | |||
577 | if (xfer->delay_usecs) | ||
578 | udelay(xfer->delay_usecs); | ||
579 | |||
580 | if (xfer->cs_change) { | ||
581 | if (list_is_last(&xfer->transfer_list, | ||
582 | &msg->transfers)) { | ||
583 | keep_cs = true; | ||
584 | } else { | ||
585 | cur_cs = !cur_cs; | ||
586 | spi_set_cs(msg->spi, cur_cs); | ||
587 | } | ||
588 | } | ||
589 | |||
590 | msg->actual_length += xfer->len; | ||
591 | } | ||
592 | |||
593 | out: | ||
594 | if (ret != 0 || !keep_cs) | ||
595 | spi_set_cs(msg->spi, false); | ||
596 | |||
597 | if (msg->status == -EINPROGRESS) | ||
598 | msg->status = ret; | ||
599 | |||
600 | spi_finalize_current_message(master); | ||
601 | |||
602 | return ret; | ||
603 | } | ||
604 | |||
605 | /** | ||
606 | * spi_finalize_current_transfer - report completion of a transfer | ||
607 | * | ||
608 | * Called by SPI drivers using the core transfer_one_message() | ||
609 | * implementation to notify it that the current interrupt driven | ||
610 | * transfer has finised and the next one may be scheduled. | ||
611 | */ | ||
612 | void spi_finalize_current_transfer(struct spi_master *master) | ||
613 | { | ||
614 | complete(&master->xfer_completion); | ||
615 | } | ||
616 | EXPORT_SYMBOL_GPL(spi_finalize_current_transfer); | ||
617 | |||
529 | /** | 618 | /** |
530 | * spi_pump_messages - kthread work function which processes spi message queue | 619 | * spi_pump_messages - kthread work function which processes spi message queue |
531 | * @work: pointer to kthread work struct contained in the master struct | 620 | * @work: pointer to kthread work struct contained in the master struct |
@@ -836,6 +925,8 @@ static int spi_master_initialize_queue(struct spi_master *master) | |||
836 | 925 | ||
837 | master->queued = true; | 926 | master->queued = true; |
838 | master->transfer = spi_queued_transfer; | 927 | master->transfer = spi_queued_transfer; |
928 | if (!master->transfer_one_message) | ||
929 | master->transfer_one_message = spi_transfer_one_message; | ||
839 | 930 | ||
840 | /* Initialize and start queue */ | 931 | /* Initialize and start queue */ |
841 | ret = spi_init_queue(master); | 932 | ret = spi_init_queue(master); |
@@ -1242,6 +1333,7 @@ int spi_register_master(struct spi_master *master) | |||
1242 | spin_lock_init(&master->bus_lock_spinlock); | 1333 | spin_lock_init(&master->bus_lock_spinlock); |
1243 | mutex_init(&master->bus_lock_mutex); | 1334 | mutex_init(&master->bus_lock_mutex); |
1244 | master->bus_lock_flag = 0; | 1335 | master->bus_lock_flag = 0; |
1336 | init_completion(&master->xfer_completion); | ||
1245 | 1337 | ||
1246 | /* register the device, then userspace will see it. | 1338 | /* register the device, then userspace will see it. |
1247 | * registration fails if the bus ID is in use. | 1339 | * registration fails if the bus ID is in use. |