diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/regmap/internal.h | 1 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-irq.c | 2 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 64 |
3 files changed, 66 insertions, 1 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 2eb719704885..b986b8660b0c 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h @@ -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; diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index fc69d29d272a..0d233cc1c7fa 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -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) diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 357294905793..0bcda488f11c 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -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; } |