Some linux drivers provide their own read/write functions to access data
from/of the regmap. Adding support for it.

Signed-off-by: Jean-Jacques Hiblot <jjhib...@ti.com>

---

Changes in v2:
- Only use custom accessors if {,SPL,TPL}_REGMAP_ACCESSORS is enabled

 drivers/core/Kconfig  | 25 +++++++++++++++++++++++++
 drivers/core/regmap.c | 22 ++++++++++++++++++++--
 include/regmap.h      | 28 +++++++++++++++++++++++++---
 3 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 3b95b5387b..3d836a63bf 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -129,6 +129,31 @@ config TPL_REGMAP
          support any bus type (I2C, SPI) but so far this only supports
          direct memory access.
 
+config REGMAP_ACCESSORS
+       bool
+       depends on REGMAP
+       default y
+
+config SPL_REGMAP_ACCESSORS
+       bool "Support custom regmap accessors in SPL"
+       depends on SPL_REGMAP
+       help
+         Allow to use a regmap with custom accessors. The acessors are the
+         low-level functions actually performing the read and write
+         operations.
+         This option can be used to access registers that are not
+         memory-mapped.
+
+config TPL_REGMAP_ACCESSORS
+       bool "Support custom regmap accessors in TPL"
+       depends on TPL_REGMAP
+       help
+         Allow to use a regmap with custom accessors. The acessors are the
+         low-level functions actually performing the read and write
+         operations.
+         This option can be used to access registers that are not
+         memory-mapped.
+
 config SYSCON
        bool "Support system controllers"
        depends on REGMAP
diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index f69ff6d12f..10ae9f918a 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -31,7 +31,11 @@ static struct regmap *regmap_alloc(int count)
        if (!map)
                return NULL;
        map->range_count = count;
-
+#if CONFIG_IS_ENABLED(REGMAP_ACCESSORS)
+       map->bus_context = NULL;
+       map->reg_read = NULL;
+       map->reg_write = NULL;
+#endif
        return map;
 }
 
@@ -241,7 +245,11 @@ struct regmap *devm_regmap_init(struct udevice *dev,
        rc = regmap_init_mem(dev_ofnode(dev), mapp);
        if (rc)
                return ERR_PTR(rc);
-
+#if CONFIG_IS_ENABLED(REGMAP_ACCESSORS)
+       (*mapp)->reg_read = config->reg_read;
+       (*mapp)->reg_write = config->reg_write;
+       (*mapp)->bus_context = bus_context;
+#endif
        devres_add(dev, mapp);
        return *mapp;
 }
@@ -320,6 +328,11 @@ int regmap_raw_read_range(struct regmap *map, uint 
range_num, uint offset,
        struct regmap_range *range;
        void *ptr;
 
+#if CONFIG_IS_ENABLED(REGMAP_ACCESSORS)
+       if (map->reg_read)
+               return map->reg_read(map->bus_context, offset, valp);
+#endif
+
        if (range_num >= map->range_count) {
                debug("%s: range index %d larger than range count\n",
                      __func__, range_num);
@@ -429,6 +442,11 @@ int regmap_raw_write_range(struct regmap *map, uint 
range_num, uint offset,
        struct regmap_range *range;
        void *ptr;
 
+#if CONFIG_IS_ENABLED(REGMAP_ACCESSORS)
+       if (map->reg_write)
+               return map->reg_write(map->bus_context, offset,
+                                     *(unsigned int *)val);
+#endif
        if (range_num >= map->range_count) {
                debug("%s: range index %d larger than range count\n",
                      __func__, range_num);
diff --git a/include/regmap.h b/include/regmap.h
index 624cdd8c98..730e747d90 100644
--- a/include/regmap.h
+++ b/include/regmap.h
@@ -74,16 +74,38 @@ struct regmap_range {
 };
 
 struct regmap_bus;
-struct regmap_config;
+/**
+ * struct regmap_config - a way of accessing hardware/bus registers
+ *
+ * @reg_read:    Optional callback that if filled will be used to perform
+ *               all the reads from the registers. Should only be provided for
+ *               devices whose read operation cannot be represented as a simple
+ *               read operation on a bus such as SPI, I2C, etc. Most of the
+ *               devices do not need this.
+ * @reg_write:   Same as above for writing.
+ */
+struct regmap_config {
+       int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
+       int (*reg_write)(void *context, unsigned int reg, unsigned int val);
+};
 
 /**
  * struct regmap - a way of accessing hardware/bus registers
  *
  * @range_count:       Number of ranges available within the map
  * @ranges:            Array of ranges
+ * @bus_context:       Data passed to bus-specific callbacks
+ * @reg_read:          Optional callback that if filled will be used to perform
+ *                     all the reads from the registers.
+ * @reg_write:         Same as above for writing.
  */
 struct regmap {
        enum regmap_endianness_t endianness;
+#if CONFIG_IS_ENABLED(REGMAP_ACCESSORS)
+       void *bus_context;
+       int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
+       int (*reg_write)(void *context, unsigned int reg, unsigned int val);
+#endif
        int range_count;
        struct regmap_range ranges[0];
 };
@@ -341,8 +363,8 @@ int regmap_init_mem_index(ofnode node, struct regmap 
**mapp, int index);
  *
  * @dev: Device that will be interacted with
  * @bus: Bus-specific callbacks to use with device (IGNORED)
- * @bus_context: Data passed to bus-specific callbacks (IGNORED)
- * @config: Configuration for register map (IGNORED)
+ * @bus_context: Data passed to bus-specific callbacks
+ * @config: Configuration for register map
  *
  * @Return a valid pointer to a struct regmap or a ERR_PTR() on error.
  * The structure is automatically freed when the device is unbound
-- 
2.17.1

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to