diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2020-03-24 13:34:57 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2020-04-14 09:13:19 +0200 |
commit | 1813487725e85b6ca0b64e03965e6ac4f56e556e (patch) | |
tree | 2191ccff47cc1a1c27d11de918b08a2969411dc5 /drivers/spi/spi.c | |
parent | ef46f2db0001d4d5b66ddd34346aa36625dbf452 (diff) | |
download | barebox-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/spi/spi.c')
-rw-r--r-- | drivers/spi/spi.c | 46 |
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); } |