
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 jjhiblot@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