Loading drivers/base/regmap/internal.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -91,6 +91,8 @@ struct regmap { int (*reg_read)(void *context, unsigned int reg, unsigned int *val); int (*reg_read)(void *context, unsigned int reg, unsigned int *val); int (*reg_write)(void *context, unsigned int reg, unsigned int val); int (*reg_write)(void *context, unsigned int reg, unsigned int val); bool defer_caching; u8 read_flag_mask; u8 read_flag_mask; u8 write_flag_mask; u8 write_flag_mask; Loading drivers/base/regmap/regmap.c +46 −12 Original line number Original line Diff line number Diff line Loading @@ -389,7 +389,7 @@ struct regmap *regmap_init(struct device *dev, enum regmap_endian reg_endian, val_endian; enum regmap_endian reg_endian, val_endian; int i, j; int i, j; if (!bus || !config) if (!config) goto err; goto err; map = kzalloc(sizeof(*map), GFP_KERNEL); map = kzalloc(sizeof(*map), GFP_KERNEL); Loading @@ -403,7 +403,8 @@ struct regmap *regmap_init(struct device *dev, map->unlock = config->unlock; map->unlock = config->unlock; map->lock_arg = config->lock_arg; map->lock_arg = config->lock_arg; } else { } else { if (bus->fast_io) { if ((bus && bus->fast_io) || config->fast_io) { spin_lock_init(&map->spinlock); spin_lock_init(&map->spinlock); map->lock = regmap_lock_spinlock; map->lock = regmap_lock_spinlock; map->unlock = regmap_unlock_spinlock; map->unlock = regmap_unlock_spinlock; Loading Loading @@ -447,11 +448,19 @@ struct regmap *regmap_init(struct device *dev, if (config->read_flag_mask || config->write_flag_mask) { if (config->read_flag_mask || config->write_flag_mask) { map->read_flag_mask = config->read_flag_mask; map->read_flag_mask = config->read_flag_mask; map->write_flag_mask = config->write_flag_mask; map->write_flag_mask = config->write_flag_mask; } else { } else if (bus) { map->read_flag_mask = bus->read_flag_mask; map->read_flag_mask = bus->read_flag_mask; } } if (!bus) { map->reg_read = config->reg_read; map->reg_write = config->reg_write; map->defer_caching = false; goto skip_format_initialization; } else { map->reg_read = _regmap_bus_read; map->reg_read = _regmap_bus_read; } reg_endian = config->reg_format_endian; reg_endian = config->reg_format_endian; if (reg_endian == REGMAP_ENDIAN_DEFAULT) if (reg_endian == REGMAP_ENDIAN_DEFAULT) Loading Loading @@ -604,10 +613,15 @@ struct regmap *regmap_init(struct device *dev, goto err_map; goto err_map; } } if (map->format.format_write) if (map->format.format_write) { map->defer_caching = false; map->reg_write = _regmap_bus_formatted_write; map->reg_write = _regmap_bus_formatted_write; else if (map->format.format_val) } else if (map->format.format_val) { map->defer_caching = true; map->reg_write = _regmap_bus_raw_write; map->reg_write = _regmap_bus_raw_write; } skip_format_initialization: map->range_tree = RB_ROOT; map->range_tree = RB_ROOT; for (i = 0; i < config->num_ranges; i++) { for (i = 0; i < config->num_ranges; i++) { Loading Loading @@ -810,7 +824,7 @@ void regmap_exit(struct regmap *map) regcache_exit(map); regcache_exit(map); regmap_debugfs_exit(map); regmap_debugfs_exit(map); regmap_range_exit(map); regmap_range_exit(map); if (map->bus->free_context) if (map->bus && map->bus->free_context) map->bus->free_context(map->bus_context); map->bus->free_context(map->bus_context); kfree(map->work_buf); kfree(map->work_buf); kfree(map); kfree(map); Loading Loading @@ -916,6 +930,8 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, size_t len; size_t len; int i; int i; BUG_ON(!map->bus); /* Check for unwritable registers before we start */ /* Check for unwritable registers before we start */ if (map->writeable_reg) if (map->writeable_reg) for (i = 0; i < val_len / map->format.val_bytes; i++) for (i = 0; i < val_len / map->format.val_bytes; i++) Loading Loading @@ -1068,7 +1084,7 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg, struct regmap_range_node *range; struct regmap_range_node *range; struct regmap *map = context; struct regmap *map = context; BUG_ON(!map->format.format_write); BUG_ON(!map->bus || !map->format.format_write); range = _regmap_range_lookup(map, reg); range = _regmap_range_lookup(map, reg); if (range) { if (range) { Loading @@ -1094,7 +1110,7 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg, { { struct regmap *map = context; struct regmap *map = context; BUG_ON(!map->format.format_val); BUG_ON(!map->bus || !map->format.format_val); map->format.format_val(map->work_buf + map->format.reg_bytes map->format.format_val(map->work_buf + map->format.reg_bytes + map->format.pad_bytes, val, 0); + map->format.pad_bytes, val, 0); Loading @@ -1105,12 +1121,18 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg, map->format.val_bytes, false); map->format.val_bytes, false); } } static inline void *_regmap_map_get_context(struct regmap *map) { return (map->bus) ? map : map->bus_context; } int _regmap_write(struct regmap *map, unsigned int reg, int _regmap_write(struct regmap *map, unsigned int reg, unsigned int val) unsigned int val) { { int ret; int ret; void *context = _regmap_map_get_context(map); if (!map->cache_bypass && map->format.format_write) { if (!map->cache_bypass && !map->defer_caching) { ret = regcache_write(map, reg, val); ret = regcache_write(map, reg, val); if (ret != 0) if (ret != 0) return ret; return ret; Loading @@ -1127,7 +1149,7 @@ int _regmap_write(struct regmap *map, unsigned int reg, trace_regmap_reg_write(map->dev, reg, val); trace_regmap_reg_write(map->dev, reg, val); return map->reg_write(map, reg, val); return map->reg_write(context, reg, val); } } /** /** Loading Loading @@ -1178,6 +1200,8 @@ int regmap_raw_write(struct regmap *map, unsigned int reg, { { int ret; int ret; if (!map->bus) return -EINVAL; if (val_len % map->format.val_bytes) if (val_len % map->format.val_bytes) return -EINVAL; return -EINVAL; if (reg % map->reg_stride) if (reg % map->reg_stride) Loading Loading @@ -1214,6 +1238,8 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, size_t val_bytes = map->format.val_bytes; size_t val_bytes = map->format.val_bytes; void *wval; void *wval; if (!map->bus) return -EINVAL; if (!map->format.parse_val) if (!map->format.parse_val) return -EINVAL; return -EINVAL; if (reg % map->reg_stride) if (reg % map->reg_stride) Loading Loading @@ -1310,6 +1336,8 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, u8 *u8 = map->work_buf; u8 *u8 = map->work_buf; int ret; int ret; BUG_ON(!map->bus); range = _regmap_range_lookup(map, reg); range = _regmap_range_lookup(map, reg); if (range) { if (range) { ret = _regmap_select_page(map, ®, range, ret = _regmap_select_page(map, ®, range, Loading Loading @@ -1361,6 +1389,8 @@ static int _regmap_read(struct regmap *map, unsigned int reg, unsigned int *val) unsigned int *val) { { int ret; int ret; void *context = _regmap_map_get_context(map); BUG_ON(!map->reg_read); BUG_ON(!map->reg_read); if (!map->cache_bypass) { if (!map->cache_bypass) { Loading @@ -1372,7 +1402,7 @@ static int _regmap_read(struct regmap *map, unsigned int reg, if (map->cache_only) if (map->cache_only) return -EBUSY; return -EBUSY; ret = map->reg_read(map, reg, val); ret = map->reg_read(context, reg, val); if (ret == 0) { if (ret == 0) { #ifdef LOG_DEVICE #ifdef LOG_DEVICE if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) Loading Loading @@ -1434,6 +1464,8 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, unsigned int v; unsigned int v; int ret, i; int ret, i; if (!map->bus) return -EINVAL; if (val_len % map->format.val_bytes) if (val_len % map->format.val_bytes) return -EINVAL; return -EINVAL; if (reg % map->reg_stride) if (reg % map->reg_stride) Loading Loading @@ -1485,6 +1517,8 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, size_t val_bytes = map->format.val_bytes; size_t val_bytes = map->format.val_bytes; bool vol = regmap_volatile_range(map, reg, val_count); bool vol = regmap_volatile_range(map, reg, val_count); if (!map->bus) return -EINVAL; if (!map->format.parse_val) if (!map->format.parse_val) return -EINVAL; return -EINVAL; if (reg % map->reg_stride) if (reg % map->reg_stride) Loading include/linux/regmap.h +17 −1 Original line number Original line Diff line number Diff line Loading @@ -128,7 +128,18 @@ typedef void (*regmap_unlock)(void *); * @lock_arg: this field is passed as the only argument of lock/unlock * @lock_arg: this field is passed as the only argument of lock/unlock * functions (ignored in case regular lock/unlock functions * functions (ignored in case regular lock/unlock functions * are not overridden). * are not overridden). * * @reg_read: Optional callback that if filled will be used to perform * all the reads from the registers. Should only be provided for * devices whos 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. * @fast_io: Register IO is fast. Use a spinlock instead of a mutex * to perform locking. This field is ignored if custom lock/unlock * functions are used (see fields lock/unlock of struct regmap_config). * This field is a duplicate of a similar file in * 'struct regmap_bus' and serves exact same purpose. * Use it only for "no-bus" cases. * @max_register: Optional, specifies the maximum valid register index. * @max_register: Optional, specifies the maximum valid register index. * @wr_table: Optional, points to a struct regmap_access_table specifying * @wr_table: Optional, points to a struct regmap_access_table specifying * valid ranges for write access. * valid ranges for write access. Loading Loading @@ -178,6 +189,11 @@ struct regmap_config { regmap_unlock unlock; regmap_unlock unlock; void *lock_arg; void *lock_arg; int (*reg_read)(void *context, unsigned int reg, unsigned int *val); int (*reg_write)(void *context, unsigned int reg, unsigned int val); bool fast_io; unsigned int max_register; unsigned int max_register; const struct regmap_access_table *wr_table; const struct regmap_access_table *wr_table; const struct regmap_access_table *rd_table; const struct regmap_access_table *rd_table; Loading Loading
drivers/base/regmap/internal.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -91,6 +91,8 @@ struct regmap { int (*reg_read)(void *context, unsigned int reg, unsigned int *val); int (*reg_read)(void *context, unsigned int reg, unsigned int *val); int (*reg_write)(void *context, unsigned int reg, unsigned int val); int (*reg_write)(void *context, unsigned int reg, unsigned int val); bool defer_caching; u8 read_flag_mask; u8 read_flag_mask; u8 write_flag_mask; u8 write_flag_mask; Loading
drivers/base/regmap/regmap.c +46 −12 Original line number Original line Diff line number Diff line Loading @@ -389,7 +389,7 @@ struct regmap *regmap_init(struct device *dev, enum regmap_endian reg_endian, val_endian; enum regmap_endian reg_endian, val_endian; int i, j; int i, j; if (!bus || !config) if (!config) goto err; goto err; map = kzalloc(sizeof(*map), GFP_KERNEL); map = kzalloc(sizeof(*map), GFP_KERNEL); Loading @@ -403,7 +403,8 @@ struct regmap *regmap_init(struct device *dev, map->unlock = config->unlock; map->unlock = config->unlock; map->lock_arg = config->lock_arg; map->lock_arg = config->lock_arg; } else { } else { if (bus->fast_io) { if ((bus && bus->fast_io) || config->fast_io) { spin_lock_init(&map->spinlock); spin_lock_init(&map->spinlock); map->lock = regmap_lock_spinlock; map->lock = regmap_lock_spinlock; map->unlock = regmap_unlock_spinlock; map->unlock = regmap_unlock_spinlock; Loading Loading @@ -447,11 +448,19 @@ struct regmap *regmap_init(struct device *dev, if (config->read_flag_mask || config->write_flag_mask) { if (config->read_flag_mask || config->write_flag_mask) { map->read_flag_mask = config->read_flag_mask; map->read_flag_mask = config->read_flag_mask; map->write_flag_mask = config->write_flag_mask; map->write_flag_mask = config->write_flag_mask; } else { } else if (bus) { map->read_flag_mask = bus->read_flag_mask; map->read_flag_mask = bus->read_flag_mask; } } if (!bus) { map->reg_read = config->reg_read; map->reg_write = config->reg_write; map->defer_caching = false; goto skip_format_initialization; } else { map->reg_read = _regmap_bus_read; map->reg_read = _regmap_bus_read; } reg_endian = config->reg_format_endian; reg_endian = config->reg_format_endian; if (reg_endian == REGMAP_ENDIAN_DEFAULT) if (reg_endian == REGMAP_ENDIAN_DEFAULT) Loading Loading @@ -604,10 +613,15 @@ struct regmap *regmap_init(struct device *dev, goto err_map; goto err_map; } } if (map->format.format_write) if (map->format.format_write) { map->defer_caching = false; map->reg_write = _regmap_bus_formatted_write; map->reg_write = _regmap_bus_formatted_write; else if (map->format.format_val) } else if (map->format.format_val) { map->defer_caching = true; map->reg_write = _regmap_bus_raw_write; map->reg_write = _regmap_bus_raw_write; } skip_format_initialization: map->range_tree = RB_ROOT; map->range_tree = RB_ROOT; for (i = 0; i < config->num_ranges; i++) { for (i = 0; i < config->num_ranges; i++) { Loading Loading @@ -810,7 +824,7 @@ void regmap_exit(struct regmap *map) regcache_exit(map); regcache_exit(map); regmap_debugfs_exit(map); regmap_debugfs_exit(map); regmap_range_exit(map); regmap_range_exit(map); if (map->bus->free_context) if (map->bus && map->bus->free_context) map->bus->free_context(map->bus_context); map->bus->free_context(map->bus_context); kfree(map->work_buf); kfree(map->work_buf); kfree(map); kfree(map); Loading Loading @@ -916,6 +930,8 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, size_t len; size_t len; int i; int i; BUG_ON(!map->bus); /* Check for unwritable registers before we start */ /* Check for unwritable registers before we start */ if (map->writeable_reg) if (map->writeable_reg) for (i = 0; i < val_len / map->format.val_bytes; i++) for (i = 0; i < val_len / map->format.val_bytes; i++) Loading Loading @@ -1068,7 +1084,7 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg, struct regmap_range_node *range; struct regmap_range_node *range; struct regmap *map = context; struct regmap *map = context; BUG_ON(!map->format.format_write); BUG_ON(!map->bus || !map->format.format_write); range = _regmap_range_lookup(map, reg); range = _regmap_range_lookup(map, reg); if (range) { if (range) { Loading @@ -1094,7 +1110,7 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg, { { struct regmap *map = context; struct regmap *map = context; BUG_ON(!map->format.format_val); BUG_ON(!map->bus || !map->format.format_val); map->format.format_val(map->work_buf + map->format.reg_bytes map->format.format_val(map->work_buf + map->format.reg_bytes + map->format.pad_bytes, val, 0); + map->format.pad_bytes, val, 0); Loading @@ -1105,12 +1121,18 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg, map->format.val_bytes, false); map->format.val_bytes, false); } } static inline void *_regmap_map_get_context(struct regmap *map) { return (map->bus) ? map : map->bus_context; } int _regmap_write(struct regmap *map, unsigned int reg, int _regmap_write(struct regmap *map, unsigned int reg, unsigned int val) unsigned int val) { { int ret; int ret; void *context = _regmap_map_get_context(map); if (!map->cache_bypass && map->format.format_write) { if (!map->cache_bypass && !map->defer_caching) { ret = regcache_write(map, reg, val); ret = regcache_write(map, reg, val); if (ret != 0) if (ret != 0) return ret; return ret; Loading @@ -1127,7 +1149,7 @@ int _regmap_write(struct regmap *map, unsigned int reg, trace_regmap_reg_write(map->dev, reg, val); trace_regmap_reg_write(map->dev, reg, val); return map->reg_write(map, reg, val); return map->reg_write(context, reg, val); } } /** /** Loading Loading @@ -1178,6 +1200,8 @@ int regmap_raw_write(struct regmap *map, unsigned int reg, { { int ret; int ret; if (!map->bus) return -EINVAL; if (val_len % map->format.val_bytes) if (val_len % map->format.val_bytes) return -EINVAL; return -EINVAL; if (reg % map->reg_stride) if (reg % map->reg_stride) Loading Loading @@ -1214,6 +1238,8 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, size_t val_bytes = map->format.val_bytes; size_t val_bytes = map->format.val_bytes; void *wval; void *wval; if (!map->bus) return -EINVAL; if (!map->format.parse_val) if (!map->format.parse_val) return -EINVAL; return -EINVAL; if (reg % map->reg_stride) if (reg % map->reg_stride) Loading Loading @@ -1310,6 +1336,8 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, u8 *u8 = map->work_buf; u8 *u8 = map->work_buf; int ret; int ret; BUG_ON(!map->bus); range = _regmap_range_lookup(map, reg); range = _regmap_range_lookup(map, reg); if (range) { if (range) { ret = _regmap_select_page(map, ®, range, ret = _regmap_select_page(map, ®, range, Loading Loading @@ -1361,6 +1389,8 @@ static int _regmap_read(struct regmap *map, unsigned int reg, unsigned int *val) unsigned int *val) { { int ret; int ret; void *context = _regmap_map_get_context(map); BUG_ON(!map->reg_read); BUG_ON(!map->reg_read); if (!map->cache_bypass) { if (!map->cache_bypass) { Loading @@ -1372,7 +1402,7 @@ static int _regmap_read(struct regmap *map, unsigned int reg, if (map->cache_only) if (map->cache_only) return -EBUSY; return -EBUSY; ret = map->reg_read(map, reg, val); ret = map->reg_read(context, reg, val); if (ret == 0) { if (ret == 0) { #ifdef LOG_DEVICE #ifdef LOG_DEVICE if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) Loading Loading @@ -1434,6 +1464,8 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, unsigned int v; unsigned int v; int ret, i; int ret, i; if (!map->bus) return -EINVAL; if (val_len % map->format.val_bytes) if (val_len % map->format.val_bytes) return -EINVAL; return -EINVAL; if (reg % map->reg_stride) if (reg % map->reg_stride) Loading Loading @@ -1485,6 +1517,8 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, size_t val_bytes = map->format.val_bytes; size_t val_bytes = map->format.val_bytes; bool vol = regmap_volatile_range(map, reg, val_count); bool vol = regmap_volatile_range(map, reg, val_count); if (!map->bus) return -EINVAL; if (!map->format.parse_val) if (!map->format.parse_val) return -EINVAL; return -EINVAL; if (reg % map->reg_stride) if (reg % map->reg_stride) Loading
include/linux/regmap.h +17 −1 Original line number Original line Diff line number Diff line Loading @@ -128,7 +128,18 @@ typedef void (*regmap_unlock)(void *); * @lock_arg: this field is passed as the only argument of lock/unlock * @lock_arg: this field is passed as the only argument of lock/unlock * functions (ignored in case regular lock/unlock functions * functions (ignored in case regular lock/unlock functions * are not overridden). * are not overridden). * * @reg_read: Optional callback that if filled will be used to perform * all the reads from the registers. Should only be provided for * devices whos 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. * @fast_io: Register IO is fast. Use a spinlock instead of a mutex * to perform locking. This field is ignored if custom lock/unlock * functions are used (see fields lock/unlock of struct regmap_config). * This field is a duplicate of a similar file in * 'struct regmap_bus' and serves exact same purpose. * Use it only for "no-bus" cases. * @max_register: Optional, specifies the maximum valid register index. * @max_register: Optional, specifies the maximum valid register index. * @wr_table: Optional, points to a struct regmap_access_table specifying * @wr_table: Optional, points to a struct regmap_access_table specifying * valid ranges for write access. * valid ranges for write access. Loading Loading @@ -178,6 +189,11 @@ struct regmap_config { regmap_unlock unlock; regmap_unlock unlock; void *lock_arg; void *lock_arg; int (*reg_read)(void *context, unsigned int reg, unsigned int *val); int (*reg_write)(void *context, unsigned int reg, unsigned int val); bool fast_io; unsigned int max_register; unsigned int max_register; const struct regmap_access_table *wr_table; const struct regmap_access_table *wr_table; const struct regmap_access_table *rd_table; const struct regmap_access_table *rd_table; Loading