diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 588c2633f..64568976b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -195,3 +195,44 @@ int spi_sync(struct spi_device *spi, struct spi_message *message) return spi->master->transfer(spi, message); } +/** + * spi_write_then_read - SPI synchronous write followed by read + * @spi: device with which data will be exchanged + * @txbuf: data to be written + * @n_tx: size of txbuf, in bytes + * @rxbuf: buffer into which data will be read + * @n_rx: size of rxbuf, in bytes + * Context: can sleep + * + * This performs a half duplex MicroWire style transaction with the + * device, sending txbuf and then reading rxbuf. The return value + * is zero for success, else a negative errno status code. + * This call may only be used from a context that may sleep. + */ +int spi_write_then_read(struct spi_device *spi, + const void *txbuf, unsigned n_tx, + void *rxbuf, unsigned n_rx) +{ + int status; + struct spi_message message; + struct spi_transfer x[2]; + + spi_message_init(&message); + memset(x, 0, sizeof x); + if (n_tx) { + x[0].len = n_tx; + spi_message_add_tail(&x[0], &message); + } + if (n_rx) { + x[1].len = n_rx; + spi_message_add_tail(&x[1], &message); + } + + x[0].tx_buf = txbuf; + x[1].rx_buf = rxbuf; + + /* do the i/o */ + status = spi_sync(spi, &message); + return status; +} +EXPORT_SYMBOL(spi_write_then_read); diff --git a/include/spi/spi.h b/include/spi/spi.h index c76f3b792..ac2013ad5 100644 --- a/include/spi/spi.h +++ b/include/spi/spi.h @@ -349,6 +349,80 @@ static inline int spi_register_board_info(struct spi_board_info const *info, } #endif +/** + * spi_write - SPI synchronous write + * @spi: device to which data will be written + * @buf: data buffer + * @len: data buffer size + * Context: can sleep + * + * This writes the buffer and returns zero or a negative error code. + * Callable only from contexts that can sleep. + */ +static inline int +spi_write(struct spi_device *spi, const void *buf, size_t len) +{ + struct spi_transfer t = { + .tx_buf = buf, + .len = len, + }; + struct spi_message m; + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + return spi_sync(spi, &m); +} + +/** + * spi_read - SPI synchronous read + * @spi: device from which data will be read + * @buf: data buffer + * @len: data buffer size + * Context: can sleep + * + * This reads the buffer and returns zero or a negative error code. + * Callable only from contexts that can sleep. + */ +static inline int +spi_read(struct spi_device *spi, void *buf, size_t len) +{ + struct spi_transfer t = { + .rx_buf = buf, + .len = len, + }; + struct spi_message m; + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + return spi_sync(spi, &m); +} + +/* this copies txbuf and rxbuf data; for small transfers only! */ +extern int spi_write_then_read(struct spi_device *spi, + const void *txbuf, unsigned n_tx, + void *rxbuf, unsigned n_rx); + +/** + * spi_w8r8 - SPI synchronous 8 bit write followed by 8 bit read + * @spi: device with which data will be exchanged + * @cmd: command to be written before data is read back + * Context: can sleep + * + * This returns the (unsigned) eight bit number returned by the + * device, or else a negative error code. Callable only from + * contexts that can sleep. + */ +static inline ssize_t spi_w8r8(struct spi_device *spi, u8 cmd) +{ + ssize_t status; + u8 result; + + status = spi_write_then_read(spi, &cmd, 1, &result, 1); + + /* return negative errno or unsigned value */ + return (status < 0) ? status : result; +} + #endif /* DOXYGEN_SHOULD_SKIP_THIS */ #endif /* __INCLUDE_SPI_H */