Merge remote-tracking branches 'regulator/topic/devm' and 'regulator/topic/stub'...
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Sun, 18 Mar 2012 21:38:28 +0000 (21:38 +0000)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Sun, 18 Mar 2012 21:38:28 +0000 (21:38 +0000)
1  2 
Documentation/driver-model/devres.txt
drivers/regulator/core.c

index 41c0c5d1ba145a392e17d42dc4ce8ac9c3c41a49,0cab4af0e2cf58a049fc5b6a402a5bfff365978c..2a596a4fc23eeb03f1c04cbcc9415b121adfdc04
@@@ -233,10 -233,6 +233,10 @@@ certainly invest a bit more effort int
    6. List of managed interfaces
    -----------------------------
  
 +MEM
 +  devm_kzalloc()
 +  devm_kfree()
 +
  IO region
    devm_request_region()
    devm_request_mem_region()
@@@ -271,3 -267,8 +271,8 @@@ IOMA
    pcim_iounmap()
    pcim_iomap_table()  : array of mapped addresses indexed by BAR
    pcim_iomap_regions()        : do request_region() and iomap() on multiple BARs
+ REGULATOR
+   devm_regulator_get()
+   devm_regulator_put()
+   devm_regulator_bulk_get()
diff --combined drivers/regulator/core.c
index 8f11d0eb59a52e5073ca18a6f248a522d8da7a53,1432c22926b5e19c97ce59c8647757487f0a7467..f4d31830f12b1cff77ed0806ce14380a06cfcccf
@@@ -13,6 -13,8 +13,6 @@@
   *
   */
  
 -#define pr_fmt(fmt) "%s: " fmt, __func__
 -
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/debugfs.h>
@@@ -52,7 -54,9 +52,7 @@@ static LIST_HEAD(regulator_map_list)
  static bool has_full_constraints;
  static bool board_wants_dummy_regulator;
  
 -#ifdef CONFIG_DEBUG_FS
  static struct dentry *debugfs_root;
 -#endif
  
  /*
   * struct regulator_map
@@@ -80,7 -84,9 +80,7 @@@ struct regulator 
        char *supply_name;
        struct device_attribute dev_attr;
        struct regulator_dev *rdev;
 -#ifdef CONFIG_DEBUG_FS
        struct dentry *debugfs;
 -#endif
  };
  
  static int _regulator_is_enabled(struct regulator_dev *rdev);
@@@ -148,7 -154,7 +148,7 @@@ static struct device_node *of_get_regul
        regnode = of_parse_phandle(dev->of_node, prop_name, 0);
  
        if (!regnode) {
 -              dev_warn(dev, "%s property in node %s references invalid phandle",
 +              dev_dbg(dev, "Looking up %s property in node %s failed",
                                prop_name, dev->of_node->full_name);
                return NULL;
        }
@@@ -801,11 -807,6 +801,11 @@@ static void print_constraints(struct re
                count += sprintf(buf + count, "standby");
  
        rdev_info(rdev, "%s\n", buf);
 +
 +      if ((constraints->min_uV != constraints->max_uV) &&
 +          !(constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE))
 +              rdev_warn(rdev,
 +                        "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n");
  }
  
  static int machine_constraints_voltage(struct regulator_dev *rdev,
@@@ -1141,10 -1142,12 +1141,10 @@@ static struct regulator *create_regulat
                        goto attr_err;
        }
  
 -#ifdef CONFIG_DEBUG_FS
        regulator->debugfs = debugfs_create_dir(regulator->supply_name,
                                                rdev->debugfs);
 -      if (IS_ERR_OR_NULL(regulator->debugfs)) {
 +      if (!regulator->debugfs) {
                rdev_warn(rdev, "Failed to create debugfs directory\n");
 -              regulator->debugfs = NULL;
        } else {
                debugfs_create_u32("uA_load", 0444, regulator->debugfs,
                                   &regulator->uA_load);
                debugfs_create_u32("max_uV", 0444, regulator->debugfs,
                                   &regulator->max_uV);
        }
 -#endif
  
        mutex_unlock(&rdev->mutex);
        return regulator;
@@@ -1316,6 -1320,40 +1316,40 @@@ struct regulator *regulator_get(struct 
  }
  EXPORT_SYMBOL_GPL(regulator_get);
  
+ static void devm_regulator_release(struct device *dev, void *res)
+ {
+       regulator_put(*(struct regulator **)res);
+ }
+ /**
+  * devm_regulator_get - Resource managed regulator_get()
+  * @dev: device for regulator "consumer"
+  * @id: Supply name or regulator ID.
+  *
+  * Managed regulator_get(). Regulators returned from this function are
+  * automatically regulator_put() on driver detach. See regulator_get() for more
+  * information.
+  */
+ struct regulator *devm_regulator_get(struct device *dev, const char *id)
+ {
+       struct regulator **ptr, *regulator;
+       ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+       regulator = regulator_get(dev, id);
+       if (!IS_ERR(regulator)) {
+               *ptr = regulator;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+       return regulator;
+ }
+ EXPORT_SYMBOL_GPL(devm_regulator_get);
  /**
   * regulator_get_exclusive - obtain exclusive access to a regulator.
   * @dev: device for regulator "consumer"
@@@ -1361,7 -1399,9 +1395,7 @@@ void regulator_put(struct regulator *re
        mutex_lock(&regulator_list_mutex);
        rdev = regulator->rdev;
  
 -#ifdef CONFIG_DEBUG_FS
        debugfs_remove_recursive(regulator->debugfs);
 -#endif
  
        /* remove any sysfs entries */
        if (regulator->dev) {
  }
  EXPORT_SYMBOL_GPL(regulator_put);
  
+ static int devm_regulator_match(struct device *dev, void *res, void *data)
+ {
+       struct regulator **r = res;
+       if (!r || !*r) {
+               WARN_ON(!r || !*r);
+               return 0;
+       }
+       return *r == data;
+ }
+ /**
+  * devm_regulator_put - Resource managed regulator_put()
+  * @regulator: regulator to free
+  *
+  * Deallocate a regulator allocated with devm_regulator_get(). Normally
+  * this function will not need to be called and the resource management
+  * code will ensure that the resource is freed.
+  */
+ void devm_regulator_put(struct regulator *regulator)
+ {
+       int rc;
+       rc = devres_destroy(regulator->dev, devm_regulator_release,
+                           devm_regulator_match, regulator);
+       WARN_ON(rc);
+ }
+ EXPORT_SYMBOL_GPL(devm_regulator_put);
  static int _regulator_can_change_status(struct regulator_dev *rdev)
  {
        if (!rdev->constraints)
@@@ -1836,12 -1904,8 +1898,12 @@@ static int _regulator_do_set_voltage(st
                        if (ret < 0)
                                return ret;
                        old_selector = ret;
 -                      delay = rdev->desc->ops->set_voltage_time_sel(rdev,
 +                      ret = rdev->desc->ops->set_voltage_time_sel(rdev,
                                                old_selector, selector);
 +                      if (ret < 0)
 +                              rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", ret);
 +                      else
 +                              delay = ret;
                }
  
                if (best_val != INT_MAX) {
@@@ -2392,13 -2456,59 +2454,59 @@@ int regulator_bulk_get(struct device *d
        return 0;
  
  err:
 -      for (i = 0; i < num_consumers && consumers[i].consumer; i++)
 +      while (--i >= 0)
                regulator_put(consumers[i].consumer);
  
        return ret;
  }
  EXPORT_SYMBOL_GPL(regulator_bulk_get);
  
+ /**
+  * devm_regulator_bulk_get - managed get multiple regulator consumers
+  *
+  * @dev:           Device to supply
+  * @num_consumers: Number of consumers to register
+  * @consumers:     Configuration of consumers; clients are stored here.
+  *
+  * @return 0 on success, an errno on failure.
+  *
+  * This helper function allows drivers to get several regulator
+  * consumers in one operation with management, the regulators will
+  * automatically be freed when the device is unbound.  If any of the
+  * regulators cannot be acquired then any regulators that were
+  * allocated will be freed before returning to the caller.
+  */
+ int devm_regulator_bulk_get(struct device *dev, int num_consumers,
+                           struct regulator_bulk_data *consumers)
+ {
+       int i;
+       int ret;
+       for (i = 0; i < num_consumers; i++)
+               consumers[i].consumer = NULL;
+       for (i = 0; i < num_consumers; i++) {
+               consumers[i].consumer = devm_regulator_get(dev,
+                                                          consumers[i].supply);
+               if (IS_ERR(consumers[i].consumer)) {
+                       ret = PTR_ERR(consumers[i].consumer);
+                       dev_err(dev, "Failed to get supply '%s': %d\n",
+                               consumers[i].supply, ret);
+                       consumers[i].consumer = NULL;
+                       goto err;
+               }
+       }
+       return 0;
+ err:
+       for (i = 0; i < num_consumers && consumers[i].consumer; i++)
+               devm_regulator_put(consumers[i].consumer);
+       return ret;
+ }
+ EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
  static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
  {
        struct regulator_bulk_data *bulk = data;
@@@ -2442,9 -2552,12 +2550,9 @@@ int regulator_bulk_enable(int num_consu
        return 0;
  
  err:
 -      for (i = 0; i < num_consumers; i++)
 -              if (consumers[i].ret == 0)
 -                      regulator_disable(consumers[i].consumer);
 -              else
 -                      pr_err("Failed to enable %s: %d\n",
 -                             consumers[i].supply, consumers[i].ret);
 +      pr_err("Failed to enable %s: %d\n", consumers[i].supply, ret);
 +      while (--i >= 0)
 +              regulator_disable(consumers[i].consumer);
  
        return ret;
  }
@@@ -2458,8 -2571,8 +2566,8 @@@ EXPORT_SYMBOL_GPL(regulator_bulk_enable
   * @return         0 on success, an errno on failure
   *
   * This convenience API allows consumers to disable multiple regulator
 - * clients in a single API call.  If any consumers cannot be enabled
 - * then any others that were disabled will be disabled again prior to
 + * clients in a single API call.  If any consumers cannot be disabled
 + * then any others that were disabled will be enabled again prior to
   * return.
   */
  int regulator_bulk_disable(int num_consumers,
        int i;
        int ret;
  
 -      for (i = 0; i < num_consumers; i++) {
 +      for (i = num_consumers - 1; i >= 0; --i) {
                ret = regulator_disable(consumers[i].consumer);
                if (ret != 0)
                        goto err;
  
  err:
        pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret);
 -      for (--i; i >= 0; --i)
 +      for (++i; i < num_consumers; ++i)
                regulator_enable(consumers[i].consumer);
  
        return ret;
@@@ -2705,9 -2818,11 +2813,9 @@@ static int add_regulator_attributes(str
  
  static void rdev_init_debugfs(struct regulator_dev *rdev)
  {
 -#ifdef CONFIG_DEBUG_FS
        rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root);
 -      if (IS_ERR(rdev->debugfs) || !rdev->debugfs) {
 +      if (!rdev->debugfs) {
                rdev_warn(rdev, "Failed to create debugfs directory\n");
 -              rdev->debugfs = NULL;
                return;
        }
  
                           &rdev->use_count);
        debugfs_create_u32("open_count", 0444, rdev->debugfs,
                           &rdev->open_count);
 -#endif
  }
  
  /**
   * @dev: struct device for the regulator
   * @init_data: platform provided init data, passed through by driver
   * @driver_data: private regulator data
 + * @of_node: OpenFirmware node to parse for device tree bindings (may be
 + *           NULL).
   *
   * Called by regulator drivers to register a regulator.
   * Returns 0 on success.
@@@ -2894,7 -3008,9 +3002,7 @@@ void regulator_unregister(struct regula
                return;
  
        mutex_lock(&regulator_list_mutex);
 -#ifdef CONFIG_DEBUG_FS
        debugfs_remove_recursive(rdev->debugfs);
 -#endif
        flush_work_sync(&rdev->disable_work.work);
        WARN_ON(rdev->open_count);
        unset_regulator_supplies(rdev);
@@@ -3104,14 -3220,12 +3212,14 @@@ static ssize_t supply_map_read_file(str
  
        return ret;
  }
 +#endif
  
  static const struct file_operations supply_map_fops = {
 +#ifdef CONFIG_DEBUG_FS
        .read = supply_map_read_file,
        .llseek = default_llseek,
 -};
  #endif
 +};
  
  static int __init regulator_init(void)
  {
  
        ret = class_register(&regulator_class);
  
 -#ifdef CONFIG_DEBUG_FS
        debugfs_root = debugfs_create_dir("regulator", NULL);
 -      if (IS_ERR(debugfs_root) || !debugfs_root) {
 +      if (!debugfs_root)
                pr_warn("regulator: Failed to create debugfs directory\n");
 -              debugfs_root = NULL;
 -      }
  
 -      if (IS_ERR(debugfs_create_file("supply_map", 0444, debugfs_root,
 -                                     NULL, &supply_map_fops)))
 -              pr_warn("regulator: Failed to create supplies debugfs\n");
 -#endif
 +      debugfs_create_file("supply_map", 0444, debugfs_root, NULL,
 +                          &supply_map_fops);
  
        regulator_dummy_init();