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:
parent
b02fbd830e
commit
06a807e6e5
@ -117,6 +117,15 @@ static void axp20x_usb_power_poll_vbus(struct work_struct *work)
|
|||||||
if (val != power->old_status)
|
if (val != power->old_status)
|
||||||
power_supply_changed(power->supply);
|
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->old_status = val;
|
||||||
power->online = val & AXP20X_PWR_STATUS_VBUS_USED;
|
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,
|
static int axp20x_usb_power_set_input_current_limit(struct axp20x_usb_power *power,
|
||||||
int intval)
|
int intval)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
unsigned int reg;
|
unsigned int reg;
|
||||||
const unsigned int max = power->axp_data->curr_lim_table_size;
|
const unsigned int max = power->axp_data->curr_lim_table_size;
|
||||||
|
|
||||||
if (intval == -1)
|
if (intval == -1)
|
||||||
return -EINVAL;
|
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--)
|
for (reg = max - 1; reg > 0; reg--)
|
||||||
if (power->axp_data->curr_lim_table[reg] <= intval)
|
if (power->axp_data->curr_lim_table[reg] <= intval)
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user