diff options
| -rw-r--r-- | drivers/base/regmap/internal.h | 1 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap.c | 61 | ||||
| -rw-r--r-- | include/linux/regmap.h | 8 |
3 files changed, 69 insertions, 1 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index e46c279f8280..c994bc9bc04f 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h | |||
| @@ -45,6 +45,7 @@ struct regmap { | |||
| 45 | struct regmap_format format; /* Buffer format */ | 45 | struct regmap_format format; /* Buffer format */ |
| 46 | const struct regmap_bus *bus; | 46 | const struct regmap_bus *bus; |
| 47 | void *bus_context; | 47 | void *bus_context; |
| 48 | const char *name; | ||
| 48 | 49 | ||
| 49 | #ifdef CONFIG_DEBUG_FS | 50 | #ifdef CONFIG_DEBUG_FS |
| 50 | struct dentry *debugfs; | 51 | struct dentry *debugfs; |
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index ee4fea351220..618173e4c2b1 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
| @@ -178,6 +178,15 @@ static void regmap_unlock_spinlock(struct regmap *map) | |||
| 178 | spin_unlock(&map->spinlock); | 178 | spin_unlock(&map->spinlock); |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | static void dev_get_regmap_release(struct device *dev, void *res) | ||
| 182 | { | ||
| 183 | /* | ||
| 184 | * We don't actually have anything to do here; the goal here | ||
| 185 | * is not to manage the regmap but to provide a simple way to | ||
| 186 | * get the regmap back given a struct device. | ||
| 187 | */ | ||
| 188 | } | ||
| 189 | |||
| 181 | /** | 190 | /** |
| 182 | * regmap_init(): Initialise register map | 191 | * regmap_init(): Initialise register map |
| 183 | * | 192 | * |
| @@ -195,7 +204,7 @@ struct regmap *regmap_init(struct device *dev, | |||
| 195 | void *bus_context, | 204 | void *bus_context, |
| 196 | const struct regmap_config *config) | 205 | const struct regmap_config *config) |
| 197 | { | 206 | { |
| 198 | struct regmap *map; | 207 | struct regmap *map, **m; |
| 199 | int ret = -EINVAL; | 208 | int ret = -EINVAL; |
| 200 | 209 | ||
| 201 | if (!bus || !config) | 210 | if (!bus || !config) |
| @@ -230,6 +239,7 @@ struct regmap *regmap_init(struct device *dev, | |||
| 230 | map->volatile_reg = config->volatile_reg; | 239 | map->volatile_reg = config->volatile_reg; |
| 231 | map->precious_reg = config->precious_reg; | 240 | map->precious_reg = config->precious_reg; |
| 232 | map->cache_type = config->cache_type; | 241 | map->cache_type = config->cache_type; |
| 242 | map->name = config->name; | ||
| 233 | 243 | ||
| 234 | if (config->read_flag_mask || config->write_flag_mask) { | 244 | if (config->read_flag_mask || config->write_flag_mask) { |
| 235 | map->read_flag_mask = config->read_flag_mask; | 245 | map->read_flag_mask = config->read_flag_mask; |
| @@ -326,8 +336,19 @@ struct regmap *regmap_init(struct device *dev, | |||
| 326 | if (ret < 0) | 336 | if (ret < 0) |
| 327 | goto err_free_workbuf; | 337 | goto err_free_workbuf; |
| 328 | 338 | ||
| 339 | /* Add a devres resource for dev_get_regmap() */ | ||
| 340 | m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL); | ||
| 341 | if (!m) { | ||
| 342 | ret = -ENOMEM; | ||
| 343 | goto err_cache; | ||
| 344 | } | ||
| 345 | *m = map; | ||
| 346 | devres_add(dev, m); | ||
| 347 | |||
| 329 | return map; | 348 | return map; |
| 330 | 349 | ||
| 350 | err_cache: | ||
| 351 | regcache_exit(map); | ||
| 331 | err_free_workbuf: | 352 | err_free_workbuf: |
| 332 | kfree(map->work_buf); | 353 | kfree(map->work_buf); |
| 333 | err_map: | 354 | err_map: |
| @@ -431,6 +452,44 @@ void regmap_exit(struct regmap *map) | |||
| 431 | } | 452 | } |
| 432 | EXPORT_SYMBOL_GPL(regmap_exit); | 453 | EXPORT_SYMBOL_GPL(regmap_exit); |
| 433 | 454 | ||
| 455 | static int dev_get_regmap_match(struct device *dev, void *res, void *data) | ||
| 456 | { | ||
| 457 | struct regmap **r = res; | ||
| 458 | if (!r || !*r) { | ||
| 459 | WARN_ON(!r || !*r); | ||
| 460 | return 0; | ||
| 461 | } | ||
| 462 | |||
| 463 | /* If the user didn't specify a name match any */ | ||
| 464 | if (data) | ||
| 465 | return (*r)->name == data; | ||
| 466 | else | ||
| 467 | return 1; | ||
| 468 | } | ||
| 469 | |||
| 470 | /** | ||
| 471 | * dev_get_regmap(): Obtain the regmap (if any) for a device | ||
| 472 | * | ||
| 473 | * @dev: Device to retrieve the map for | ||
| 474 | * @name: Optional name for the register map, usually NULL. | ||
| 475 | * | ||
| 476 | * Returns the regmap for the device if one is present, or NULL. If | ||
| 477 | * name is specified then it must match the name specified when | ||
| 478 | * registering the device, if it is NULL then the first regmap found | ||
| 479 | * will be used. Devices with multiple register maps are very rare, | ||
| 480 | * generic code should normally not need to specify a name. | ||
| 481 | */ | ||
| 482 | struct regmap *dev_get_regmap(struct device *dev, const char *name) | ||
| 483 | { | ||
| 484 | struct regmap **r = devres_find(dev, dev_get_regmap_release, | ||
| 485 | dev_get_regmap_match, (void *)name); | ||
| 486 | |||
| 487 | if (!r) | ||
| 488 | return NULL; | ||
| 489 | return *r; | ||
| 490 | } | ||
| 491 | EXPORT_SYMBOL_GPL(dev_get_regmap); | ||
| 492 | |||
| 434 | static int _regmap_raw_write(struct regmap *map, unsigned int reg, | 493 | static int _regmap_raw_write(struct regmap *map, unsigned int reg, |
| 435 | const void *val, size_t val_len) | 494 | const void *val, size_t val_len) |
| 436 | { | 495 | { |
diff --git a/include/linux/regmap.h b/include/linux/regmap.h index f6abc8d33d64..90a4652eaaea 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h | |||
| @@ -156,6 +156,7 @@ struct regmap *devm_regmap_init_mmio(struct device *dev, | |||
| 156 | void regmap_exit(struct regmap *map); | 156 | void regmap_exit(struct regmap *map); |
| 157 | int regmap_reinit_cache(struct regmap *map, | 157 | int regmap_reinit_cache(struct regmap *map, |
| 158 | const struct regmap_config *config); | 158 | const struct regmap_config *config); |
| 159 | struct regmap *dev_get_regmap(struct device *dev, const char *name); | ||
| 159 | int regmap_write(struct regmap *map, unsigned int reg, unsigned int val); | 160 | int regmap_write(struct regmap *map, unsigned int reg, unsigned int val); |
| 160 | int regmap_raw_write(struct regmap *map, unsigned int reg, | 161 | int regmap_raw_write(struct regmap *map, unsigned int reg, |
| 161 | const void *val, size_t val_len); | 162 | const void *val, size_t val_len); |
| @@ -340,6 +341,13 @@ static inline int regmap_register_patch(struct regmap *map, | |||
| 340 | return -EINVAL; | 341 | return -EINVAL; |
| 341 | } | 342 | } |
| 342 | 343 | ||
| 344 | static inline struct regmap *dev_get_regmap(struct device *dev, | ||
| 345 | const char *name) | ||
| 346 | { | ||
| 347 | WARN_ONCE(1, "regmap API is disabled"); | ||
| 348 | return NULL; | ||
| 349 | } | ||
| 350 | |||
| 343 | #endif | 351 | #endif |
| 344 | 352 | ||
| 345 | #endif | 353 | #endif |
