···5252struct regmap {5353 struct mutex mutex;5454 spinlock_t spinlock;5555+ unsigned long spinlock_flags;5556 regmap_lock lock;5657 regmap_unlock unlock;5758 void *lock_arg; /* This is passed to lock/unlock functions */···149148 int (*read)(struct regmap *map, unsigned int reg, unsigned int *value);150149 int (*write)(struct regmap *map, unsigned int reg, unsigned int value);151150 int (*sync)(struct regmap *map, unsigned int min, unsigned int max);151151+ int (*drop)(struct regmap *map, unsigned int min, unsigned int max);152152};153153154154bool regmap_writeable(struct regmap *map, unsigned int reg);
+48-14
drivers/base/regmap/regcache-rbtree.c
···304304 return 0;305305}306306307307+static struct regcache_rbtree_node *308308+regcache_rbtree_node_alloc(struct regmap *map, unsigned int reg)309309+{310310+ struct regcache_rbtree_node *rbnode;311311+ const struct regmap_range *range;312312+ int i;313313+314314+ rbnode = kzalloc(sizeof(*rbnode), GFP_KERNEL);315315+ if (!rbnode)316316+ return NULL;317317+318318+ /* If there is a read table then use it to guess at an allocation */319319+ if (map->rd_table) {320320+ for (i = 0; i < map->rd_table->n_yes_ranges; i++) {321321+ if (regmap_reg_in_range(reg,322322+ &map->rd_table->yes_ranges[i]))323323+ break;324324+ }325325+326326+ if (i != map->rd_table->n_yes_ranges) {327327+ range = &map->rd_table->yes_ranges[i];328328+ rbnode->blklen = range->range_max - range->range_min329329+ + 1;330330+ rbnode->base_reg = range->range_min;331331+ }332332+ }333333+334334+ if (!rbnode->blklen) {335335+ rbnode->blklen = sizeof(*rbnode);336336+ rbnode->base_reg = reg;337337+ }338338+339339+ rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size,340340+ GFP_KERNEL);341341+ if (!rbnode->block) {342342+ kfree(rbnode);343343+ return NULL;344344+ }345345+346346+ return rbnode;347347+}348348+307349static int regcache_rbtree_write(struct regmap *map, unsigned int reg,308350 unsigned int value)309351{···396354 return 0;397355 }398356 }399399- /* we did not manage to find a place to insert it in an existing400400- * block so create a new rbnode with a single register in its block.401401- * This block will get populated further if any other adjacent402402- * registers get modified in the future.357357+358358+ /* We did not manage to find a place to insert it in359359+ * an existing block so create a new rbnode.403360 */404404- rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL);361361+ rbnode = regcache_rbtree_node_alloc(map, reg);405362 if (!rbnode)406363 return -ENOMEM;407407- rbnode->blklen = sizeof(*rbnode);408408- rbnode->base_reg = reg;409409- rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size,410410- GFP_KERNEL);411411- if (!rbnode->block) {412412- kfree(rbnode);413413- return -ENOMEM;414414- }415415- regcache_rbtree_set_register(map, rbnode, 0, value);364364+ regcache_rbtree_set_register(map, rbnode,365365+ reg - rbnode->base_reg, value);416366 regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode);417367 rbtree_ctx->cached_rbnode = rbnode;418368 }
+79-4
drivers/base/regmap/regcache.c
···250250 return 0;251251}252252253253+static int regcache_default_sync(struct regmap *map, unsigned int min,254254+ unsigned int max)255255+{256256+ unsigned int reg;257257+258258+ for (reg = min; reg <= max; reg++) {259259+ unsigned int val;260260+ int ret;261261+262262+ if (regmap_volatile(map, reg))263263+ continue;264264+265265+ ret = regcache_read(map, reg, &val);266266+ if (ret)267267+ return ret;268268+269269+ /* Is this the hardware default? If so skip. */270270+ ret = regcache_lookup_reg(map, reg);271271+ if (ret >= 0 && val == map->reg_defaults[ret].def)272272+ continue;273273+274274+ map->cache_bypass = 1;275275+ ret = _regmap_write(map, reg, val);276276+ map->cache_bypass = 0;277277+ if (ret)278278+ return ret;279279+ dev_dbg(map->dev, "Synced register %#x, value %#x\n", reg, val);280280+ }281281+282282+ return 0;283283+}284284+253285/**254286 * regcache_sync: Sync the register cache with the hardware.255287 *···300268 const char *name;301269 unsigned int bypass;302270303303- BUG_ON(!map->cache_ops || !map->cache_ops->sync);271271+ BUG_ON(!map->cache_ops);304272305273 map->lock(map->lock_arg);306274 /* Remember the initial bypass state */···329297 }330298 map->cache_bypass = 0;331299332332- ret = map->cache_ops->sync(map, 0, map->max_register);300300+ if (map->cache_ops->sync)301301+ ret = map->cache_ops->sync(map, 0, map->max_register);302302+ else303303+ ret = regcache_default_sync(map, 0, map->max_register);333304334305 if (ret == 0)335306 map->cache_dirty = false;···366331 const char *name;367332 unsigned int bypass;368333369369- BUG_ON(!map->cache_ops || !map->cache_ops->sync);334334+ BUG_ON(!map->cache_ops);370335371336 map->lock(map->lock_arg);372337···381346 if (!map->cache_dirty)382347 goto out;383348384384- ret = map->cache_ops->sync(map, min, max);349349+ if (map->cache_ops->sync)350350+ ret = map->cache_ops->sync(map, min, max);351351+ else352352+ ret = regcache_default_sync(map, min, max);385353386354out:387355 trace_regcache_sync(map->dev, name, "stop region");···395357 return ret;396358}397359EXPORT_SYMBOL_GPL(regcache_sync_region);360360+361361+/**362362+ * regcache_drop_region: Discard part of the register cache363363+ *364364+ * @map: map to operate on365365+ * @min: first register to discard366366+ * @max: last register to discard367367+ *368368+ * Discard part of the register cache.369369+ *370370+ * Return a negative value on failure, 0 on success.371371+ */372372+int regcache_drop_region(struct regmap *map, unsigned int min,373373+ unsigned int max)374374+{375375+ unsigned int reg;376376+ int ret = 0;377377+378378+ if (!map->cache_present && !(map->cache_ops && map->cache_ops->drop))379379+ return -EINVAL;380380+381381+ map->lock(map->lock_arg);382382+383383+ trace_regcache_drop_region(map->dev, min, max);384384+385385+ if (map->cache_present)386386+ for (reg = min; reg < max + 1; reg++)387387+ clear_bit(reg, map->cache_present);388388+389389+ if (map->cache_ops && map->cache_ops->drop)390390+ ret = map->cache_ops->drop(map, min, max);391391+392392+ map->unlock(map->lock_arg);393393+394394+ return ret;395395+}396396+EXPORT_SYMBOL_GPL(regcache_drop_region);398397399398/**400399 * regcache_cache_only: Put a register map into cache only mode
+4
drivers/base/regmap/regmap-debugfs.c
···8484 unsigned int fpos_offset;8585 unsigned int reg_offset;86868787+ /* Suppress the cache if we're using a subrange */8888+ if (from)8989+ return from;9090+8791 /*8892 * If we don't have a cache build one so we don't have to do a8993 * linear scan each time.