Merge remote-tracking branch 'regulator/topic/coupled' into regulator-next
authorMark Brown <broonie@kernel.org>
Fri, 21 Dec 2018 13:43:35 +0000 (13:43 +0000)
committerMark Brown <broonie@kernel.org>
Fri, 21 Dec 2018 13:43:35 +0000 (13:43 +0000)
1  2 
drivers/regulator/core.c

diff --combined drivers/regulator/core.c
@@@ -99,7 -99,7 +99,7 @@@ struct regulator_supply_alias 
  };
  
  static int _regulator_is_enabled(struct regulator_dev *rdev);
 -static int _regulator_disable(struct regulator_dev *rdev);
 +static int _regulator_disable(struct regulator *regulator);
  static int _regulator_get_voltage(struct regulator_dev *rdev);
  static int _regulator_get_current_limit(struct regulator_dev *rdev);
  static unsigned int _regulator_get_mode(struct regulator_dev *rdev);
@@@ -211,6 -211,7 +211,7 @@@ void regulator_lock(struct regulator_de
  {
        regulator_lock_nested(rdev, NULL);
  }
+ EXPORT_SYMBOL_GPL(regulator_lock);
  
  /**
   * regulator_unlock - unlock a single regulator
@@@ -232,6 -233,7 +233,7 @@@ void regulator_unlock(struct regulator_
  
        mutex_unlock(&regulator_nesting_mutex);
  }
+ EXPORT_SYMBOL_GPL(regulator_unlock);
  
  static bool regulator_supply_is_couple(struct regulator_dev *rdev)
  {
@@@ -375,37 -377,6 +377,37 @@@ static void regulator_lock_dependent(st
  }
  
  /**
 + * of_get_child_regulator - get a child regulator device node
 + * based on supply name
 + * @parent: Parent device node
 + * @prop_name: Combination regulator supply name and "-supply"
 + *
 + * Traverse all child nodes.
 + * Extract the child regulator device node corresponding to the supply name.
 + * returns the device node corresponding to the regulator if found, else
 + * returns NULL.
 + */
 +static struct device_node *of_get_child_regulator(struct device_node *parent,
 +                                                const char *prop_name)
 +{
 +      struct device_node *regnode = NULL;
 +      struct device_node *child = NULL;
 +
 +      for_each_child_of_node(parent, child) {
 +              regnode = of_parse_phandle(child, prop_name, 0);
 +
 +              if (!regnode) {
 +                      regnode = of_get_child_regulator(child, prop_name);
 +                      if (regnode)
 +                              return regnode;
 +              } else {
 +                      return regnode;
 +              }
 +      }
 +      return NULL;
 +}
 +
 +/**
   * of_get_regulator - get a regulator device node based on supply name
   * @dev: Device pointer for the consumer (of regulator) device
   * @supply: regulator supply name
@@@ -425,10 -396,6 +427,10 @@@ static struct device_node *of_get_regul
        regnode = of_parse_phandle(dev->of_node, prop_name, 0);
  
        if (!regnode) {
 +              regnode = of_get_child_regulator(dev->of_node, prop_name);
 +              if (regnode)
 +                      return regnode;
 +
                dev_dbg(dev, "Looking up %s property in node %pOF failed\n",
                                prop_name, dev->of_node);
                return NULL;
@@@ -764,10 -731,8 +766,10 @@@ static ssize_t regulator_total_uA_show(
        int uA = 0;
  
        regulator_lock(rdev);
 -      list_for_each_entry(regulator, &rdev->consumer_list, list)
 -              uA += regulator->uA_load;
 +      list_for_each_entry(regulator, &rdev->consumer_list, list) {
 +              if (regulator->enable_count)
 +                      uA += regulator->uA_load;
 +      }
        regulator_unlock(rdev);
        return sprintf(buf, "%d\n", uA);
  }
@@@ -940,10 -905,8 +942,10 @@@ static int drms_uA_update(struct regula
                return -EINVAL;
  
        /* calc total requested load */
 -      list_for_each_entry(sibling, &rdev->consumer_list, list)
 -              current_uA += sibling->uA_load;
 +      list_for_each_entry(sibling, &rdev->consumer_list, list) {
 +              if (sibling->enable_count)
 +                      current_uA += sibling->uA_load;
 +      }
  
        current_uA += rdev->constraints->system_load;
  
@@@ -1342,12 -1305,17 +1344,12 @@@ static int set_machine_constraints(stru
                        rdev_err(rdev, "failed to set initial mode: %d\n", ret);
                        return ret;
                }
 -      }
 -
 -      /* If the constraints say the regulator should be on at this point
 -       * and we have control then make sure it is enabled.
 -       */
 -      if (rdev->constraints->always_on || rdev->constraints->boot_on) {
 -              ret = _regulator_do_enable(rdev);
 -              if (ret < 0 && ret != -EINVAL) {
 -                      rdev_err(rdev, "failed to enable\n");
 -                      return ret;
 -              }
 +      } else if (rdev->constraints->system_load) {
 +              /*
 +               * We'll only apply the initial system load if an
 +               * initial mode wasn't specified.
 +               */
 +              drms_uA_update(rdev);
        }
  
        if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable)
                }
        }
  
 +      /* If the constraints say the regulator should be on at this point
 +       * and we have control then make sure it is enabled.
 +       */
 +      if (rdev->constraints->always_on || rdev->constraints->boot_on) {
 +              if (rdev->supply) {
 +                      ret = regulator_enable(rdev->supply);
 +                      if (ret < 0) {
 +                              _regulator_put(rdev->supply);
 +                              rdev->supply = NULL;
 +                              return ret;
 +                      }
 +              }
 +
 +              ret = _regulator_do_enable(rdev);
 +              if (ret < 0 && ret != -EINVAL) {
 +                      rdev_err(rdev, "failed to enable\n");
 +                      return ret;
 +              }
 +              rdev->use_count++;
 +      }
 +
        print_constraints(rdev);
        return 0;
  }
@@@ -1830,12 -1777,8 +1832,12 @@@ static int regulator_resolve_supply(str
                return ret;
        }
  
 -      /* Cascade always-on state to supply */
 -      if (_regulator_is_enabled(rdev)) {
 +      /*
 +       * In set_machine_constraints() we may have turned this regulator on
 +       * but we couldn't propagate to the supply if it hadn't been resolved
 +       * yet.  Do it now.
 +       */
 +      if (rdev->use_count) {
                ret = regulator_enable(rdev->supply);
                if (ret < 0) {
                        _regulator_put(rdev->supply);
@@@ -2048,9 -1991,6 +2050,9 @@@ static void _regulator_put(struct regul
  
        lockdep_assert_held_once(&regulator_list_mutex);
  
 +      /* Docs say you must disable before calling regulator_put() */
 +      WARN_ON(regulator->enable_count);
 +
        rdev = regulator->rdev;
  
        debugfs_remove_recursive(regulator->debugfs);
@@@ -2444,75 -2384,15 +2446,75 @@@ static int _regulator_do_enable(struct 
        return 0;
  }
  
 +/**
 + * _regulator_handle_consumer_enable - handle that a consumer enabled
 + * @regulator: regulator source
 + *
 + * Some things on a regulator consumer (like the contribution towards total
 + * load on the regulator) only have an effect when the consumer wants the
 + * regulator enabled.  Explained in example with two consumers of the same
 + * regulator:
 + *   consumer A: set_load(100);       => total load = 0
 + *   consumer A: regulator_enable();  => total load = 100
 + *   consumer B: set_load(1000);      => total load = 100
 + *   consumer B: regulator_enable();  => total load = 1100
 + *   consumer A: regulator_disable(); => total_load = 1000
 + *
 + * This function (together with _regulator_handle_consumer_disable) is
 + * responsible for keeping track of the refcount for a given regulator consumer
 + * and applying / unapplying these things.
 + *
 + * Returns 0 upon no error; -error upon error.
 + */
 +static int _regulator_handle_consumer_enable(struct regulator *regulator)
 +{
 +      struct regulator_dev *rdev = regulator->rdev;
 +
 +      lockdep_assert_held_once(&rdev->mutex.base);
 +
 +      regulator->enable_count++;
 +      if (regulator->uA_load && regulator->enable_count == 1)
 +              return drms_uA_update(rdev);
 +
 +      return 0;
 +}
 +
 +/**
 + * _regulator_handle_consumer_disable - handle that a consumer disabled
 + * @regulator: regulator source
 + *
 + * The opposite of _regulator_handle_consumer_enable().
 + *
 + * Returns 0 upon no error; -error upon error.
 + */
 +static int _regulator_handle_consumer_disable(struct regulator *regulator)
 +{
 +      struct regulator_dev *rdev = regulator->rdev;
 +
 +      lockdep_assert_held_once(&rdev->mutex.base);
 +
 +      if (!regulator->enable_count) {
 +              rdev_err(rdev, "Underflow of regulator enable count\n");
 +              return -EINVAL;
 +      }
 +
 +      regulator->enable_count--;
 +      if (regulator->uA_load && regulator->enable_count == 0)
 +              return drms_uA_update(rdev);
 +
 +      return 0;
 +}
 +
  /* locks held by regulator_enable() */
 -static int _regulator_enable(struct regulator_dev *rdev)
 +static int _regulator_enable(struct regulator *regulator)
  {
 +      struct regulator_dev *rdev = regulator->rdev;
        int ret;
  
        lockdep_assert_held_once(&rdev->mutex.base);
  
 -      if (rdev->supply) {
 -              ret = _regulator_enable(rdev->supply->rdev);
 +      if (rdev->use_count == 0 && rdev->supply) {
 +              ret = _regulator_enable(rdev->supply);
                if (ret < 0)
                        return ret;
        }
                        goto err_disable_supply;
        }
  
 -      /* check voltage and requested load before enabling */
 -      if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS))
 -              drms_uA_update(rdev);
 +      ret = _regulator_handle_consumer_enable(regulator);
 +      if (ret < 0)
 +              goto err_disable_supply;
  
        if (rdev->use_count == 0) {
                /* The regulator may on if it's not switchable or left on */
                        if (!regulator_ops_is_valid(rdev,
                                        REGULATOR_CHANGE_STATUS)) {
                                ret = -EPERM;
 -                              goto err_disable_supply;
 +                              goto err_consumer_disable;
                        }
  
                        ret = _regulator_do_enable(rdev);
                        if (ret < 0)
 -                              goto err_disable_supply;
 +                              goto err_consumer_disable;
  
                        _notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE,
                                             NULL);
                } else if (ret < 0) {
                        rdev_err(rdev, "is_enabled() failed: %d\n", ret);
 -                      goto err_disable_supply;
 +                      goto err_consumer_disable;
                }
                /* Fallthrough on positive return values - already enabled */
        }
  
        return 0;
  
 +err_consumer_disable:
 +      _regulator_handle_consumer_disable(regulator);
 +
  err_disable_supply:
 -      if (rdev->supply)
 -              _regulator_disable(rdev->supply->rdev);
 +      if (rdev->use_count == 0 && rdev->supply)
 +              _regulator_disable(rdev->supply);
  
        return ret;
  }
@@@ -2580,10 -2457,13 +2582,10 @@@ int regulator_enable(struct regulator *
  {
        struct regulator_dev *rdev = regulator->rdev;
        struct ww_acquire_ctx ww_ctx;
 -      int ret = 0;
 -
 -      if (regulator->always_on)
 -              return 0;
 +      int ret;
  
        regulator_lock_dependent(rdev, &ww_ctx);
 -      ret = _regulator_enable(rdev);
 +      ret = _regulator_enable(regulator);
        regulator_unlock_dependent(rdev, &ww_ctx);
  
        return ret;
@@@ -2622,9 -2502,8 +2624,9 @@@ static int _regulator_do_disable(struc
  }
  
  /* locks held by regulator_disable() */
 -static int _regulator_disable(struct regulator_dev *rdev)
 +static int _regulator_disable(struct regulator *regulator)
  {
 +      struct regulator_dev *rdev = regulator->rdev;
        int ret = 0;
  
        lockdep_assert_held_once(&rdev->mutex.base);
  
                rdev->use_count = 0;
        } else if (rdev->use_count > 1) {
 -              if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS))
 -                      drms_uA_update(rdev);
 -
                rdev->use_count--;
        }
  
 +      if (ret == 0)
 +              ret = _regulator_handle_consumer_disable(regulator);
 +
        if (ret == 0 && rdev->coupling_desc.n_coupled > 1)
                ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);
  
 -      if (ret == 0 && rdev->supply)
 -              ret = _regulator_disable(rdev->supply->rdev);
 +      if (ret == 0 && rdev->use_count == 0 && rdev->supply)
 +              ret = _regulator_disable(rdev->supply);
  
        return ret;
  }
@@@ -2690,10 -2569,13 +2692,10 @@@ int regulator_disable(struct regulator 
  {
        struct regulator_dev *rdev = regulator->rdev;
        struct ww_acquire_ctx ww_ctx;
 -      int ret = 0;
 -
 -      if (regulator->always_on)
 -              return 0;
 +      int ret;
  
        regulator_lock_dependent(rdev, &ww_ctx);
 -      ret = _regulator_disable(rdev);
 +      ret = _regulator_disable(regulator);
        regulator_unlock_dependent(rdev, &ww_ctx);
  
        return ret;
@@@ -2742,21 -2624,15 +2744,21 @@@ int regulator_force_disable(struct regu
        int ret;
  
        regulator_lock_dependent(rdev, &ww_ctx);
 -      regulator->uA_load = 0;
 +
        ret = _regulator_force_disable(regulator->rdev);
 +
        if (rdev->coupling_desc.n_coupled > 1)
                regulator_balance_voltage(rdev, PM_SUSPEND_ON);
 -      regulator_unlock_dependent(rdev, &ww_ctx);
  
 -      if (rdev->supply)
 -              while (rdev->open_count--)
 -                      regulator_disable(rdev->supply);
 +      if (regulator->uA_load) {
 +              regulator->uA_load = 0;
 +              ret = drms_uA_update(rdev);
 +      }
 +
 +      if (rdev->use_count != 0 && rdev->supply)
 +              _regulator_disable(rdev->supply);
 +
 +      regulator_unlock_dependent(rdev, &ww_ctx);
  
        return ret;
  }
@@@ -2768,11 -2644,14 +2770,11 @@@ static void regulator_disable_work(stru
                                                  disable_work.work);
        struct ww_acquire_ctx ww_ctx;
        int count, i, ret;
 +      struct regulator *regulator;
 +      int total_count = 0;
  
        regulator_lock_dependent(rdev, &ww_ctx);
  
 -      BUG_ON(!rdev->deferred_disables);
 -
 -      count = rdev->deferred_disables;
 -      rdev->deferred_disables = 0;
 -
        /*
         * Workqueue functions queue the new work instance while the previous
         * work instance is being processed. Cancel the queued work instance
         */
        cancel_delayed_work(&rdev->disable_work);
  
 -      for (i = 0; i < count; i++) {
 -              ret = _regulator_disable(rdev);
 -              if (ret != 0)
 -                      rdev_err(rdev, "Deferred disable failed: %d\n", ret);
 +      list_for_each_entry(regulator, &rdev->consumer_list, list) {
 +              count = regulator->deferred_disables;
 +
 +              if (!count)
 +                      continue;
 +
 +              total_count += count;
 +              regulator->deferred_disables = 0;
 +
 +              for (i = 0; i < count; i++) {
 +                      ret = _regulator_disable(regulator);
 +                      if (ret != 0)
 +                              rdev_err(rdev, "Deferred disable failed: %d\n", ret);
 +              }
        }
 +      WARN_ON(!total_count);
  
        if (rdev->coupling_desc.n_coupled > 1)
                regulator_balance_voltage(rdev, PM_SUSPEND_ON);
  
        regulator_unlock_dependent(rdev, &ww_ctx);
-       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);
-                       }
-               }
-       }
  }
  
  /**
@@@ -2830,11 -2688,14 +2822,11 @@@ int regulator_disable_deferred(struct r
  {
        struct regulator_dev *rdev = regulator->rdev;
  
 -      if (regulator->always_on)
 -              return 0;
 -
        if (!ms)
                return regulator_disable(regulator);
  
        regulator_lock(rdev);
 -      rdev->deferred_disables++;
 +      regulator->deferred_disables++;
        mod_delayed_work(system_power_efficient_wq, &rdev->disable_work,
                         msecs_to_jiffies(ms));
        regulator_unlock(rdev);
@@@ -4241,30 -4102,16 +4233,30 @@@ EXPORT_SYMBOL_GPL(regulator_get_error_f
   * DRMS will sum the total requested load on the regulator and change
   * to the most efficient operating mode if platform constraints allow.
   *
 + * NOTE: when a regulator consumer requests to have a regulator
 + * disabled then any load that consumer requested no longer counts
 + * toward the total requested load.  If the regulator is re-enabled
 + * then the previously requested load will start counting again.
 + *
 + * If a regulator is an always-on regulator then an individual consumer's
 + * load will still be removed if that consumer is fully disabled.
 + *
   * On error a negative errno is returned.
   */
  int regulator_set_load(struct regulator *regulator, int uA_load)
  {
        struct regulator_dev *rdev = regulator->rdev;
 -      int ret;
 +      int old_uA_load;
 +      int ret = 0;
  
        regulator_lock(rdev);
 +      old_uA_load = regulator->uA_load;
        regulator->uA_load = uA_load;
 -      ret = drms_uA_update(rdev);
 +      if (regulator->enable_count && old_uA_load != uA_load) {
 +              ret = drms_uA_update(rdev);
 +              if (ret < 0)
 +                      regulator->uA_load = old_uA_load;
 +      }
        regulator_unlock(rdev);
  
        return ret;
@@@ -4435,8 -4282,11 +4427,8 @@@ int regulator_bulk_enable(int num_consu
        int ret = 0;
  
        for (i = 0; i < num_consumers; i++) {
 -              if (consumers[i].consumer->always_on)
 -                      consumers[i].ret = 0;
 -              else
 -                      async_schedule_domain(regulator_bulk_enable_async,
 -                                            &consumers[i], &async_domain);
 +              async_schedule_domain(regulator_bulk_enable_async,
 +                                    &consumers[i], &async_domain);
        }
  
        async_synchronize_full_domain(&async_domain);
@@@ -4672,6 -4522,10 +4664,6 @@@ static umode_t regulator_attr_is_visibl
        if (attr == &dev_attr_bypass.attr)
                return ops->get_bypass ? mode : 0;
  
 -      /* some attributes are type-specific */
 -      if (attr == &dev_attr_requested_microamps.attr)
 -              return rdev->desc->type == REGULATOR_CURRENT ? mode : 0;
 -
        /* constraints need specific supporting methods */
        if (attr == &dev_attr_min_microvolts.attr ||
            attr == &dev_attr_max_microvolts.attr)
@@@ -4881,33 -4735,21 +4873,33 @@@ regulator_register(const struct regulat
        struct regulator_config *config = NULL;
        static atomic_t regulator_no = ATOMIC_INIT(-1);
        struct regulator_dev *rdev;
 +      bool dangling_cfg_gpiod = false;
 +      bool dangling_of_gpiod = false;
        struct device *dev;
        int ret, i;
  
 -      if (regulator_desc == NULL || cfg == NULL)
 +      if (cfg == NULL)
                return ERR_PTR(-EINVAL);
 +      if (cfg->ena_gpiod)
 +              dangling_cfg_gpiod = true;
 +      if (regulator_desc == NULL) {
 +              ret = -EINVAL;
 +              goto rinse;
 +      }
  
        dev = cfg->dev;
        WARN_ON(!dev);
  
 -      if (regulator_desc->name == NULL || regulator_desc->ops == NULL)
 -              return ERR_PTR(-EINVAL);
 +      if (regulator_desc->name == NULL || regulator_desc->ops == NULL) {
 +              ret = -EINVAL;
 +              goto rinse;
 +      }
  
        if (regulator_desc->type != REGULATOR_VOLTAGE &&
 -          regulator_desc->type != REGULATOR_CURRENT)
 -              return ERR_PTR(-EINVAL);
 +          regulator_desc->type != REGULATOR_CURRENT) {
 +              ret = -EINVAL;
 +              goto rinse;
 +      }
  
        /* Only one of each should be implemented */
        WARN_ON(regulator_desc->ops->get_voltage &&
        /* If we're using selectors we must implement list_voltage. */
        if (regulator_desc->ops->get_voltage_sel &&
            !regulator_desc->ops->list_voltage) {
 -              return ERR_PTR(-EINVAL);
 +              ret = -EINVAL;
 +              goto rinse;
        }
        if (regulator_desc->ops->set_voltage_sel &&
            !regulator_desc->ops->list_voltage) {
 -              return ERR_PTR(-EINVAL);
 +              ret = -EINVAL;
 +              goto rinse;
        }
  
        rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
 -      if (rdev == NULL)
 -              return ERR_PTR(-ENOMEM);
 +      if (rdev == NULL) {
 +              ret = -ENOMEM;
 +              goto rinse;
 +      }
  
        /*
         * Duplicate the config so the driver could override it after
        config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL);
        if (config == NULL) {
                kfree(rdev);
 -              return ERR_PTR(-ENOMEM);
 +              ret = -ENOMEM;
 +              goto rinse;
        }
  
        init_data = regulator_of_get_init_data(dev, regulator_desc, config,
                                               &rdev->dev.of_node);
 +      /*
 +       * We need to keep track of any GPIO descriptor coming from the
 +       * device tree until we have handled it over to the core. If the
 +       * config that was passed in to this function DOES NOT contain
 +       * a descriptor, and the config after this call DOES contain
 +       * a descriptor, we definately got one from parsing the device
 +       * tree.
 +       */
 +      if (!cfg->ena_gpiod && config->ena_gpiod)
 +              dangling_of_gpiod = true;
        if (!init_data) {
                init_data = config->init_data;
                rdev->dev.of_node = of_node_get(config->of_node);
                                 config->ena_gpio, ret);
                        goto clean;
                }
 +              /* The regulator core took over the GPIO descriptor */
 +              dangling_cfg_gpiod = false;
 +              dangling_of_gpiod = false;
        }
  
        /* register with sysfs */
@@@ -5082,13 -4906,8 +5074,13 @@@ wash
        regulator_ena_gpio_free(rdev);
        mutex_unlock(&regulator_list_mutex);
  clean:
 +      if (dangling_of_gpiod)
 +              gpiod_put(config->ena_gpiod);
        kfree(rdev);
        kfree(config);
 +rinse:
 +      if (dangling_cfg_gpiod)
 +              gpiod_put(cfg->ena_gpiod);
        return ERR_PTR(ret);
  }
  EXPORT_SYMBOL_GPL(regulator_register);
@@@ -5278,8 -5097,23 +5270,8 @@@ static int supply_map_show(struct seq_f
  
        return 0;
  }
 +DEFINE_SHOW_ATTRIBUTE(supply_map);
  
 -static int supply_map_open(struct inode *inode, struct file *file)
 -{
 -      return single_open(file, supply_map_show, inode->i_private);
 -}
 -#endif
 -
 -static const struct file_operations supply_map_fops = {
 -#ifdef CONFIG_DEBUG_FS
 -      .open = supply_map_open,
 -      .read = seq_read,
 -      .llseek = seq_lseek,
 -      .release = single_release,
 -#endif
 -};
 -
 -#ifdef CONFIG_DEBUG_FS
  struct summary_data {
        struct seq_file *s;
        struct regulator_dev *parent;
@@@ -5352,11 -5186,8 +5344,11 @@@ static void regulator_summary_show_subt
  
                switch (rdev->desc->type) {
                case REGULATOR_VOLTAGE:
 -                      seq_printf(s, "%37dmA %5dmV %5dmV",
 +                      seq_printf(s, "%3d %33dmA%c%5dmV %5dmV",
 +                                 consumer->enable_count,
                                   consumer->uA_load / 1000,
 +                                 consumer->uA_load && !consumer->enable_count ?
 +                                 '*' : ' ',
                                   consumer->voltage[PM_SUSPEND_ON].min_uV / 1000,
                                   consumer->voltage[PM_SUSPEND_ON].max_uV / 1000);
                        break;
@@@ -5501,8 -5332,21 +5493,8 @@@ static int regulator_summary_show(struc
  
        return 0;
  }
 -
 -static int regulator_summary_open(struct inode *inode, struct file *file)
 -{
 -      return single_open(file, regulator_summary_show, inode->i_private);
 -}
 -#endif
 -
 -static const struct file_operations regulator_summary_fops = {
 -#ifdef CONFIG_DEBUG_FS
 -      .open           = regulator_summary_open,
 -      .read           = seq_read,
 -      .llseek         = seq_lseek,
 -      .release        = single_release,
 -#endif
 -};
 +DEFINE_SHOW_ATTRIBUTE(regulator_summary);
 +#endif /* CONFIG_DEBUG_FS */
  
  static int __init regulator_init(void)
  {
        if (!debugfs_root)
                pr_warn("regulator: Failed to create debugfs directory\n");
  
 +#ifdef CONFIG_DEBUG_FS
        debugfs_create_file("supply_map", 0444, debugfs_root, NULL,
                            &supply_map_fops);
  
        debugfs_create_file("regulator_summary", 0444, debugfs_root,
                            NULL, &regulator_summary_fops);
 -
 +#endif
        regulator_dummy_init();
  
        return ret;