diff options
author | Steffen Trumtrar <s.trumtrar@pengutronix.de> | 2019-05-03 11:33:54 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-05-08 10:52:51 +0200 |
commit | c8516869c49677bb1468e0e2e351bc05b815e4ef (patch) | |
tree | 233230d051ce0166cbdbb75ccaad7d599f61ad9c /include/spi | |
parent | 167a27b5354910b92c7a4654a44d72a3d167f0ab (diff) | |
download | barebox-c8516869c49677bb1468e0e2e351bc05b815e4ef.tar.gz barebox-c8516869c49677bb1468e0e2e351bc05b815e4ef.tar.xz |
spi: Extend the core to ease integration of SPI memory controllers
Sync with Linux v5.1-rc1.
This is the barebox adoption of the commit
commit c36ff266dc82f4ae797a6f3513c6ffa344f7f1c7
Author: Boris Brezillon <boris.brezillon@bootlin.com>
Date: Thu Apr 26 18:18:14 2018 +0200
spi: Extend the core to ease integration of SPI memory controllers
Some controllers are exposing high-level interfaces to access various
kind of SPI memories. Unfortunately they do not fit in the current
spi_controller model and usually have drivers placed in
drivers/mtd/spi-nor which are only supporting SPI NORs and not SPI
memories in general.
This is an attempt at defining a SPI memory interface which works for
all kinds of SPI memories (NORs, NANDs, SRAMs).
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Reviewed-by: Frieder Schrempf <frieder.schrempf@exceet.de>
Tested-by: Frieder Schrempf <frieder.schrempf@exceet.de>
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'include/spi')
-rw-r--r-- | include/spi/spi.h | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/include/spi/spi.h b/include/spi/spi.h index 6eeaf254c7..bdcda0bb60 100644 --- a/include/spi/spi.h +++ b/include/spi/spi.h @@ -2,8 +2,12 @@ #define __INCLUDE_SPI_H #include <driver.h> +#include <linux/err.h> +#include <linux/kernel.h> #include <linux/string.h> +struct spi_controller_mem_ops; + struct spi_board_info { char *name; int max_speed_hz; @@ -62,6 +66,7 @@ struct spi_device { struct device_d dev; struct spi_controller *controller; struct spi_controller *master; /* compatibility layer */ + struct spi_mem *mem; u32 max_speed_hz; u8 chip_select; u8 mode; @@ -109,6 +114,13 @@ struct spi_message; * @dev: device interface to this driver * @bus_num: board-specific (and often SOC-specific) identifier for a * given SPI controller. + * @mem_ops: optimized/dedicated operations for interactions with SPI + * memory. This field is optional and should only be implemented + * if the controller has native support for memory like operations. + * @max_transfer_size: function that returns the max transfer size for + * a &spi_device; may be %NULL, so the default %SIZE_MAX will be used. + * @max_message_size: function that returns the max message size for + * a &spi_device; may be %NULL, so the default %SIZE_MAX will be used. * @num_chipselect: chipselects are used to distinguish individual * SPI slaves, and are numbered from zero to num_chipselects. * each slave has a chipselect signal, but it's common that not @@ -144,6 +156,15 @@ struct spi_controller { */ s16 bus_num; + /* Optimized handlers for SPI memory-like operations */ + const struct spi_controller_mem_ops *mem_ops; + /* + * on some hardware transfer size may be constrained + * the limit may depend on device transfer settings + */ + size_t (*max_transfer_size)(struct spi_device *spi); + size_t (*max_message_size)(struct spi_device *spi); + /* chipselects will be integral to many controllers; some others * might use board-specific GPIOs. */ @@ -180,6 +201,40 @@ struct spi_controller { struct list_head list; }; +static inline void *spi_controller_get_devdata(struct spi_controller *ctlr) +{ + if (ctlr->dev->platform_data) + return ctlr->dev->platform_data; + else + return ERR_PTR(-EINVAL); +} + +static inline void spi_controller_set_devdata(struct spi_controller *ctlr, + void *data) +{ + ctlr->dev->platform_data = data; +} + +static inline size_t spi_max_message_size(struct spi_device *spi) +{ + struct spi_controller *ctrl = spi->controller; + if (!ctrl->max_transfer_size) + return SIZE_MAX; + return ctrl->max_transfer_size(spi); +} + +static inline size_t spi_max_transfer_size(struct spi_device *spi) +{ + struct spi_controller *ctrl = spi->controller; + size_t tr_max = SIZE_MAX; + size_t msg_max = spi_max_message_size(spi); + + if (ctrl->max_transfer_size) + tr_max = ctrl->max_transfer_size(spi); + + return min(tr_max, msg_max); +} + #define spi_master spi_controller #define spi_register_master(_ctrl) spi_register_controller(_ctrl) |