|
@@ -1529,6 +1529,42 @@ static void regulator_ena_gpio_free(struct regulator_dev *rdev)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Balance enable_count of each GPIO and actual GPIO pin control.
|
|
|
+ * GPIO is enabled in case of initial use. (enable_count is 0)
|
|
|
+ * GPIO is disabled when it is not shared any more. (enable_count <= 1)
|
|
|
+ */
|
|
|
+static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
|
|
|
+{
|
|
|
+ struct regulator_enable_gpio *pin = rdev->ena_pin;
|
|
|
+
|
|
|
+ if (!pin)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (enable) {
|
|
|
+ /* Enable GPIO at initial use */
|
|
|
+ if (pin->enable_count == 0)
|
|
|
+ gpio_set_value_cansleep(pin->gpio,
|
|
|
+ !pin->ena_gpio_invert);
|
|
|
+
|
|
|
+ pin->enable_count++;
|
|
|
+ } else {
|
|
|
+ if (pin->enable_count > 1) {
|
|
|
+ pin->enable_count--;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Disable GPIO if not used */
|
|
|
+ if (pin->enable_count <= 1) {
|
|
|
+ gpio_set_value_cansleep(pin->gpio,
|
|
|
+ pin->ena_gpio_invert);
|
|
|
+ pin->enable_count = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int _regulator_do_enable(struct regulator_dev *rdev)
|
|
|
{
|
|
|
int ret, delay;
|
|
@@ -1544,9 +1580,10 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
|
|
|
|
|
|
trace_regulator_enable(rdev_get_name(rdev));
|
|
|
|
|
|
- if (rdev->ena_gpio) {
|
|
|
- gpio_set_value_cansleep(rdev->ena_gpio,
|
|
|
- !rdev->ena_gpio_invert);
|
|
|
+ if (rdev->ena_pin) {
|
|
|
+ ret = regulator_ena_gpio_ctrl(rdev, true);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
rdev->ena_gpio_state = 1;
|
|
|
} else if (rdev->desc->ops->enable) {
|
|
|
ret = rdev->desc->ops->enable(rdev);
|
|
@@ -1648,9 +1685,10 @@ static int _regulator_do_disable(struct regulator_dev *rdev)
|
|
|
|
|
|
trace_regulator_disable(rdev_get_name(rdev));
|
|
|
|
|
|
- if (rdev->ena_gpio) {
|
|
|
- gpio_set_value_cansleep(rdev->ena_gpio,
|
|
|
- rdev->ena_gpio_invert);
|
|
|
+ if (rdev->ena_pin) {
|
|
|
+ ret = regulator_ena_gpio_ctrl(rdev, false);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
rdev->ena_gpio_state = 0;
|
|
|
|
|
|
} else if (rdev->desc->ops->disable) {
|