--- zzzz-none-000/linux-3.10.107/drivers/regulator/core.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/regulator/core.c 2021-02-04 17:41:59.000000000 +0000 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -32,10 +33,12 @@ #include #include +#include #define CREATE_TRACE_POINTS #include #include "dummy.h" +#include "internal.h" #define rdev_crit(rdev, fmt, ...) \ pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) @@ -49,14 +52,15 @@ pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) static DEFINE_MUTEX(regulator_list_mutex); -static LIST_HEAD(regulator_list); static LIST_HEAD(regulator_map_list); static LIST_HEAD(regulator_ena_gpio_list); +static LIST_HEAD(regulator_supply_alias_list); static bool has_full_constraints; -static bool board_wants_dummy_regulator; static struct dentry *debugfs_root; +static struct class regulator_class; + /* * struct regulator_map * @@ -76,29 +80,23 @@ */ struct regulator_enable_gpio { struct list_head list; - int gpio; + struct gpio_desc *gpiod; u32 enable_count; /* a number of enabled shared GPIO */ u32 request_count; /* a number of requested shared GPIO */ unsigned int ena_gpio_invert:1; }; /* - * struct regulator + * struct regulator_supply_alias * - * One for each consumer device. + * Used to map lookups for a supply onto an alternative device. */ -struct regulator { - struct device *dev; +struct regulator_supply_alias { struct list_head list; - unsigned int always_on:1; - unsigned int bypass:1; - int uA_load; - int min_uV; - int max_uV; - char *supply_name; - struct device_attribute dev_attr; - struct regulator_dev *rdev; - struct dentry *debugfs; + struct device *src_dev; + const char *src_supply; + struct device *alias_dev; + const char *alias_supply; }; static int _regulator_is_enabled(struct regulator_dev *rdev); @@ -106,13 +104,21 @@ 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); -static void _notifier_call_chain(struct regulator_dev *rdev, +static int _notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data); static int _regulator_do_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV); static struct regulator *create_regulator(struct regulator_dev *rdev, struct device *dev, const char *supply_name); +static void _regulator_put(struct regulator *regulator); +static int _regulator_list_voltage(struct regulator *regulator, + unsigned selector, int lock); + +static struct regulator_dev *dev_to_rdev(struct device *dev) +{ + return container_of(dev, struct regulator_dev, dev); +} static const char *rdev_get_name(struct regulator_dev *rdev) { @@ -124,6 +130,50 @@ return ""; } +static bool have_full_constraints(void) +{ + return has_full_constraints || of_have_populated_dt(); +} + +static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev) +{ + if (rdev && rdev->supply) + return rdev->supply->rdev; + + return NULL; +} + +/** + * regulator_lock_supply - lock a regulator and its supplies + * @rdev: regulator source + */ +static void regulator_lock_supply(struct regulator_dev *rdev) +{ + int i; + + for (i = 0; rdev; rdev = rdev_get_supply(rdev), i++) + mutex_lock_nested(&rdev->mutex, i); +} + +/** + * regulator_unlock_supply - unlock a regulator and its supplies + * @rdev: regulator source + */ +static void regulator_unlock_supply(struct regulator_dev *rdev) +{ + struct regulator *supply; + + while (1) { + mutex_unlock(&rdev->mutex); + supply = rdev->supply; + + if (!rdev->supply) + return; + + rdev = supply->rdev; + } +} + /** * of_get_regulator - get a regulator device node based on supply name * @dev: Device pointer for the consumer (of regulator) device @@ -173,7 +223,7 @@ return -ENODEV; } if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { - rdev_err(rdev, "operation not allowed\n"); + rdev_err(rdev, "voltage operation not allowed\n"); return -EPERM; } @@ -233,7 +283,7 @@ return -ENODEV; } if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) { - rdev_err(rdev, "operation not allowed\n"); + rdev_err(rdev, "current operation not allowed\n"); return -EPERM; } @@ -270,7 +320,7 @@ return -ENODEV; } if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) { - rdev_err(rdev, "operation not allowed\n"); + rdev_err(rdev, "mode operation not allowed\n"); return -EPERM; } @@ -294,7 +344,7 @@ return -ENODEV; } if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) { - rdev_err(rdev, "operation not allowed\n"); + rdev_dbg(rdev, "drms operation not allowed\n"); return -EPERM; } return 0; @@ -323,13 +373,14 @@ } static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); -static ssize_t regulator_name_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t name_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); return sprintf(buf, "%s\n", rdev_get_name(rdev)); } +static DEVICE_ATTR_RO(name); static ssize_t regulator_print_opmode(char *buf, int mode) { @@ -489,15 +540,16 @@ } static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); -static ssize_t regulator_num_users_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t num_users_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); return sprintf(buf, "%d\n", rdev->use_count); } +static DEVICE_ATTR_RO(num_users); -static ssize_t regulator_type_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t type_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); @@ -509,6 +561,7 @@ } return sprintf(buf, "unknown\n"); } +static DEVICE_ATTR_RO(type); static ssize_t regulator_suspend_mem_uV_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -628,48 +681,38 @@ static DEVICE_ATTR(bypass, 0444, regulator_bypass_show, NULL); -/* - * These are the only attributes are present for all regulators. - * Other attributes are a function of regulator functionality. - */ -static struct device_attribute regulator_dev_attrs[] = { - __ATTR(name, 0444, regulator_name_show, NULL), - __ATTR(num_users, 0444, regulator_num_users_show, NULL), - __ATTR(type, 0444, regulator_type_show, NULL), - __ATTR_NULL, -}; - -static void regulator_dev_release(struct device *dev) -{ - struct regulator_dev *rdev = dev_get_drvdata(dev); - kfree(rdev); -} - -static struct class regulator_class = { - .name = "regulator", - .dev_release = regulator_dev_release, - .dev_attrs = regulator_dev_attrs, -}; - /* Calculate the new optimum regulator operating mode based on the new total * consumer load. All locks held by caller */ -static void drms_uA_update(struct regulator_dev *rdev) +static int drms_uA_update(struct regulator_dev *rdev) { struct regulator *sibling; int current_uA = 0, output_uV, input_uV, err; unsigned int mode; + lockdep_assert_held_once(&rdev->mutex); + + /* + * first check to see if we can set modes at all, otherwise just + * tell the consumer everything is OK. + */ err = regulator_check_drms(rdev); - if (err < 0 || !rdev->desc->ops->get_optimum_mode || - (!rdev->desc->ops->get_voltage && - !rdev->desc->ops->get_voltage_sel) || - !rdev->desc->ops->set_mode) - return; + if (err < 0) + return 0; + + if (!rdev->desc->ops->get_optimum_mode && + !rdev->desc->ops->set_load) + return 0; + + if (!rdev->desc->ops->set_mode && + !rdev->desc->ops->set_load) + return -EINVAL; /* get output voltage */ output_uV = _regulator_get_voltage(rdev); - if (output_uV <= 0) - return; + if (output_uV <= 0) { + rdev_err(rdev, "invalid output voltage found\n"); + return -EINVAL; + } /* get input voltage */ input_uV = 0; @@ -677,21 +720,41 @@ input_uV = regulator_get_voltage(rdev->supply); if (input_uV <= 0) input_uV = rdev->constraints->input_uV; - if (input_uV <= 0) - return; + if (input_uV <= 0) { + rdev_err(rdev, "invalid input voltage found\n"); + return -EINVAL; + } /* calc total requested load */ list_for_each_entry(sibling, &rdev->consumer_list, list) current_uA += sibling->uA_load; - /* now get the optimum mode for our new total regulator load */ - mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, - output_uV, current_uA); - - /* check the new mode is allowed */ - err = regulator_mode_constrain(rdev, &mode); - if (err == 0) - rdev->desc->ops->set_mode(rdev, mode); + current_uA += rdev->constraints->system_load; + + if (rdev->desc->ops->set_load) { + /* set the optimum mode for our new total regulator load */ + err = rdev->desc->ops->set_load(rdev, current_uA); + if (err < 0) + rdev_err(rdev, "failed to set load %d\n", current_uA); + } else { + /* now get the optimum mode for our new total regulator load */ + mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, + output_uV, current_uA); + + /* check the new mode is allowed */ + err = regulator_mode_constrain(rdev, &mode); + if (err < 0) { + rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", + current_uA, input_uV, output_uV); + return err; + } + + err = rdev->desc->ops->set_mode(rdev, mode); + if (err < 0) + rdev_err(rdev, "failed to set optimum mode %x\n", mode); + } + + return err; } static int suspend_set_state(struct regulator_dev *rdev, @@ -748,6 +811,8 @@ /* locks held by caller */ static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) { + lockdep_assert_held_once(&rdev->mutex); + if (!rdev->constraints) return -EINVAL; @@ -770,60 +835,65 @@ { struct regulation_constraints *constraints = rdev->constraints; char buf[160] = ""; + size_t len = sizeof(buf) - 1; int count = 0; int ret; if (constraints->min_uV && constraints->max_uV) { if (constraints->min_uV == constraints->max_uV) - count += sprintf(buf + count, "%d mV ", - constraints->min_uV / 1000); + count += scnprintf(buf + count, len - count, "%d mV ", + constraints->min_uV / 1000); else - count += sprintf(buf + count, "%d <--> %d mV ", - constraints->min_uV / 1000, - constraints->max_uV / 1000); + count += scnprintf(buf + count, len - count, + "%d <--> %d mV ", + constraints->min_uV / 1000, + constraints->max_uV / 1000); } if (!constraints->min_uV || constraints->min_uV != constraints->max_uV) { ret = _regulator_get_voltage(rdev); if (ret > 0) - count += sprintf(buf + count, "at %d mV ", ret / 1000); + count += scnprintf(buf + count, len - count, + "at %d mV ", ret / 1000); } if (constraints->uV_offset) - count += sprintf(buf, "%dmV offset ", - constraints->uV_offset / 1000); + count += scnprintf(buf + count, len - count, "%dmV offset ", + constraints->uV_offset / 1000); if (constraints->min_uA && constraints->max_uA) { if (constraints->min_uA == constraints->max_uA) - count += sprintf(buf + count, "%d mA ", - constraints->min_uA / 1000); + count += scnprintf(buf + count, len - count, "%d mA ", + constraints->min_uA / 1000); else - count += sprintf(buf + count, "%d <--> %d mA ", - constraints->min_uA / 1000, - constraints->max_uA / 1000); + count += scnprintf(buf + count, len - count, + "%d <--> %d mA ", + constraints->min_uA / 1000, + constraints->max_uA / 1000); } if (!constraints->min_uA || constraints->min_uA != constraints->max_uA) { ret = _regulator_get_current_limit(rdev); if (ret > 0) - count += sprintf(buf + count, "at %d mA ", ret / 1000); + count += scnprintf(buf + count, len - count, + "at %d mA ", ret / 1000); } if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) - count += sprintf(buf + count, "fast "); + count += scnprintf(buf + count, len - count, "fast "); if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) - count += sprintf(buf + count, "normal "); + count += scnprintf(buf + count, len - count, "normal "); if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) - count += sprintf(buf + count, "idle "); + count += scnprintf(buf + count, len - count, "idle "); if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) - count += sprintf(buf + count, "standby"); + count += scnprintf(buf + count, len - count, "standby"); if (!count) - sprintf(buf, "no parameters"); + scnprintf(buf, len, "no parameters"); - rdev_info(rdev, "%s\n", buf); + rdev_dbg(rdev, "%s\n", buf); if ((constraints->min_uV != constraints->max_uV) && !(constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) @@ -834,19 +904,30 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, struct regulation_constraints *constraints) { - struct regulator_ops *ops = rdev->desc->ops; + const struct regulator_ops *ops = rdev->desc->ops; int ret; /* do we need to apply the constraint voltage */ if (rdev->constraints->apply_uV && rdev->constraints->min_uV == rdev->constraints->max_uV) { - ret = _regulator_do_set_voltage(rdev, - rdev->constraints->min_uV, - rdev->constraints->max_uV); - if (ret < 0) { - rdev_err(rdev, "failed to apply %duV constraint\n", - rdev->constraints->min_uV); - return ret; + int current_uV = _regulator_get_voltage(rdev); + if (current_uV < 0) { + rdev_err(rdev, + "failed to get the current voltage(%d)\n", + current_uV); + return current_uV; + } + if (current_uV < rdev->constraints->min_uV || + current_uV > rdev->constraints->max_uV) { + ret = _regulator_do_set_voltage( + rdev, rdev->constraints->min_uV, + rdev->constraints->max_uV); + if (ret < 0) { + rdev_err(rdev, + "failed to apply %duV constraint(%d)\n", + rdev->constraints->min_uV, ret); + return ret; + } } } @@ -919,6 +1000,36 @@ return 0; } +static int machine_constraints_current(struct regulator_dev *rdev, + struct regulation_constraints *constraints) +{ + const struct regulator_ops *ops = rdev->desc->ops; + int ret; + + if (!constraints->min_uA && !constraints->max_uA) + return 0; + + if (constraints->min_uA > constraints->max_uA) { + rdev_err(rdev, "Invalid current constraints\n"); + return -EINVAL; + } + + if (!ops->set_current_limit || !ops->get_current_limit) { + rdev_warn(rdev, "Operation of current configuration missing\n"); + return 0; + } + + /* Set regulator current in constraints range */ + ret = ops->set_current_limit(rdev, constraints->min_uA, + constraints->max_uA); + if (ret < 0) { + rdev_err(rdev, "Failed to set current constraint, %d\n", ret); + return ret; + } + + return 0; +} + static int _regulator_do_enable(struct regulator_dev *rdev); /** @@ -936,7 +1047,7 @@ const struct regulation_constraints *constraints) { int ret = 0; - struct regulator_ops *ops = rdev->desc->ops; + const struct regulator_ops *ops = rdev->desc->ops; if (constraints) rdev->constraints = kmemdup(constraints, sizeof(*constraints), @@ -951,6 +1062,19 @@ if (ret != 0) goto out; + ret = machine_constraints_current(rdev, rdev->constraints); + if (ret != 0) + goto out; + + if (rdev->constraints->ilim_uA && ops->set_input_current_limit) { + ret = ops->set_input_current_limit(rdev, + rdev->constraints->ilim_uA); + if (ret < 0) { + rdev_err(rdev, "failed to set input limit\n"); + goto out; + } + } + /* do we need to setup our suspend state */ if (rdev->constraints->initial_state) { ret = suspend_prepare(rdev, rdev->constraints->initial_state); @@ -985,7 +1109,8 @@ } } - if (rdev->constraints->ramp_delay && ops->set_ramp_delay) { + if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) + && ops->set_ramp_delay) { ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); if (ret < 0) { rdev_err(rdev, "failed to set ramp_delay\n"); @@ -993,6 +1118,31 @@ } } + if (rdev->constraints->pull_down && ops->set_pull_down) { + ret = ops->set_pull_down(rdev); + if (ret < 0) { + rdev_err(rdev, "failed to set pull down\n"); + goto out; + } + } + + if (rdev->constraints->soft_start && ops->set_soft_start) { + ret = ops->set_soft_start(rdev); + if (ret < 0) { + rdev_err(rdev, "failed to set soft start\n"); + goto out; + } + } + + if (rdev->constraints->over_current_protection + && ops->set_over_current_protection) { + ret = ops->set_over_current_protection(rdev); + if (ret < 0) { + rdev_err(rdev, "failed to set over current protection\n"); + goto out; + } + } + print_constraints(rdev); return 0; out: @@ -1017,6 +1167,9 @@ rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); + if (!try_module_get(supply_rdev->owner)) + return -ENODEV; + rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); if (rdev->supply == NULL) { err = -ENOMEM; @@ -1136,10 +1289,10 @@ if (regulator->supply_name == NULL) goto overflow_err; - err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj, + err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj, buf); if (err) { - rdev_warn(rdev, "could not add device link %s err %d\n", + rdev_dbg(rdev, "could not add device link %s err %d\n", dev->kobj.name, err); /* non-fatal */ } @@ -1152,7 +1305,7 @@ regulator->debugfs = debugfs_create_dir(regulator->supply_name, rdev->debugfs); if (!regulator->debugfs) { - rdev_warn(rdev, "Failed to create debugfs directory\n"); + rdev_dbg(rdev, "Failed to create debugfs directory\n"); } else { debugfs_create_u32("uA_load", 0444, regulator->debugfs, ®ulator->uA_load); @@ -1182,11 +1335,80 @@ static int _regulator_get_enable_time(struct regulator_dev *rdev) { + if (rdev->constraints && rdev->constraints->enable_time) + return rdev->constraints->enable_time; if (!rdev->desc->ops->enable_time) return rdev->desc->enable_time; return rdev->desc->ops->enable_time(rdev); } +static struct regulator_supply_alias *regulator_find_supply_alias( + struct device *dev, const char *supply) +{ + struct regulator_supply_alias *map; + + list_for_each_entry(map, ®ulator_supply_alias_list, list) + if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0) + return map; + + return NULL; +} + +static void regulator_supply_alias(struct device **dev, const char **supply) +{ + struct regulator_supply_alias *map; + + map = regulator_find_supply_alias(*dev, *supply); + if (map) { + dev_dbg(*dev, "Mapping supply %s to %s,%s\n", + *supply, map->alias_supply, + dev_name(map->alias_dev)); + *dev = map->alias_dev; + *supply = map->alias_supply; + } +} + +static int of_node_match(struct device *dev, const void *data) +{ + return dev->of_node == data; +} + +static struct regulator_dev *of_find_regulator_by_node(struct device_node *np) +{ + struct device *dev; + + dev = class_find_device(®ulator_class, NULL, np, of_node_match); + + return dev ? dev_to_rdev(dev) : NULL; +} + +static int regulator_match(struct device *dev, const void *data) +{ + struct regulator_dev *r = dev_to_rdev(dev); + + return strcmp(rdev_get_name(r), data) == 0; +} + +static struct regulator_dev *regulator_lookup_by_name(const char *name) +{ + struct device *dev; + + dev = class_find_device(®ulator_class, NULL, name, regulator_match); + + return dev ? dev_to_rdev(dev) : NULL; +} + +/** + * regulator_dev_lookup - lookup a regulator device. + * @dev: device for regulator "consumer". + * @supply: Supply name or regulator ID. + * @ret: 0 on success, -ENODEV if lookup fails permanently, -EPROBE_DEFER if + * lookup could succeed in the future. + * + * If successful, returns a struct regulator_dev that corresponds to the name + * @supply and with the embedded struct device refcount incremented by one, + * or NULL on failure. The refcount must be dropped by calling put_device(). + */ static struct regulator_dev *regulator_dev_lookup(struct device *dev, const char *supply, int *ret) @@ -1196,14 +1418,17 @@ struct regulator_map *map; const char *devname = NULL; + regulator_supply_alias(&dev, &supply); + /* first do a dt based lookup */ if (dev && dev->of_node) { node = of_get_regulator(dev, supply); if (node) { - list_for_each_entry(r, ®ulator_list, list) - if (r->dev.parent && - node == r->dev.of_node) - return r; + r = of_find_regulator_by_node(node); + if (r) + return r; + *ret = -EPROBE_DEFER; + return NULL; } else { /* * If we couldn't even get the node then it's @@ -1219,98 +1444,178 @@ if (dev) devname = dev_name(dev); - list_for_each_entry(r, ®ulator_list, list) - if (strcmp(rdev_get_name(r), supply) == 0) - return r; + r = regulator_lookup_by_name(supply); + if (r) + return r; + mutex_lock(®ulator_list_mutex); list_for_each_entry(map, ®ulator_map_list, list) { /* If the mapping has a device set up it must match */ if (map->dev_name && (!devname || strcmp(map->dev_name, devname))) continue; - if (strcmp(map->supply, supply) == 0) + if (strcmp(map->supply, supply) == 0 && + get_device(&map->regulator->dev)) { + mutex_unlock(®ulator_list_mutex); return map->regulator; + } } - + mutex_unlock(®ulator_list_mutex); return NULL; } +static int regulator_resolve_supply(struct regulator_dev *rdev) +{ + struct regulator_dev *r; + struct device *dev = rdev->dev.parent; + int ret; + + /* No supply to resovle? */ + if (!rdev->supply_name) + return 0; + + /* Supply already resolved? */ + if (rdev->supply) + return 0; + + r = regulator_dev_lookup(dev, rdev->supply_name, &ret); + if (!r) { + if (ret == -ENODEV) { + /* + * No supply was specified for this regulator and + * there will never be one. + */ + return 0; + } + + /* Did the lookup explicitly defer for us? */ + if (ret == -EPROBE_DEFER) + return ret; + + if (have_full_constraints()) { + r = dummy_regulator_rdev; + get_device(&r->dev); + } else { + dev_err(dev, "Failed to resolve %s-supply for %s\n", + rdev->supply_name, rdev->desc->name); + return -EPROBE_DEFER; + } + } + + /* Recursively resolve the supply of the supply */ + ret = regulator_resolve_supply(r); + if (ret < 0) { + put_device(&r->dev); + return ret; + } + + ret = set_supply(rdev, r); + if (ret < 0) { + put_device(&r->dev); + return ret; + } + + /* Cascade always-on state to supply */ + if (_regulator_is_enabled(rdev) && rdev->supply) { + ret = regulator_enable(rdev->supply); + if (ret < 0) { + _regulator_put(rdev->supply); + return ret; + } + } + + return 0; +} + /* Internal regulator request function */ static struct regulator *_regulator_get(struct device *dev, const char *id, - int exclusive) + bool exclusive, bool allow_dummy) { struct regulator_dev *rdev; struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); const char *devname = NULL; - int ret = 0; + int ret; if (id == NULL) { pr_err("get() with no identifier\n"); - return regulator; + return ERR_PTR(-EINVAL); } if (dev) devname = dev_name(dev); - mutex_lock(®ulator_list_mutex); + if (have_full_constraints()) + ret = -ENODEV; + else + ret = -EPROBE_DEFER; rdev = regulator_dev_lookup(dev, id, &ret); if (rdev) goto found; + regulator = ERR_PTR(ret); + /* * If we have return value from dev_lookup fail, we do not expect to * succeed, so, quit with appropriate error value */ - if (ret) { - regulator = ERR_PTR(ret); - goto out; - } - - if (board_wants_dummy_regulator) { - rdev = dummy_regulator_rdev; - goto found; - } + if (ret && ret != -ENODEV) + return regulator; -#ifdef CONFIG_REGULATOR_DUMMY if (!devname) devname = "deviceless"; - /* If the board didn't flag that it was fully constrained then - * substitute in a dummy regulator so consumers can continue. + /* + * Assume that a regulator is physically present and enabled + * even if it isn't hooked up and just provide a dummy. */ - if (!has_full_constraints) { + if (have_full_constraints() && allow_dummy) { pr_warn("%s supply %s not found, using dummy regulator\n", devname, id); + rdev = dummy_regulator_rdev; + get_device(&rdev->dev); goto found; + /* Don't log an error when called from regulator_get_optional() */ + } else if (!have_full_constraints() || exclusive) { + dev_warn(dev, "dummy supplies not allowed\n"); } -#endif - mutex_unlock(®ulator_list_mutex); return regulator; found: if (rdev->exclusive) { regulator = ERR_PTR(-EPERM); - goto out; + put_device(&rdev->dev); + return regulator; } if (exclusive && rdev->open_count) { regulator = ERR_PTR(-EBUSY); - goto out; + put_device(&rdev->dev); + return regulator; } - if (!try_module_get(rdev->owner)) - goto out; + ret = regulator_resolve_supply(rdev); + if (ret < 0) { + regulator = ERR_PTR(ret); + put_device(&rdev->dev); + return regulator; + } + + if (!try_module_get(rdev->owner)) { + put_device(&rdev->dev); + return regulator; + } regulator = create_regulator(rdev, dev, id); if (regulator == NULL) { regulator = ERR_PTR(-ENOMEM); + put_device(&rdev->dev); module_put(rdev->owner); - goto out; + return regulator; } rdev->open_count++; @@ -1324,9 +1629,6 @@ rdev->use_count = 0; } -out: - mutex_unlock(®ulator_list_mutex); - return regulator; } @@ -1345,44 +1647,10 @@ */ struct regulator *regulator_get(struct device *dev, const char *id) { - return _regulator_get(dev, id, 0); + return _regulator_get(dev, id, false, true); } 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" @@ -1390,9 +1658,9 @@ * * Returns a struct regulator corresponding to the regulator producer, * or IS_ERR() condition containing errno. Other consumers will be - * unable to obtain this reference is held and the use count for the - * regulator will be initialised to reflect the current state of the - * regulator. + * unable to obtain this regulator while this reference is held and the + * use count for the regulator will be initialised to reflect the current + * state of the regulator. * * This is intended for use by consumers which cannot tolerate shared * use of the regulator such as those which need to force the @@ -1406,18 +1674,46 @@ */ struct regulator *regulator_get_exclusive(struct device *dev, const char *id) { - return _regulator_get(dev, id, 1); + return _regulator_get(dev, id, true, false); } EXPORT_SYMBOL_GPL(regulator_get_exclusive); +/** + * regulator_get_optional - obtain optional access to a regulator. + * @dev: device for regulator "consumer" + * @id: Supply name or regulator ID. + * + * Returns a struct regulator corresponding to the regulator producer, + * or IS_ERR() condition containing errno. + * + * This is intended for use by consumers for devices which can have + * some supplies unconnected in normal use, such as some MMC devices. + * It can allow the regulator core to provide stub supplies for other + * supplies requested using normal regulator_get() calls without + * disrupting the operation of drivers that can handle absent + * supplies. + * + * Use of supply names configured via regulator_set_device_supply() is + * strongly encouraged. It is recommended that the supply name used + * should match the name used for the supply and/or the relevant + * device pins in the datasheet. + */ +struct regulator *regulator_get_optional(struct device *dev, const char *id) +{ + return _regulator_get(dev, id, false, false); +} +EXPORT_SYMBOL_GPL(regulator_get_optional); + /* regulator_list_mutex lock held by regulator_put() */ static void _regulator_put(struct regulator *regulator) { struct regulator_dev *rdev; - if (regulator == NULL || IS_ERR(regulator)) + if (IS_ERR_OR_NULL(regulator)) return; + lockdep_assert_held_once(®ulator_list_mutex); + rdev = regulator->rdev; debugfs_remove_recursive(regulator->debugfs); @@ -1426,14 +1722,16 @@ if (regulator->dev) sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); mutex_lock(&rdev->mutex); - kfree(regulator->supply_name); list_del(®ulator->list); - kfree(regulator); rdev->open_count--; rdev->exclusive = 0; + put_device(&rdev->dev); mutex_unlock(&rdev->mutex); + kfree(regulator->supply_name); + kfree(regulator); + module_put(rdev->owner); } @@ -1453,44 +1751,147 @@ } EXPORT_SYMBOL_GPL(regulator_put); -static int devm_regulator_match(struct device *dev, void *res, void *data) +/** + * regulator_register_supply_alias - Provide device alias for supply lookup + * + * @dev: device that will be given as the regulator "consumer" + * @id: Supply name or regulator ID + * @alias_dev: device that should be used to lookup the supply + * @alias_id: Supply name or regulator ID that should be used to lookup the + * supply + * + * All lookups for id on dev will instead be conducted for alias_id on + * alias_dev. + */ +int regulator_register_supply_alias(struct device *dev, const char *id, + struct device *alias_dev, + const char *alias_id) { - struct regulator **r = res; - if (!r || !*r) { - WARN_ON(!r || !*r); - return 0; + struct regulator_supply_alias *map; + + map = regulator_find_supply_alias(dev, id); + if (map) + return -EEXIST; + + map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL); + if (!map) + return -ENOMEM; + + map->src_dev = dev; + map->src_supply = id; + map->alias_dev = alias_dev; + map->alias_supply = alias_id; + + list_add(&map->list, ®ulator_supply_alias_list); + + pr_info("Adding alias for supply %s,%s -> %s,%s\n", + id, dev_name(dev), alias_id, dev_name(alias_dev)); + + return 0; +} +EXPORT_SYMBOL_GPL(regulator_register_supply_alias); + +/** + * regulator_unregister_supply_alias - Remove device alias + * + * @dev: device that will be given as the regulator "consumer" + * @id: Supply name or regulator ID + * + * Remove a lookup alias if one exists for id on dev. + */ +void regulator_unregister_supply_alias(struct device *dev, const char *id) +{ + struct regulator_supply_alias *map; + + map = regulator_find_supply_alias(dev, id); + if (map) { + list_del(&map->list); + kfree(map); + } +} +EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); + +/** + * regulator_bulk_register_supply_alias - register multiple aliases + * + * @dev: device that will be given as the regulator "consumer" + * @id: List of supply names or regulator IDs + * @alias_dev: device that should be used to lookup the supply + * @alias_id: List of supply names or regulator IDs that should be used to + * lookup the supply + * @num_id: Number of aliases to register + * + * @return 0 on success, an errno on failure. + * + * This helper function allows drivers to register several supply + * aliases in one operation. If any of the aliases cannot be + * registered any aliases that were registered will be removed + * before returning to the caller. + */ +int regulator_bulk_register_supply_alias(struct device *dev, + const char *const *id, + struct device *alias_dev, + const char *const *alias_id, + int num_id) +{ + int i; + int ret; + + for (i = 0; i < num_id; ++i) { + ret = regulator_register_supply_alias(dev, id[i], alias_dev, + alias_id[i]); + if (ret < 0) + goto err; } - return *r == data; + + return 0; + +err: + dev_err(dev, + "Failed to create supply alias %s,%s -> %s,%s\n", + id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); + + while (--i >= 0) + regulator_unregister_supply_alias(dev, id[i]); + + return ret; } +EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); /** - * devm_regulator_put - Resource managed regulator_put() - * @regulator: regulator to free + * regulator_bulk_unregister_supply_alias - unregister multiple aliases * - * 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. + * @dev: device that will be given as the regulator "consumer" + * @id: List of supply names or regulator IDs + * @num_id: Number of aliases to unregister + * + * This helper function allows drivers to unregister several supply + * aliases in one operation. */ -void devm_regulator_put(struct regulator *regulator) +void regulator_bulk_unregister_supply_alias(struct device *dev, + const char *const *id, + int num_id) { - int rc; + int i; - rc = devres_release(regulator->dev, devm_regulator_release, - devm_regulator_match, regulator); - if (rc != 0) - WARN_ON(rc); + for (i = 0; i < num_id; ++i) + regulator_unregister_supply_alias(dev, id[i]); } -EXPORT_SYMBOL_GPL(devm_regulator_put); +EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias); + /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ static int regulator_ena_gpio_request(struct regulator_dev *rdev, const struct regulator_config *config) { struct regulator_enable_gpio *pin; + struct gpio_desc *gpiod; int ret; + gpiod = gpio_to_desc(config->ena_gpio); + list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { - if (pin->gpio == config->ena_gpio) { + if (pin->gpiod == gpiod) { rdev_dbg(rdev, "GPIO %d is already used\n", config->ena_gpio); goto update_ena_gpio_to_rdev; @@ -1509,7 +1910,7 @@ return -ENOMEM; } - pin->gpio = config->ena_gpio; + pin->gpiod = gpiod; pin->ena_gpio_invert = config->ena_gpio_invert; list_add(&pin->list, ®ulator_ena_gpio_list); @@ -1528,12 +1929,14 @@ /* Free the GPIO only in case of no use */ list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { - if (pin->gpio == rdev->ena_pin->gpio) { + if (pin->gpiod == rdev->ena_pin->gpiod) { if (pin->request_count <= 1) { pin->request_count = 0; - gpio_free(pin->gpio); + gpiod_put(pin->gpiod); list_del(&pin->list); kfree(pin); + rdev->ena_pin = NULL; + return; } else { pin->request_count--; } @@ -1559,8 +1962,8 @@ if (enable) { /* Enable GPIO at initial use */ if (pin->enable_count == 0) - gpio_set_value_cansleep(pin->gpio, - !pin->ena_gpio_invert); + gpiod_set_value_cansleep(pin->gpiod, + !pin->ena_gpio_invert); pin->enable_count++; } else { @@ -1571,8 +1974,8 @@ /* Disable GPIO if not used */ if (pin->enable_count <= 1) { - gpio_set_value_cansleep(pin->gpio, - pin->ena_gpio_invert); + gpiod_set_value_cansleep(pin->gpiod, + pin->ena_gpio_invert); pin->enable_count = 0; } } @@ -1580,6 +1983,45 @@ return 0; } +/** + * _regulator_enable_delay - a delay helper function + * @delay: time to delay in microseconds + * + * Delay for the requested amount of time as per the guidelines in: + * + * Documentation/timers/timers-howto.txt + * + * The assumption here is that regulators will never be enabled in + * atomic context and therefore sleeping functions can be used. + */ +static void _regulator_enable_delay(unsigned int delay) +{ + unsigned int ms = delay / 1000; + unsigned int us = delay % 1000; + + if (ms > 0) { + /* + * For small enough values, handle super-millisecond + * delays in the usleep_range() call below. + */ + if (ms < 20) + us += ms * 1000; + else + msleep(ms); + } + + /* + * Give the scheduler some room to coalesce with any other + * wakeup sources. For delays shorter than 10 us, don't even + * bother setting up high-resolution timers and just busy- + * loop. + */ + if (us >= 10) + usleep_range(us, us + 100); + else + udelay(us); +} + static int _regulator_do_enable(struct regulator_dev *rdev) { int ret, delay; @@ -1595,6 +2037,31 @@ trace_regulator_enable(rdev_get_name(rdev)); + if (rdev->desc->off_on_delay) { + /* if needed, keep a distance of off_on_delay from last time + * this regulator was disabled. + */ + unsigned long start_jiffy = jiffies; + unsigned long intended, max_delay, remaining; + + max_delay = usecs_to_jiffies(rdev->desc->off_on_delay); + intended = rdev->last_off_jiffy + max_delay; + + if (time_before(start_jiffy, intended)) { + /* calc remaining jiffies to deal with one-time + * timer wrapping. + * in case of multiple timer wrapping, either it can be + * detected by out-of-range remaining, or it cannot be + * detected and we gets a panelty of + * _regulator_enable_delay(). + */ + remaining = intended - start_jiffy; + if (remaining <= max_delay) + _regulator_enable_delay( + jiffies_to_usecs(remaining)); + } + } + if (rdev->ena_pin) { if (!rdev->ena_gpio_state) { ret = regulator_ena_gpio_ctrl(rdev, true); @@ -1615,12 +2082,7 @@ * together. */ trace_regulator_enable_delay(rdev_get_name(rdev)); - if (delay >= 1000) { - mdelay(delay / 1000); - udelay(delay % 1000); - } else if (delay) { - udelay(delay); - } + _regulator_enable_delay(delay); trace_regulator_enable_complete(rdev_get_name(rdev)); @@ -1632,6 +2094,8 @@ { int ret; + lockdep_assert_held_once(&rdev->mutex); + /* check voltage and requested load before enabling */ if (rdev->constraints && (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) @@ -1716,6 +2180,12 @@ return ret; } + /* cares about last_off_jiffy only if off_on_delay is required by + * device. + */ + if (rdev->desc->off_on_delay) + rdev->last_off_jiffy = jiffies; + trace_regulator_disable_complete(rdev_get_name(rdev)); return 0; @@ -1726,6 +2196,8 @@ { int ret = 0; + lockdep_assert_held_once(&rdev->mutex); + if (WARN(rdev->use_count <= 0, "unbalanced disables for %s\n", rdev_get_name(rdev))) return -EIO; @@ -1736,9 +2208,18 @@ /* we are last user */ if (_regulator_can_change_status(rdev)) { + ret = _notifier_call_chain(rdev, + REGULATOR_EVENT_PRE_DISABLE, + NULL); + if (ret & NOTIFY_STOP_MASK) + return -EINVAL; + ret = _regulator_do_disable(rdev); if (ret < 0) { rdev_err(rdev, "failed to disable\n"); + _notifier_call_chain(rdev, + REGULATOR_EVENT_ABORT_DISABLE, + NULL); return ret; } _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, @@ -1795,9 +2276,18 @@ { int ret = 0; + lockdep_assert_held_once(&rdev->mutex); + + ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | + REGULATOR_EVENT_PRE_DISABLE, NULL); + if (ret & NOTIFY_STOP_MASK) + return -EINVAL; + ret = _regulator_do_disable(rdev); if (ret < 0) { rdev_err(rdev, "failed to force disable\n"); + _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | + REGULATOR_EVENT_ABORT_DISABLE, NULL); return ret; } @@ -1893,8 +2383,9 @@ rdev->deferred_disables++; mutex_unlock(&rdev->mutex); - ret = schedule_delayed_work(&rdev->disable_work, - msecs_to_jiffies(ms)); + ret = queue_delayed_work(system_power_efficient_wq, + &rdev->disable_work, + msecs_to_jiffies(ms)); if (ret < 0) return ret; else @@ -1902,88 +2393,56 @@ } EXPORT_SYMBOL_GPL(regulator_disable_deferred); -/** - * regulator_is_enabled_regmap - standard is_enabled() for regmap users - * - * @rdev: regulator to operate on - * - * Regulators that use regmap for their register I/O can set the - * enable_reg and enable_mask fields in their descriptor and then use - * this as their is_enabled operation, saving some code. - */ -int regulator_is_enabled_regmap(struct regulator_dev *rdev) +static int _regulator_is_enabled(struct regulator_dev *rdev) { - unsigned int val; - int ret; + /* A GPIO control always takes precedence */ + if (rdev->ena_pin) + return rdev->ena_gpio_state; - ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); - if (ret != 0) - return ret; + /* If we don't know then assume that the regulator is always on */ + if (!rdev->desc->ops->is_enabled) + return 1; - if (rdev->desc->enable_is_inverted) - return (val & rdev->desc->enable_mask) == 0; - else - return (val & rdev->desc->enable_mask) != 0; + return rdev->desc->ops->is_enabled(rdev); } -EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap); -/** - * regulator_enable_regmap - standard enable() for regmap users - * - * @rdev: regulator to operate on - * - * Regulators that use regmap for their register I/O can set the - * enable_reg and enable_mask fields in their descriptor and then use - * this as their enable() operation, saving some code. - */ -int regulator_enable_regmap(struct regulator_dev *rdev) +static int _regulator_rdev_list_voltage(struct regulator_dev *rdev, + unsigned selector, int lock) { - unsigned int val; - - if (rdev->desc->enable_is_inverted) - val = 0; - else - val = rdev->desc->enable_mask; + const struct regulator_ops *ops = rdev->desc->ops; + int ret; - return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - rdev->desc->enable_mask, val); -} -EXPORT_SYMBOL_GPL(regulator_enable_regmap); + if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) + return rdev->desc->fixed_uV; -/** - * regulator_disable_regmap - standard disable() for regmap users - * - * @rdev: regulator to operate on - * - * Regulators that use regmap for their register I/O can set the - * enable_reg and enable_mask fields in their descriptor and then use - * this as their disable() operation, saving some code. - */ -int regulator_disable_regmap(struct regulator_dev *rdev) -{ - unsigned int val; + if (ops->list_voltage) { + if (selector >= rdev->desc->n_voltages) + return -EINVAL; + if (lock) + mutex_lock(&rdev->mutex); + ret = ops->list_voltage(rdev, selector); + if (lock) + mutex_unlock(&rdev->mutex); + } else if (rdev->supply) { + ret = _regulator_list_voltage(rdev->supply, selector, lock); + } else { + return -EINVAL; + } - if (rdev->desc->enable_is_inverted) - val = rdev->desc->enable_mask; - else - val = 0; + if (ret > 0) { + if (ret < rdev->constraints->min_uV) + ret = 0; + else if (ret > rdev->constraints->max_uV) + ret = 0; + } - return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - rdev->desc->enable_mask, val); + return ret; } -EXPORT_SYMBOL_GPL(regulator_disable_regmap); -static int _regulator_is_enabled(struct regulator_dev *rdev) +static int _regulator_list_voltage(struct regulator *regulator, + unsigned selector, int lock) { - /* A GPIO control always takes precedence */ - if (rdev->ena_pin) - return rdev->ena_gpio_state; - - /* If we don't know then assume that the regulator is always on */ - if (!rdev->desc->ops->is_enabled) - return 1; - - return rdev->desc->ops->is_enabled(rdev); + return _regulator_rdev_list_voltage(regulator->rdev, selector, lock); } /** @@ -2018,7 +2477,7 @@ * @regulator: regulator source * * Returns positive if the regulator driver backing the source/client - * can change its voltage, false otherwise. Usefull for detecting fixed + * can change its voltage, false otherwise. Useful for detecting fixed * or dummy regulators and disabling voltage change logic in the client * driver. */ @@ -2053,92 +2512,117 @@ { struct regulator_dev *rdev = regulator->rdev; - return rdev->desc->n_voltages ? : -EINVAL; + if (rdev->desc->n_voltages) + return rdev->desc->n_voltages; + + if (!rdev->supply) + return -EINVAL; + + return regulator_count_voltages(rdev->supply); } EXPORT_SYMBOL_GPL(regulator_count_voltages); /** - * regulator_list_voltage_linear - List voltages with simple calculation - * - * @rdev: Regulator device - * @selector: Selector to convert into a voltage + * regulator_list_voltage - enumerate supported voltages + * @regulator: regulator source + * @selector: identify voltage to list + * Context: can sleep * - * Regulators with a simple linear mapping between voltages and - * selectors can set min_uV and uV_step in the regulator descriptor - * and then use this function as their list_voltage() operation, + * Returns a voltage that can be passed to @regulator_set_voltage(), + * zero if this selector code can't be used on this system, or a + * negative errno. */ -int regulator_list_voltage_linear(struct regulator_dev *rdev, - unsigned int selector) +int regulator_list_voltage(struct regulator *regulator, unsigned selector) { - if (selector >= rdev->desc->n_voltages) - return -EINVAL; - if (selector < rdev->desc->linear_min_sel) - return 0; + return _regulator_list_voltage(regulator, selector, 1); +} +EXPORT_SYMBOL_GPL(regulator_list_voltage); - selector -= rdev->desc->linear_min_sel; +/** + * regulator_get_regmap - get the regulator's register map + * @regulator: regulator source + * + * Returns the register map for the given regulator, or an ERR_PTR value + * if the regulator doesn't use regmap. + */ +struct regmap *regulator_get_regmap(struct regulator *regulator) +{ + struct regmap *map = regulator->rdev->regmap; - return rdev->desc->min_uV + (rdev->desc->uV_step * selector); + return map ? map : ERR_PTR(-EOPNOTSUPP); } -EXPORT_SYMBOL_GPL(regulator_list_voltage_linear); /** - * regulator_list_voltage_table - List voltages with table based mapping - * - * @rdev: Regulator device - * @selector: Selector to convert into a voltage + * regulator_get_hardware_vsel_register - get the HW voltage selector register + * @regulator: regulator source + * @vsel_reg: voltage selector register, output parameter + * @vsel_mask: mask for voltage selector bitfield, output parameter * - * Regulators with table based mapping between voltages and - * selectors can set volt_table in the regulator descriptor - * and then use this function as their list_voltage() operation. - */ -int regulator_list_voltage_table(struct regulator_dev *rdev, - unsigned int selector) + * Returns the hardware register offset and bitmask used for setting the + * regulator voltage. This might be useful when configuring voltage-scaling + * hardware or firmware that can make I2C requests behind the kernel's back, + * for example. + * + * On success, the output parameters @vsel_reg and @vsel_mask are filled in + * and 0 is returned, otherwise a negative errno is returned. + */ +int regulator_get_hardware_vsel_register(struct regulator *regulator, + unsigned *vsel_reg, + unsigned *vsel_mask) { - if (!rdev->desc->volt_table) { - BUG_ON(!rdev->desc->volt_table); - return -EINVAL; - } + struct regulator_dev *rdev = regulator->rdev; + const struct regulator_ops *ops = rdev->desc->ops; - if (selector >= rdev->desc->n_voltages) - return -EINVAL; + if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) + return -EOPNOTSUPP; - return rdev->desc->volt_table[selector]; + *vsel_reg = rdev->desc->vsel_reg; + *vsel_mask = rdev->desc->vsel_mask; + + return 0; } -EXPORT_SYMBOL_GPL(regulator_list_voltage_table); +EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register); /** - * regulator_list_voltage - enumerate supported voltages + * regulator_list_hardware_vsel - get the HW-specific register value for a selector * @regulator: regulator source * @selector: identify voltage to list - * Context: can sleep * - * Returns a voltage that can be passed to @regulator_set_voltage(), - * zero if this selector code can't be used on this system, or a - * negative errno. + * Converts the selector to a hardware-specific voltage selector that can be + * directly written to the regulator registers. The address of the voltage + * register can be determined by calling @regulator_get_hardware_vsel_register. + * + * On error a negative errno is returned. */ -int regulator_list_voltage(struct regulator *regulator, unsigned selector) +int regulator_list_hardware_vsel(struct regulator *regulator, + unsigned selector) { - struct regulator_dev *rdev = regulator->rdev; - struct regulator_ops *ops = rdev->desc->ops; - int ret; + struct regulator_dev *rdev = regulator->rdev; + const struct regulator_ops *ops = rdev->desc->ops; - if (!ops->list_voltage || selector >= rdev->desc->n_voltages) + if (selector >= rdev->desc->n_voltages) return -EINVAL; + if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) + return -EOPNOTSUPP; - mutex_lock(&rdev->mutex); - ret = ops->list_voltage(rdev, selector); - mutex_unlock(&rdev->mutex); + return selector; +} +EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel); - if (ret > 0) { - if (ret < rdev->constraints->min_uV) - ret = 0; - else if (ret > rdev->constraints->max_uV) - ret = 0; - } +/** + * regulator_get_linear_step - return the voltage step size between VSEL values + * @regulator: regulator source + * + * Returns the voltage step size between VSEL values for linear + * regulators, or return 0 if the regulator isn't a linear regulator. + */ +unsigned int regulator_get_linear_step(struct regulator *regulator) +{ + struct regulator_dev *rdev = regulator->rdev; - return ret; + return rdev->desc->uV_step; } -EXPORT_SYMBOL_GPL(regulator_list_voltage); +EXPORT_SYMBOL_GPL(regulator_get_linear_step); /** * regulator_is_supported_voltage - check if a voltage range can be supported @@ -2159,7 +2643,7 @@ if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { ret = regulator_get_voltage(regulator); if (ret >= 0) - return (min_uV <= ret && ret <= max_uV); + return min_uV <= ret && ret <= max_uV; else return ret; } @@ -2185,176 +2669,71 @@ } EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); -/** - * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users - * - * @rdev: regulator to operate on - * - * Regulators that use regmap for their register I/O can set the - * vsel_reg and vsel_mask fields in their descriptor and then use this - * as their get_voltage_vsel operation, saving some code. - */ -int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev) +static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV, + int max_uV) { - unsigned int val; - int ret; + const struct regulator_desc *desc = rdev->desc; - ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val); - if (ret != 0) - return ret; + if (desc->ops->map_voltage) + return desc->ops->map_voltage(rdev, min_uV, max_uV); - val &= rdev->desc->vsel_mask; - val >>= ffs(rdev->desc->vsel_mask) - 1; + if (desc->ops->list_voltage == regulator_list_voltage_linear) + return regulator_map_voltage_linear(rdev, min_uV, max_uV); - return val; -} -EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap); + if (desc->ops->list_voltage == regulator_list_voltage_linear_range) + return regulator_map_voltage_linear_range(rdev, min_uV, max_uV); -/** - * regulator_set_voltage_sel_regmap - standard set_voltage_sel for regmap users - * - * @rdev: regulator to operate on - * @sel: Selector to set - * - * Regulators that use regmap for their register I/O can set the - * vsel_reg and vsel_mask fields in their descriptor and then use this - * as their set_voltage_vsel operation, saving some code. - */ -int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel) -{ - int ret; - - sel <<= ffs(rdev->desc->vsel_mask) - 1; - - ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, - rdev->desc->vsel_mask, sel); - if (ret) - return ret; - - if (rdev->desc->apply_bit) - ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg, - rdev->desc->apply_bit, - rdev->desc->apply_bit); - return ret; + return regulator_map_voltage_iterate(rdev, min_uV, max_uV); } -EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap); -/** - * regulator_map_voltage_iterate - map_voltage() based on list_voltage() - * - * @rdev: Regulator to operate on - * @min_uV: Lower bound for voltage - * @max_uV: Upper bound for voltage - * - * Drivers implementing set_voltage_sel() and list_voltage() can use - * this as their map_voltage() operation. It will find a suitable - * voltage by calling list_voltage() until it gets something in bounds - * for the requested voltages. - */ -int regulator_map_voltage_iterate(struct regulator_dev *rdev, - int min_uV, int max_uV) +static int _regulator_call_set_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV, + unsigned *selector) { - int best_val = INT_MAX; - int selector = 0; - int i, ret; - - /* Find the smallest voltage that falls within the specified - * range. - */ - for (i = 0; i < rdev->desc->n_voltages; i++) { - ret = rdev->desc->ops->list_voltage(rdev, i); - if (ret < 0) - continue; - - if (ret < best_val && ret >= min_uV && ret <= max_uV) { - best_val = ret; - selector = i; - } - } + struct pre_voltage_change_data data; + int ret; - if (best_val != INT_MAX) - return selector; - else + data.old_uV = _regulator_get_voltage(rdev); + data.min_uV = min_uV; + data.max_uV = max_uV; + ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, + &data); + if (ret & NOTIFY_STOP_MASK) return -EINVAL; -} -EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate); - -/** - * regulator_map_voltage_ascend - map_voltage() for ascendant voltage list - * - * @rdev: Regulator to operate on - * @min_uV: Lower bound for voltage - * @max_uV: Upper bound for voltage - * - * Drivers that have ascendant voltage list can use this as their - * map_voltage() operation. - */ -int regulator_map_voltage_ascend(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - int i, ret; - - for (i = 0; i < rdev->desc->n_voltages; i++) { - ret = rdev->desc->ops->list_voltage(rdev, i); - if (ret < 0) - continue; - if (ret > max_uV) - break; + ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector); + if (ret >= 0) + return ret; - if (ret >= min_uV && ret <= max_uV) - return i; - } + _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, + (void *)data.old_uV); - return -EINVAL; + return ret; } -EXPORT_SYMBOL_GPL(regulator_map_voltage_ascend); -/** - * regulator_map_voltage_linear - map_voltage() for simple linear mappings - * - * @rdev: Regulator to operate on - * @min_uV: Lower bound for voltage - * @max_uV: Upper bound for voltage - * - * Drivers providing min_uV and uV_step in their regulator_desc can - * use this as their map_voltage() operation. - */ -int regulator_map_voltage_linear(struct regulator_dev *rdev, - int min_uV, int max_uV) +static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev, + int uV, unsigned selector) { - int ret, voltage; - - /* Allow uV_step to be 0 for fixed voltage */ - if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) { - if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV) - return 0; - else - return -EINVAL; - } + struct pre_voltage_change_data data; + int ret; - if (!rdev->desc->uV_step) { - BUG_ON(!rdev->desc->uV_step); + data.old_uV = _regulator_get_voltage(rdev); + data.min_uV = uV; + data.max_uV = uV; + ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, + &data); + if (ret & NOTIFY_STOP_MASK) return -EINVAL; - } - - if (min_uV < rdev->desc->min_uV) - min_uV = rdev->desc->min_uV; - ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); - if (ret < 0) + ret = rdev->desc->ops->set_voltage_sel(rdev, selector); + if (ret >= 0) return ret; - ret += rdev->desc->linear_min_sel; - - /* Map back into a voltage to verify we're still in bounds */ - voltage = rdev->desc->ops->list_voltage(rdev, ret); - if (voltage < min_uV || voltage > max_uV) - return -EINVAL; + _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, + (void *)data.old_uV); return ret; } -EXPORT_SYMBOL_GPL(regulator_map_voltage_linear); static int _regulator_do_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) @@ -2383,8 +2762,8 @@ } if (rdev->desc->ops->set_voltage) { - ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, - &selector); + ret = _regulator_call_set_voltage(rdev, min_uV, max_uV, + &selector); if (ret >= 0) { if (rdev->desc->ops->list_voltage) @@ -2395,19 +2774,7 @@ } } else if (rdev->desc->ops->set_voltage_sel) { - if (rdev->desc->ops->map_voltage) { - ret = rdev->desc->ops->map_voltage(rdev, min_uV, - max_uV); - } else { - if (rdev->desc->ops->list_voltage == - regulator_list_voltage_linear) - ret = regulator_map_voltage_linear(rdev, - min_uV, max_uV); - else - ret = regulator_map_voltage_iterate(rdev, - min_uV, max_uV); - } - + ret = regulator_map_voltage(rdev, min_uV, max_uV); if (ret >= 0) { best_val = rdev->desc->ops->list_voltage(rdev, ret); if (min_uV <= best_val && max_uV >= best_val) { @@ -2415,8 +2782,8 @@ if (old_selector == selector) ret = 0; else - ret = rdev->desc->ops->set_voltage_sel( - rdev, ret); + ret = _regulator_call_set_voltage_sel( + rdev, best_val, selector); } else { ret = -EINVAL; } @@ -2426,8 +2793,8 @@ } /* Call set_voltage_time_sel if successfully obtained old_selector */ - if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 && - old_selector != selector && rdev->desc->ops->set_voltage_time_sel) { + if (ret == 0 && !rdev->constraints->ramp_disable && old_selector >= 0 + && old_selector != selector) { delay = rdev->desc->ops->set_voltage_time_sel(rdev, old_selector, selector); @@ -2458,31 +2825,15 @@ return ret; } -/** - * regulator_set_voltage - set regulator output voltage - * @regulator: regulator source - * @min_uV: Minimum required voltage in uV - * @max_uV: Maximum acceptable voltage in uV - * - * Sets a voltage regulator to the desired output voltage. This can be set - * during any regulator state. IOW, regulator can be disabled or enabled. - * - * If the regulator is enabled then the voltage will change to the new value - * immediately otherwise if the regulator is disabled the regulator will - * output at the new voltage when enabled. - * - * NOTE: If the regulator is shared between several devices then the lowest - * request voltage that meets the system constraints will be used. - * Regulator system constraints must be set for this regulator before - * calling this function otherwise this call will fail. - */ -int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) +static int regulator_set_voltage_unlocked(struct regulator *regulator, + int min_uV, int max_uV) { struct regulator_dev *rdev = regulator->rdev; int ret = 0; int old_min_uV, old_max_uV; - - mutex_lock(&rdev->mutex); + int current_uV; + int best_supply_uV = 0; + int supply_change_uV = 0; /* If we're setting the same range as last time the change * should be a noop (some cpufreq implementations use the same @@ -2491,6 +2842,19 @@ if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) goto out; + /* If we're trying to set a range that overlaps the current voltage, + * return successfully even though the regulator does not support + * changing the voltage. + */ + if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { + current_uV = _regulator_get_voltage(rdev); + if (min_uV <= current_uV && current_uV <= max_uV) { + regulator->min_uV = min_uV; + regulator->max_uV = max_uV; + goto out; + } + } + /* sanity check */ if (!rdev->desc->ops->set_voltage && !rdev->desc->ops->set_voltage_sel) { @@ -2502,7 +2866,7 @@ ret = regulator_check_voltage(rdev, &min_uV, &max_uV); if (ret < 0) goto out; - + /* restore original values in case of error */ old_min_uV = regulator->min_uV; old_max_uV = regulator->max_uV; @@ -2513,17 +2877,166 @@ if (ret < 0) goto out2; + if (rdev->supply && (rdev->desc->min_dropout_uV || + !rdev->desc->ops->get_voltage)) { + int current_supply_uV; + int selector; + + selector = regulator_map_voltage(rdev, min_uV, max_uV); + if (selector < 0) { + ret = selector; + goto out2; + } + + best_supply_uV = _regulator_list_voltage(regulator, selector, 0); + if (best_supply_uV < 0) { + ret = best_supply_uV; + goto out2; + } + + best_supply_uV += rdev->desc->min_dropout_uV; + + current_supply_uV = _regulator_get_voltage(rdev->supply->rdev); + if (current_supply_uV < 0) { + ret = current_supply_uV; + goto out2; + } + + supply_change_uV = best_supply_uV - current_supply_uV; + } + + if (supply_change_uV > 0) { + ret = regulator_set_voltage_unlocked(rdev->supply, + best_supply_uV, INT_MAX); + if (ret) { + dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n", + ret); + goto out2; + } + } + ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); if (ret < 0) goto out2; - + + if (supply_change_uV < 0) { + ret = regulator_set_voltage_unlocked(rdev->supply, + best_supply_uV, INT_MAX); + if (ret) + dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n", + ret); + /* No need to fail here */ + ret = 0; + } + out: - mutex_unlock(&rdev->mutex); return ret; out2: regulator->min_uV = old_min_uV; regulator->max_uV = old_max_uV; - mutex_unlock(&rdev->mutex); + + return ret; +} + +static int regulator_dev_set_voltage_unlocked(struct regulator_dev *rdev, + int min_uV, int max_uV) +{ + int ret = 0; + int best_supply_uV = 0; + int supply_change_uV = 0; + + if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) + return ret; + + if (!rdev->desc->ops->set_voltage && + !rdev->desc->ops->set_voltage_sel) + return -EINVAL; + + ret = regulator_check_voltage(rdev, &min_uV, &max_uV); + if (ret < 0) + return ret; + + ret = regulator_check_consumers(rdev, &min_uV, &max_uV); + if (ret < 0) + return ret; + + if (rdev->supply && (rdev->desc->min_dropout_uV || + !rdev->desc->ops->get_voltage)) { + int current_supply_uV; + int selector; + + selector = regulator_map_voltage(rdev, min_uV, max_uV); + if (selector < 0) + return selector; + + best_supply_uV = _regulator_rdev_list_voltage(rdev, + selector, 0); + if (best_supply_uV < 0) + return best_supply_uV; + + best_supply_uV += rdev->desc->min_dropout_uV; + current_supply_uV = _regulator_get_voltage(rdev->supply->rdev); + if (current_supply_uV < 0) + return current_supply_uV; + + supply_change_uV = best_supply_uV - current_supply_uV; + } + + if (supply_change_uV > 0) { + ret = regulator_set_voltage_unlocked(rdev->supply, + best_supply_uV, INT_MAX); + if (ret) { + dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n", + ret); + return ret; + } + } + + ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); + if (ret < 0) + return ret; + + if (supply_change_uV < 0) { + ret = regulator_set_voltage_unlocked(rdev->supply, + best_supply_uV, INT_MAX); + if (ret) + dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n", + ret); + /* No need to fail here */ + ret = 0; + } + + return ret; +} + +/** + * regulator_set_voltage - set regulator output voltage + * @regulator: regulator source + * @min_uV: Minimum required voltage in uV + * @max_uV: Maximum acceptable voltage in uV + * + * Sets a voltage regulator to the desired output voltage. This can be set + * during any regulator state. IOW, regulator can be disabled or enabled. + * + * If the regulator is enabled then the voltage will change to the new value + * immediately otherwise if the regulator is disabled the regulator will + * output at the new voltage when enabled. + * + * NOTE: If the regulator is shared between several devices then the lowest + * request voltage that meets the system constraints will be used. + * Regulator system constraints must be set for this regulator before + * calling this function otherwise this call will fail. + */ +int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) +{ + int ret = 0; + + regulator_lock_supply(regulator->rdev); + + ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV); + + regulator_unlock_supply(regulator->rdev); + return ret; } EXPORT_SYMBOL_GPL(regulator_set_voltage); @@ -2541,8 +3054,8 @@ int regulator_set_voltage_time(struct regulator *regulator, int old_uV, int new_uV) { - struct regulator_dev *rdev = regulator->rdev; - struct regulator_ops *ops = rdev->desc->ops; + struct regulator_dev *rdev = regulator->rdev; + const struct regulator_ops *ops = rdev->desc->ops; int old_sel = -1; int new_sel = -1; int voltage; @@ -2673,6 +3186,10 @@ ret = rdev->desc->ops->get_voltage(rdev); } else if (rdev->desc->ops->list_voltage) { ret = rdev->desc->ops->list_voltage(rdev, 0); + } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { + ret = rdev->desc->fixed_uV; + } else if (rdev->supply) { + ret = _regulator_get_voltage(rdev->supply->rdev); } else { return -EINVAL; } @@ -2695,11 +3212,11 @@ { int ret; - mutex_lock(®ulator->rdev->mutex); + regulator_lock_supply(regulator->rdev); ret = _regulator_get_voltage(regulator->rdev); - mutex_unlock(®ulator->rdev->mutex); + regulator_unlock_supply(regulator->rdev); return ret; } @@ -2857,7 +3374,7 @@ EXPORT_SYMBOL_GPL(regulator_get_mode); /** - * regulator_set_optimum_mode - set regulator optimum operating mode + * regulator_set_load - set regulator load * @regulator: regulator source * @uA_load: load current * @@ -2880,124 +3397,21 @@ * DRMS will sum the total requested load on the regulator and change * to the most efficient operating mode if platform constraints allow. * - * Returns the new regulator mode or error. + * On error a negative errno is returned. */ -int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) +int regulator_set_load(struct regulator *regulator, int uA_load) { struct regulator_dev *rdev = regulator->rdev; - struct regulator *consumer; - int ret, output_uV, input_uV = 0, total_uA_load = 0; - unsigned int mode; - - if (rdev->supply) - input_uV = regulator_get_voltage(rdev->supply); + int ret; mutex_lock(&rdev->mutex); - - /* - * first check to see if we can set modes at all, otherwise just - * tell the consumer everything is OK. - */ regulator->uA_load = uA_load; - ret = regulator_check_drms(rdev); - if (ret < 0) { - ret = 0; - goto out; - } - - if (!rdev->desc->ops->get_optimum_mode) - goto out; - - /* - * we can actually do this so any errors are indicators of - * potential real failure. - */ - ret = -EINVAL; - - if (!rdev->desc->ops->set_mode) - goto out; - - /* get output voltage */ - output_uV = _regulator_get_voltage(rdev); - if (output_uV <= 0) { - rdev_err(rdev, "invalid output voltage found\n"); - goto out; - } - - /* No supply? Use constraint voltage */ - if (input_uV <= 0) - input_uV = rdev->constraints->input_uV; - if (input_uV <= 0) { - rdev_err(rdev, "invalid input voltage found\n"); - goto out; - } - - /* calc total requested load for this regulator */ - list_for_each_entry(consumer, &rdev->consumer_list, list) - total_uA_load += consumer->uA_load; - - mode = rdev->desc->ops->get_optimum_mode(rdev, - input_uV, output_uV, - total_uA_load); - ret = regulator_mode_constrain(rdev, &mode); - if (ret < 0) { - rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", - total_uA_load, input_uV, output_uV); - goto out; - } - - ret = rdev->desc->ops->set_mode(rdev, mode); - if (ret < 0) { - rdev_err(rdev, "failed to set optimum mode %x\n", mode); - goto out; - } - ret = mode; -out: + ret = drms_uA_update(rdev); mutex_unlock(&rdev->mutex); - return ret; -} -EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); - -/** - * regulator_set_bypass_regmap - Default set_bypass() using regmap - * - * @rdev: device to operate on. - * @enable: state to set. - */ -int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable) -{ - unsigned int val; - - if (enable) - val = rdev->desc->bypass_mask; - else - val = 0; - - return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg, - rdev->desc->bypass_mask, val); -} -EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap); - -/** - * regulator_get_bypass_regmap - Default get_bypass() using regmap - * - * @rdev: device to operate on. - * @enable: current state. - */ -int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable) -{ - unsigned int val; - int ret; - - ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val); - if (ret != 0) - return ret; - *enable = val & rdev->desc->bypass_mask; - - return 0; + return ret; } -EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap); +EXPORT_SYMBOL_GPL(regulator_set_load); /** * regulator_allow_bypass - allow the regulator to go into bypass mode @@ -3085,11 +3499,11 @@ /* notify regulator consumers and downstream regulator consumers. * Note mutex must be held by caller. */ -static void _notifier_call_chain(struct regulator_dev *rdev, +static int _notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data) { /* call rdev chain first */ - blocking_notifier_call_chain(&rdev->notifier, event, data); + return blocking_notifier_call_chain(&rdev->notifier, event, data); } /** @@ -3137,52 +3551,6 @@ } 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; @@ -3352,6 +3720,8 @@ int regulator_notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data) { + lockdep_assert_held_once(&rdev->mutex); + _notifier_call_chain(rdev, event, data); return NOTIFY_DONE; @@ -3382,128 +3752,216 @@ } EXPORT_SYMBOL_GPL(regulator_mode_to_status); +static struct attribute *regulator_dev_attrs[] = { + &dev_attr_name.attr, + &dev_attr_num_users.attr, + &dev_attr_type.attr, + &dev_attr_microvolts.attr, + &dev_attr_microamps.attr, + &dev_attr_opmode.attr, + &dev_attr_state.attr, + &dev_attr_status.attr, + &dev_attr_bypass.attr, + &dev_attr_requested_microamps.attr, + &dev_attr_min_microvolts.attr, + &dev_attr_max_microvolts.attr, + &dev_attr_min_microamps.attr, + &dev_attr_max_microamps.attr, + &dev_attr_suspend_standby_state.attr, + &dev_attr_suspend_mem_state.attr, + &dev_attr_suspend_disk_state.attr, + &dev_attr_suspend_standby_microvolts.attr, + &dev_attr_suspend_mem_microvolts.attr, + &dev_attr_suspend_disk_microvolts.attr, + &dev_attr_suspend_standby_mode.attr, + &dev_attr_suspend_mem_mode.attr, + &dev_attr_suspend_disk_mode.attr, + NULL +}; + /* * To avoid cluttering sysfs (and memory) with useless state, only * create attributes that can be meaningfully displayed. */ -static int add_regulator_attributes(struct regulator_dev *rdev) +static umode_t regulator_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int idx) { - struct device *dev = &rdev->dev; - struct regulator_ops *ops = rdev->desc->ops; - int status = 0; + struct device *dev = kobj_to_dev(kobj); + struct regulator_dev *rdev = container_of(dev, struct regulator_dev, dev); + const struct regulator_ops *ops = rdev->desc->ops; + umode_t mode = attr->mode; + + /* these three are always present */ + if (attr == &dev_attr_name.attr || + attr == &dev_attr_num_users.attr || + attr == &dev_attr_type.attr) + return mode; /* some attributes need specific methods to be displayed */ - if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || - (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || - (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0)) { - status = device_create_file(dev, &dev_attr_microvolts); - if (status < 0) - return status; - } - if (ops->get_current_limit) { - status = device_create_file(dev, &dev_attr_microamps); - if (status < 0) - return status; - } - if (ops->get_mode) { - status = device_create_file(dev, &dev_attr_opmode); - if (status < 0) - return status; - } - if (rdev->ena_pin || ops->is_enabled) { - status = device_create_file(dev, &dev_attr_state); - if (status < 0) - return status; - } - if (ops->get_status) { - status = device_create_file(dev, &dev_attr_status); - if (status < 0) - return status; - } - if (ops->get_bypass) { - status = device_create_file(dev, &dev_attr_bypass); - if (status < 0) - return status; + if (attr == &dev_attr_microvolts.attr) { + if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || + (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || + (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || + (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1)) + return mode; + return 0; } - /* some attributes are type-specific */ - if (rdev->desc->type == REGULATOR_CURRENT) { - status = device_create_file(dev, &dev_attr_requested_microamps); - if (status < 0) - return status; - } + if (attr == &dev_attr_microamps.attr) + return ops->get_current_limit ? mode : 0; - /* all the other attributes exist to support constraints; - * don't show them if there are no constraints, or if the - * relevant supporting methods are missing. - */ - if (!rdev->constraints) - return status; + if (attr == &dev_attr_opmode.attr) + return ops->get_mode ? mode : 0; + + if (attr == &dev_attr_state.attr) + return (rdev->ena_pin || ops->is_enabled) ? mode : 0; + + if (attr == &dev_attr_status.attr) + return ops->get_status ? mode : 0; + + 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 (ops->set_voltage || ops->set_voltage_sel) { - status = device_create_file(dev, &dev_attr_min_microvolts); - if (status < 0) - return status; - status = device_create_file(dev, &dev_attr_max_microvolts); - if (status < 0) - return status; - } - if (ops->set_current_limit) { - status = device_create_file(dev, &dev_attr_min_microamps); - if (status < 0) - return status; - status = device_create_file(dev, &dev_attr_max_microamps); - if (status < 0) - return status; - } + if (attr == &dev_attr_min_microvolts.attr || + attr == &dev_attr_max_microvolts.attr) + return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0; + + if (attr == &dev_attr_min_microamps.attr || + attr == &dev_attr_max_microamps.attr) + return ops->set_current_limit ? mode : 0; + + if (attr == &dev_attr_suspend_standby_state.attr || + attr == &dev_attr_suspend_mem_state.attr || + attr == &dev_attr_suspend_disk_state.attr) + return mode; + + if (attr == &dev_attr_suspend_standby_microvolts.attr || + attr == &dev_attr_suspend_mem_microvolts.attr || + attr == &dev_attr_suspend_disk_microvolts.attr) + return ops->set_suspend_voltage ? mode : 0; + + if (attr == &dev_attr_suspend_standby_mode.attr || + attr == &dev_attr_suspend_mem_mode.attr || + attr == &dev_attr_suspend_disk_mode.attr) + return ops->set_suspend_mode ? mode : 0; + + return mode; +} + +static const struct attribute_group regulator_dev_group = { + .attrs = regulator_dev_attrs, + .is_visible = regulator_attr_is_visible, +}; - status = device_create_file(dev, &dev_attr_suspend_standby_state); - if (status < 0) - return status; - status = device_create_file(dev, &dev_attr_suspend_mem_state); - if (status < 0) - return status; - status = device_create_file(dev, &dev_attr_suspend_disk_state); - if (status < 0) - return status; +static const struct attribute_group *regulator_dev_groups[] = { + ®ulator_dev_group, + NULL +}; + +static void regulator_dev_release(struct device *dev) +{ + struct regulator_dev *rdev = dev_get_drvdata(dev); + + kfree(rdev->constraints); + of_node_put(rdev->dev.of_node); + kfree(rdev); +} + +static struct class regulator_class = { + .name = "regulator", + .dev_release = regulator_dev_release, + .dev_groups = regulator_dev_groups, +}; + +#ifdef CONFIG_DEBUG_FS + +#define MAX_DEBUG_BUF_LEN 32 + +static ssize_t reg_debug_volt_set(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + int filled; + int voltage = -1; + int voltage_tolerance = -1; + char debug_buf[MAX_DEBUG_BUF_LEN]; + + if (count >= MAX_DEBUG_BUF_LEN) { + pr_err("Error-Input voltage pair string exceeds maximum buffer length\n"); + return -ENOMEM; + } - if (ops->set_suspend_voltage) { - status = device_create_file(dev, - &dev_attr_suspend_standby_microvolts); - if (status < 0) - return status; - status = device_create_file(dev, - &dev_attr_suspend_mem_microvolts); - if (status < 0) - return status; - status = device_create_file(dev, - &dev_attr_suspend_disk_microvolts); - if (status < 0) - return status; - } - - if (ops->set_suspend_mode) { - status = device_create_file(dev, - &dev_attr_suspend_standby_mode); - if (status < 0) - return status; - status = device_create_file(dev, - &dev_attr_suspend_mem_mode); - if (status < 0) - return status; - status = device_create_file(dev, - &dev_attr_suspend_disk_mode); - if (status < 0) - return status; + if (copy_from_user(debug_buf, buf, count)) + return -EFAULT; + debug_buf[count] = '\0'; + + filled = sscanf(debug_buf, "%d %d", &voltage, &voltage_tolerance); + + /* check for voltage and tolerance input */ + if (filled < 2 || voltage < 0 || voltage_tolerance < 0) { + pr_info("Error, correct format: echo \"voltage tolerance\" > voltage\n"); + return -EINVAL; } - return status; + regulator_lock_supply(file->private_data); + + regulator_dev_set_voltage_unlocked(file->private_data, + voltage, (voltage + (voltage_tolerance * voltage) / 100)); + + regulator_unlock_supply(file->private_data); + + return count; } +static ssize_t reg_debug_volt_get(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + int voltage, output, rc; + char debug_buf[MAX_DEBUG_BUF_LEN]; + + regulator_lock_supply(file->private_data); + + voltage = _regulator_get_voltage(file->private_data); + + regulator_unlock_supply(file->private_data); + + output = snprintf(debug_buf, MAX_DEBUG_BUF_LEN - 1, "%d\n", voltage); + rc = simple_read_from_buffer(buf, output, ppos, + debug_buf, output); + + return rc; +} +#endif + +static const struct file_operations reg_volt_fops = { +#ifdef CONFIG_DEBUG_FS + .write = reg_debug_volt_set, + .open = simple_open, + .read = reg_debug_volt_get, +#endif +}; + static void rdev_init_debugfs(struct regulator_dev *rdev) { - rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root); + struct device *parent = rdev->dev.parent; + const char *rname = rdev_get_name(rdev); + char name[NAME_MAX]; + struct dentry *err_ptr; + const struct regulator_ops *reg_ops = rdev->desc->ops; + umode_t mode = 0; + + /* Avoid duplicate debugfs directory names */ + if (parent && rname == rdev->desc->name) { + snprintf(name, sizeof(name), "%s-%s", dev_name(parent), + rname); + rname = name; + } + + rdev->debugfs = debugfs_create_dir(rname, debugfs_root); if (!rdev->debugfs) { rdev_warn(rdev, "Failed to create debugfs directory\n"); return; @@ -3515,12 +3973,28 @@ &rdev->open_count); debugfs_create_u32("bypass_count", 0444, rdev->debugfs, &rdev->bypass_count); + + /* Voltage File */ + if (reg_ops->get_voltage) + mode |= S_IRUGO; + + if (reg_ops->set_voltage) + mode |= S_IWUSR; + + if (mode) { + err_ptr = debugfs_create_file("voltage", mode, rdev->debugfs, + rdev, ®_volt_fops); + if (IS_ERR_OR_NULL(err_ptr)) { + pr_err("Error-Could not create voltage file\n"); + return; + } + } } /** * regulator_register - register regulator * @regulator_desc: regulator to register - * @config: runtime configuration for regulator + * @cfg: runtime configuration for regulator * * Called by regulator drivers to register a regulator. * Returns a valid pointer to struct regulator_dev on success @@ -3528,20 +4002,20 @@ */ struct regulator_dev * regulator_register(const struct regulator_desc *regulator_desc, - const struct regulator_config *config) + const struct regulator_config *cfg) { const struct regulation_constraints *constraints = NULL; const struct regulator_init_data *init_data; - static atomic_t regulator_no = ATOMIC_INIT(0); + struct regulator_config *config = NULL; + static atomic_t regulator_no = ATOMIC_INIT(-1); struct regulator_dev *rdev; struct device *dev; int ret, i; - const char *supply = NULL; - if (regulator_desc == NULL || config == NULL) + if (regulator_desc == NULL || cfg == NULL) return ERR_PTR(-EINVAL); - dev = config->dev; + dev = cfg->dev; WARN_ON(!dev); if (regulator_desc->name == NULL || regulator_desc->ops == NULL) @@ -3567,12 +4041,27 @@ return ERR_PTR(-EINVAL); } - init_data = config->init_data; - rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); if (rdev == NULL) return ERR_PTR(-ENOMEM); + /* + * Duplicate the config so the driver could override it after + * parsing init data. + */ + config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL); + if (config == NULL) { + kfree(rdev); + return ERR_PTR(-ENOMEM); + } + + init_data = regulator_of_get_init_data(dev, regulator_desc, config, + &rdev->dev.of_node); + if (!init_data) { + init_data = config->init_data; + rdev->dev.of_node = of_node_get(config->of_node); + } + mutex_lock(®ulator_list_mutex); mutex_init(&rdev->mutex); @@ -3599,10 +4088,9 @@ /* register with sysfs */ rdev->dev.class = ®ulator_class; - rdev->dev.of_node = config->of_node; rdev->dev.parent = dev; - dev_set_name(&rdev->dev, "regulator.%d", - atomic_inc_return(®ulator_no) - 1); + dev_set_name(&rdev->dev, "regulator.%lu", + (unsigned long) atomic_inc_return(®ulator_no)); ret = device_register(&rdev->dev); if (ret != 0) { put_device(&rdev->dev); @@ -3611,7 +4099,8 @@ dev_set_drvdata(&rdev->dev, rdev); - if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) { + if ((config->ena_gpio || config->ena_gpio_initialized) && + gpio_is_valid(config->ena_gpio)) { ret = regulator_ena_gpio_request(rdev, config); if (ret != 0) { rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", @@ -3628,47 +4117,11 @@ if (ret < 0) goto scrub; - /* add attributes supported by this regulator */ - ret = add_regulator_attributes(rdev); - if (ret < 0) - goto scrub; - if (init_data && init_data->supply_regulator) - supply = init_data->supply_regulator; + rdev->supply_name = init_data->supply_regulator; else if (regulator_desc->supply_name) - supply = regulator_desc->supply_name; - - if (supply) { - struct regulator_dev *r; - - r = regulator_dev_lookup(dev, supply, &ret); - - if (ret == -ENODEV) { - /* - * No supply was specified for this regulator and - * there will never be one. - */ - ret = 0; - goto add_dev; - } else if (!r) { - dev_err(dev, "Failed to find supply %s\n", supply); - ret = -EPROBE_DEFER; - goto scrub; - } - - ret = set_supply(rdev, r); - if (ret < 0) - goto scrub; - - /* Enable supply if rail is enabled */ - if (_regulator_is_enabled(rdev)) { - ret = regulator_enable(rdev->supply); - if (ret < 0) - goto scrub; - } - } + rdev->supply_name = regulator_desc->supply_name; -add_dev: /* add consumers devices */ if (init_data) { for (i = 0; i < init_data->num_consumer_supplies; i++) { @@ -3683,19 +4136,16 @@ } } - list_add(&rdev->list, ®ulator_list); - rdev_init_debugfs(rdev); out: mutex_unlock(®ulator_list_mutex); + kfree(config); return rdev; unset_supplies: unset_regulator_supplies(rdev); scrub: - if (rdev->supply) - _regulator_put(rdev->supply); regulator_ena_gpio_free(rdev); kfree(rdev->constraints); wash: @@ -3722,21 +4172,36 @@ if (rdev == NULL) return; - if (rdev->supply) + if (rdev->supply) { + while (rdev->use_count--) + regulator_disable(rdev->supply); regulator_put(rdev->supply); + } mutex_lock(®ulator_list_mutex); debugfs_remove_recursive(rdev->debugfs); flush_work(&rdev->disable_work.work); WARN_ON(rdev->open_count); unset_regulator_supplies(rdev); list_del(&rdev->list); - kfree(rdev->constraints); + mutex_unlock(®ulator_list_mutex); regulator_ena_gpio_free(rdev); device_unregister(&rdev->dev); - mutex_unlock(®ulator_list_mutex); } EXPORT_SYMBOL_GPL(regulator_unregister); +static int _regulator_suspend_prepare(struct device *dev, void *data) +{ + struct regulator_dev *rdev = dev_to_rdev(dev); + const suspend_state_t *state = data; + int ret; + + mutex_lock(&rdev->mutex); + ret = suspend_prepare(rdev, *state); + mutex_unlock(&rdev->mutex); + + return ret; +} + /** * regulator_suspend_prepare - prepare regulators for system wide suspend * @state: system suspend state @@ -3746,30 +4211,45 @@ */ int regulator_suspend_prepare(suspend_state_t state) { - struct regulator_dev *rdev; - int ret = 0; - /* ON is handled by regulator active state */ if (state == PM_SUSPEND_ON) return -EINVAL; - mutex_lock(®ulator_list_mutex); - list_for_each_entry(rdev, ®ulator_list, list) { + return class_for_each_device(®ulator_class, NULL, &state, + _regulator_suspend_prepare); +} +EXPORT_SYMBOL_GPL(regulator_suspend_prepare); - mutex_lock(&rdev->mutex); - ret = suspend_prepare(rdev, state); - mutex_unlock(&rdev->mutex); +static int _regulator_suspend_finish(struct device *dev, void *data) +{ + struct regulator_dev *rdev = dev_to_rdev(dev); + int ret; - if (ret < 0) { - rdev_err(rdev, "failed to prepare\n"); - goto out; + mutex_lock(&rdev->mutex); + if (rdev->use_count > 0 || rdev->constraints->always_on) { + if (!_regulator_is_enabled(rdev)) { + ret = _regulator_do_enable(rdev); + if (ret) + dev_err(dev, + "Failed to resume regulator %d\n", + ret); } + } else { + if (!have_full_constraints()) + goto unlock; + if (!_regulator_is_enabled(rdev)) + goto unlock; + + ret = _regulator_do_disable(rdev); + if (ret) + dev_err(dev, "Failed to suspend regulator %d\n", ret); } -out: - mutex_unlock(®ulator_list_mutex); - return ret; +unlock: + mutex_unlock(&rdev->mutex); + + /* Keep processing regulators in spite of any errors */ + return 0; } -EXPORT_SYMBOL_GPL(regulator_suspend_prepare); /** * regulator_suspend_finish - resume regulators from system wide suspend @@ -3779,33 +4259,8 @@ */ int regulator_suspend_finish(void) { - struct regulator_dev *rdev; - int ret = 0, error; - - mutex_lock(®ulator_list_mutex); - list_for_each_entry(rdev, ®ulator_list, list) { - mutex_lock(&rdev->mutex); - if (rdev->use_count > 0 || rdev->constraints->always_on) { - if (!_regulator_is_enabled(rdev)) { - error = _regulator_do_enable(rdev); - if (error) - ret = error; - } - } else { - if (!has_full_constraints) - goto unlock; - if (!_regulator_is_enabled(rdev)) - goto unlock; - - error = _regulator_do_disable(rdev); - if (error) - ret = error; - } -unlock: - mutex_unlock(&rdev->mutex); - } - mutex_unlock(®ulator_list_mutex); - return ret; + return class_for_each_device(®ulator_class, NULL, NULL, + _regulator_suspend_finish); } EXPORT_SYMBOL_GPL(regulator_suspend_finish); @@ -3827,22 +4282,6 @@ EXPORT_SYMBOL_GPL(regulator_has_full_constraints); /** - * regulator_use_dummy_regulator - Provide a dummy regulator when none is found - * - * Calling this function will cause the regulator API to provide a - * dummy regulator to consumers if no physical regulator is found, - * allowing most consumers to proceed as though a regulator were - * configured. This allows systems such as those with software - * controllable regulators for the CPU core only to be brought up more - * readily. - */ -void regulator_use_dummy_regulator(void) -{ - board_wants_dummy_regulator = true; -} -EXPORT_SYMBOL_GPL(regulator_use_dummy_regulator); - -/** * rdev_get_drvdata - get rdev regulator driver data * @rdev: regulator * @@ -3940,6 +4379,131 @@ #endif }; +#ifdef CONFIG_DEBUG_FS +struct summary_data { + struct seq_file *s; + struct regulator_dev *parent; + int level; +}; + +static void regulator_summary_show_subtree(struct seq_file *s, + struct regulator_dev *rdev, + int level); + +static int regulator_summary_show_children(struct device *dev, void *data) +{ + struct regulator_dev *rdev = dev_to_rdev(dev); + struct summary_data *summary_data = data; + + if (rdev->supply && rdev->supply->rdev == summary_data->parent) + regulator_summary_show_subtree(summary_data->s, rdev, + summary_data->level + 1); + + return 0; +} + +static void regulator_summary_show_subtree(struct seq_file *s, + struct regulator_dev *rdev, + int level) +{ + struct regulation_constraints *c; + struct regulator *consumer; + struct summary_data summary_data; + + if (!rdev) + return; + + seq_printf(s, "%*s%-*s %3d %4d %6d ", + level * 3 + 1, "", + 30 - level * 3, rdev_get_name(rdev), + rdev->use_count, rdev->open_count, rdev->bypass_count); + + seq_printf(s, "%5dmV ", _regulator_get_voltage(rdev) / 1000); + seq_printf(s, "%5dmA ", _regulator_get_current_limit(rdev) / 1000); + + c = rdev->constraints; + if (c) { + switch (rdev->desc->type) { + case REGULATOR_VOLTAGE: + seq_printf(s, "%5dmV %5dmV ", + c->min_uV / 1000, c->max_uV / 1000); + break; + case REGULATOR_CURRENT: + seq_printf(s, "%5dmA %5dmA ", + c->min_uA / 1000, c->max_uA / 1000); + break; + } + } + + seq_puts(s, "\n"); + + list_for_each_entry(consumer, &rdev->consumer_list, list) { + if (consumer->dev && consumer->dev->class == ®ulator_class) + continue; + + seq_printf(s, "%*s%-*s ", + (level + 1) * 3 + 1, "", + 30 - (level + 1) * 3, + consumer->dev ? dev_name(consumer->dev) : "deviceless"); + + switch (rdev->desc->type) { + case REGULATOR_VOLTAGE: + seq_printf(s, "%37dmV %5dmV", + consumer->min_uV / 1000, + consumer->max_uV / 1000); + break; + case REGULATOR_CURRENT: + break; + } + + seq_puts(s, "\n"); + } + + summary_data.s = s; + summary_data.level = level; + summary_data.parent = rdev; + + class_for_each_device(®ulator_class, NULL, &summary_data, + regulator_summary_show_children); +} + +static int regulator_summary_show_roots(struct device *dev, void *data) +{ + struct regulator_dev *rdev = dev_to_rdev(dev); + struct seq_file *s = data; + + if (!rdev->supply) + regulator_summary_show_subtree(s, rdev, 0); + + return 0; +} + +static int regulator_summary_show(struct seq_file *s, void *data) +{ + seq_puts(s, " regulator use open bypass voltage current min max\n"); + seq_puts(s, "-------------------------------------------------------------------------------\n"); + + class_for_each_device(®ulator_class, NULL, s, + regulator_summary_show_roots); + + 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 +}; + static int __init regulator_init(void) { int ret; @@ -3953,6 +4517,9 @@ debugfs_create_file("supply_map", 0444, debugfs_root, NULL, &supply_map_fops); + debugfs_create_file("regulator_summary", 0444, debugfs_root, + NULL, ®ulator_summary_fops); + regulator_dummy_init(); return ret; @@ -3961,13 +4528,57 @@ /* init early to allow our consumers to complete system booting */ core_initcall(regulator_init); -static int __init regulator_init_complete(void) +static int __init regulator_late_cleanup(struct device *dev, void *data) { - struct regulator_dev *rdev; - struct regulator_ops *ops; - struct regulation_constraints *c; + struct regulator_dev *rdev = dev_to_rdev(dev); + const struct regulator_ops *ops = rdev->desc->ops; + struct regulation_constraints *c = rdev->constraints; int enabled, ret; + if (c && c->always_on) + return 0; + + if (c && !(c->valid_ops_mask & REGULATOR_CHANGE_STATUS)) + return 0; + + mutex_lock(&rdev->mutex); + + if (rdev->use_count) + goto unlock; + + /* If we can't read the status assume it's on. */ + if (ops->is_enabled) + enabled = ops->is_enabled(rdev); + else + enabled = 1; + + if (!enabled) + goto unlock; + + if (have_full_constraints()) { + /* We log since this may kill the system if it goes + * wrong. */ + rdev_info(rdev, "disabling\n"); + ret = _regulator_do_disable(rdev); + if (ret != 0) + rdev_err(rdev, "couldn't disable: %d\n", ret); + } else { + /* The intention is that in future we will + * assume that full constraints are provided + * so warn even if we aren't going to do + * anything here. + */ + rdev_warn(rdev, "incomplete constraints, leaving on\n"); + } + +unlock: + mutex_unlock(&rdev->mutex); + + return 0; +} + +static int __init regulator_init_complete(void) +{ /* * Since DT doesn't provide an idiomatic mechanism for * enabling full constraints and since it's much more natural @@ -3977,56 +4588,14 @@ if (of_have_populated_dt()) has_full_constraints = true; - mutex_lock(®ulator_list_mutex); - /* If we have a full configuration then disable any regulators - * which are not in use or always_on. This will become the - * default behaviour in the future. + * we have permission to change the status for and which are + * not in use or always_on. This is effectively the default + * for DT and ACPI as they have full constraints. */ - list_for_each_entry(rdev, ®ulator_list, list) { - ops = rdev->desc->ops; - c = rdev->constraints; - - if (c && c->always_on) - continue; - - mutex_lock(&rdev->mutex); - - if (rdev->use_count) - goto unlock; - - /* If we can't read the status assume it's on. */ - if (ops->is_enabled) - enabled = ops->is_enabled(rdev); - else - enabled = 1; - - if (!enabled) - goto unlock; - - if (has_full_constraints) { - /* We log since this may kill the system if it - * goes wrong. */ - rdev_info(rdev, "disabling\n"); - ret = _regulator_do_disable(rdev); - if (ret != 0) { - rdev_err(rdev, "couldn't disable: %d\n", ret); - } - } else { - /* The intention is that in future we will - * assume that full constraints are provided - * so warn even if we aren't going to do - * anything here. - */ - rdev_warn(rdev, "incomplete constraints, leaving on\n"); - } - -unlock: - mutex_unlock(&rdev->mutex); - } - - mutex_unlock(®ulator_list_mutex); + class_for_each_device(®ulator_class, NULL, NULL, + regulator_late_cleanup); return 0; } -late_initcall(regulator_init_complete); +late_initcall_sync(regulator_init_complete);