|
@@ -178,6 +178,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
|
|
|
*
|
|
@@ -195,7 +204,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)
|
|
@@ -230,6 +239,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;
|
|
@@ -326,8 +336,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:
|
|
@@ -431,6 +452,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)
|
|
|
{
|