Skip to content

Commit bcfb7ae

Browse files
smaeulsre
authored andcommitted
power: supply: axp20x_usb_power: Only poll while offline
Investigation on the AXP803 shows that VBUS_PLUGIN/VBUS_REMOVAL IRQs are triggered on the rising/falling edge of AXP20X_PWR_STATUS_VBUS_USED. The reason IRQs do not arrive while N_VBUSEN/DRIVEVBUS is high is because AXP20X_PWR_STATUS_VBUS_USED also never goes high. This also means that if VBUS is online, a VBUS_REMOVAL IRQ is received immediately on setting N_VBUSEN/DRIVEVBUS high (and VBUS_PLUGIN shortly after it is set back low). This was also verified to be the case when manually offlining VBUS through AXP20X_VBUS_PATH_SELECT. As long as VBUS is online, a present->absent transition necessarily implies an online->offline transition. Since will cause an IRQ, there is no need to poll while VBUS is online. To ensure the driver's view of VBUS online status remains accurate, unconditionally poll once when receiving an IRQ and when resuming. If VBUS is still online at that time, polling will cease until the next VBUS_REMOVAL IRQ. Reviewed-by: Chen-Yu Tsai <[email protected]> Signed-off-by: Samuel Holland <[email protected]> Signed-off-by: Sebastian Reichel <[email protected]>
1 parent 09aaaec commit bcfb7ae

File tree

1 file changed

+21
-9
lines changed

1 file changed

+21
-9
lines changed

drivers/power/supply/axp20x_usb_power.c

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,32 @@ struct axp20x_usb_power {
6868
struct iio_channel *vbus_i;
6969
struct delayed_work vbus_detect;
7070
unsigned int old_status;
71+
unsigned int online;
7172
unsigned int num_irqs;
7273
unsigned int irqs[];
7374
};
7475

76+
static bool axp20x_usb_vbus_needs_polling(struct axp20x_usb_power *power)
77+
{
78+
/*
79+
* Polling is only necessary while VBUS is offline. While online, a
80+
* present->absent transition implies an online->offline transition
81+
* and will triger the VBUS_REMOVAL IRQ.
82+
*/
83+
if (power->axp20x_id >= AXP221_ID && !power->online)
84+
return true;
85+
86+
return false;
87+
}
88+
7589
static irqreturn_t axp20x_usb_power_irq(int irq, void *devid)
7690
{
7791
struct axp20x_usb_power *power = devid;
7892

7993
power_supply_changed(power->supply);
8094

95+
mod_delayed_work(system_wq, &power->vbus_detect, DEBOUNCE_TIME);
96+
8197
return IRQ_HANDLED;
8298
}
8399

@@ -97,17 +113,11 @@ static void axp20x_usb_power_poll_vbus(struct work_struct *work)
97113
power_supply_changed(power->supply);
98114

99115
power->old_status = val;
116+
power->online = val & AXP20X_PWR_STATUS_VBUS_USED;
100117

101118
out:
102-
mod_delayed_work(system_wq, &power->vbus_detect, DEBOUNCE_TIME);
103-
}
104-
105-
static bool axp20x_usb_vbus_needs_polling(struct axp20x_usb_power *power)
106-
{
107-
if (power->axp20x_id >= AXP221_ID)
108-
return true;
109-
110-
return false;
119+
if (axp20x_usb_vbus_needs_polling(power))
120+
mod_delayed_work(system_wq, &power->vbus_detect, DEBOUNCE_TIME);
111121
}
112122

113123
static int axp20x_get_current_max(struct axp20x_usb_power *power, int *val)
@@ -515,6 +525,8 @@ static int axp20x_usb_power_resume(struct device *dev)
515525
while (i < power->num_irqs)
516526
enable_irq(power->irqs[i++]);
517527

528+
mod_delayed_work(system_wq, &power->vbus_detect, DEBOUNCE_TIME);
529+
518530
return 0;
519531
}
520532
#endif

0 commit comments

Comments
 (0)