]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge remote-tracking branches 'regmap/topic/defaults', 'regmap/topic/irq' and 'regma...
authorMark Brown <broonie@kernel.org>
Wed, 17 Jun 2015 16:40:08 +0000 (17:40 +0100)
committerMark Brown <broonie@kernel.org>
Wed, 17 Jun 2015 16:40:08 +0000 (17:40 +0100)
drivers/base/regmap/internal.h
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap-irq.c
drivers/base/regmap/regmap.c
include/linux/regmap.h

index a13587b5c2be32b912f9fe0fd7544761a280bd57..b2b2849fc6d3b34d1294a02ef009a10af86d49de 100644 (file)
@@ -131,7 +131,10 @@ struct regmap {
        struct reg_default *reg_defaults;
        const void *reg_defaults_raw;
        void *cache;
+       /* if set, the cache contains newer data than the HW */
        u32 cache_dirty;
+       /* if set, the HW registers are known to match map->reg_defaults */
+       bool no_sync_defaults;
 
        struct reg_default *patch;
        int patch_regs;
index 7eb7b3b98794849c6718c068504c7ac1acf3a2c9..b9862d741a56210885638b3cfc9ce8c92f435254 100644 (file)
@@ -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,9 +282,7 @@ 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;
@@ -342,6 +356,7 @@ int regcache_sync(struct regmap *map)
        /* 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);
@@ -397,6 +412,7 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
        /* 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,10 +634,7 @@ 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;
@@ -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)
index a6c3f75b4b01e1145c6eb5bb9816182a0f9c9fde..2597600a5d26d8c115321a8688c871e29b66d2a4 100644 (file)
@@ -109,7 +109,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
                if (!d->chip->init_ack_masked)
                        continue;
                /*
-                * Ack all the masked interrupts uncondictionly,
+                * Ack all the masked interrupts unconditionally,
                 * OR if there is masked interrupt which hasn't been Acked,
                 * it'll be ignored in irq handler, then may introduce irq storm
                 */
@@ -306,19 +306,12 @@ static int regmap_irq_map(struct irq_domain *h, unsigned int virq,
        irq_set_chip_data(virq, data);
        irq_set_chip(virq, &data->irq_chip);
        irq_set_nested_thread(virq, 1);
-
-       /* ARM needs us to explicitly flag the IRQ as valid
-        * and will set them noprobe when we do so. */
-#ifdef CONFIG_ARM
-       set_irq_flags(virq, IRQF_VALID);
-#else
        irq_set_noprobe(virq);
-#endif
 
        return 0;
 }
 
-static struct irq_domain_ops regmap_domain_ops = {
+static const struct irq_domain_ops regmap_domain_ops = {
        .map    = regmap_irq_map,
        .xlate  = irq_domain_xlate_twocell,
 };
index 473f6743874c5550d3faffb961c8927c7303dc3e..7111d04f26218be0529f4702cb1b361ae07a0b00 100644 (file)
@@ -2609,6 +2609,30 @@ int regmap_get_val_bytes(struct regmap *map)
 }
 EXPORT_SYMBOL_GPL(regmap_get_val_bytes);
 
+/**
+ * regmap_get_max_register(): Report the max register value
+ *
+ * Report the max register value, mainly intended to for use by
+ * generic infrastructure built on top of regmap.
+ */
+int regmap_get_max_register(struct regmap *map)
+{
+       return map->max_register ? map->max_register : -EINVAL;
+}
+EXPORT_SYMBOL_GPL(regmap_get_max_register);
+
+/**
+ * regmap_get_reg_stride(): Report the register address stride
+ *
+ * Report the register address stride, mainly intended to for use by
+ * generic infrastructure built on top of regmap.
+ */
+int regmap_get_reg_stride(struct regmap *map)
+{
+       return map->reg_stride;
+}
+EXPORT_SYMBOL_GPL(regmap_get_reg_stride);
+
 int regmap_parse_val(struct regmap *map, const void *buf,
                        unsigned int *val)
 {
index 116655d922691b3143b8c9d840b944fed3a70adb..59c55ea0f0b50c270d64bebe9dd6c25a717ca5ec 100644 (file)
@@ -433,6 +433,8 @@ int regmap_update_bits_check_async(struct regmap *map, unsigned int reg,
                                   unsigned int mask, unsigned int val,
                                   bool *change);
 int regmap_get_val_bytes(struct regmap *map);
+int regmap_get_max_register(struct regmap *map);
+int regmap_get_reg_stride(struct regmap *map);
 int regmap_async_complete(struct regmap *map);
 bool regmap_can_raw_write(struct regmap *map);
 
@@ -676,6 +678,18 @@ static inline int regmap_get_val_bytes(struct regmap *map)
        return -EINVAL;
 }
 
+static inline int regmap_get_max_register(struct regmap *map)
+{
+       WARN_ONCE(1, "regmap API is disabled");
+       return -EINVAL;
+}
+
+static inline int regmap_get_reg_stride(struct regmap *map)
+{
+       WARN_ONCE(1, "regmap API is disabled");
+       return -EINVAL;
+}
+
 static inline int regcache_sync(struct regmap *map)
 {
        WARN_ONCE(1, "regmap API is disabled");