Commit 568d0697f42771425ae9f1e9a3db769fef7e10b6
Committed by
Linus Torvalds
1 parent
7869c0b9ed
Exists in
master
and in
7 other branches
spi: handle TX-only/RX-only
Support two new half-duplex SPI implementation restrictions, for links that talk to TX-only or RX-only devices. (Existing half-duplex flavors support both transfer directions, just not at the same time.) Move spi_async() into the spi.c core, and stop inlining it. Then make that function perform error checks and reject messages that demand more than the underlying controller can support. Based on a patch from Marek Szyprowski which did this only for the bitbanged GPIO driver. Cc: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 2 changed files with 62 additions and 36 deletions Side-by-side Diff
drivers/spi/spi.c
... | ... | @@ -663,6 +663,65 @@ |
663 | 663 | } |
664 | 664 | EXPORT_SYMBOL_GPL(spi_setup); |
665 | 665 | |
666 | +/** | |
667 | + * spi_async - asynchronous SPI transfer | |
668 | + * @spi: device with which data will be exchanged | |
669 | + * @message: describes the data transfers, including completion callback | |
670 | + * Context: any (irqs may be blocked, etc) | |
671 | + * | |
672 | + * This call may be used in_irq and other contexts which can't sleep, | |
673 | + * as well as from task contexts which can sleep. | |
674 | + * | |
675 | + * The completion callback is invoked in a context which can't sleep. | |
676 | + * Before that invocation, the value of message->status is undefined. | |
677 | + * When the callback is issued, message->status holds either zero (to | |
678 | + * indicate complete success) or a negative error code. After that | |
679 | + * callback returns, the driver which issued the transfer request may | |
680 | + * deallocate the associated memory; it's no longer in use by any SPI | |
681 | + * core or controller driver code. | |
682 | + * | |
683 | + * Note that although all messages to a spi_device are handled in | |
684 | + * FIFO order, messages may go to different devices in other orders. | |
685 | + * Some device might be higher priority, or have various "hard" access | |
686 | + * time requirements, for example. | |
687 | + * | |
688 | + * On detection of any fault during the transfer, processing of | |
689 | + * the entire message is aborted, and the device is deselected. | |
690 | + * Until returning from the associated message completion callback, | |
691 | + * no other spi_message queued to that device will be processed. | |
692 | + * (This rule applies equally to all the synchronous transfer calls, | |
693 | + * which are wrappers around this core asynchronous primitive.) | |
694 | + */ | |
695 | +int spi_async(struct spi_device *spi, struct spi_message *message) | |
696 | +{ | |
697 | + struct spi_master *master = spi->master; | |
698 | + | |
699 | + /* Half-duplex links include original MicroWire, and ones with | |
700 | + * only one data pin like SPI_3WIRE (switches direction) or where | |
701 | + * either MOSI or MISO is missing. They can also be caused by | |
702 | + * software limitations. | |
703 | + */ | |
704 | + if ((master->flags & SPI_MASTER_HALF_DUPLEX) | |
705 | + || (spi->mode & SPI_3WIRE)) { | |
706 | + struct spi_transfer *xfer; | |
707 | + unsigned flags = master->flags; | |
708 | + | |
709 | + list_for_each_entry(xfer, &message->transfers, transfer_list) { | |
710 | + if (xfer->rx_buf && xfer->tx_buf) | |
711 | + return -EINVAL; | |
712 | + if ((flags & SPI_MASTER_NO_TX) && xfer->tx_buf) | |
713 | + return -EINVAL; | |
714 | + if ((flags & SPI_MASTER_NO_RX) && xfer->rx_buf) | |
715 | + return -EINVAL; | |
716 | + } | |
717 | + } | |
718 | + | |
719 | + message->spi = spi; | |
720 | + message->status = -EINPROGRESS; | |
721 | + return master->transfer(spi, message); | |
722 | +} | |
723 | +EXPORT_SYMBOL_GPL(spi_async); | |
724 | + | |
666 | 725 | |
667 | 726 | /*-------------------------------------------------------------------------*/ |
668 | 727 |
include/linux/spi/spi.h
... | ... | @@ -258,6 +258,8 @@ |
258 | 258 | /* other constraints relevant to this driver */ |
259 | 259 | u16 flags; |
260 | 260 | #define SPI_MASTER_HALF_DUPLEX BIT(0) /* can't do full duplex */ |
261 | +#define SPI_MASTER_NO_RX BIT(1) /* can't do buffer read */ | |
262 | +#define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */ | |
261 | 263 | |
262 | 264 | /* Setup mode and clock, etc (spi driver may call many times). |
263 | 265 | * |
... | ... | @@ -538,42 +540,7 @@ |
538 | 540 | } |
539 | 541 | |
540 | 542 | extern int spi_setup(struct spi_device *spi); |
541 | - | |
542 | -/** | |
543 | - * spi_async - asynchronous SPI transfer | |
544 | - * @spi: device with which data will be exchanged | |
545 | - * @message: describes the data transfers, including completion callback | |
546 | - * Context: any (irqs may be blocked, etc) | |
547 | - * | |
548 | - * This call may be used in_irq and other contexts which can't sleep, | |
549 | - * as well as from task contexts which can sleep. | |
550 | - * | |
551 | - * The completion callback is invoked in a context which can't sleep. | |
552 | - * Before that invocation, the value of message->status is undefined. | |
553 | - * When the callback is issued, message->status holds either zero (to | |
554 | - * indicate complete success) or a negative error code. After that | |
555 | - * callback returns, the driver which issued the transfer request may | |
556 | - * deallocate the associated memory; it's no longer in use by any SPI | |
557 | - * core or controller driver code. | |
558 | - * | |
559 | - * Note that although all messages to a spi_device are handled in | |
560 | - * FIFO order, messages may go to different devices in other orders. | |
561 | - * Some device might be higher priority, or have various "hard" access | |
562 | - * time requirements, for example. | |
563 | - * | |
564 | - * On detection of any fault during the transfer, processing of | |
565 | - * the entire message is aborted, and the device is deselected. | |
566 | - * Until returning from the associated message completion callback, | |
567 | - * no other spi_message queued to that device will be processed. | |
568 | - * (This rule applies equally to all the synchronous transfer calls, | |
569 | - * which are wrappers around this core asynchronous primitive.) | |
570 | - */ | |
571 | -static inline int | |
572 | -spi_async(struct spi_device *spi, struct spi_message *message) | |
573 | -{ | |
574 | - message->spi = spi; | |
575 | - return spi->master->transfer(spi, message); | |
576 | -} | |
543 | +extern int spi_async(struct spi_device *spi, struct spi_message *message); | |
577 | 544 | |
578 | 545 | /*---------------------------------------------------------------------------*/ |
579 | 546 |