regulator: lp8788-ldo: Use ldo->en_pin to check if regulator is enabled by external pin
PATCH 1/1 regulator: lp8788-ldo: Use ldo->en_pin to check if regulator is enabled by external pin
ldo->en_pin is set iff the regulator is enabled by external pin.
This patch sets ldo->en_pin to NULL if lp8788_gpio_request_ldo_en() fails, then we can use it to determinate if the regulator is controlled by external pin or register.
lp8788_get_ldo_enable_mode(), lp8788_ldo_ctrl_by_extern_pin() and lp8788_ldo_is_enabled_by_extern_pin() functions are not used now, remove them.
--- drivers/regulator/lp8788-ldo.c | 107 ++++++---------------------------------- 1 file changed, 14 insertions(+), 93 deletions(-)
drivers/regulator/lp8788-ldo.c +14 -93
@@ -88,11 +88,6 @@#define ENABLE GPIOF_OUT_INIT_HIGH#define DISABLE GPIOF_OUT_INIT_LOW -enum lp8788_enable_mode { -REGISTER , -EXTPIN , -}; -enum lp8788_ldo_id {DLDO1 ,DLDO2 ,
@@ -189,114 +184,38 @@ static enum lp8788_ldo_id lp8788_aldo_id[] = { ALDO10, }; -/* DLDO 7, 9 and 11, ALDO 1 ~ 5 and 7 -: can be enabled either by external pin or by i2c register */ -static enum lp8788_enable_mode -lp8788_get_ldo_enable_mode (struct lp8788_ldo *ldo,enum lp8788_ldo_id id) -{ -int ret; -u8 val, mask; - - ret =lp8788_read_byte (ldo->lp,LP8788_EN_SEL , &val); -if (ret) -return ret; - -switch (id) { -case DLDO7 : - mask =LP8788_EN_SEL_DLDO7_M ; -break ; -case DLDO9 : -case DLDO11 : - mask =LP8788_EN_SEL_DLDO911_M ; -break ; -case ALDO1 : - mask =LP8788_EN_SEL_ALDO1_M ; -break ; - case ALDO2 ... ALDO4: - mask =LP8788_EN_SEL_ALDO234_M ; -break ; -case ALDO5 : - mask =LP8788_EN_SEL_ALDO5_M ; -break ; -case ALDO7 : - mask =LP8788_EN_SEL_ALDO7_M ; -break ; -default : -return REGISTER ; - } - -return val & mask ?EXTPIN :REGISTER ; -} - -static int lp8788_ldo_ctrl_by_extern_pin (struct lp8788_ldo *ldo,int pinstate) -{ -struct lp8788_ldo_enable_pin *pin = ldo->en_pin; - -if (!pin) -return -EINVAL ; - -if (gpio_is_valid (pin->gpio)) -gpio_set_value (pin->gpio, pinstate); - -return 0 ; -} - -static int lp8788_ldo_is_enabled_by_extern_pin (struct lp8788_ldo *ldo) -{ -struct lp8788_ldo_enable_pin *pin = ldo->en_pin; - -if (!pin) -return -EINVAL ; - -return gpio_get_value (pin->gpio) ?1 :0 ; -} -static int lp8788_ldo_enable (struct regulator_dev *rdev) {struct lp8788_ldo *ldo =rdev_get_drvdata (rdev); -enum lp8788_ldo_id id =rdev_get_id (rdev); -enum lp8788_enable_mode mode =lp8788_get_ldo_enable_mode (ldo, id); -switch (mode) { -case EXTPIN : -return lp8788_ldo_ctrl_by_extern_pin (ldo,ENABLE ); -case REGISTER : +if (ldo->en_pin) { +gpio_set_value (ldo->en_pin->gpio,ENABLE ); +return 0 ; + }else {return regulator_enable_regmap (rdev); -default : -return -EINVAL ; } }static int lp8788_ldo_disable (struct regulator_dev *rdev) {struct lp8788_ldo *ldo =rdev_get_drvdata (rdev); -enum lp8788_ldo_id id =rdev_get_id (rdev); -enum lp8788_enable_mode mode =lp8788_get_ldo_enable_mode (ldo, id); -switch (mode) { -case EXTPIN : -return lp8788_ldo_ctrl_by_extern_pin (ldo,DISABLE ); -case REGISTER : +if (ldo->en_pin) { +gpio_set_value (ldo->en_pin->gpio,DISABLE ); +return 0 ; + }else {return regulator_disable_regmap (rdev); -default : -return -EINVAL ; } }static int lp8788_ldo_is_enabled (struct regulator_dev *rdev) {struct lp8788_ldo *ldo =rdev_get_drvdata (rdev); -enum lp8788_ldo_id id =rdev_get_id (rdev); -enum lp8788_enable_mode mode =lp8788_get_ldo_enable_mode (ldo, id); -switch (mode) { -case EXTPIN : -return lp8788_ldo_is_enabled_by_extern_pin (ldo); -case REGISTER : +if (ldo->en_pin) +return gpio_get_value (ldo->en_pin->gpio) ?1 :0 ; +else return regulator_is_enabled_regmap (rdev); -default : -return -EINVAL ; - } }static int lp8788_ldo_enable_time (struct regulator_dev *rdev)
@@ -696,8 +615,10 @@ static int lp8788_config_ldo_enable_mode(struct platform_device *pdev, ldo->en_pin = pdata->ldo_pin[enable_id]; ret =lp8788_gpio_request_ldo_en (pdev, ldo, enable_id); -if (ret) +if (ret) { + ldo->en_pin =NULL ; goto set_default_ldo_enable_mode; + }return ret;
Signature · 1 line
1.7.9.5
Hi Axel,
Quoted 16 lines
-----Original Message-----
From: Axel Lin [mailto:[email protected]]
Sent: Saturday, January 05, 2013 4:34 PM
To: Mark Brown
Cc: Kim, Milo; Girdwood, Liam; [email protected]
Subject: [PATCH RFT] regulator: lp8788-ldo: Useldo->en_pinto check if regulator is enabled by external pin
ldo->en_pinis set iff the regulator is enabled by external pin.This patch sets
ldo->en_pinto NULL iflp8788_gpio_request_ldo_en()fails, then
we can use it to determinate if the regulator is controlled by external pin or
register.
Quoted 3 lines
lp8788_get_ldo_enable_mode(),lp8788_ldo_ctrl_by_extern_pin()andlp8788_ldo_is_enabled_by_extern_pin()functions are not used now, remove them.
I love this patch and it works in a real board.
Initial driver code controls LDOs by reading the regulator control mode. It guarantees working even if the control mode is changed by mistake. But this case can be fixed using LP8788 platform data.
This patch makes the driver simpler, so I do ack your patch. Thanks!
���{.n�+�������+%�����ݶ��w��{.n�+����{��G�����{ay�ʇڙ�,j��f���h��������z_�(�階�ݢj"���m������G������?����&���~��iO��z��v�^�m����������?�I�
Mark Brown
AppliedQuoted 5 lines · Axel Lin
ldo->en_pinis set iff the regulator is enabled by external pin.This patch sets
ldo->en_pinto NULL iflp8788_gpio_request_ldo_en()fails, then we can use it to determinate if the regulator is controlled by external pin or register.
Applied, thanks. However we should be converting the driver to use the core support for this - the GPIO can just be given to the core in the regulator config which should handle everything transparently.
Quoted 12 lines
-----Original Message-----
From: Mark Brown [mailto:[email protected]]
Sent: Monday, January 07, 2013 8:08 PM
To: Axel Lin
Cc: Kim, Milo; Girdwood, Liam; [email protected]
Subject: Re: [PATCH RFT] regulator: lp8788-ldo: Useldo->en_pinto check if regulator is enabled by external pinQuoted 3 lines · Axel Lin
ldo->en_pinis set iff the regulator is enabled by external pin.This patch sets
ldo->en_pinto NULL iflp8788_gpio_request_ldo_en()
Quoted 8 lines
fails, then
Quoted 1 line
we can use it to determinate if the regulator is controlled by
external pin or
Quoted 1 line
register.
Applied, thanks. However we should be converting the driver to use the core support for this - the GPIO can just be given to the core in the regulator config which should handle everything transparently.
Thanks, Mark!
I have a question.
Do you mean the dependency of CONFIG_GENERIC_GPIO in this driver?
If yes, lp8788-ldo driver still works.
If the gpio_request_one() gets failed on loading the driver, then the lp8788-ldo
driver refers to register based by default.
So LDOs can be enabled/disabled by the I2C, not external GPIO pins. In that case, GPIO functions are not invoked any more.
Milo
Quoted 6 lines · Milo
Quoted 3 lines
Applied, thanks. However we should be converting the driver to use the core support for this - the GPIO can just be given to the core in the regulator config which should handle everything transparently.
I have a question.
Do you mean the dependency ofCONFIG_GENERIC_GPIOin this driver?
No. I mean you should use the regulator API core functionality for managing GPIO enables instead of open coding it.
A message that is not in the archive (sent off-list or not yet received): CAFRkauBBHtjR+GYogpVPxBwGnoJD2==MUaqhZ6KOC7TJE4SpAA@mail.gmail.com
Quoted 5 lines · Axel Lin
In this driver,
There is a case that one gpio controls more than one regulator. e.g. ALDO2, ALDO3, ALDO4 are controlled by the same pin.It looks like current regulator core does not support this case.
Then the code to cope with this should be ported over to the core instead of being open coded in the driver.
Quoted 10 lines
-----Original Message-----
From: Mark Brown [mailto:[email protected]]
Sent: Tuesday, January 08, 2013 7:44 PM
To: Axel Lin
Cc: Kim, Milo; Girdwood, Liam; [email protected]
Subject: Re: [PATCH RFT] regulator: lp8788-ldo: Useldo->en_pinto check if regulator is enabled by external pinOn Tue, Jan 08, 2013 at 12:06:44PM +0800, Axel Lin wrote:
Quoted 8 lines
Quoted 5 lines
In this driver,
There is a case that one gpio controls more than one regulator. e.g. ALDO2, ALDO3, ALDO4 are controlled by the same pin.It looks like current regulator core does not support this case.
Then the code to cope with this should be ported over to the core instead of being open coded in the driver.
Mark, could you review the code below?
This covers multiple regulators are enabled by shared one GPIO pin. It doesn't look nice yet, but I'd like to get your feedback on this idea first.
drivers/regulator/core.c +15 -7
@@ -3328,6 +3328,7 @@ regulator_register(const struct regulator_desc *regulator_desc,struct device *dev;int ret, i;const char *supply =NULL ; +bool shared_ena_pin = false;if (regulator_desc ==NULL || config ==NULL )return ERR_PTR (-EINVAL );
@@ -3409,17 +3410,24 @@ regulator_register(const struct regulator_desc *regulator_desc,if (ret !=0 ) {rdev_err (rdev,"Failed to request enable GPIO%d: %d\n" , config->ena_gpio, ret); - goto wash; + +if (ret == -EBUSY && config->is_gpio_shared) + shared_ena_pin = true; + +if (!shared_ena_pin) + goto wash; } - rdev->ena_gpio = config->ena_gpio; - rdev->ena_gpio_invert = config->ena_gpio_invert; +if (!shared_ena_pin) { + rdev->ena_gpio = config->ena_gpio; + rdev->ena_gpio_invert = config->ena_gpio_invert; -if (config->ena_gpio_flags &GPIOF_OUT_INIT_HIGH ) - rdev->ena_gpio_state =1 ; +if (config->ena_gpio_flags &GPIOF_OUT_INIT_HIGH ) + rdev->ena_gpio_state =1 ; -if (rdev->ena_gpio_invert) - rdev->ena_gpio_state = !rdev->ena_gpio_state; +if (rdev->ena_gpio_invert) + rdev->ena_gpio_state = !rdev->ena_gpio_state; + } }/* set regulator constraints */
include/linux/regulator/driver.h +3 -0
@@ -241,6 +241,8 @@ struct regulator_desc {* @regmap: regmap to use for core regmap helpers if dev_get_regulator() is * insufficient. * @ena_gpio: GPIO controlling regulator enable. +* @is_gpio_shared: Set true if enable GPIO is shared (multiple regulators are +* enabled by one GPIO pin). * @ena_gpio_invert: Sense for GPIO enable control. * @ena_gpio_flags: Flags to use when calling gpio_request_one() */
@@ -252,6 +254,7 @@ struct regulator_config {struct regmap *regmap;int ena_gpio; +bool is_gpio_shared; unsigned int ena_gpio_invert:1;unsigned int ena_gpio_flags; };
Thanks,
Milo
drivers/regulator/core.c regulator_register(const struct regulator_desc *regulator_desc, · line 3418
Quoted 7 lines · Milo
drivers/regulator/core.c +6
-1- goto wash; + +if (ret == -EBUSY && config->is_gpio_shared) + shared_ena_pin = true; + +if (!shared_ena_pin) + goto wash;
It'd be much nicer if we were able to just keep a list of GPIOs controlling regulators as we see them and automatically work out if they're shared. Probably we should just refactor the code so that the GPIO object is a separate thing rather than just storing the state directly in the regulator struct.