regmap: Add support for discarding parts of the register cache
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Wed, 8 May 2013 12:55:22 +0000 (13:55 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Sun, 12 May 2013 14:46:47 +0000 (18:46 +0400)
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>
drivers/base/regmap/internal.h
drivers/base/regmap/regcache.c
include/linux/regmap.h
include/trace/events/regmap.h

index c130536..b33a4ff 100644 (file)
@@ -148,6 +148,7 @@ struct regcache_ops {
        int (*read)(struct regmap *map, unsigned int reg, unsigned int *value);
        int (*write)(struct regmap *map, unsigned int reg, unsigned int value);
        int (*sync)(struct regmap *map, unsigned int min, unsigned int max);
+       int (*drop)(struct regmap *map, unsigned int min, unsigned int max);
 };
 
 bool regmap_writeable(struct regmap *map, unsigned int reg);
index 75923f2..8a0ab5f 100644 (file)
@@ -359,6 +359,43 @@ out:
 EXPORT_SYMBOL_GPL(regcache_sync_region);
 
 /**
+ * regcache_drop_region: Discard part of the register cache
+ *
+ * @map: map to operate on
+ * @min: first register to discard
+ * @max: last register to discard
+ *
+ * Discard part of the register cache.
+ *
+ * Return a negative value on failure, 0 on success.
+ */
+int regcache_drop_region(struct regmap *map, unsigned int min,
+                        unsigned int max)
+{
+       unsigned int reg;
+       int ret = 0;
+
+       if (!map->cache_present && !(map->cache_ops && map->cache_ops->drop))
+               return -EINVAL;
+
+       map->lock(map);
+
+       trace_regcache_drop_region(map->dev, min, max);
+
+       if (map->cache_present)
+               for (reg = min; reg < max + 1; reg++)
+                       clear_bit(reg, map->cache_present);
+
+       if (map->cache_ops && map->cache_ops->drop)
+               ret = map->cache_ops->drop(map, min, max);
+
+       map->unlock(map);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(regcache_drop_region);
+
+/**
  * regcache_cache_only: Put a register map into cache only mode
  *
  * @map: map to configure
index 02d84e2..5067ee9 100644 (file)
@@ -394,6 +394,8 @@ bool regmap_can_raw_write(struct regmap *map);
 int regcache_sync(struct regmap *map);
 int regcache_sync_region(struct regmap *map, unsigned int min,
                         unsigned int max);
+int regcache_drop_region(struct regmap *map, unsigned int min,
+                        unsigned int max);
 void regcache_cache_only(struct regmap *map, bool enable);
 void regcache_cache_bypass(struct regmap *map, bool enable);
 void regcache_mark_dirty(struct regmap *map);
@@ -562,6 +564,13 @@ static inline int regcache_sync_region(struct regmap *map, unsigned int min,
        return -EINVAL;
 }
 
+static inline int regcache_drop_region(struct regmap *map, unsigned int min,
+                                      unsigned int max)
+{
+       WARN_ONCE(1, "regmap API is disabled");
+       return -EINVAL;
+}
+
 static inline void regcache_cache_only(struct regmap *map, bool enable)
 {
        WARN_ONCE(1, "regmap API is disabled");
index a43a2f6..23d5615 100644 (file)
@@ -223,6 +223,29 @@ DEFINE_EVENT(regmap_async, regmap_async_complete_done,
 
 );
 
+TRACE_EVENT(regcache_drop_region,
+
+       TP_PROTO(struct device *dev, unsigned int from,
+                unsigned int to),
+
+       TP_ARGS(dev, from, to),
+
+       TP_STRUCT__entry(
+               __string(       name,           dev_name(dev)   )
+               __field(        unsigned int,   from            )
+               __field(        unsigned int,   to              )
+       ),
+
+       TP_fast_assign(
+               __assign_str(name, dev_name(dev));
+               __entry->from = from;
+               __entry->to = to;
+       ),
+
+       TP_printk("%s %u-%u", __get_str(name), (unsigned int)__entry->from,
+                 (unsigned int)__entry->to)
+);
+
 #endif /* _TRACE_REGMAP_H */
 
 /* This part must be outside protection */