These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / base / regmap / regcache.c
index 7eb7b3b..4c07802 100644 (file)
@@ -54,11 +54,11 @@ static int regcache_hw_init(struct regmap *map)
                return -ENOMEM;
 
        if (!map->reg_defaults_raw) {
-               u32 cache_bypass = map->cache_bypass;
+               bool cache_bypass = map->cache_bypass;
                dev_warn(map->dev, "No cache defaults, reading back from HW\n");
 
                /* Bypass the cache access till data read from HW*/
-               map->cache_bypass = 1;
+               map->cache_bypass = true;
                tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL);
                if (!tmp_buf) {
                        ret = -ENOMEM;
@@ -249,6 +249,22 @@ int regcache_write(struct regmap *map,
        return 0;
 }
 
+static bool regcache_reg_needs_sync(struct regmap *map, unsigned int reg,
+                                   unsigned int val)
+{
+       int ret;
+
+       /* If we don't know the chip just got reset, then sync everything. */
+       if (!map->no_sync_defaults)
+               return true;
+
+       /* Is this the hardware default?  If so skip. */
+       ret = regcache_lookup_reg(map, reg);
+       if (ret >= 0 && val == map->reg_defaults[ret].def)
+               return false;
+       return true;
+}
+
 static int regcache_default_sync(struct regmap *map, unsigned int min,
                                 unsigned int max)
 {
@@ -266,14 +282,12 @@ static int regcache_default_sync(struct regmap *map, unsigned int min,
                if (ret)
                        return ret;
 
-               /* Is this the hardware default?  If so skip. */
-               ret = regcache_lookup_reg(map, reg);
-               if (ret >= 0 && val == map->reg_defaults[ret].def)
+               if (!regcache_reg_needs_sync(map, reg, val))
                        continue;
 
-               map->cache_bypass = 1;
+               map->cache_bypass = true;
                ret = _regmap_write(map, reg, val);
-               map->cache_bypass = 0;
+               map->cache_bypass = false;
                if (ret) {
                        dev_err(map->dev, "Unable to sync register %#x. %d\n",
                                reg, ret);
@@ -301,7 +315,7 @@ int regcache_sync(struct regmap *map)
        int ret = 0;
        unsigned int i;
        const char *name;
-       unsigned int bypass;
+       bool bypass;
 
        BUG_ON(!map->cache_ops);
 
@@ -319,7 +333,7 @@ int regcache_sync(struct regmap *map)
        map->async = true;
 
        /* Apply any patch first */
-       map->cache_bypass = 1;
+       map->cache_bypass = true;
        for (i = 0; i < map->patch_regs; i++) {
                ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def);
                if (ret != 0) {
@@ -328,7 +342,7 @@ int regcache_sync(struct regmap *map)
                        goto out;
                }
        }
-       map->cache_bypass = 0;
+       map->cache_bypass = false;
 
        if (map->cache_ops->sync)
                ret = map->cache_ops->sync(map, 0, map->max_register);
@@ -342,6 +356,7 @@ out:
        /* Restore the bypass state */
        map->async = false;
        map->cache_bypass = bypass;
+       map->no_sync_defaults = false;
        map->unlock(map->lock_arg);
 
        regmap_async_complete(map);
@@ -369,7 +384,7 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
 {
        int ret = 0;
        const char *name;
-       unsigned int bypass;
+       bool bypass;
 
        BUG_ON(!map->cache_ops);
 
@@ -397,6 +412,7 @@ out:
        /* Restore the bypass state */
        map->cache_bypass = bypass;
        map->async = false;
+       map->no_sync_defaults = false;
        map->unlock(map->lock_arg);
 
        regmap_async_complete(map);
@@ -461,18 +477,23 @@ void regcache_cache_only(struct regmap *map, bool enable)
 EXPORT_SYMBOL_GPL(regcache_cache_only);
 
 /**
- * regcache_mark_dirty: Mark the register cache as dirty
+ * regcache_mark_dirty: Indicate that HW registers were reset to default values
  *
  * @map: map to mark
  *
- * Mark the register cache as dirty, for example due to the device
- * having been powered down for suspend.  If the cache is not marked
- * as dirty then the cache sync will be suppressed.
+ * Inform regcache that the device has been powered down or reset, so that
+ * on resume, regcache_sync() knows to write out all non-default values
+ * stored in the cache.
+ *
+ * If this function is not called, regcache_sync() will assume that
+ * the hardware state still matches the cache state, modulo any writes that
+ * happened when cache_only was true.
  */
 void regcache_mark_dirty(struct regmap *map)
 {
        map->lock(map->lock_arg);
        map->cache_dirty = true;
+       map->no_sync_defaults = true;
        map->unlock(map->lock_arg);
 }
 EXPORT_SYMBOL_GPL(regcache_mark_dirty);
@@ -613,17 +634,14 @@ static int regcache_sync_block_single(struct regmap *map, void *block,
                        continue;
 
                val = regcache_get_val(map, block, i);
-
-               /* Is this the hardware default?  If so skip. */
-               ret = regcache_lookup_reg(map, regtmp);
-               if (ret >= 0 && val == map->reg_defaults[ret].def)
+               if (!regcache_reg_needs_sync(map, regtmp, val))
                        continue;
 
-               map->cache_bypass = 1;
+               map->cache_bypass = true;
 
                ret = _regmap_write(map, regtmp, val);
 
-               map->cache_bypass = 0;
+               map->cache_bypass = false;
                if (ret != 0) {
                        dev_err(map->dev, "Unable to sync register %#x. %d\n",
                                regtmp, ret);
@@ -650,14 +668,14 @@ static int regcache_sync_block_raw_flush(struct regmap *map, const void **data,
        dev_dbg(map->dev, "Writing %zu bytes for %d registers from 0x%x-0x%x\n",
                count * val_bytes, count, base, cur - map->reg_stride);
 
-       map->cache_bypass = 1;
+       map->cache_bypass = true;
 
        ret = _regmap_raw_write(map, base, *data, count * val_bytes);
        if (ret)
                dev_err(map->dev, "Unable to sync registers %#x-%#x. %d\n",
                        base, cur - map->reg_stride, ret);
 
-       map->cache_bypass = 0;
+       map->cache_bypass = false;
 
        *data = NULL;
 
@@ -688,10 +706,7 @@ static int regcache_sync_block_raw(struct regmap *map, void *block,
                }
 
                val = regcache_get_val(map, block, i);
-
-               /* Is this the hardware default?  If so skip. */
-               ret = regcache_lookup_reg(map, regtmp);
-               if (ret >= 0 && val == map->reg_defaults[ret].def) {
+               if (!regcache_reg_needs_sync(map, regtmp, val)) {
                        ret = regcache_sync_block_raw_flush(map, &data,
                                                            base, regtmp);
                        if (ret != 0)
@@ -714,7 +729,7 @@ int regcache_sync_block(struct regmap *map, void *block,
                        unsigned int block_base, unsigned int start,
                        unsigned int end)
 {
-       if (regmap_can_raw_write(map) && !map->use_single_rw)
+       if (regmap_can_raw_write(map) && !map->use_single_write)
                return regcache_sync_block_raw(map, block, cache_present,
                                               block_base, start, end);
        else