[PATCH v4 2/7] spi: Make support for regular transfers optional when ->mem_ops != NULL
Frieder Schrempf
frieder.schrempf at exceet.de
Thu May 3 11:40:48 PDT 2018
On 26.04.2018 18:18, Boris Brezillon wrote:
> 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 at bootlin.com>
Reviewed-by: Frieder Schrempf <frieder.schrempf at exceet.de>
Tested-by: Frieder Schrempf <frieder.schrempf at exceet.de>
Regards,
Frieder
> ---
> Changes in v4:
> - none
>
> Changes in v3:
> - none
>
> Changes in v2:
> - patch added in v2
> ---
> 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);
>
More information about the linux-mtd
mailing list