diff options
| -rw-r--r-- | drivers/regulator/core.c | 50 | 
1 files changed, 44 insertions, 6 deletions
| diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 71d6adc4eeab..57d434d3145a 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -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) { | 
