power: supply: axp20x_usb_power: fix race condition with usb bc

When input_current_limit is set while USB BC is in progress, the BC
module will overwrite the value that was set when it finishes detection.

Signed-off-by: Aren Moynihan <aren@peacevolution.org>
Link: https://lore.kernel.org/r/20240130203714.3020464-4-aren@peacevolution.org
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
This commit is contained in:
Aren Moynihan 2024-01-30 15:27:59 -05:00 committed by Sebastian Reichel
parent b02fbd830e
commit 06a807e6e5

View file

@ -117,6 +117,15 @@ static void axp20x_usb_power_poll_vbus(struct work_struct *work)
if (val != power->old_status)
power_supply_changed(power->supply);
if (power->usb_bc_en_bit && (val & AXP20X_PWR_STATUS_VBUS_PRESENT) !=
(power->old_status & AXP20X_PWR_STATUS_VBUS_PRESENT)) {
dev_dbg(power->dev, "Cable status changed, re-enabling USB BC");
ret = regmap_field_write(power->usb_bc_en_bit, 1);
if (ret)
dev_err(power->dev, "failed to enable USB BC: errno %d",
ret);
}
power->old_status = val;
power->online = val & AXP20X_PWR_STATUS_VBUS_USED;
@ -265,12 +274,26 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
static int axp20x_usb_power_set_input_current_limit(struct axp20x_usb_power *power,
int intval)
{
int ret;
unsigned int reg;
const unsigned int max = power->axp_data->curr_lim_table_size;
if (intval == -1)
return -EINVAL;
/*
* BC1.2 detection can cause a race condition if we try to set a current
* limit while it's in progress. When it finishes it will overwrite the
* current limit we just set.
*/
if (power->usb_bc_en_bit) {
dev_dbg(power->dev,
"disabling BC1.2 detection because current limit was set");
ret = regmap_field_write(power->usb_bc_en_bit, 0);
if (ret)
return ret;
}
for (reg = max - 1; reg > 0; reg--)
if (power->axp_data->curr_lim_table[reg] <= intval)
break;