Merge branches 'regmap-core', 'regmap-stride', 'regmap-mmio' and 'regmap-irq' into...
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Sun, 13 May 2012 18:20:47 +0000 (19:20 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Sun, 13 May 2012 18:20:47 +0000 (19:20 +0100)
drivers/base/regmap/internal.h
drivers/base/regmap/regmap-irq.c
drivers/base/regmap/regmap.c
drivers/mfd/da9052-core.c
include/linux/mfd/da9052/da9052.h
include/linux/regmap.h

index 2eb719704885cbfe9497e0c04de7f5d088d990a6..b986b8660b0c4e72da132a0a32ab2960ca99e183 100644 (file)
@@ -45,6 +45,7 @@ struct regmap {
        struct regmap_format format;  /* Buffer format */
        const struct regmap_bus *bus;
        void *bus_context;
+       const char *name;
 
 #ifdef CONFIG_DEBUG_FS
        struct dentry *debugfs;
index fc69d29d272aa56cea9d8cd9910e2c4399f26c12..0d233cc1c7fa72adeaf3d977b456a1ffe316e00d 100644 (file)
@@ -206,6 +206,8 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
        if (!d)
                return -ENOMEM;
 
+       *data = d;
+
        d->status_buf = kzalloc(sizeof(unsigned int) * chip->num_regs,
                                GFP_KERNEL);
        if (!d->status_buf)
index 357294905793c840aea6826262bbab4dda2d3660..0bcda488f11cd45e6252e113ffd025b058309e99 100644 (file)
@@ -199,6 +199,15 @@ static void regmap_unlock_spinlock(struct regmap *map)
        spin_unlock(&map->spinlock);
 }
 
+static void dev_get_regmap_release(struct device *dev, void *res)
+{
+       /*
+        * We don't actually have anything to do here; the goal here
+        * is not to manage the regmap but to provide a simple way to
+        * get the regmap back given a struct device.
+        */
+}
+
 /**
  * regmap_init(): Initialise register map
  *
@@ -216,7 +225,7 @@ struct regmap *regmap_init(struct device *dev,
                           void *bus_context,
                           const struct regmap_config *config)
 {
-       struct regmap *map;
+       struct regmap *map, **m;
        int ret = -EINVAL;
 
        if (!bus || !config)
@@ -257,6 +266,7 @@ struct regmap *regmap_init(struct device *dev,
        map->volatile_reg = config->volatile_reg;
        map->precious_reg = config->precious_reg;
        map->cache_type = config->cache_type;
+       map->name = config->name;
 
        if (config->read_flag_mask || config->write_flag_mask) {
                map->read_flag_mask = config->read_flag_mask;
@@ -360,8 +370,19 @@ struct regmap *regmap_init(struct device *dev,
        if (ret < 0)
                goto err_free_workbuf;
 
+       /* Add a devres resource for dev_get_regmap() */
+       m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL);
+       if (!m) {
+               ret = -ENOMEM;
+               goto err_cache;
+       }
+       *m = map;
+       devres_add(dev, m);
+
        return map;
 
+err_cache:
+       regcache_exit(map);
 err_free_workbuf:
        kfree(map->work_buf);
 err_map:
@@ -465,6 +486,44 @@ void regmap_exit(struct regmap *map)
 }
 EXPORT_SYMBOL_GPL(regmap_exit);
 
+static int dev_get_regmap_match(struct device *dev, void *res, void *data)
+{
+       struct regmap **r = res;
+       if (!r || !*r) {
+               WARN_ON(!r || !*r);
+               return 0;
+       }
+
+       /* If the user didn't specify a name match any */
+       if (data)
+               return (*r)->name == data;
+       else
+               return 1;
+}
+
+/**
+ * dev_get_regmap(): Obtain the regmap (if any) for a device
+ *
+ * @dev: Device to retrieve the map for
+ * @name: Optional name for the register map, usually NULL.
+ *
+ * Returns the regmap for the device if one is present, or NULL.  If
+ * name is specified then it must match the name specified when
+ * registering the device, if it is NULL then the first regmap found
+ * will be used.  Devices with multiple register maps are very rare,
+ * generic code should normally not need to specify a name.
+ */
+struct regmap *dev_get_regmap(struct device *dev, const char *name)
+{
+       struct regmap **r = devres_find(dev, dev_get_regmap_release,
+                                       dev_get_regmap_match, (void *)name);
+
+       if (!r)
+               return NULL;
+       return *r;
+}
+EXPORT_SYMBOL_GPL(dev_get_regmap);
+
 static int _regmap_raw_write(struct regmap *map, unsigned int reg,
                             const void *val, size_t val_len)
 {
@@ -768,6 +827,9 @@ static int _regmap_read(struct regmap *map, unsigned int reg,
                trace_regmap_reg_read(map->dev, reg, *val);
        }
 
+       if (ret == 0 && !map->cache_bypass)
+               regcache_write(map, reg, *val);
+
        return ret;
 }
 
index 7ff313fe9fb112afd5175dc9b091d224ea936f7e..7776aff46269c38134bc4ca67d81d703989545b1 100644 (file)
@@ -659,12 +659,11 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
        ret = regmap_add_irq_chip(da9052->regmap, da9052->chip_irq,
                                  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
                                  da9052->irq_base, &da9052_regmap_irq_chip,
-                                 NULL);
+                                 &da9052->irq_data);
        if (ret < 0)
                goto regmap_err;
 
-       desc = irq_to_desc(da9052->chip_irq);
-       da9052->irq_base = regmap_irq_chip_get_base(desc->action->dev_id);
+       da9052->irq_base = regmap_irq_chip_get_base(da9052->irq_data);
 
        ret = mfd_add_devices(da9052->dev, -1, da9052_subdev_info,
                              ARRAY_SIZE(da9052_subdev_info), NULL, 0);
@@ -681,8 +680,7 @@ regmap_err:
 
 void da9052_device_exit(struct da9052 *da9052)
 {
-       regmap_del_irq_chip(da9052->chip_irq,
-                           irq_get_irq_data(da9052->irq_base)->chip_data);
+       regmap_del_irq_chip(da9052->chip_irq, da9052->irq_data);
        mfd_remove_devices(da9052->dev);
 }
 
index 7ffbd6e9e7fc00f428c4c036fe53443cbcc3e80f..8313cd9658e391487ee07d085ad585071184da63 100644 (file)
@@ -80,6 +80,7 @@ struct da9052 {
        struct regmap *regmap;
 
        int irq_base;
+       struct regmap_irq_chip_data *irq_data;
        u8 chip_id;
 
        int chip_irq;
index ae797b142aa8cb5f5eeb2fda088f6a5ee30426da..9dbc9a1bec43b9de67e12e526f663739195b1685 100644 (file)
@@ -170,6 +170,7 @@ struct regmap *devm_regmap_init_mmio(struct device *dev,
 void regmap_exit(struct regmap *map);
 int regmap_reinit_cache(struct regmap *map,
                        const struct regmap_config *config);
+struct regmap *dev_get_regmap(struct device *dev, const char *name);
 int regmap_write(struct regmap *map, unsigned int reg, unsigned int val);
 int regmap_raw_write(struct regmap *map, unsigned int reg,
                     const void *val, size_t val_len);
@@ -354,6 +355,13 @@ static inline int regmap_register_patch(struct regmap *map,
        return -EINVAL;
 }
 
+static inline struct regmap *dev_get_regmap(struct device *dev,
+                                           const char *name)
+{
+       WARN_ONCE(1, "regmap API is disabled");
+       return NULL;
+}
+
 #endif
 
 #endif