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
next prev parent 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).