devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: David Lechner <dlechner@baylibre.com>
To: "Mark Brown" <broonie@kernel.org>,
	"Jonathan Cameron" <jic23@kernel.org>,
	"Rob Herring" <robh+dt@kernel.org>,
	"Krzysztof Kozlowski" <krzysztof.kozlowski+dt@linaro.org>,
	"Conor Dooley" <conor+dt@kernel.org>,
	"Michael Hennerich" <michael.hennerich@analog.com>,
	"Nuno Sá" <nuno.sa@analog.com>,
	"Frank Rowand" <frowand.list@gmail.com>
Cc: "David Lechner" <dlechner@baylibre.com>,
	"Thierry Reding" <thierry.reding@gmail.com>,
	"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
	"Jonathan Corbet" <corbet@lwn.net>,
	linux-spi@vger.kernel.org, linux-iio@vger.kernel.org,
	devicetree@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-pwm@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 01/13] spi: add core support for controllers with offload capabilities
Date: Wed, 10 Jan 2024 13:49:42 -0600	[thread overview]
Message-ID: <20240109-axi-spi-engine-series-3-v1-1-e42c6a986580@baylibre.com> (raw)
In-Reply-To: <20240109-axi-spi-engine-series-3-v1-0-e42c6a986580@baylibre.com>

This adds a feature for specialized SPI controllers that can record
a series of SPI transfers, including tx data, cs assertions, delays,
etc. and then play them back using a hardware trigger without CPU
intervention.

The intended use case for this is with the AXI SPI Engine to capture
data from ADCs at high rates (MSPS) with a stable sample period.

Most of the implementation is controller-specific and will be handled by
drivers that implement the offload_ops callbacks. The API follows a
prepare/enable pattern that should be familiar to users of the clk
subsystem.

Consumers of this API will make calls similar to this:

    /* in probe() */
    offload = spi_offload_get(spi, 0);
    ...

    /* in some setup function */
    ret = spi_offload_prepare(offload, xfers, ARRAY_SIZE(xfers));
    ...

    /* in some enable function */
    ret = spi_offload_enable(offload);
    ...

    /* in corresponding disable function */
    spi_offload_disable(offload);
    ...

    /* in corresponding teardown function */
    spi_offload_unprepare(offload);
    ...

Signed-off-by: David Lechner <dlechner@baylibre.com>
---
 drivers/spi/spi.c       |  39 +++++++++++++++
 include/linux/spi/spi.h | 123 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 162 insertions(+)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index a4b8c07c5951..f1d66b5d5491 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -3057,6 +3057,13 @@ static int spi_controller_check_ops(struct spi_controller *ctlr)
 		}
 	}
 
+	if (ctlr->offload_ops && !(ctlr->offload_ops->get &&
+				   ctlr->offload_ops->prepare &&
+				   ctlr->offload_ops->unprepare &&
+				   ctlr->offload_ops->enable &&
+				   ctlr->offload_ops->disable))
+		return -EINVAL;
+
 	return 0;
 }
 
@@ -4448,6 +4455,38 @@ int spi_write_then_read(struct spi_device *spi,
 }
 EXPORT_SYMBOL_GPL(spi_write_then_read);
 
+/**
+ * spi_offload_prepare - prepare offload hardware for a transfer
+ * @offload:	The offload instance.
+ * @spi:	The spi device to use for the transfers.
+ * @xfers:	The transfers to be executed.
+ * @num_xfers:	The number of transfers.
+ *
+ * Records a series of transfers to be executed later by the offload hardware
+ * trigger.
+ *
+ * Return: 0 on success, else a negative error code.
+ */
+int spi_offload_prepare(struct spi_offload *offload, struct spi_device *spi,
+			struct spi_transfer *xfers, unsigned int num_xfers)
+{
+	struct spi_controller *ctlr = offload->controller;
+	struct spi_message msg;
+	int ret;
+
+	spi_message_init_with_transfers(&msg, xfers, num_xfers);
+
+	ret = __spi_validate(spi, &msg);
+	if (ret)
+		return ret;
+
+	msg.spi = spi;
+	ret = ctlr->offload_ops->prepare(offload, &msg);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(spi_offload_prepare);
+
 /*-------------------------------------------------------------------------*/
 
 #if IS_ENABLED(CONFIG_OF_DYNAMIC)
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 5d65a6273dcf..f116dfc1d52c 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -28,6 +28,8 @@ struct spi_transfer;
 struct spi_controller_mem_ops;
 struct spi_controller_mem_caps;
 struct spi_message;
+struct spi_controller_offload_ops;
+struct spi_offload;
 
 /*
  * INTERFACES between SPI master-side drivers and SPI slave protocol handlers,
@@ -713,6 +715,9 @@ struct spi_controller {
 	const struct spi_controller_mem_ops *mem_ops;
 	const struct spi_controller_mem_caps *mem_caps;
 
+	/* Operations for controllers with offload support. */
+	const struct spi_controller_offload_ops *offload_ops;
+
 	/* GPIO chip select */
 	struct gpio_desc	**cs_gpiods;
 	bool			use_gpio_descriptors;
@@ -1505,6 +1510,124 @@ static inline ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd)
 
 /*---------------------------------------------------------------------------*/
 
+/*
+ * Offloading support.
+ *
+ * Some SPI controllers support offloading of SPI transfers. Essentially,
+ * this allows the SPI controller to record SPI transfers and then play them
+ * back later via a hardware trigger.
+ */
+
+/**
+ * SPI_OFFLOAD_RX - placeholder for indicating read transfers for offloads
+ *
+ * Assign xfer->rx_buf to this value for any read transfer passed to
+ * spi_offload_prepare(). This will act as a flag to indicate to the offload
+ * that it should do something with the data read during this transfer. What
+ * that something can be is determined by the specific hardware, e.g. it could
+ * be piped to DMA or a DSP, etc.
+ */
+#define SPI_OFFLOAD_RX_SENTINEL ((void *)1)
+
+/**
+ * struct spi_controller_offload_ops - callbacks for offload support
+ *
+ * Drivers for hardware with offload support need to implement all of these
+ * callbacks.
+ */
+struct spi_controller_offload_ops {
+	/**
+	 * @get: Callback to get the offload assigned to the given SPI device.
+	 * Index is an index in the offloads array fwnode property of the device.
+	 * Implementations must return the pointer to the device or a negative
+	 * error code (return -ENODEV rather than NULL if no matching device).
+	 */
+	struct spi_offload *(*get)(struct spi_device *spi, unsigned int index);
+	/**
+	 * @prepare: Callback to prepare the offload for the given SPI message.
+	 * @msg and any of its members (including any xfer->tx_buf) is not
+	 * guaranteed to be valid beyond the lifetime of this call.
+	 */
+	int (*prepare)(struct spi_offload *offload, struct spi_message *msg);
+	/**
+	 * @unprepare: Callback to release any resources used by prepare().
+	 */
+	void (*unprepare)(struct spi_offload *offload);
+	/**
+	 * @enable: Callback to enable the offload.
+	 */
+	int (*enable)(struct spi_offload *offload);
+	/**
+	 * @disable: Callback to disable the offload.
+	 */
+	void (*disable)(struct spi_offload *offload);
+};
+
+/** struct spi_offload - offload handle */
+struct spi_offload {
+	/** @controller: The associated SPI controller. */
+	struct spi_controller *controller;
+	/** @dev: The device associated with the offload instance. */
+	struct device *dev;
+	/** @priv: Private instance data used by the SPI controller. */
+	void *priv;
+};
+
+/**
+ * spi_offload_get - gets an offload assigned to the given SPI device
+ * @spi: SPI device.
+ * @index: Index of the offload in the SPI device's fwnode int array.
+ *
+ * The lifetime of the returned offload is tied to the struct spi_controller
+ * instance. Since @spi owns a reference to the controller, most consumers
+ * should not have to do anything extra. But if the offload is passed somewhere
+ * outside of the control of the SPI device driver, then an additional reference
+ * to the controller must be made.
+ *
+ * Return: Pointer to the offload handle or negative error code.
+ */
+static inline struct spi_offload *spi_offload_get(struct spi_device *spi,
+						  unsigned int index)
+{
+	if (!spi->controller->offload_ops)
+		return ERR_PTR(-EOPNOTSUPP);
+
+	return spi->controller->offload_ops->get(spi, index);
+}
+
+int spi_offload_prepare(struct spi_offload *offload, struct spi_device *spi,
+			struct spi_transfer *xfers, unsigned int num_xfers);
+
+/**
+ * spi_offload_unprepare - releases any resources used by spi_offload_prepare()
+ * @offload: The offload instance.
+ */
+static inline void spi_offload_unprepare(struct spi_offload *offload)
+{
+	offload->controller->offload_ops->unprepare(offload);
+}
+
+/**
+ * spi_offload_enable - enables the offload
+ * @offload: The offload instance.
+ * Return: 0 on success or negative error code.
+ */
+static inline int spi_offload_enable(struct spi_offload *offload)
+{
+	return offload->controller->offload_ops->enable(offload);
+}
+
+/**
+ * spi_offload_disable - disables the offload
+ * @offload: The offload instance.
+ */
+static inline void spi_offload_disable(struct spi_offload *offload)
+{
+	offload->controller->offload_ops->disable(offload);
+}
+
+/*---------------------------------------------------------------------------*/
+
 /*
  * INTERFACE between board init code and SPI infrastructure.
  *

-- 
2.43.0


  reply	other threads:[~2024-01-10 19:51 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-10 19:49 [PATCH 00/13] spi: axi-spi-engine: add offload support David Lechner
2024-01-10 19:49 ` David Lechner [this message]
2024-01-10 21:36   ` [PATCH 01/13] spi: add core support for controllers with offload capabilities Mark Brown
2024-01-11 20:54     ` David Lechner
2024-01-11 21:32       ` David Lechner
2024-01-11 21:49         ` Mark Brown
2024-01-12  9:03           ` David Jander
2024-01-12 20:09         ` David Lechner
2024-03-04 23:21     ` David Lechner
2024-03-05 18:50       ` Mark Brown
2024-03-09 17:54       ` Jonathan Cameron
2024-01-11  8:49   ` Nuno Sá
2024-01-11 13:33     ` Mark Brown
2024-01-11 14:11       ` Nuno Sá
2024-01-11 15:41         ` Mark Brown
2024-01-12  7:26           ` Nuno Sá
2024-01-10 19:49 ` [PATCH 02/13] scripts: dtc: checks: don't warn on SPI non-peripheral child nodes David Lechner
2024-01-11 22:03   ` Rob Herring
2024-01-10 19:49 ` [PATCH 03/13] spi: do not attempt to register DT nodes without @ in name David Lechner
2024-01-10 21:37   ` Mark Brown
2024-01-10 19:49 ` [PATCH 04/13] spi: dt-bindings: adi,axi-spi-engine: add offload bindings David Lechner
2024-01-10 23:14   ` Rob Herring
2024-01-11  0:06     ` David Lechner
2024-01-11  9:14       ` Nuno Sá
2024-01-11  9:07     ` Nuno Sá
2024-01-10 19:49 ` [PATCH 05/13] spi: axi-spi-engine: add SPI offload support David Lechner
2024-01-10 21:39   ` Mark Brown
2024-01-10 22:31     ` David Lechner
2024-01-11 13:00       ` Mark Brown
2024-01-11 17:57         ` David Lechner
2024-01-10 19:49 ` [PATCH 06/13] iio: buffer: add hardware triggered buffer support David Lechner
2024-01-12 12:37   ` Jonathan Cameron
2024-01-12 15:42     ` David Lechner
2024-01-12 16:50       ` Nuno Sá
2024-01-10 19:49 ` [PATCH 07/13] iio: buffer: dmaengine: add INDIO_HW_BUFFER_TRIGGERED flag David Lechner
2024-01-10 19:49 ` [PATCH 08/13] iio: buffer: add new hardware triggered buffer driver David Lechner
2024-01-11  9:24   ` Nuno Sá
2024-01-10 19:49 ` [PATCH 09/13] bus: auxiliary: increase AUXILIARY_NAME_SIZE David Lechner
2024-01-10 19:49 ` [PATCH 10/13] iio: buffer: dmaengine: export devm_iio_dmaengine_buffer_alloc() David Lechner
2024-01-12 12:37   ` Jonathan Cameron
2024-01-12 14:55     ` David Lechner
2024-01-10 19:49 ` [PATCH 11/13] dt-bindings: iio: offload: add binding for PWM/DMA triggered buffer David Lechner
2024-01-10 21:25   ` Rob Herring
2024-01-10 22:56   ` Rob Herring
2024-01-10 19:49 ` [PATCH 12/13] iio: offload: add new PWM triggered DMA buffer driver David Lechner
2024-01-11  9:31   ` Nuno Sá
2024-01-11 14:59   ` Nuno Sá
2024-01-12 12:51     ` Jonathan Cameron
2024-01-12 13:19       ` Nuno Sá
2024-01-12 12:45   ` Jonathan Cameron
2024-01-10 19:49 ` [PATCH 13/13] iio: adc: ad7380: add SPI offload support David Lechner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240109-axi-spi-engine-series-3-v1-1-e42c6a986580@baylibre.com \
    --to=dlechner@baylibre.com \
    --cc=broonie@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=corbet@lwn.net \
    --cc=devicetree@vger.kernel.org \
    --cc=frowand.list@gmail.com \
    --cc=jic23@kernel.org \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-iio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pwm@vger.kernel.org \
    --cc=linux-spi@vger.kernel.org \
    --cc=michael.hennerich@analog.com \
    --cc=nuno.sa@analog.com \
    --cc=robh+dt@kernel.org \
    --cc=thierry.reding@gmail.com \
    --cc=u.kleine-koenig@pengutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).