summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2020-03-24 13:34:57 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2020-04-14 09:13:19 +0200
commit1813487725e85b6ca0b64e03965e6ac4f56e556e (patch)
tree2191ccff47cc1a1c27d11de918b08a2969411dc5 /drivers
parentef46f2db0001d4d5b66ddd34346aa36625dbf452 (diff)
downloadbarebox-1813487725e85b6ca0b64e03965e6ac4f56e556e.tar.gz
barebox-1813487725e85b6ca0b64e03965e6ac4f56e556e.tar.xz
spi: validate spi messages
This adds __spi_validate() to validate spi messages. This function is a stripped down version from the Kernel. The motivation for adding this was to fill in xfer->bits_per_word from spi->bits_per_word so that a spi bus driver can use the former. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/spi/spi.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index bd615b4e99..0694f14c39 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -297,8 +297,54 @@ struct spi_controller *spi_get_controller(int bus)
return NULL;
}
+static int __spi_validate(struct spi_device *spi, struct spi_message *message)
+{
+ struct spi_controller *ctlr = spi->controller;
+ struct spi_transfer *xfer;
+ int w_size;
+
+ if (list_empty(&message->transfers))
+ return -EINVAL;
+
+ list_for_each_entry(xfer, &message->transfers, transfer_list) {
+ if (!xfer->bits_per_word)
+ xfer->bits_per_word = spi->bits_per_word;
+
+ if (!xfer->speed_hz)
+ xfer->speed_hz = spi->max_speed_hz;
+
+ if (ctlr->max_speed_hz && xfer->speed_hz > ctlr->max_speed_hz)
+ xfer->speed_hz = ctlr->max_speed_hz;
+
+ /*
+ * SPI transfer length should be multiple of SPI word size
+ * where SPI word size should be power-of-two multiple
+ */
+ if (xfer->bits_per_word <= 8)
+ w_size = 1;
+ else if (xfer->bits_per_word <= 16)
+ w_size = 2;
+ else
+ w_size = 4;
+
+ /* No partial transfers accepted */
+ if (xfer->len % w_size)
+ return -EINVAL;
+ }
+
+ message->status = -EINPROGRESS;
+
+ return 0;
+}
+
int spi_sync(struct spi_device *spi, struct spi_message *message)
{
+ int status;
+
+ status = __spi_validate(spi, message);
+ if (status != 0)
+ return status;
+
return spi->controller->transfer(spi, message);
}