The patch spi: Make support for regular transfers optional when ->mem_ops != NULL has been applied to the spi tree at https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted. You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed. If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced. Please add any relevant lists and maintainers to the CCs when replying to this mail. Thanks, Mark >From b5932f5c68e5fbe74fb7a27b4d0faf919e1e1642 Mon Sep 17 00:00:00 2001 From: Boris Brezillon <boris.brezillon@xxxxxxxxxxx> Date: Thu, 26 Apr 2018 18:18:15 +0200 Subject: [PATCH] spi: Make support for regular transfers optional when ->mem_ops != NULL Some SPI/QuadSPI controllers only expose a high-level SPI memory interface, thus preventing any regular SPI transfers from being done. In that case, SPI controller drivers can leave all ->transfer_xxx() hooks empty and only implement the spi_mem_ops interface. Adjust the core to allow such situations: - extend spi_controller_check_ops() to accept situations where all ->transfer_xxx() pointers are NULL only if ->mem_ops != NULL - make sure we do not initialize the SPI message queue if ctlr->transfer_one and ctlr->transfer_one_message are missing - return -ENOTSUPP if someone tries to do a regular SPI transfer on a controller that does not support it Signed-off-by: Boris Brezillon <boris.brezillon@xxxxxxxxxxx> Reviewed-by: Frieder Schrempf <frieder.schrempf@xxxxxxxxx> Tested-by: Frieder Schrempf <frieder.schrempf@xxxxxxxxx> Signed-off-by: Mark Brown <broonie@xxxxxxxxxx> --- drivers/spi/spi.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 9ab65fb2738e..c85b0cf7b4a9 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -28,6 +28,7 @@ #include <linux/slab.h> #include <linux/mod_devicetable.h> #include <linux/spi/spi.h> +#include <linux/spi/spi-mem.h> #include <linux/of_gpio.h> #include <linux/pm_runtime.h> #include <linux/pm_domain.h> @@ -2071,12 +2072,19 @@ static int of_spi_register_master(struct spi_controller *ctlr) static int spi_controller_check_ops(struct spi_controller *ctlr) { /* - * The controller must at least implement one of the ->transfer() - * hooks. + * The controller may implement only the high-level SPI-memory like + * operations if it does not support regular SPI transfers, and this is + * valid use case. + * If ->mem_ops is NULL, we request that at least one of the + * ->transfer_xxx() method be implemented. */ - if (!ctlr->transfer && !ctlr->transfer_one && - !ctlr->transfer_one_message) + if (ctlr->mem_ops) { + if (!ctlr->mem_ops->exec_op) + return -EINVAL; + } else if (!ctlr->transfer && !ctlr->transfer_one && + !ctlr->transfer_one_message) { return -EINVAL; + } return 0; } @@ -2187,10 +2195,14 @@ int spi_register_controller(struct spi_controller *ctlr) spi_controller_is_slave(ctlr) ? "slave" : "master", dev_name(&ctlr->dev)); - /* If we're using a queued driver, start the queue */ - if (ctlr->transfer) + /* + * If we're using a queued driver, start the queue. Note that we don't + * need the queueing logic if the driver is only supporting high-level + * memory operations. + */ + if (ctlr->transfer) { dev_info(dev, "controller is unqueued, this is deprecated\n"); - else { + } else if (ctlr->transfer_one || ctlr->transfer_one_message) { status = spi_controller_initialize_queue(ctlr); if (status) { device_del(&ctlr->dev); @@ -2920,6 +2932,13 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) { struct spi_controller *ctlr = spi->controller; + /* + * Some controllers do not support doing regular SPI transfers. Return + * ENOTSUPP when this is the case. + */ + if (!ctlr->transfer) + return -ENOTSUPP; + message->spi = spi; SPI_STATISTICS_INCREMENT_FIELD(&ctlr->statistics, spi_async); -- 2.17.0 -- To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html