spi: Add HTC spi_write_and_read function in spi.c
Change-Id: Ia7ca04d6bff5f5ab11045cf7e78153925b815191
Signed-off-by: Flemmard <flemmard@gmail.com>
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 3d8f662..3a2575b 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1439,6 +1439,73 @@
}
EXPORT_SYMBOL_GPL(spi_write_then_read);
+/**
+ * spi_write_and_read - SPI synchronous write and read in full duplex
+ * @spi: device with which data will be exchanged
+ * @txbuf: data to be written (need not be dma-safe)
+ * @rxbuf: buffer into which data will be read (need not be dma-safe)
+ * @size: size of transmission, in bytes
+ * Context: can sleep
+ * (Modify from spi_write_then_read)
+ *
+ * This performs a full duplex MicroWire style transaction with the
+ * device, sending txbuf and reading rxbuf at same time. 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.
+ *
+ * Parameters to this routine are always copied using a small buffer;
+ * portable code should never use this for more than 32 bytes.
+ * Performance-sensitive or bulk transfer code should instead use
+ * spi_{async,sync}() calls with dma-safe buffers.
+ */
+int spi_write_and_read(struct spi_device *spi,
+ u8 *txbuf, u8 *rxbuf, unsigned size)
+{
+ static DEFINE_MUTEX(lock);
+
+ int status;
+ struct spi_message message;
+ struct spi_transfer x;
+ u8 *local_buf;
+
+ if (2*size > SPI_BUFSIZ) {
+ pr_err("%s size %d is over %d\n", __func__, size, SPI_BUFSIZ);
+ return -EINVAL;
+ }
+
+ spi_message_init(&message);
+ memset(&x, 0, sizeof x);
+ if (size) {
+ x.len = size;
+ spi_message_add_tail(&x, &message);
+ }
+
+ if (!mutex_trylock(&lock)) {
+ local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
+ if (!local_buf) {
+ pr_err("%s out of memory\n", __func__);
+ return -ENOMEM;
+ }
+ } else
+ local_buf = buf;
+
+ memcpy(local_buf, txbuf, size);
+ x.tx_buf = local_buf;
+ x.rx_buf = local_buf + size;
+
+ status = spi_sync(spi, &message);
+ if (status == 0)
+ memcpy(rxbuf, x.rx_buf, size);
+
+ if (x.tx_buf == buf)
+ mutex_unlock(&lock);
+ else
+ kfree(local_buf);
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(spi_write_and_read);
+
/*-------------------------------------------------------------------------*/
static int __init spi_init(void)