diff options
| author | Andrey Smirnov <andrew.smirnov@gmail.com> | 2013-01-12 15:54:12 -0500 |
|---|---|---|
| committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-01-13 18:04:01 -0500 |
| commit | ad278406b3b8b8e454af23b63df3c3d63f6aee94 (patch) | |
| tree | c5e936e0acf0b3ae7b9d88ba1601507a18c6769d | |
| parent | 9931faca02c604c22335f5a935a501bb2ace6e20 (diff) | |
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 <andrew.smirnov@gmail.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
| -rw-r--r-- | drivers/base/regmap/internal.h | 2 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap.c | 35 |
2 files changed, 28 insertions, 9 deletions
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 { | |||
| 74 | const struct regmap_access_table *volatile_table; | 74 | const struct regmap_access_table *volatile_table; |
| 75 | const struct regmap_access_table *precious_table; | 75 | const struct regmap_access_table *precious_table; |
| 76 | 76 | ||
| 77 | int (*reg_read)(void *context, unsigned int reg, unsigned int *val); | ||
| 78 | |||
| 77 | u8 read_flag_mask; | 79 | u8 read_flag_mask; |
| 78 | u8 write_flag_mask; | 80 | u8 write_flag_mask; |
| 79 | 81 | ||
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, | |||
| 34 | unsigned int mask, unsigned int val, | 34 | unsigned int mask, unsigned int val, |
| 35 | bool *change); | 35 | bool *change); |
| 36 | 36 | ||
| 37 | static int _regmap_bus_read(void *context, unsigned int reg, | ||
| 38 | unsigned int *val); | ||
| 39 | |||
| 37 | bool regmap_reg_in_ranges(unsigned int reg, | 40 | bool regmap_reg_in_ranges(unsigned int reg, |
| 38 | const struct regmap_range *ranges, | 41 | const struct regmap_range *ranges, |
| 39 | unsigned int nranges) | 42 | unsigned int nranges) |
| @@ -430,6 +433,8 @@ struct regmap *regmap_init(struct device *dev, | |||
| 430 | map->read_flag_mask = bus->read_flag_mask; | 433 | map->read_flag_mask = bus->read_flag_mask; |
| 431 | } | 434 | } |
| 432 | 435 | ||
| 436 | map->reg_read = _regmap_bus_read; | ||
| 437 | |||
| 433 | reg_endian = config->reg_format_endian; | 438 | reg_endian = config->reg_format_endian; |
| 434 | if (reg_endian == REGMAP_ENDIAN_DEFAULT) | 439 | if (reg_endian == REGMAP_ENDIAN_DEFAULT) |
| 435 | reg_endian = bus->reg_format_endian_default; | 440 | reg_endian = bus->reg_format_endian_default; |
| @@ -1202,10 +1207,27 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
| 1202 | return ret; | 1207 | return ret; |
| 1203 | } | 1208 | } |
| 1204 | 1209 | ||
| 1210 | static int _regmap_bus_read(void *context, unsigned int reg, | ||
| 1211 | unsigned int *val) | ||
| 1212 | { | ||
| 1213 | int ret; | ||
| 1214 | struct regmap *map = context; | ||
| 1215 | |||
| 1216 | if (!map->format.parse_val) | ||
| 1217 | return -EINVAL; | ||
| 1218 | |||
| 1219 | ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes); | ||
| 1220 | if (ret == 0) | ||
| 1221 | *val = map->format.parse_val(map->work_buf); | ||
| 1222 | |||
| 1223 | return ret; | ||
| 1224 | } | ||
| 1225 | |||
| 1205 | static int _regmap_read(struct regmap *map, unsigned int reg, | 1226 | static int _regmap_read(struct regmap *map, unsigned int reg, |
| 1206 | unsigned int *val) | 1227 | unsigned int *val) |
| 1207 | { | 1228 | { |
| 1208 | int ret; | 1229 | int ret; |
| 1230 | BUG_ON(!map->reg_read); | ||
| 1209 | 1231 | ||
| 1210 | if (!map->cache_bypass) { | 1232 | if (!map->cache_bypass) { |
| 1211 | ret = regcache_read(map, reg, val); | 1233 | ret = regcache_read(map, reg, val); |
| @@ -1213,26 +1235,21 @@ static int _regmap_read(struct regmap *map, unsigned int reg, | |||
| 1213 | return 0; | 1235 | return 0; |
| 1214 | } | 1236 | } |
| 1215 | 1237 | ||
| 1216 | if (!map->format.parse_val) | ||
| 1217 | return -EINVAL; | ||
| 1218 | |||
| 1219 | if (map->cache_only) | 1238 | if (map->cache_only) |
| 1220 | return -EBUSY; | 1239 | return -EBUSY; |
| 1221 | 1240 | ||
| 1222 | ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes); | 1241 | ret = map->reg_read(map, reg, val); |
| 1223 | if (ret == 0) { | 1242 | if (ret == 0) { |
| 1224 | *val = map->format.parse_val(map->work_buf); | ||
| 1225 | |||
| 1226 | #ifdef LOG_DEVICE | 1243 | #ifdef LOG_DEVICE |
| 1227 | if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) | 1244 | if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) |
| 1228 | dev_info(map->dev, "%x => %x\n", reg, *val); | 1245 | dev_info(map->dev, "%x => %x\n", reg, *val); |
| 1229 | #endif | 1246 | #endif |
| 1230 | 1247 | ||
| 1231 | trace_regmap_reg_read(map->dev, reg, *val); | 1248 | trace_regmap_reg_read(map->dev, reg, *val); |
| 1232 | } | ||
| 1233 | 1249 | ||
| 1234 | if (ret == 0 && !map->cache_bypass) | 1250 | if (!map->cache_bypass) |
| 1235 | regcache_write(map, reg, *val); | 1251 | regcache_write(map, reg, *val); |
| 1252 | } | ||
| 1236 | 1253 | ||
| 1237 | return ret; | 1254 | return ret; |
| 1238 | } | 1255 | } |
