aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-05-08 08:55:22 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-05-12 10:46:47 -0400
commit697e85bc6a9aa44ecd73392586fe9cfd7e0467ba (patch)
treec07e5c212d9eed90f1d80bc5b923755a5f6888ea
parentf722406faae2d073cc1d01063d1123c35425939e (diff)
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>
-rw-r--r--drivers/base/regmap/internal.h1
-rw-r--r--drivers/base/regmap/regcache.c37
-rw-r--r--include/linux/regmap.h9
-rw-r--r--include/trace/events/regmap.h23
4 files changed, 70 insertions, 0 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index c130536e0ab0..b33a4ff67adf 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -148,6 +148,7 @@ struct regcache_ops {
148 int (*read)(struct regmap *map, unsigned int reg, unsigned int *value); 148 int (*read)(struct regmap *map, unsigned int reg, unsigned int *value);
149 int (*write)(struct regmap *map, unsigned int reg, unsigned int value); 149 int (*write)(struct regmap *map, unsigned int reg, unsigned int value);
150 int (*sync)(struct regmap *map, unsigned int min, unsigned int max); 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
153bool regmap_writeable(struct regmap *map, unsigned int reg); 154bool regmap_writeable(struct regmap *map, unsigned int reg);
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 75923f2396bd..8a0ab5fa75f5 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -359,6 +359,43 @@ out:
359EXPORT_SYMBOL_GPL(regcache_sync_region); 359EXPORT_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 */
372int 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}
396EXPORT_SYMBOL_GPL(regcache_drop_region);
397
398/**
362 * regcache_cache_only: Put a register map into cache only mode 399 * regcache_cache_only: Put a register map into cache only mode
363 * 400 *
364 * @map: map to configure 401 * @map: map to configure
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 02d84e24b7c2..5067ee94eb92 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -394,6 +394,8 @@ bool regmap_can_raw_write(struct regmap *map);
394int regcache_sync(struct regmap *map); 394int regcache_sync(struct regmap *map);
395int regcache_sync_region(struct regmap *map, unsigned int min, 395int regcache_sync_region(struct regmap *map, unsigned int min,
396 unsigned int max); 396 unsigned int max);
397int regcache_drop_region(struct regmap *map, unsigned int min,
398 unsigned int max);
397void regcache_cache_only(struct regmap *map, bool enable); 399void regcache_cache_only(struct regmap *map, bool enable);
398void regcache_cache_bypass(struct regmap *map, bool enable); 400void regcache_cache_bypass(struct regmap *map, bool enable);
399void regcache_mark_dirty(struct regmap *map); 401void regcache_mark_dirty(struct regmap *map);
@@ -562,6 +564,13 @@ static inline int regcache_sync_region(struct regmap *map, unsigned int min,
562 return -EINVAL; 564 return -EINVAL;
563} 565}
564 566
567static inline int regcache_drop_region(struct regmap *map, unsigned int min,
568 unsigned int max)
569{
570 WARN_ONCE(1, "regmap API is disabled");
571 return -EINVAL;
572}
573
565static inline void regcache_cache_only(struct regmap *map, bool enable) 574static inline void regcache_cache_only(struct regmap *map, bool enable)
566{ 575{
567 WARN_ONCE(1, "regmap API is disabled"); 576 WARN_ONCE(1, "regmap API is disabled");
diff --git a/include/trace/events/regmap.h b/include/trace/events/regmap.h
index a43a2f67bd8e..23d561512f64 100644
--- a/include/trace/events/regmap.h
+++ b/include/trace/events/regmap.h
@@ -223,6 +223,29 @@ DEFINE_EVENT(regmap_async, regmap_async_complete_done,
223 223
224); 224);
225 225
226TRACE_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#endif /* _TRACE_REGMAP_H */ 249#endif /* _TRACE_REGMAP_H */
227 250
228/* This part must be outside protection */ 251/* This part must be outside protection */