|
@@ -82,8 +82,7 @@ struct regulator {
|
|
|
};
|
|
|
|
|
|
static int _regulator_is_enabled(struct regulator_dev *rdev);
|
|
|
-static int _regulator_disable(struct regulator_dev *rdev,
|
|
|
- struct regulator_dev **supply_rdev_ptr);
|
|
|
+static int _regulator_disable(struct regulator_dev *rdev);
|
|
|
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);
|
|
@@ -91,6 +90,9 @@ static void _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 const char *rdev_get_name(struct regulator_dev *rdev)
|
|
|
{
|
|
@@ -930,21 +932,20 @@ out:
|
|
|
* core if it's child is enabled.
|
|
|
*/
|
|
|
static int set_supply(struct regulator_dev *rdev,
|
|
|
- struct regulator_dev *supply_rdev)
|
|
|
+ struct regulator_dev *supply_rdev)
|
|
|
{
|
|
|
int err;
|
|
|
|
|
|
- err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj,
|
|
|
- "supply");
|
|
|
- if (err) {
|
|
|
- rdev_err(rdev, "could not add device link %s err %d\n",
|
|
|
- supply_rdev->dev.kobj.name, err);
|
|
|
- goto out;
|
|
|
+ rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev));
|
|
|
+
|
|
|
+ rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY");
|
|
|
+ if (IS_ERR(rdev->supply)) {
|
|
|
+ err = PTR_ERR(rdev->supply);
|
|
|
+ rdev->supply = NULL;
|
|
|
+ return err;
|
|
|
}
|
|
|
- rdev->supply = supply_rdev;
|
|
|
- list_add(&rdev->slist, &supply_rdev->supply_list);
|
|
|
-out:
|
|
|
- return err;
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1303,19 +1304,6 @@ static int _regulator_enable(struct regulator_dev *rdev)
|
|
|
{
|
|
|
int ret, delay;
|
|
|
|
|
|
- if (rdev->use_count == 0) {
|
|
|
- /* do we need to enable the supply regulator first */
|
|
|
- if (rdev->supply) {
|
|
|
- mutex_lock(&rdev->supply->mutex);
|
|
|
- ret = _regulator_enable(rdev->supply);
|
|
|
- mutex_unlock(&rdev->supply->mutex);
|
|
|
- if (ret < 0) {
|
|
|
- rdev_err(rdev, "failed to enable: %d\n", ret);
|
|
|
- return ret;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/* check voltage and requested load before enabling */
|
|
|
if (rdev->constraints &&
|
|
|
(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS))
|
|
@@ -1390,19 +1378,27 @@ int regulator_enable(struct regulator *regulator)
|
|
|
struct regulator_dev *rdev = regulator->rdev;
|
|
|
int ret = 0;
|
|
|
|
|
|
+ if (rdev->supply) {
|
|
|
+ ret = regulator_enable(rdev->supply);
|
|
|
+ if (ret != 0)
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
mutex_lock(&rdev->mutex);
|
|
|
ret = _regulator_enable(rdev);
|
|
|
mutex_unlock(&rdev->mutex);
|
|
|
+
|
|
|
+ if (ret != 0)
|
|
|
+ regulator_disable(rdev->supply);
|
|
|
+
|
|
|
return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(regulator_enable);
|
|
|
|
|
|
/* locks held by regulator_disable() */
|
|
|
-static int _regulator_disable(struct regulator_dev *rdev,
|
|
|
- struct regulator_dev **supply_rdev_ptr)
|
|
|
+static int _regulator_disable(struct regulator_dev *rdev)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
- *supply_rdev_ptr = NULL;
|
|
|
|
|
|
if (WARN(rdev->use_count <= 0,
|
|
|
"unbalanced disables for %s\n", rdev_get_name(rdev)))
|
|
@@ -1429,9 +1425,6 @@ static int _regulator_disable(struct regulator_dev *rdev,
|
|
|
NULL);
|
|
|
}
|
|
|
|
|
|
- /* decrease our supplies ref count and disable if required */
|
|
|
- *supply_rdev_ptr = rdev->supply;
|
|
|
-
|
|
|
rdev->use_count = 0;
|
|
|
} else if (rdev->use_count > 1) {
|
|
|
|
|
@@ -1442,6 +1435,7 @@ static int _regulator_disable(struct regulator_dev *rdev,
|
|
|
|
|
|
rdev->use_count--;
|
|
|
}
|
|
|
+
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -1460,29 +1454,21 @@ static int _regulator_disable(struct regulator_dev *rdev,
|
|
|
int regulator_disable(struct regulator *regulator)
|
|
|
{
|
|
|
struct regulator_dev *rdev = regulator->rdev;
|
|
|
- struct regulator_dev *supply_rdev = NULL;
|
|
|
int ret = 0;
|
|
|
|
|
|
mutex_lock(&rdev->mutex);
|
|
|
- ret = _regulator_disable(rdev, &supply_rdev);
|
|
|
+ ret = _regulator_disable(rdev);
|
|
|
mutex_unlock(&rdev->mutex);
|
|
|
|
|
|
- /* decrease our supplies ref count and disable if required */
|
|
|
- while (supply_rdev != NULL) {
|
|
|
- rdev = supply_rdev;
|
|
|
-
|
|
|
- mutex_lock(&rdev->mutex);
|
|
|
- _regulator_disable(rdev, &supply_rdev);
|
|
|
- mutex_unlock(&rdev->mutex);
|
|
|
- }
|
|
|
+ if (ret == 0 && rdev->supply)
|
|
|
+ regulator_disable(rdev->supply);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(regulator_disable);
|
|
|
|
|
|
/* locks held by regulator_force_disable() */
|
|
|
-static int _regulator_force_disable(struct regulator_dev *rdev,
|
|
|
- struct regulator_dev **supply_rdev_ptr)
|
|
|
+static int _regulator_force_disable(struct regulator_dev *rdev)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
|
|
@@ -1499,10 +1485,6 @@ static int _regulator_force_disable(struct regulator_dev *rdev,
|
|
|
REGULATOR_EVENT_DISABLE, NULL);
|
|
|
}
|
|
|
|
|
|
- /* decrease our supplies ref count and disable if required */
|
|
|
- *supply_rdev_ptr = rdev->supply;
|
|
|
-
|
|
|
- rdev->use_count = 0;
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -1518,16 +1500,16 @@ static int _regulator_force_disable(struct regulator_dev *rdev,
|
|
|
int regulator_force_disable(struct regulator *regulator)
|
|
|
{
|
|
|
struct regulator_dev *rdev = regulator->rdev;
|
|
|
- struct regulator_dev *supply_rdev = NULL;
|
|
|
int ret;
|
|
|
|
|
|
mutex_lock(&rdev->mutex);
|
|
|
regulator->uA_load = 0;
|
|
|
- ret = _regulator_force_disable(rdev, &supply_rdev);
|
|
|
+ ret = _regulator_force_disable(regulator->rdev);
|
|
|
mutex_unlock(&rdev->mutex);
|
|
|
|
|
|
- if (supply_rdev)
|
|
|
- regulator_disable(get_device_regulator(rdev_get_dev(supply_rdev)));
|
|
|
+ if (rdev->supply)
|
|
|
+ while (rdev->open_count--)
|
|
|
+ regulator_disable(rdev->supply);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
@@ -2138,7 +2120,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
|
|
|
/* get input voltage */
|
|
|
input_uV = 0;
|
|
|
if (rdev->supply)
|
|
|
- input_uV = _regulator_get_voltage(rdev->supply);
|
|
|
+ input_uV = regulator_get_voltage(rdev->supply);
|
|
|
if (input_uV <= 0)
|
|
|
input_uV = rdev->constraints->input_uV;
|
|
|
if (input_uV <= 0) {
|
|
@@ -2208,17 +2190,8 @@ EXPORT_SYMBOL_GPL(regulator_unregister_notifier);
|
|
|
static void _notifier_call_chain(struct regulator_dev *rdev,
|
|
|
unsigned long event, void *data)
|
|
|
{
|
|
|
- struct regulator_dev *_rdev;
|
|
|
-
|
|
|
/* call rdev chain first */
|
|
|
blocking_notifier_call_chain(&rdev->notifier, event, NULL);
|
|
|
-
|
|
|
- /* now notify regulator we supply */
|
|
|
- list_for_each_entry(_rdev, &rdev->supply_list, slist) {
|
|
|
- mutex_lock(&_rdev->mutex);
|
|
|
- _notifier_call_chain(_rdev, event, data);
|
|
|
- mutex_unlock(&_rdev->mutex);
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -2610,9 +2583,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
|
|
|
rdev->owner = regulator_desc->owner;
|
|
|
rdev->desc = regulator_desc;
|
|
|
INIT_LIST_HEAD(&rdev->consumer_list);
|
|
|
- INIT_LIST_HEAD(&rdev->supply_list);
|
|
|
INIT_LIST_HEAD(&rdev->list);
|
|
|
- INIT_LIST_HEAD(&rdev->slist);
|
|
|
BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
|
|
|
|
|
|
/* preform any regulator specific init */
|
|
@@ -2724,7 +2695,7 @@ void regulator_unregister(struct regulator_dev *rdev)
|
|
|
unset_regulator_supplies(rdev);
|
|
|
list_del(&rdev->list);
|
|
|
if (rdev->supply)
|
|
|
- sysfs_remove_link(&rdev->dev.kobj, "supply");
|
|
|
+ regulator_put(rdev->supply);
|
|
|
device_unregister(&rdev->dev);
|
|
|
kfree(rdev->constraints);
|
|
|
mutex_unlock(®ulator_list_mutex);
|