summaryrefslogtreecommitdiffstats
path: root/include/spi
diff options
context:
space:
mode:
authorSteffen Trumtrar <s.trumtrar@pengutronix.de>2019-05-03 11:33:54 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2019-05-08 10:52:51 +0200
commitc8516869c49677bb1468e0e2e351bc05b815e4ef (patch)
tree233230d051ce0166cbdbb75ccaad7d599f61ad9c /include/spi
parent167a27b5354910b92c7a4654a44d72a3d167f0ab (diff)
downloadbarebox-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.h55
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)