diff options
| author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-02-14 12:11:09 -0500 |
|---|---|---|
| committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-02-14 12:11:09 -0500 |
| commit | a2b37efc4e2aa76a5be29bbde8a2cd1c9c9066bc (patch) | |
| tree | 0be4360b343ab037666d9b1d4ca326ef59e9615d | |
| parent | a31f68497e07f5fec7155bc07dc633fc6eaa0adb (diff) | |
| parent | d2a5884a64161b524cc6749ee11b95d252e497f3 (diff) | |
Merge remote-tracking branch 'regmap/topic/no-bus' into regmap-next
| -rw-r--r-- | drivers/base/regmap/internal.h | 2 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap.c | 58 | ||||
| -rw-r--r-- | include/linux/regmap.h | 18 |
3 files changed, 65 insertions, 13 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 70ca270b77e2..5a22bd33ce3d 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h | |||
| @@ -91,6 +91,8 @@ struct regmap { | |||
| 91 | int (*reg_read)(void *context, unsigned int reg, unsigned int *val); | 91 | int (*reg_read)(void *context, unsigned int reg, unsigned int *val); |
| 92 | int (*reg_write)(void *context, unsigned int reg, unsigned int val); | 92 | int (*reg_write)(void *context, unsigned int reg, unsigned int val); |
| 93 | 93 | ||
| 94 | bool defer_caching; | ||
| 95 | |||
| 94 | u8 read_flag_mask; | 96 | u8 read_flag_mask; |
| 95 | u8 write_flag_mask; | 97 | u8 write_flag_mask; |
| 96 | 98 | ||
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index b1d962434cb2..3d2367501fd0 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
| @@ -389,7 +389,7 @@ struct regmap *regmap_init(struct device *dev, | |||
| 389 | enum regmap_endian reg_endian, val_endian; | 389 | enum regmap_endian reg_endian, val_endian; |
| 390 | int i, j; | 390 | int i, j; |
| 391 | 391 | ||
| 392 | if (!bus || !config) | 392 | if (!config) |
| 393 | goto err; | 393 | goto err; |
| 394 | 394 | ||
| 395 | map = kzalloc(sizeof(*map), GFP_KERNEL); | 395 | map = kzalloc(sizeof(*map), GFP_KERNEL); |
| @@ -403,7 +403,8 @@ struct regmap *regmap_init(struct device *dev, | |||
| 403 | map->unlock = config->unlock; | 403 | map->unlock = config->unlock; |
| 404 | map->lock_arg = config->lock_arg; | 404 | map->lock_arg = config->lock_arg; |
| 405 | } else { | 405 | } else { |
| 406 | if (bus->fast_io) { | 406 | if ((bus && bus->fast_io) || |
| 407 | config->fast_io) { | ||
| 407 | spin_lock_init(&map->spinlock); | 408 | spin_lock_init(&map->spinlock); |
| 408 | map->lock = regmap_lock_spinlock; | 409 | map->lock = regmap_lock_spinlock; |
| 409 | map->unlock = regmap_unlock_spinlock; | 410 | map->unlock = regmap_unlock_spinlock; |
| @@ -447,11 +448,19 @@ struct regmap *regmap_init(struct device *dev, | |||
| 447 | if (config->read_flag_mask || config->write_flag_mask) { | 448 | if (config->read_flag_mask || config->write_flag_mask) { |
| 448 | map->read_flag_mask = config->read_flag_mask; | 449 | map->read_flag_mask = config->read_flag_mask; |
| 449 | map->write_flag_mask = config->write_flag_mask; | 450 | map->write_flag_mask = config->write_flag_mask; |
| 450 | } else { | 451 | } else if (bus) { |
| 451 | map->read_flag_mask = bus->read_flag_mask; | 452 | map->read_flag_mask = bus->read_flag_mask; |
| 452 | } | 453 | } |
| 453 | 454 | ||
| 454 | map->reg_read = _regmap_bus_read; | 455 | if (!bus) { |
| 456 | map->reg_read = config->reg_read; | ||
| 457 | map->reg_write = config->reg_write; | ||
| 458 | |||
| 459 | map->defer_caching = false; | ||
| 460 | goto skip_format_initialization; | ||
| 461 | } else { | ||
| 462 | map->reg_read = _regmap_bus_read; | ||
| 463 | } | ||
| 455 | 464 | ||
| 456 | reg_endian = config->reg_format_endian; | 465 | reg_endian = config->reg_format_endian; |
| 457 | if (reg_endian == REGMAP_ENDIAN_DEFAULT) | 466 | if (reg_endian == REGMAP_ENDIAN_DEFAULT) |
| @@ -604,10 +613,15 @@ struct regmap *regmap_init(struct device *dev, | |||
| 604 | goto err_map; | 613 | goto err_map; |
| 605 | } | 614 | } |
| 606 | 615 | ||
| 607 | if (map->format.format_write) | 616 | if (map->format.format_write) { |
| 617 | map->defer_caching = false; | ||
| 608 | map->reg_write = _regmap_bus_formatted_write; | 618 | map->reg_write = _regmap_bus_formatted_write; |
| 609 | else if (map->format.format_val) | 619 | } else if (map->format.format_val) { |
| 620 | map->defer_caching = true; | ||
| 610 | map->reg_write = _regmap_bus_raw_write; | 621 | map->reg_write = _regmap_bus_raw_write; |
| 622 | } | ||
| 623 | |||
| 624 | skip_format_initialization: | ||
| 611 | 625 | ||
| 612 | map->range_tree = RB_ROOT; | 626 | map->range_tree = RB_ROOT; |
| 613 | for (i = 0; i < config->num_ranges; i++) { | 627 | for (i = 0; i < config->num_ranges; i++) { |
| @@ -810,7 +824,7 @@ void regmap_exit(struct regmap *map) | |||
| 810 | regcache_exit(map); | 824 | regcache_exit(map); |
| 811 | regmap_debugfs_exit(map); | 825 | regmap_debugfs_exit(map); |
| 812 | regmap_range_exit(map); | 826 | regmap_range_exit(map); |
| 813 | if (map->bus->free_context) | 827 | if (map->bus && map->bus->free_context) |
| 814 | map->bus->free_context(map->bus_context); | 828 | map->bus->free_context(map->bus_context); |
| 815 | kfree(map->work_buf); | 829 | kfree(map->work_buf); |
| 816 | kfree(map); | 830 | kfree(map); |
| @@ -916,6 +930,8 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
| 916 | size_t len; | 930 | size_t len; |
| 917 | int i; | 931 | int i; |
| 918 | 932 | ||
| 933 | BUG_ON(!map->bus); | ||
| 934 | |||
| 919 | /* Check for unwritable registers before we start */ | 935 | /* Check for unwritable registers before we start */ |
| 920 | if (map->writeable_reg) | 936 | if (map->writeable_reg) |
| 921 | for (i = 0; i < val_len / map->format.val_bytes; i++) | 937 | for (i = 0; i < val_len / map->format.val_bytes; i++) |
| @@ -1068,7 +1084,7 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg, | |||
| 1068 | struct regmap_range_node *range; | 1084 | struct regmap_range_node *range; |
| 1069 | struct regmap *map = context; | 1085 | struct regmap *map = context; |
| 1070 | 1086 | ||
| 1071 | BUG_ON(!map->format.format_write); | 1087 | BUG_ON(!map->bus || !map->format.format_write); |
| 1072 | 1088 | ||
| 1073 | range = _regmap_range_lookup(map, reg); | 1089 | range = _regmap_range_lookup(map, reg); |
| 1074 | if (range) { | 1090 | if (range) { |
| @@ -1094,7 +1110,7 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg, | |||
| 1094 | { | 1110 | { |
| 1095 | struct regmap *map = context; | 1111 | struct regmap *map = context; |
| 1096 | 1112 | ||
| 1097 | BUG_ON(!map->format.format_val); | 1113 | BUG_ON(!map->bus || !map->format.format_val); |
| 1098 | 1114 | ||
| 1099 | map->format.format_val(map->work_buf + map->format.reg_bytes | 1115 | map->format.format_val(map->work_buf + map->format.reg_bytes |
| 1100 | + map->format.pad_bytes, val, 0); | 1116 | + map->format.pad_bytes, val, 0); |
| @@ -1105,12 +1121,18 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg, | |||
| 1105 | map->format.val_bytes, false); | 1121 | map->format.val_bytes, false); |
| 1106 | } | 1122 | } |
| 1107 | 1123 | ||
| 1124 | static inline void *_regmap_map_get_context(struct regmap *map) | ||
| 1125 | { | ||
| 1126 | return (map->bus) ? map : map->bus_context; | ||
| 1127 | } | ||
| 1128 | |||
| 1108 | int _regmap_write(struct regmap *map, unsigned int reg, | 1129 | int _regmap_write(struct regmap *map, unsigned int reg, |
| 1109 | unsigned int val) | 1130 | unsigned int val) |
| 1110 | { | 1131 | { |
| 1111 | int ret; | 1132 | int ret; |
| 1133 | void *context = _regmap_map_get_context(map); | ||
| 1112 | 1134 | ||
| 1113 | if (!map->cache_bypass && map->format.format_write) { | 1135 | if (!map->cache_bypass && !map->defer_caching) { |
| 1114 | ret = regcache_write(map, reg, val); | 1136 | ret = regcache_write(map, reg, val); |
| 1115 | if (ret != 0) | 1137 | if (ret != 0) |
| 1116 | return ret; | 1138 | return ret; |
| @@ -1127,7 +1149,7 @@ int _regmap_write(struct regmap *map, unsigned int reg, | |||
| 1127 | 1149 | ||
| 1128 | trace_regmap_reg_write(map->dev, reg, val); | 1150 | trace_regmap_reg_write(map->dev, reg, val); |
| 1129 | 1151 | ||
| 1130 | return map->reg_write(map, reg, val); | 1152 | return map->reg_write(context, reg, val); |
| 1131 | } | 1153 | } |
| 1132 | 1154 | ||
| 1133 | /** | 1155 | /** |
| @@ -1178,6 +1200,8 @@ int regmap_raw_write(struct regmap *map, unsigned int reg, | |||
| 1178 | { | 1200 | { |
| 1179 | int ret; | 1201 | int ret; |
| 1180 | 1202 | ||
| 1203 | if (!map->bus) | ||
| 1204 | return -EINVAL; | ||
| 1181 | if (val_len % map->format.val_bytes) | 1205 | if (val_len % map->format.val_bytes) |
| 1182 | return -EINVAL; | 1206 | return -EINVAL; |
| 1183 | if (reg % map->reg_stride) | 1207 | if (reg % map->reg_stride) |
| @@ -1214,6 +1238,8 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
| 1214 | size_t val_bytes = map->format.val_bytes; | 1238 | size_t val_bytes = map->format.val_bytes; |
| 1215 | void *wval; | 1239 | void *wval; |
| 1216 | 1240 | ||
| 1241 | if (!map->bus) | ||
| 1242 | return -EINVAL; | ||
| 1217 | if (!map->format.parse_val) | 1243 | if (!map->format.parse_val) |
| 1218 | return -EINVAL; | 1244 | return -EINVAL; |
| 1219 | if (reg % map->reg_stride) | 1245 | if (reg % map->reg_stride) |
| @@ -1310,6 +1336,8 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
| 1310 | u8 *u8 = map->work_buf; | 1336 | u8 *u8 = map->work_buf; |
| 1311 | int ret; | 1337 | int ret; |
| 1312 | 1338 | ||
| 1339 | BUG_ON(!map->bus); | ||
| 1340 | |||
| 1313 | range = _regmap_range_lookup(map, reg); | 1341 | range = _regmap_range_lookup(map, reg); |
| 1314 | if (range) { | 1342 | if (range) { |
| 1315 | ret = _regmap_select_page(map, ®, range, | 1343 | ret = _regmap_select_page(map, ®, range, |
| @@ -1361,6 +1389,8 @@ static int _regmap_read(struct regmap *map, unsigned int reg, | |||
| 1361 | unsigned int *val) | 1389 | unsigned int *val) |
| 1362 | { | 1390 | { |
| 1363 | int ret; | 1391 | int ret; |
| 1392 | void *context = _regmap_map_get_context(map); | ||
| 1393 | |||
| 1364 | BUG_ON(!map->reg_read); | 1394 | BUG_ON(!map->reg_read); |
| 1365 | 1395 | ||
| 1366 | if (!map->cache_bypass) { | 1396 | if (!map->cache_bypass) { |
| @@ -1372,7 +1402,7 @@ static int _regmap_read(struct regmap *map, unsigned int reg, | |||
| 1372 | if (map->cache_only) | 1402 | if (map->cache_only) |
| 1373 | return -EBUSY; | 1403 | return -EBUSY; |
| 1374 | 1404 | ||
| 1375 | ret = map->reg_read(map, reg, val); | 1405 | ret = map->reg_read(context, reg, val); |
| 1376 | if (ret == 0) { | 1406 | if (ret == 0) { |
| 1377 | #ifdef LOG_DEVICE | 1407 | #ifdef LOG_DEVICE |
| 1378 | if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) | 1408 | if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) |
| @@ -1434,6 +1464,8 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
| 1434 | unsigned int v; | 1464 | unsigned int v; |
| 1435 | int ret, i; | 1465 | int ret, i; |
| 1436 | 1466 | ||
| 1467 | if (!map->bus) | ||
| 1468 | return -EINVAL; | ||
| 1437 | if (val_len % map->format.val_bytes) | 1469 | if (val_len % map->format.val_bytes) |
| 1438 | return -EINVAL; | 1470 | return -EINVAL; |
| 1439 | if (reg % map->reg_stride) | 1471 | if (reg % map->reg_stride) |
| @@ -1485,6 +1517,8 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, | |||
| 1485 | size_t val_bytes = map->format.val_bytes; | 1517 | size_t val_bytes = map->format.val_bytes; |
| 1486 | bool vol = regmap_volatile_range(map, reg, val_count); | 1518 | bool vol = regmap_volatile_range(map, reg, val_count); |
| 1487 | 1519 | ||
| 1520 | if (!map->bus) | ||
| 1521 | return -EINVAL; | ||
| 1488 | if (!map->format.parse_val) | 1522 | if (!map->format.parse_val) |
| 1489 | return -EINVAL; | 1523 | return -EINVAL; |
| 1490 | if (reg % map->reg_stride) | 1524 | if (reg % map->reg_stride) |
diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 017b3bd085a2..bf77dfdabef9 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h | |||
| @@ -128,7 +128,18 @@ typedef void (*regmap_unlock)(void *); | |||
| 128 | * @lock_arg: this field is passed as the only argument of lock/unlock | 128 | * @lock_arg: this field is passed as the only argument of lock/unlock |
| 129 | * functions (ignored in case regular lock/unlock functions | 129 | * functions (ignored in case regular lock/unlock functions |
| 130 | * are not overridden). | 130 | * are not overridden). |
| 131 | * | 131 | * @reg_read: Optional callback that if filled will be used to perform |
| 132 | * all the reads from the registers. Should only be provided for | ||
| 133 | * devices whos read operation cannot be represented as a simple read | ||
| 134 | * operation on a bus such as SPI, I2C, etc. Most of the devices do | ||
| 135 | * not need this. | ||
| 136 | * @reg_write: Same as above for writing. | ||
| 137 | * @fast_io: Register IO is fast. Use a spinlock instead of a mutex | ||
| 138 | * to perform locking. This field is ignored if custom lock/unlock | ||
| 139 | * functions are used (see fields lock/unlock of struct regmap_config). | ||
| 140 | * This field is a duplicate of a similar file in | ||
| 141 | * 'struct regmap_bus' and serves exact same purpose. | ||
| 142 | * Use it only for "no-bus" cases. | ||
| 132 | * @max_register: Optional, specifies the maximum valid register index. | 143 | * @max_register: Optional, specifies the maximum valid register index. |
| 133 | * @wr_table: Optional, points to a struct regmap_access_table specifying | 144 | * @wr_table: Optional, points to a struct regmap_access_table specifying |
| 134 | * valid ranges for write access. | 145 | * valid ranges for write access. |
| @@ -178,6 +189,11 @@ struct regmap_config { | |||
| 178 | regmap_unlock unlock; | 189 | regmap_unlock unlock; |
| 179 | void *lock_arg; | 190 | void *lock_arg; |
| 180 | 191 | ||
| 192 | int (*reg_read)(void *context, unsigned int reg, unsigned int *val); | ||
| 193 | int (*reg_write)(void *context, unsigned int reg, unsigned int val); | ||
| 194 | |||
| 195 | bool fast_io; | ||
| 196 | |||
| 181 | unsigned int max_register; | 197 | unsigned int max_register; |
| 182 | const struct regmap_access_table *wr_table; | 198 | const struct regmap_access_table *wr_table; |
| 183 | const struct regmap_access_table *rd_table; | 199 | const struct regmap_access_table *rd_table; |
