diff mbox series

[v2,1/2] power: supply: bq25890: Factor out chip state update

Message ID 20221126120849.74632-1-marex@denx.de
State Accepted
Commit d1b25092b3dce96a69fc31b462e61291848fda9f
Headers show
Series [v2,1/2] power: supply: bq25890: Factor out chip state update | expand

Commit Message

Marek Vasut Nov. 26, 2022, 12:08 p.m. UTC
Pull the chip state and ADC conversion update functionality out into
separate function, so it can be reused elsewhere in the driver. This
is a preparatory patch, no functional change.

Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Marek Vasut <marex@denx.de>
---
Cc: Hans de Goede <hdegoede@redhat.com>
Cc: Sebastian Reichel <sebastian.reichel@collabora.com>
Cc: Sebastian Reichel <sre@kernel.org>
---
V2: Add RB from Hans
---
 drivers/power/supply/bq25890_charger.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

Comments

Hans de Goede Nov. 27, 2022, 4:43 p.m. UTC | #1
Hi Marek,

On 11/26/22 13:08, Marek Vasut wrote:
> The bq25890 is capable of disconnecting itself from the external supply,
> in which case the system is supplied only from the battery. This can be
> useful e.g. to test the pure battery operation, or draw no power from
> USB port.
> 
> Implement support for this mode, which can be toggled by writing 0 or
> non-zero to sysfs 'online' attribute, to select either offline or online
> mode.
> 
> The IRQ handler has to be triggered to update chip state, as switching
> to and from HiZ mode does not generate an interrupt automatically.
> 
> The IRQ handler reinstates the HiZ mode in case a cable is replugged by
> the user, the chip itself clears the HiZ mode bit when cable is plugged
> in by the user and the chip detects PG bad-to-good transition.
> 
> Signed-off-by: Marek Vasut <marex@denx.de>
> ---
> Cc: Hans de Goede <hdegoede@redhat.com>
> Cc: Sebastian Reichel <sebastian.reichel@collabora.com>
> Cc: Sebastian Reichel <sre@kernel.org>
> ---
> V2: - Mix HiZ mode check into POWER_SUPPLY_PROP_STATUS,
>       POWER_SUPPLY_PROP_CHARGE_TYPE, POWER_SUPPLY_PROP_ONLINE
>       read back, so those behave as if the system was offline
>       in case HiZ mode is enabled and cable is plugged in
>     - Cache user HiZ configuration in bq->force_hiz, reinstate
>       the user HiZ configuration in IRQ handler on offline to
>       online transition as the chip clears the HiZ bit on that
>       transition when the cable is replugged.
> ---
>  drivers/power/supply/bq25890_charger.c | 58 +++++++++++++++++++-------
>  1 file changed, 44 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c
> index 374ab66ba8770..e40c8a94cf2e1 100644
> --- a/drivers/power/supply/bq25890_charger.c
> +++ b/drivers/power/supply/bq25890_charger.c
> @@ -95,6 +95,7 @@ struct bq25890_init_data {
>  
>  struct bq25890_state {
>  	u8 online;
> +	u8 hiz;
>  	u8 chrg_status;
>  	u8 chrg_fault;
>  	u8 vsys_status;
> @@ -119,6 +120,7 @@ struct bq25890_device {
>  
>  	bool skip_reset;
>  	bool read_back_init_data;
> +	bool force_hiz;
>  	u32 pump_express_vbus_max;
>  	enum bq25890_chip_version chip_version;
>  	struct bq25890_init_data init_data;
> @@ -487,7 +489,7 @@ static int bq25890_power_supply_get_property(struct power_supply *psy,
>  
>  	switch (psp) {
>  	case POWER_SUPPLY_PROP_STATUS:
> -		if (!state.online)
> +		if (!state.online || state.hiz)
>  			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
>  		else if (state.chrg_status == STATUS_NOT_CHARGING)
>  			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
> @@ -502,7 +504,8 @@ static int bq25890_power_supply_get_property(struct power_supply *psy,
>  		break;
>  
>  	case POWER_SUPPLY_PROP_CHARGE_TYPE:
> -		if (!state.online || state.chrg_status == STATUS_NOT_CHARGING ||
> +		if (!state.online || state.hiz ||
> +		    state.chrg_status == STATUS_NOT_CHARGING ||
>  		    state.chrg_status == STATUS_TERMINATION_DONE)
>  			val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
>  		else if (state.chrg_status == STATUS_PRE_CHARGING)
> @@ -522,7 +525,7 @@ static int bq25890_power_supply_get_property(struct power_supply *psy,
>  		break;
>  
>  	case POWER_SUPPLY_PROP_ONLINE:
> -		val->intval = state.online;
> +		val->intval = state.online & !state.hiz;

Please use "&&" instead of "&" here, since these are both 1 bit values the "&"
will also work but "&&" better expresses that this is a boolean compare and you
use "||" in the negated cases above, so using "&&" is consistent with that.

I have fixed this up in my local copy of the patch.

I have also noticed some other issues, which are best addressed with a follow-up
patch.

Once I have run a few final tests I plan to submit a bigger bq25890_charger
patch series, which includes a bugfix to your previous series, as well as
a few follow up patches to this series.

To make things easier for Sebastian, I'm going to include your patches
in my bigger series, making that series look like this:

1. A couple of bug fixes for the current bq25890 code
2. Your patches (this series) with the mentioned small "&" -> "&&" squashed in + my Reviewed-by
3. Some follow up patches from me to this series
4. My recent patches building on top of this series.

This way Sebastian can apply all the patches without conflict,
which I hope makes things easier for him.

Marek, I will Cc you on the entire series.

Regards,

Hans



>  		break;
>  
>  	case POWER_SUPPLY_PROP_HEALTH:
> @@ -676,7 +679,8 @@ static int bq25890_power_supply_set_property(struct power_supply *psy,
>  					     const union power_supply_propval *val)
>  {
>  	struct bq25890_device *bq = power_supply_get_drvdata(psy);
> -	int maxval;
> +	struct bq25890_state state;
> +	int maxval, ret;
>  	u8 lval;
>  
>  	switch (psp) {
> @@ -691,6 +695,12 @@ static int bq25890_power_supply_set_property(struct power_supply *psy,
>  	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
>  		lval = bq25890_find_idx(val->intval, TBL_IINLIM);
>  		return bq25890_field_write(bq, F_IINLIM, lval);
> +	case POWER_SUPPLY_PROP_ONLINE:
> +		ret = bq25890_field_write(bq, F_EN_HIZ, !val->intval);
> +		if (!ret)
> +			bq->force_hiz = !val->intval;
> +		bq25890_update_state(bq, psp, &state);
> +		return ret;
>  	default:
>  		return -EINVAL;
>  	}
> @@ -703,6 +713,7 @@ static int bq25890_power_supply_property_is_writeable(struct power_supply *psy,
>  	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
>  	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
>  	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
> +	case POWER_SUPPLY_PROP_ONLINE:
>  		return true;
>  	default:
>  		return false;
> @@ -757,6 +768,7 @@ static int bq25890_get_chip_state(struct bq25890_device *bq,
>  	} state_fields[] = {
>  		{F_CHG_STAT,	&state->chrg_status},
>  		{F_PG_STAT,	&state->online},
> +		{F_EN_HIZ,	&state->hiz},
>  		{F_VSYS_STAT,	&state->vsys_status},
>  		{F_BOOST_FAULT, &state->boost_fault},
>  		{F_BAT_FAULT,	&state->bat_fault},
> @@ -772,10 +784,11 @@ static int bq25890_get_chip_state(struct bq25890_device *bq,
>  		*state_fields[i].data = ret;
>  	}
>  
> -	dev_dbg(bq->dev, "S:CHG/PG/VSYS=%d/%d/%d, F:CHG/BOOST/BAT/NTC=%d/%d/%d/%d\n",
> -		state->chrg_status, state->online, state->vsys_status,
> -		state->chrg_fault, state->boost_fault, state->bat_fault,
> -		state->ntc_fault);
> +	dev_dbg(bq->dev, "S:CHG/PG/HIZ/VSYS=%d/%d/%d/%d, F:CHG/BOOST/BAT/NTC=%d/%d/%d/%d\n",
> +		state->chrg_status, state->online,
> +		state->hiz, state->vsys_status,
> +		state->chrg_fault, state->boost_fault,
> +		state->bat_fault, state->ntc_fault);
>  
>  	return 0;
>  }
> @@ -792,16 +805,33 @@ static irqreturn_t __bq25890_handle_irq(struct bq25890_device *bq)
>  	if (!memcmp(&bq->state, &new_state, sizeof(new_state)))
>  		return IRQ_NONE;
>  
> -	if (!new_state.online && bq->state.online) {	    /* power removed */
> +	/* power removed or HiZ */
> +	if ((!new_state.online || new_state.hiz) && bq->state.online) {
>  		/* disable ADC */
>  		ret = bq25890_field_write(bq, F_CONV_RATE, 0);
>  		if (ret < 0)
>  			goto error;
> -	} else if (new_state.online && !bq->state.online) { /* power inserted */
> -		/* enable ADC, to have control of charge current/voltage */
> -		ret = bq25890_field_write(bq, F_CONV_RATE, 1);
> -		if (ret < 0)
> -			goto error;
> +	} else if (new_state.online && !bq->state.online) {
> +		/*
> +		 * Restore HiZ bit in case it was set by user.
> +		 * The chip does not retain this bit once the
> +		 * cable is re-plugged, hence the bit must be
> +		 * reset manually here.
> +		 */
> +		if (bq->force_hiz) {
> +			ret = bq25890_field_write(bq, F_EN_HIZ, bq->force_hiz);
> +			if (ret < 0)
> +				goto error;
> +			new_state.hiz = 1;
> +		}
> +
> +		if (!new_state.hiz) {
> +			/* power inserted and not HiZ */
> +			/* enable ADC, to have control of charge current/voltage */
> +			ret = bq25890_field_write(bq, F_CONV_RATE, 1);
> +			if (ret < 0)
> +				goto error;
> +		}
>  	}
>  
>  	bq->state = new_state;
Marek Vasut Nov. 27, 2022, 5:38 p.m. UTC | #2
On 11/27/22 17:43, Hans de Goede wrote:

Hi,

[...]

>> @@ -522,7 +525,7 @@ static int bq25890_power_supply_get_property(struct power_supply *psy,
>>   		break;
>>   
>>   	case POWER_SUPPLY_PROP_ONLINE:
>> -		val->intval = state.online;
>> +		val->intval = state.online & !state.hiz;
> 
> Please use "&&" instead of "&" here, since these are both 1 bit values the "&"
> will also work but "&&" better expresses that this is a boolean compare and you
> use "||" in the negated cases above, so using "&&" is consistent with that.
> 
> I have fixed this up in my local copy of the patch.
> 
> I have also noticed some other issues, which are best addressed with a follow-up
> patch.
> 
> Once I have run a few final tests I plan to submit a bigger bq25890_charger
> patch series, which includes a bugfix to your previous series, as well as
> a few follow up patches to this series.
> 
> To make things easier for Sebastian, I'm going to include your patches
> in my bigger series, making that series look like this:
> 
> 1. A couple of bug fixes for the current bq25890 code
> 2. Your patches (this series) with the mentioned small "&" -> "&&" squashed in + my Reviewed-by
> 3. Some follow up patches from me to this series
> 4. My recent patches building on top of this series.
> 
> This way Sebastian can apply all the patches without conflict,
> which I hope makes things easier for him.
> 
> Marek, I will Cc you on the entire series.

Sounds good, thanks !
diff mbox series

Patch

diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c
index bfdd2213ba69a..374ab66ba8770 100644
--- a/drivers/power/supply/bq25890_charger.c
+++ b/drivers/power/supply/bq25890_charger.c
@@ -454,20 +454,18 @@  static int bq25890_get_vbus_voltage(struct bq25890_device *bq)
 	return bq25890_find_val(ret, TBL_VBUSV);
 }
 
-static int bq25890_power_supply_get_property(struct power_supply *psy,
-					     enum power_supply_property psp,
-					     union power_supply_propval *val)
+static void bq25890_update_state(struct bq25890_device *bq,
+				 enum power_supply_property psp,
+				 struct bq25890_state *state)
 {
-	struct bq25890_device *bq = power_supply_get_drvdata(psy);
-	struct bq25890_state state;
 	bool do_adc_conv;
 	int ret;
 
 	mutex_lock(&bq->lock);
 	/* update state in case we lost an interrupt */
 	__bq25890_handle_irq(bq);
-	state = bq->state;
-	do_adc_conv = !state.online && bq25890_is_adc_property(psp);
+	*state = bq->state;
+	do_adc_conv = !state->online && bq25890_is_adc_property(psp);
 	if (do_adc_conv)
 		bq25890_field_write(bq, F_CONV_START, 1);
 	mutex_unlock(&bq->lock);
@@ -475,6 +473,17 @@  static int bq25890_power_supply_get_property(struct power_supply *psy,
 	if (do_adc_conv)
 		regmap_field_read_poll_timeout(bq->rmap_fields[F_CONV_START],
 			ret, !ret, 25000, 1000000);
+}
+
+static int bq25890_power_supply_get_property(struct power_supply *psy,
+					     enum power_supply_property psp,
+					     union power_supply_propval *val)
+{
+	struct bq25890_device *bq = power_supply_get_drvdata(psy);
+	struct bq25890_state state;
+	int ret;
+
+	bq25890_update_state(bq, psp, &state);
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_STATUS: