Merge branch 'for-linus' of git://opensource.wolfsonmicro.com/regulator
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Nov 2011 22:06:20 +0000 (15:06 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Nov 2011 22:06:20 +0000 (15:06 -0700)
* 'for-linus' of git://opensource.wolfsonmicro.com/regulator: (22 commits)
  regulator: Constify constraints name
  regulator: Fix possible nullpointer dereference in regulator_enable()
  regulator: gpio-regulator add dependency on GENERIC_GPIO
  regulator: Add module.h include to gpio-regulator
  regulator: Add driver for gpio-controlled regulators
  regulator: remove duplicate REG_CTRL2 defines in tps65023
  regulator: Clarify documentation for regulator-regulator supplies
  regulator: Fix some bitrot in the machine driver documentation
  regulator: tps65023: Added support for the similiar TPS65020 chip
  regulator: tps65023: Setting correct core regulator for tps65021
  regulator: tps65023: Set missing bit for update core-voltage
  regulator: tps65023: Fixes i2c configuration issues
  regulator: Add debugfs file showing the supply map table
  regulator: tps6586x: add SMx slew rate setting
  regulator: tps65023: Fixes i2c configuration issues
  regulator: tps6507x: Remove num_voltages array
  regulator: max8952: removed unused mutex.
  regulator: fix regulator/consumer.h kernel-doc warning
  regulator: Ensure enough enable time for max8649
  regulator: 88pm8607: Fix off-by-one value range checking in the case of no id is matched
  ...

1  2 
drivers/regulator/core.c

diff --combined drivers/regulator/core.c
@@@ -1425,7 -1425,7 +1425,7 @@@ int regulator_enable(struct regulator *
        ret = _regulator_enable(rdev);
        mutex_unlock(&rdev->mutex);
  
-       if (ret != 0)
+       if (ret != 0 && rdev->supply)
                regulator_disable(rdev->supply);
  
        return ret;
@@@ -1552,68 -1552,6 +1552,68 @@@ int regulator_force_disable(struct regu
  }
  EXPORT_SYMBOL_GPL(regulator_force_disable);
  
 +static void regulator_disable_work(struct work_struct *work)
 +{
 +      struct regulator_dev *rdev = container_of(work, struct regulator_dev,
 +                                                disable_work.work);
 +      int count, i, ret;
 +
 +      mutex_lock(&rdev->mutex);
 +
 +      BUG_ON(!rdev->deferred_disables);
 +
 +      count = rdev->deferred_disables;
 +      rdev->deferred_disables = 0;
 +
 +      for (i = 0; i < count; i++) {
 +              ret = _regulator_disable(rdev);
 +              if (ret != 0)
 +                      rdev_err(rdev, "Deferred disable failed: %d\n", ret);
 +      }
 +
 +      mutex_unlock(&rdev->mutex);
 +
 +      if (rdev->supply) {
 +              for (i = 0; i < count; i++) {
 +                      ret = regulator_disable(rdev->supply);
 +                      if (ret != 0) {
 +                              rdev_err(rdev,
 +                                       "Supply disable failed: %d\n", ret);
 +                      }
 +              }
 +      }
 +}
 +
 +/**
 + * regulator_disable_deferred - disable regulator output with delay
 + * @regulator: regulator source
 + * @ms: miliseconds until the regulator is disabled
 + *
 + * Execute regulator_disable() on the regulator after a delay.  This
 + * is intended for use with devices that require some time to quiesce.
 + *
 + * NOTE: this will only disable the regulator output if no other consumer
 + * devices have it enabled, the regulator device supports disabling and
 + * machine constraints permit this operation.
 + */
 +int regulator_disable_deferred(struct regulator *regulator, int ms)
 +{
 +      struct regulator_dev *rdev = regulator->rdev;
 +      int ret;
 +
 +      mutex_lock(&rdev->mutex);
 +      rdev->deferred_disables++;
 +      mutex_unlock(&rdev->mutex);
 +
 +      ret = schedule_delayed_work(&rdev->disable_work,
 +                                  msecs_to_jiffies(ms));
 +      if (ret < 0)
 +              return ret;
 +      else
 +              return 0;
 +}
 +EXPORT_SYMBOL_GPL(regulator_disable_deferred);
 +
  static int _regulator_is_enabled(struct regulator_dev *rdev)
  {
        /* If we don't know then assume that the regulator is always on */
@@@ -2684,7 -2622,6 +2684,7 @@@ struct regulator_dev *regulator_registe
        INIT_LIST_HEAD(&rdev->consumer_list);
        INIT_LIST_HEAD(&rdev->list);
        BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
 +      INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work);
  
        /* preform any regulator specific init */
        if (init_data->regulator_init) {
@@@ -2792,7 -2729,6 +2792,7 @@@ void regulator_unregister(struct regula
  #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);
        list_del(&rdev->list);
@@@ -2971,6 -2907,43 +2971,43 @@@ void *regulator_get_init_drvdata(struc
  }
  EXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
  
+ #ifdef CONFIG_DEBUG_FS
+ static ssize_t supply_map_read_file(struct file *file, char __user *user_buf,
+                                   size_t count, loff_t *ppos)
+ {
+       char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       ssize_t len, ret = 0;
+       struct regulator_map *map;
+       if (!buf)
+               return -ENOMEM;
+       list_for_each_entry(map, &regulator_map_list, list) {
+               len = snprintf(buf + ret, PAGE_SIZE - ret,
+                              "%s -> %s.%s\n",
+                              rdev_get_name(map->regulator), map->dev_name,
+                              map->supply);
+               if (len >= 0)
+                       ret += len;
+               if (ret > PAGE_SIZE) {
+                       ret = PAGE_SIZE;
+                       break;
+               }
+       }
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+       kfree(buf);
+       return ret;
+ }
+ static const struct file_operations supply_map_fops = {
+       .read = supply_map_read_file,
+       .llseek = default_llseek,
+ };
+ #endif
  static int __init regulator_init(void)
  {
        int ret;
                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
  
        regulator_dummy_init();