return "";
}
--/* gets the regulator for a given consumer device */
--static struct regulator *get_device_regulator(struct device *dev)
--{
-- struct regulator *regulator = NULL;
-- struct regulator_dev *rdev;
--
-- mutex_lock(®ulator_list_mutex);
-- list_for_each_entry(rdev, ®ulator_list, list) {
-- mutex_lock(&rdev->mutex);
-- list_for_each_entry(regulator, &rdev->consumer_list, list) {
-- if (regulator->dev == dev) {
-- mutex_unlock(&rdev->mutex);
-- mutex_unlock(®ulator_list_mutex);
-- return regulator;
-- }
-- }
-- mutex_unlock(&rdev->mutex);
-- }
-- mutex_unlock(®ulator_list_mutex);
-- return NULL;
--}
--
/**
* of_get_regulator - get a regulator device node based on supply name
* @dev: Device pointer for the consumer (of regulator) device
return 0;
}
--static ssize_t device_requested_uA_show(struct device *dev,
-- struct device_attribute *attr, char *buf)
--{
-- struct regulator *regulator;
--
-- regulator = get_device_regulator(dev);
-- if (regulator == NULL)
-- return 0;
--
-- return sprintf(buf, "%d\n", regulator->uA_load);
--}
--
static ssize_t regulator_uV_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
case REGULATOR_STATUS_STANDBY:
label = "standby";
break;
++ case REGULATOR_STATUS_UNDEFINED:
++ label = "undefined";
++ break;
default:
return -ERANGE;
}
list_add(®ulator->list, &rdev->consumer_list);
if (dev) {
-- /* create a 'requested_microamps_name' sysfs entry */
-- size = scnprintf(buf, REG_STR_SIZE,
-- "microamps_requested_%s-%s",
-- dev_name(dev), supply_name);
-- if (size >= REG_STR_SIZE)
-- goto overflow_err;
--
regulator->dev = dev;
-- sysfs_attr_init(®ulator->dev_attr.attr);
-- regulator->dev_attr.attr.name = kstrdup(buf, GFP_KERNEL);
-- if (regulator->dev_attr.attr.name == NULL)
-- goto attr_name_err;
--
-- regulator->dev_attr.attr.mode = 0444;
-- regulator->dev_attr.show = device_requested_uA_show;
-- err = device_create_file(dev, ®ulator->dev_attr);
-- if (err < 0) {
-- rdev_warn(rdev, "could not add regulator_dev requested microamps sysfs entry\n");
-- goto attr_name_err;
-- }
-- /* also add a link to the device sysfs entry */
++ /* Add a link to the device sysfs entry */
size = scnprintf(buf, REG_STR_SIZE, "%s-%s",
dev->kobj.name, supply_name);
if (size >= REG_STR_SIZE)
-- goto attr_err;
++ goto overflow_err;
regulator->supply_name = kstrdup(buf, GFP_KERNEL);
if (regulator->supply_name == NULL)
-- goto attr_err;
++ goto overflow_err;
err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj,
buf);
if (err) {
rdev_warn(rdev, "could not add device link %s err %d\n",
dev->kobj.name, err);
-- goto link_name_err;
++ /* non-fatal */
}
} else {
regulator->supply_name = kstrdup(supply_name, GFP_KERNEL);
if (regulator->supply_name == NULL)
-- goto attr_err;
++ goto overflow_err;
}
regulator->debugfs = debugfs_create_dir(regulator->supply_name,
mutex_unlock(&rdev->mutex);
return regulator;
--link_name_err:
-- kfree(regulator->supply_name);
--attr_err:
-- device_remove_file(regulator->dev, ®ulator->dev_attr);
--attr_name_err:
-- kfree(regulator->dev_attr.attr.name);
overflow_err:
list_del(®ulator->list);
kfree(regulator);
debugfs_remove_recursive(regulator->debugfs);
/* remove any sysfs entries */
-- if (regulator->dev) {
++ if (regulator->dev)
sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
-- device_remove_file(regulator->dev, ®ulator->dev_attr);
-- kfree(regulator->dev_attr.attr.name);
-- }
kfree(regulator->supply_name);
list_del(®ulator->list);
kfree(regulator);
{
int rc;
-- rc = devres_destroy(regulator->dev, devm_regulator_release,
++ rc = devres_release(regulator->dev, devm_regulator_release,
devm_regulator_match, regulator);
-- if (rc == 0)
-- regulator_put(regulator);
-- else
++ if (rc != 0)
WARN_ON(rc);
}
EXPORT_SYMBOL_GPL(devm_regulator_put);
}
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
++ *
++ * 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)
++{
++ if (!rdev->desc->volt_table) {
++ BUG_ON(!rdev->desc->volt_table);
++ return -EINVAL;
++ }
++
++ if (selector >= rdev->desc->n_voltages)
++ return -EINVAL;
++
++ return rdev->desc->volt_table[selector];
++}
++EXPORT_SYMBOL_GPL(regulator_list_voltage_table);
++
/**
* regulator_list_voltage - enumerate supported voltages
* @regulator: regulator source
int regulator_is_supported_voltage(struct regulator *regulator,
int min_uV, int max_uV)
{
++ struct regulator_dev *rdev = regulator->rdev;
int i, voltages, ret;
++ /* If we can't change voltage check the current voltage */
++ if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
++ ret = regulator_get_voltage(regulator);
++ if (ret >= 0)
++ return (min_uV >= ret && ret <= max_uV);
++ else
++ return ret;
++ }
++
ret = regulator_count_voltages(regulator);
if (ret < 0)
return ret;
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)
return ret;
{
int ret;
int delay = 0;
-- int best_val;
++ int best_val = 0;
unsigned int selector;
int old_selector = -1;
* If we can't obtain the old selector there is not enough
* info to call set_voltage_time_sel().
*/
-- if (rdev->desc->ops->set_voltage_time_sel &&
++ if (_regulator_is_enabled(rdev) &&
++ rdev->desc->ops->set_voltage_time_sel &&
rdev->desc->ops->get_voltage_sel) {
old_selector = rdev->desc->ops->get_voltage_sel(rdev);
if (old_selector < 0)
if (rdev->desc->ops->set_voltage) {
ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV,
&selector);
++
++ if (ret >= 0) {
++ if (rdev->desc->ops->list_voltage)
++ best_val = rdev->desc->ops->list_voltage(rdev,
++ selector);
++ else
++ best_val = _regulator_get_voltage(rdev);
++ }
++
} else if (rdev->desc->ops->set_voltage_sel) {
-- if (rdev->desc->ops->map_voltage)
++ if (rdev->desc->ops->map_voltage) {
ret = rdev->desc->ops->map_voltage(rdev, min_uV,
max_uV);
-- else
-- ret = regulator_map_voltage_iterate(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);
++ }
if (ret >= 0) {
-- selector = ret;
-- ret = rdev->desc->ops->set_voltage_sel(rdev, ret);
++ best_val = rdev->desc->ops->list_voltage(rdev, ret);
++ if (min_uV <= best_val && max_uV >= best_val) {
++ selector = ret;
++ ret = rdev->desc->ops->set_voltage_sel(rdev,
++ ret);
++ } else {
++ ret = -EINVAL;
++ }
}
} else {
ret = -EINVAL;
}
-- if (rdev->desc->ops->list_voltage)
-- best_val = rdev->desc->ops->list_voltage(rdev, selector);
-- else
-- best_val = -1;
--
/* Call set_voltage_time_sel if successfully obtained old_selector */
-- if (ret == 0 && old_selector >= 0 &&
++ if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 &&
rdev->desc->ops->set_voltage_time_sel) {
delay = rdev->desc->ops->set_voltage_time_sel(rdev,
delay);
delay = 0;
}
-- }
-- /* Insert any necessary delays */
-- if (delay >= 1000) {
-- mdelay(delay / 1000);
-- udelay(delay % 1000);
-- } else if (delay) {
-- udelay(delay);
++ /* Insert any necessary delays */
++ if (delay >= 1000) {
++ mdelay(delay / 1000);
++ udelay(delay % 1000);
++ } else if (delay) {
++ udelay(delay);
++ }
}
-- if (ret == 0)
++ if (ret == 0 && best_val >= 0)
_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
-- NULL);
++ (void *)best_val);
trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
unsigned long event, void *data)
{
/* call rdev chain first */
-- blocking_notifier_call_chain(&rdev->notifier, event, NULL);
++ blocking_notifier_call_chain(&rdev->notifier, event, data);
}
/**
return REGULATOR_STATUS_NORMAL;
case REGULATOR_MODE_IDLE:
return REGULATOR_STATUS_IDLE;
-- case REGULATOR_STATUS_STANDBY:
++ case REGULATOR_MODE_STANDBY:
return REGULATOR_STATUS_STANDBY;
default:
-- return 0;
++ return REGULATOR_STATUS_UNDEFINED;
}
}
EXPORT_SYMBOL_GPL(regulator_mode_to_status);
rdev->reg_data = config->driver_data;
rdev->owner = regulator_desc->owner;
rdev->desc = regulator_desc;
-- rdev->regmap = config->regmap;
++ if (config->regmap)
++ rdev->regmap = config->regmap;
++ else
++ rdev->regmap = dev_get_regmap(dev, NULL);
INIT_LIST_HEAD(&rdev->consumer_list);
INIT_LIST_HEAD(&rdev->list);
BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
struct regulation_constraints *c;
int enabled, ret;
+ + /*
+ + * Since DT doesn't provide an idiomatic mechanism for
+ + * enabling full constraints and since it's much more natural
+ + * with DT to provide them just assume that a DT enabled
+ + * system has full constraints.
+ + */
+ + if (of_have_populated_dt())
+ + has_full_constraints = true;
+ +
mutex_lock(®ulator_list_mutex);
/* If we have a full configuration then disable any regulators