summaryrefslogtreecommitdiff
path: root/driver/charger
diff options
context:
space:
mode:
authorRobert Zieba <robertzieba@google.com>2022-10-31 11:07:33 -0600
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-12-09 16:54:17 +0000
commit8c08a74f84ded8ebdfd9b14d91c849cc7e5986a9 (patch)
tree0b9af533d21e0461e95b0652bc3bc25a8b24bfe2 /driver/charger
parent18eedb20812b2ffe66981caa65f5b5d3142a28b2 (diff)
downloadchrome-ec-8c08a74f84ded8ebdfd9b14d91c849cc7e5986a9.tar.gz
driver/charger/isl9241: Add function to help debug PROCHOT
This commit adds the `isl9241_dump_prochot_status` function to dump out prochot information to help debug what caused the prochot. This function is behind a config to help conserve flash space as it includes a fair amount of strings. BRANCH=none BUG=b:227768313 TEST=Verified that `isl9241_dump_prochot_status` works LOW_COVERAGE_REASON=No isl9241 emulator yet Change-Id: Ib6202f8264bbf3b98a71f7f05c2444512a7d1960 Signed-off-by: Robert Zieba <robertzieba@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3994441 Reviewed-by: Diana Z <dzigterman@chromium.org> Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com>
Diffstat (limited to 'driver/charger')
-rw-r--r--driver/charger/isl9241.c184
-rw-r--r--driver/charger/isl9241.h4
2 files changed, 188 insertions, 0 deletions
diff --git a/driver/charger/isl9241.c b/driver/charger/isl9241.c
index 445d94734c..0478b1a221 100644
--- a/driver/charger/isl9241.c
+++ b/driver/charger/isl9241.c
@@ -457,6 +457,187 @@ int isl9241_set_dc_prochot(int chgnum, int ma)
return rv;
}
+#ifdef CONFIG_CHARGER_DUMP_PROCHOT
+static int isl9241_get_ac_prochot(int chgnum, int *out_ma)
+{
+ return isl9241_read(chgnum, ISL9241_REG_AC_PROCHOT, out_ma);
+}
+
+static int isl9241_get_dc_prochot(int chgnum, int *out_ma)
+{
+ return isl9241_read(chgnum, ISL9241_REG_DC_PROCHOT, out_ma);
+}
+
+static int isl9241_get_prochot_status(int chgnum, bool *out_low_vsys,
+ bool *out_dcprochot, bool *out_acprochot,
+ int *out_input_current,
+ int *out_charge_current,
+ int *out_discharge_current, int *out_vsys,
+ int *out_vbus)
+{
+ int rv;
+ int val;
+ bool restore_adc = false;
+
+ /* Get prochot statuses. */
+ rv = isl9241_read(chgnum, ISL9241_REG_INFORMATION1, &val);
+ if (rv) {
+ CPRINTS("%s: failed to read prochot status (%d)", __func__, rv);
+ return rv;
+ }
+
+ *out_low_vsys = val & ISL9241_REG_INFORMATION1_LOW_VSYS_PROCHOT;
+ *out_dcprochot = val & ISL9241_REG_INFORMATION1_DC_PROCHOT;
+ *out_acprochot = val & ISL9241_REG_INFORMATION1_AC_PROCHOT;
+
+ /* Get current Control3 value */
+ rv = isl9241_read(chgnum, ISL9241_REG_CONTROL3, &val);
+ if (rv) {
+ CPRINTS("%s: failed to read control3 (%d)", __func__, rv);
+ return rv;
+ }
+
+ /* Enable ADC */
+ if (!(val & ISL9241_CONTROL3_ENABLE_ADC)) {
+ rv = isl9241_write(chgnum, ISL9241_REG_CONTROL3,
+ val | ISL9241_CONTROL3_ENABLE_ADC);
+ if (rv) {
+ CPRINTS("%s: failed to enable ADC (%d)", __func__, rv);
+ return rv;
+ }
+
+ /*
+ * Since this function will generally run in an interrupt
+ * handler using a mutex for control3 could cause a deadlock.
+ * Instead we keep track of if the ADC was enabled and restore
+ * it accordingly.
+ */
+ restore_adc = true;
+ }
+
+ usleep(ISL9241_ADC_POLLING_TIME_US);
+
+ /* Get input current */
+ rv = isl9241_read(chgnum, ISL9241_REG_IADP_ADC_RESULTS,
+ out_input_current);
+ if (rv) {
+ CPRINTS("%s: failed to get input current (%d)", __func__, rv);
+ goto restore_control3;
+ }
+
+ /* Input current is in steps of 22.2 mA, occupies bits 0-7 */
+ *out_input_current &= 0xff;
+ *out_input_current = (*out_input_current * 222) / 10;
+
+ /* Get battery discharge current */
+ rv = isl9241_read(chgnum, ISL9241_REG_DC_ADC_RESULTS,
+ out_discharge_current);
+ if (rv) {
+ CPRINTS("%s: failed to get battery discharge current (%d)",
+ __func__, rv);
+ goto restore_control3;
+ }
+
+ /* Discharge current is in steps of 44.4 mA, occupies bits 0-7 */
+ *out_discharge_current &= 0xff;
+ *out_discharge_current = (*out_discharge_current * 444) / 10;
+
+ /* Get battery charge current */
+ rv = isl9241_read(chgnum, ISL9241_REG_CC_ADC_RESULTS,
+ out_charge_current);
+ if (rv) {
+ CPRINTS("%s: failed to get battery charge current (%d)",
+ __func__, rv);
+ goto restore_control3;
+ }
+
+ /* Discharge current is in steps of 22.2 mA, occupies bits 0-7 */
+ *out_charge_current &= 0xff;
+ *out_charge_current = (*out_charge_current * 222) / 10;
+
+ /* Get Vsys */
+ rv = isl9241_read(chgnum, ISL9241_REG_VSYS_ADC_RESULTS, out_vsys);
+ if (rv) {
+ CPRINTS("%s: failed to get vsys (%d)", __func__, rv);
+ goto restore_control3;
+ }
+
+ /* Bits [13:6] hold the value in steps of 96 mV, same as Vbus */
+ *out_vsys >>= ISL9241_VIN_ADC_BIT_OFFSET;
+ *out_vsys *= ISL9241_VIN_ADC_STEP_MV;
+
+ /* Get Vbus */
+ rv = isl9241_read(chgnum, ISL9241_REG_VIN_ADC_RESULTS, out_vbus);
+ if (rv) {
+ CPRINTS("%s: failed to get vbus (%d)", __func__, rv);
+ goto restore_control3;
+ }
+
+ /* Bits [13:6] hold the value in steps of 96 mV */
+ *out_vbus >>= ISL9241_VIN_ADC_BIT_OFFSET;
+ *out_vbus *= ISL9241_VIN_ADC_STEP_MV;
+
+restore_control3:
+ if (restore_adc) {
+ /* Disable ADC measurements */
+ rv = isl9241_update(chgnum, ISL9241_REG_CONTROL3,
+ ISL9241_CONTROL3_ENABLE_ADC, MASK_CLR);
+ if (rv)
+ CPRINTS("%s: failed to disable ADC (%d)", __func__, rv);
+ }
+
+ return rv;
+}
+
+static void isl9241_dump_prochot_status(int chgnum)
+{
+ int input_current = 0;
+ int battery_charge = 0;
+ int battery_discharge = 0;
+ int vsys = 0;
+ int vin = 0;
+ int dc_prochot_limit = 0;
+ int ac_prochot_limit = 0;
+ bool low_vsys_prochot = false;
+ bool dc_prochot = false;
+ bool ac_prochot = false;
+ int rv = 0;
+
+ rv = isl9241_get_ac_prochot(chgnum, &ac_prochot_limit);
+ if (rv) {
+ CPRINTS("Failed to get prochot AC limit (%d)", rv);
+ return;
+ }
+
+ rv = isl9241_get_dc_prochot(chgnum, &dc_prochot_limit);
+ if (rv) {
+ CPRINTS("Failed to get prochot DC limit (%d)", rv);
+ return;
+ }
+
+ rv = isl9241_get_prochot_status(chgnum, &low_vsys_prochot, &dc_prochot,
+ &ac_prochot, &input_current,
+ &battery_charge, &battery_discharge,
+ &vsys, &vin);
+ if (rv) {
+ CPRINTS("Failed to get prochot status (%d)", rv);
+ return;
+ }
+
+ CPRINTS("prochot status for charger %d", chgnum);
+ CPRINTS("\tProchot status: %s %s %s", low_vsys_prochot ? "LOWVSYS" : "",
+ dc_prochot ? "DC" : "", ac_prochot ? "AC" : "");
+
+ CPRINTS("\tDC prochot limit: %d mA", dc_prochot_limit);
+ CPRINTS("\tAC prochot limit: %d mA", ac_prochot_limit);
+ CPRINTS("\tInput current: %d mA", input_current);
+ CPRINTS("\tBattery charge current: %d mA", battery_charge);
+ CPRINTS("\tBattery discharge current: %d mA", battery_discharge);
+ CPRINTS("\tVsys: %d mV", vsys);
+ CPRINTS("\tVin: %d mV", vin);
+}
+#endif
+
static bool isl9241_is_ac_present(int chgnum)
{
static bool ac_is_present;
@@ -1027,4 +1208,7 @@ const struct charger_drv isl9241_drv = {
#ifdef CONFIG_CMD_CHARGER_DUMP
.dump_registers = &command_isl9241_dump,
#endif
+#ifdef CONFIG_CHARGER_DUMP_PROCHOT
+ .dump_prochot = &isl9241_dump_prochot_status,
+#endif
};
diff --git a/driver/charger/isl9241.h b/driver/charger/isl9241.h
index e1b4d18b14..c3f843f380 100644
--- a/driver/charger/isl9241.h
+++ b/driver/charger/isl9241.h
@@ -49,6 +49,10 @@
#define ISL9241_CONTROL0_NGATE_OFF BIT(12)
#define ISL9241_REG_INFORMATION1 0x3A
+#define ISL9241_REG_INFORMATION1_LOW_VSYS_PROCHOT BIT(10)
+#define ISL9241_REG_INFORMATION1_DC_PROCHOT BIT(11)
+#define ISL9241_REG_INFORMATION1_AC_PROCHOT BIT(12)
+
#define ISL9241_REG_ADAPTER_CUR_LIMIT2 0x3B
/* Configures various charger options */