diff options
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r-- | drivers/spi/spi.c | 85 |
1 files changed, 84 insertions, 1 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 70845ccd85c3..b76f2468a84a 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/cache.h> | 24 | #include <linux/cache.h> |
25 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
26 | #include <linux/mod_devicetable.h> | ||
26 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
27 | 28 | ||
28 | 29 | ||
@@ -59,9 +60,32 @@ static struct device_attribute spi_dev_attrs[] = { | |||
59 | * and the sysfs version makes coldplug work too. | 60 | * and the sysfs version makes coldplug work too. |
60 | */ | 61 | */ |
61 | 62 | ||
63 | static const struct spi_device_id *spi_match_id(const struct spi_device_id *id, | ||
64 | const struct spi_device *sdev) | ||
65 | { | ||
66 | while (id->name[0]) { | ||
67 | if (!strcmp(sdev->modalias, id->name)) | ||
68 | return id; | ||
69 | id++; | ||
70 | } | ||
71 | return NULL; | ||
72 | } | ||
73 | |||
74 | const struct spi_device_id *spi_get_device_id(const struct spi_device *sdev) | ||
75 | { | ||
76 | const struct spi_driver *sdrv = to_spi_driver(sdev->dev.driver); | ||
77 | |||
78 | return spi_match_id(sdrv->id_table, sdev); | ||
79 | } | ||
80 | EXPORT_SYMBOL_GPL(spi_get_device_id); | ||
81 | |||
62 | static int spi_match_device(struct device *dev, struct device_driver *drv) | 82 | static int spi_match_device(struct device *dev, struct device_driver *drv) |
63 | { | 83 | { |
64 | const struct spi_device *spi = to_spi_device(dev); | 84 | const struct spi_device *spi = to_spi_device(dev); |
85 | const struct spi_driver *sdrv = to_spi_driver(drv); | ||
86 | |||
87 | if (sdrv->id_table) | ||
88 | return !!spi_match_id(sdrv->id_table, spi); | ||
65 | 89 | ||
66 | return strcmp(spi->modalias, drv->name) == 0; | 90 | return strcmp(spi->modalias, drv->name) == 0; |
67 | } | 91 | } |
@@ -70,7 +94,7 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
70 | { | 94 | { |
71 | const struct spi_device *spi = to_spi_device(dev); | 95 | const struct spi_device *spi = to_spi_device(dev); |
72 | 96 | ||
73 | add_uevent_var(env, "MODALIAS=%s", spi->modalias); | 97 | add_uevent_var(env, "MODALIAS=%s%s", SPI_MODULE_PREFIX, spi->modalias); |
74 | return 0; | 98 | return 0; |
75 | } | 99 | } |
76 | 100 | ||
@@ -639,6 +663,65 @@ int spi_setup(struct spi_device *spi) | |||
639 | } | 663 | } |
640 | EXPORT_SYMBOL_GPL(spi_setup); | 664 | EXPORT_SYMBOL_GPL(spi_setup); |
641 | 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 | |||
642 | 725 | ||
643 | /*-------------------------------------------------------------------------*/ | 726 | /*-------------------------------------------------------------------------*/ |
644 | 727 | ||