diff options
| author | David Lechner <dlechner@baylibre.com> | 2025-02-07 23:08:59 +0300 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2025-02-07 23:17:08 +0300 |
| commit | d7231be4b4657e5f922a4c6dc11e8dffc71fee87 (patch) | |
| tree | 7d05466ee5f89c58b6ccaca2cfe61f4b65bfd342 /include/linux/spi/offload | |
| parent | 8e02d188698851436f76038ea998b726193d1b10 (diff) | |
| download | linux-d7231be4b4657e5f922a4c6dc11e8dffc71fee87.tar.xz | |
spi: offload: add support for hardware triggers
Extend SPI offloading to support hardware triggers.
This allows an arbitrary hardware trigger to be used to start a SPI
transfer that was previously set up with spi_optimize_message().
A new struct spi_offload_trigger is introduced that can be used to
configure any type of trigger. It has a type discriminator and a union
to allow it to be extended in the future. Two trigger types are defined
to start with. One is a trigger that indicates that the SPI peripheral
is ready to read or write data. The other is a periodic trigger to
repeat a SPI message at a fixed rate.
There is also a spi_offload_hw_trigger_validate() function that works
similar to clk_round_rate(). It basically asks the question of if we
enabled the hardware trigger what would the actual parameters be. This
can be used to test if the requested trigger type is actually supported
by the hardware and for periodic triggers, it can be used to find the
actual rate that the hardware is capable of.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Nuno Sa <nuno.sa@analog.com>
Signed-off-by: David Lechner <dlechner@baylibre.com>
Link: https://patch.msgid.link/20250207-dlech-mainline-spi-engine-offload-2-v8-2-e48a489be48c@baylibre.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'include/linux/spi/offload')
| -rw-r--r-- | include/linux/spi/offload/consumer.h | 12 | ||||
| -rw-r--r-- | include/linux/spi/offload/provider.h | 28 | ||||
| -rw-r--r-- | include/linux/spi/offload/types.h | 37 |
3 files changed, 77 insertions, 0 deletions
diff --git a/include/linux/spi/offload/consumer.h b/include/linux/spi/offload/consumer.h index 05543dbedf30..5a0ec5303d60 100644 --- a/include/linux/spi/offload/consumer.h +++ b/include/linux/spi/offload/consumer.h @@ -19,4 +19,16 @@ struct spi_device; struct spi_offload *devm_spi_offload_get(struct device *dev, struct spi_device *spi, const struct spi_offload_config *config); +struct spi_offload_trigger +*devm_spi_offload_trigger_get(struct device *dev, + struct spi_offload *offload, + enum spi_offload_trigger_type type); +int spi_offload_trigger_validate(struct spi_offload_trigger *trigger, + struct spi_offload_trigger_config *config); +int spi_offload_trigger_enable(struct spi_offload *offload, + struct spi_offload_trigger *trigger, + struct spi_offload_trigger_config *config); +void spi_offload_trigger_disable(struct spi_offload *offload, + struct spi_offload_trigger *trigger); + #endif /* __LINUX_SPI_OFFLOAD_CONSUMER_H */ diff --git a/include/linux/spi/offload/provider.h b/include/linux/spi/offload/provider.h index 278c4edfcdb7..76c7cf651092 100644 --- a/include/linux/spi/offload/provider.h +++ b/include/linux/spi/offload/provider.h @@ -8,12 +8,40 @@ #define __LINUX_SPI_OFFLOAD_PROVIDER_H #include <linux/module.h> +#include <linux/spi/offload/types.h> #include <linux/types.h> MODULE_IMPORT_NS("SPI_OFFLOAD"); struct device; +struct spi_offload_trigger; struct spi_offload *devm_spi_offload_alloc(struct device *dev, size_t priv_size); +struct spi_offload_trigger_ops { + bool (*match)(struct spi_offload_trigger *trigger, + enum spi_offload_trigger_type type, u64 *args, u32 nargs); + int (*request)(struct spi_offload_trigger *trigger, + enum spi_offload_trigger_type type, u64 *args, u32 nargs); + void (*release)(struct spi_offload_trigger *trigger); + int (*validate)(struct spi_offload_trigger *trigger, + struct spi_offload_trigger_config *config); + int (*enable)(struct spi_offload_trigger *trigger, + struct spi_offload_trigger_config *config); + void (*disable)(struct spi_offload_trigger *trigger); +}; + +struct spi_offload_trigger_info { + /** @fwnode: Provider fwnode, used to match to consumer. */ + struct fwnode_handle *fwnode; + /** @ops: Provider-specific callbacks. */ + const struct spi_offload_trigger_ops *ops; + /** Provider-specific state to be used in callbacks. */ + void *priv; +}; + +int devm_spi_offload_trigger_register(struct device *dev, + struct spi_offload_trigger_info *info); +void *spi_offload_trigger_get_priv(struct spi_offload_trigger *trigger); + #endif /* __LINUX_SPI_OFFLOAD_PROVIDER_H */ diff --git a/include/linux/spi/offload/types.h b/include/linux/spi/offload/types.h index a74f8d84541b..7476f2073b02 100644 --- a/include/linux/spi/offload/types.h +++ b/include/linux/spi/offload/types.h @@ -38,6 +38,43 @@ struct spi_offload { struct device *provider_dev; /** @priv: provider driver private data */ void *priv; + /** @ops: callbacks for offload support */ + const struct spi_offload_ops *ops; +}; + +enum spi_offload_trigger_type { + /* Indication from SPI peripheral that data is read to read. */ + SPI_OFFLOAD_TRIGGER_DATA_READY, + /* Trigger comes from a periodic source such as a clock. */ + SPI_OFFLOAD_TRIGGER_PERIODIC, +}; + +struct spi_offload_trigger_periodic { + u64 frequency_hz; +}; + +struct spi_offload_trigger_config { + /** @type: type discriminator for union */ + enum spi_offload_trigger_type type; + union { + struct spi_offload_trigger_periodic periodic; + }; +}; + +/** + * struct spi_offload_ops - callbacks implemented by offload providers + */ +struct spi_offload_ops { + /** + * @trigger_enable: Optional callback to enable the trigger for the + * given offload instance. + */ + int (*trigger_enable)(struct spi_offload *offload); + /** + * @trigger_disable: Optional callback to disable the trigger for the + * given offload instance. + */ + void (*trigger_disable)(struct spi_offload *offload); }; #endif /* __LINUX_SPI_OFFLOAD_TYPES_H */ |
