Commit 697e85bc6a9aa44ecd73392586fe9cfd7e0467ba

Authored by Mark Brown
1 parent f722406faa

regmap: Add support for discarding parts of the register cache

Allow drivers to discard parts of the register cache, for example if part
of the hardware has been reset.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

Showing 4 changed files with 70 additions and 0 deletions Side-by-side Diff

drivers/base/regmap/internal.h
... ... @@ -148,6 +148,7 @@
148 148 int (*read)(struct regmap *map, unsigned int reg, unsigned int *value);
149 149 int (*write)(struct regmap *map, unsigned int reg, unsigned int value);
150 150 int (*sync)(struct regmap *map, unsigned int min, unsigned int max);
  151 + int (*drop)(struct regmap *map, unsigned int min, unsigned int max);
151 152 };
152 153  
153 154 bool regmap_writeable(struct regmap *map, unsigned int reg);
drivers/base/regmap/regcache.c
... ... @@ -359,6 +359,43 @@
359 359 EXPORT_SYMBOL_GPL(regcache_sync_region);
360 360  
361 361 /**
  362 + * regcache_drop_region: Discard part of the register cache
  363 + *
  364 + * @map: map to operate on
  365 + * @min: first register to discard
  366 + * @max: last register to discard
  367 + *
  368 + * Discard part of the register cache.
  369 + *
  370 + * Return a negative value on failure, 0 on success.
  371 + */
  372 +int regcache_drop_region(struct regmap *map, unsigned int min,
  373 + unsigned int max)
  374 +{
  375 + unsigned int reg;
  376 + int ret = 0;
  377 +
  378 + if (!map->cache_present && !(map->cache_ops && map->cache_ops->drop))
  379 + return -EINVAL;
  380 +
  381 + map->lock(map);
  382 +
  383 + trace_regcache_drop_region(map->dev, min, max);
  384 +
  385 + if (map->cache_present)
  386 + for (reg = min; reg < max + 1; reg++)
  387 + clear_bit(reg, map->cache_present);
  388 +
  389 + if (map->cache_ops && map->cache_ops->drop)
  390 + ret = map->cache_ops->drop(map, min, max);
  391 +
  392 + map->unlock(map);
  393 +
  394 + return ret;
  395 +}
  396 +EXPORT_SYMBOL_GPL(regcache_drop_region);
  397 +
  398 +/**
362 399 * regcache_cache_only: Put a register map into cache only mode
363 400 *
364 401 * @map: map to configure
include/linux/regmap.h
... ... @@ -394,6 +394,8 @@
394 394 int regcache_sync(struct regmap *map);
395 395 int regcache_sync_region(struct regmap *map, unsigned int min,
396 396 unsigned int max);
  397 +int regcache_drop_region(struct regmap *map, unsigned int min,
  398 + unsigned int max);
397 399 void regcache_cache_only(struct regmap *map, bool enable);
398 400 void regcache_cache_bypass(struct regmap *map, bool enable);
399 401 void regcache_mark_dirty(struct regmap *map);
... ... @@ -556,6 +558,13 @@
556 558 }
557 559  
558 560 static inline int regcache_sync_region(struct regmap *map, unsigned int min,
  561 + unsigned int max)
  562 +{
  563 + WARN_ONCE(1, "regmap API is disabled");
  564 + return -EINVAL;
  565 +}
  566 +
  567 +static inline int regcache_drop_region(struct regmap *map, unsigned int min,
559 568 unsigned int max)
560 569 {
561 570 WARN_ONCE(1, "regmap API is disabled");
include/trace/events/regmap.h
... ... @@ -223,6 +223,29 @@
223 223  
224 224 );
225 225  
  226 +TRACE_EVENT(regcache_drop_region,
  227 +
  228 + TP_PROTO(struct device *dev, unsigned int from,
  229 + unsigned int to),
  230 +
  231 + TP_ARGS(dev, from, to),
  232 +
  233 + TP_STRUCT__entry(
  234 + __string( name, dev_name(dev) )
  235 + __field( unsigned int, from )
  236 + __field( unsigned int, to )
  237 + ),
  238 +
  239 + TP_fast_assign(
  240 + __assign_str(name, dev_name(dev));
  241 + __entry->from = from;
  242 + __entry->to = to;
  243 + ),
  244 +
  245 + TP_printk("%s %u-%u", __get_str(name), (unsigned int)__entry->from,
  246 + (unsigned int)__entry->to)
  247 +);
  248 +
226 249 #endif /* _TRACE_REGMAP_H */
227 250  
228 251 /* This part must be outside protection */