From: Andrey Smirnov Date: Sat, 12 Jan 2013 20:54:12 +0000 (-0800) Subject: regmap: Add provisions to have user-defined read operation X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=ad278406b3b8b8e454af23b63df3c3d63f6aee94;p=openwrt%2Fstaging%2Fblogic.git regmap: Add provisions to have user-defined read operation This commit is a preparatory commit to provide "no-bus" configuration option for regmap API. It adds necessary plumbing needed to have the ability to provide user define register read function. Signed-off-by: Andrey Smirnov Signed-off-by: Mark Brown --- diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 401d1919635a..471eb90276e4 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h @@ -74,6 +74,8 @@ struct regmap { const struct regmap_access_table *volatile_table; const struct regmap_access_table *precious_table; + int (*reg_read)(void *context, unsigned int reg, unsigned int *val); + u8 read_flag_mask; u8 write_flag_mask; diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 42d5cb0f503f..ceaefcfda8de 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -34,6 +34,9 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg, unsigned int mask, unsigned int val, bool *change); +static int _regmap_bus_read(void *context, unsigned int reg, + unsigned int *val); + bool regmap_reg_in_ranges(unsigned int reg, const struct regmap_range *ranges, unsigned int nranges) @@ -430,6 +433,8 @@ struct regmap *regmap_init(struct device *dev, map->read_flag_mask = bus->read_flag_mask; } + map->reg_read = _regmap_bus_read; + reg_endian = config->reg_format_endian; if (reg_endian == REGMAP_ENDIAN_DEFAULT) reg_endian = bus->reg_format_endian_default; @@ -1202,10 +1207,27 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, return ret; } +static int _regmap_bus_read(void *context, unsigned int reg, + unsigned int *val) +{ + int ret; + struct regmap *map = context; + + if (!map->format.parse_val) + return -EINVAL; + + ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes); + if (ret == 0) + *val = map->format.parse_val(map->work_buf); + + return ret; +} + static int _regmap_read(struct regmap *map, unsigned int reg, unsigned int *val) { int ret; + BUG_ON(!map->reg_read); if (!map->cache_bypass) { ret = regcache_read(map, reg, val); @@ -1213,26 +1235,21 @@ static int _regmap_read(struct regmap *map, unsigned int reg, return 0; } - if (!map->format.parse_val) - return -EINVAL; - if (map->cache_only) return -EBUSY; - ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes); + ret = map->reg_read(map, reg, val); if (ret == 0) { - *val = map->format.parse_val(map->work_buf); - #ifdef LOG_DEVICE if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) dev_info(map->dev, "%x => %x\n", reg, *val); #endif trace_regmap_reg_read(map->dev, reg, *val); - } - if (ret == 0 && !map->cache_bypass) - regcache_write(map, reg, *val); + if (!map->cache_bypass) + regcache_write(map, reg, *val); + } return ret; }