summaryrefslogtreecommitdiff
path: root/driver/charger/isl923x.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/charger/isl923x.c')
-rw-r--r--driver/charger/isl923x.c37
1 files changed, 31 insertions, 6 deletions
diff --git a/driver/charger/isl923x.c b/driver/charger/isl923x.c
index 24e9e488a5..a5fae9329d 100644
--- a/driver/charger/isl923x.c
+++ b/driver/charger/isl923x.c
@@ -887,7 +887,28 @@ enum ec_error_list raa489000_is_acok(int chgnum, bool *acok)
rv = raw_read16(chgnum, ISL9238_REG_INFO2, &regval);
if (rv != EC_SUCCESS)
return rv;
- *acok = (regval & RAA489000_INFO2_ACOK);
+
+ /*
+ * ACOK can sometimes be asserted when RAA489000 is sourcing VBUS in OTG
+ * mode, because that bit is derived from the VBUS comparator. If the
+ * charger reports it's in OTG mode, always say ACOK is false because we
+ * can't be running from a charger if we're also sourcing VBUS and the
+ * ACOK bit may be untrustworthy.
+ *
+ * This may sometimes report incorrectly because the state bits of
+ * the Information2 register take a small amount of time to update on
+ * a state change. In most cases the event hooks used to trigger
+ * raa489000_check_ac_present are good indications of a state change,
+ * but during power role swaps there may be no hooks executed so it's
+ * most consistent to use the charger's reported state only (otherwise
+ * some situations could use the EC's view of the current state and
+ * others would require asking the charger).
+ */
+ if (((regval >> RAA489000_INFO2_STATE_SHIFT) &
+ RAA489000_INFO2_STATE_MASK) == RAA489000_INFO2_STATE_OTG)
+ *acok = false;
+ else
+ *acok = (regval & RAA489000_INFO2_ACOK) != 0;
return EC_SUCCESS;
}
@@ -1460,6 +1481,7 @@ static enum ec_error_list raa489000_set_vsys_compensation(int chgnum,
*/
return EC_ERROR_UNIMPLEMENTED;
}
+#endif /* CONFIG_CHARGER_RAA489000 && CONFIG_OCPC */
#ifdef CONFIG_PLATFORM_EC_RAA489000_AC_PRESENT_CONTROL
/*
@@ -1477,8 +1499,14 @@ void raa489000_check_ac_delayed(void)
static bool current_val;
bool new_val;
int rv, regval;
+ int chgnum =
+#ifdef CONFIG_OCPC
+ CHARGER_PRIMARY;
+#else
+ 0;
+#endif
- rv = raw_read16(CHARGER_PRIMARY, ISL9238_REG_INFO2, &regval);
+ rv = raw_read16(chgnum, ISL9238_REG_INFO2, &regval);
if (rv == EC_SUCCESS) {
new_val = (((regval >> RAA489000_INFO2_STATE_SHIFT) &
RAA489000_INFO2_STATE_MASK) ==
@@ -1492,8 +1520,7 @@ void raa489000_check_ac_delayed(void)
* be low.
*/
current_val = new_val;
- isl923x_set_comparator_inversion(CHARGER_PRIMARY,
- new_val);
+ isl923x_set_comparator_inversion(chgnum, new_val);
}
}
}
@@ -1521,8 +1548,6 @@ DECLARE_HOOK(HOOK_POWER_SUPPLY_CHANGE, raa489000_check_ac_present,
HOOK_PRIO_DEFAULT);
#endif /* CONFIG_PLATFORM_EC_RAA489000_AC_PRESENT_CONTROL */
-#endif /* CONFIG_CHARGER_RAA489000 && CONFIG_OCPC */
-
const struct charger_drv isl923x_drv = {
.init = &isl923x_init,
.post_init = &isl923x_post_init,