|
@@ -919,6 +919,36 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int machine_constraints_current(struct regulator_dev *rdev,
|
|
|
+ struct regulation_constraints *constraints)
|
|
|
+{
|
|
|
+ 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;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* set_machine_constraints - sets regulator constraints
|
|
|
* @rdev: regulator source
|
|
@@ -949,6 +979,10 @@ static int set_machine_constraints(struct regulator_dev *rdev,
|
|
|
if (ret != 0)
|
|
|
goto out;
|
|
|
|
|
|
+ ret = machine_constraints_current(rdev, rdev->constraints);
|
|
|
+ if (ret != 0)
|
|
|
+ goto out;
|
|
|
+
|
|
|
/* do we need to setup our suspend state */
|
|
|
if (rdev->constraints->initial_state) {
|
|
|
ret = suspend_prepare(rdev, rdev->constraints->initial_state);
|
|
@@ -1182,6 +1216,8 @@ overflow_err:
|
|
|
|
|
|
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);
|
|
@@ -1276,7 +1312,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
|
|
|
|
|
|
if (id == NULL) {
|
|
|
pr_err("get() with no identifier\n");
|
|
|
- return regulator;
|
|
|
+ return ERR_PTR(-EINVAL);
|
|
|
}
|
|
|
|
|
|
if (dev)
|
|
@@ -1733,11 +1769,39 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
|
|
|
* together. */
|
|
|
trace_regulator_enable_delay(rdev_get_name(rdev));
|
|
|
|
|
|
- if (delay >= 1000) {
|
|
|
- mdelay(delay / 1000);
|
|
|
- udelay(delay % 1000);
|
|
|
- } else if (delay) {
|
|
|
- udelay(delay);
|
|
|
+ /*
|
|
|
+ * 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.
|
|
|
+ */
|
|
|
+ if (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);
|
|
|
}
|
|
|
|
|
|
trace_regulator_enable_complete(rdev_get_name(rdev));
|