summaryrefslogtreecommitdiff
path: root/common/ocpc.c
diff options
context:
space:
mode:
authorAseda Aboagye <aaboagye@google.com>2020-07-09 11:14:47 -0700
committerCommit Bot <commit-bot@chromium.org>2020-07-21 01:34:31 +0000
commit032bbb26f089d6285cf4198442c65c2621294290 (patch)
treed57367e1bcba479758ad63508674aa3e386822bd /common/ocpc.c
parent3e083f33a6739b00ea69ba1387dedfc4af8821a6 (diff)
downloadchrome-ec-032bbb26f089d6285cf4198442c65c2621294290.tar.gz
OCPC: Calculate system & battery resistance
In order to optimize charging from the auxiliary charger, we need to calculate the system resistance as well as the battery resistance. This allows some charger ICs to compensate for the losses from their output node to the battery. In order to perform this calculation, we must do it when the AP is off (or in suspend) which provides the condition that nearly all of the charge current is entering the battery and isn't being largely consumed by the rest of the system. The combined Rsys+Rbatt calculation is relatively straightforward as it's the delta between the VSYS output and the battery voltage divided by the current entering the battery. In order to separate out the two terms, we can look at the delta between the VSYS output and the VSYS node that's connected to the BFET as well as look at the egress current from the auxiliary charger and the current entering the battery. This commit adds this system resistance measurements and enables it for the RAA489000. The resistances are updated in S5/G3 when charging from the auxiliary charger every ~2.4s. BUG=b:148980020 BRANCH=None TEST=Build and flash waddledoo, verify that charging continues to work in all power states and battery can become full. TEST=Verify that charge current is still close to the target without excessively exceeding it. TEST=Verify charging in constant load via `stressapptest`. TEST=Verify charging in bursty workload via `stressapptest` with pauses for power spikes while monitoring charge current with a current probe. TEST=Verify charging works out of battery cutoff from the auxiliary charger. Signed-off-by: Aseda Aboagye <aaboagye@google.com> Change-Id: I1faa3a0b2b3d8f4fd44d72cd1f546226268df0c6 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2290058 Reviewed-by: Diana Z <dzigterman@chromium.org> Tested-by: Aseda Aboagye <aaboagye@chromium.org> Commit-Queue: Aseda Aboagye <aaboagye@chromium.org>
Diffstat (limited to 'common/ocpc.c')
-rw-r--r--common/ocpc.c74
1 files changed, 66 insertions, 8 deletions
diff --git a/common/ocpc.c b/common/ocpc.c
index e03afa9bbd..3b16485690 100644
--- a/common/ocpc.c
+++ b/common/ocpc.c
@@ -53,6 +53,32 @@ enum phase {
PHASE_CV_COMPLETE,
};
+enum ec_error_list ocpc_calc_resistances(struct ocpc_data *ocpc,
+ struct batt_params *battery)
+{
+ if ((battery->current <= 0) || (ocpc->isys_ma <= 0) ||
+ (ocpc->vsys_aux_mv < ocpc->vsys_mv)) {
+ CPRINTS_DBG("Not charging... won't determine resistance");
+ CPRINTS_DBG("vsys_aux_mv: %dmV vsys_mv: %dmV",
+ ocpc->vsys_aux_mv, ocpc->vsys_mv);
+ return EC_ERROR_INVALID_CONFIG; /* We must be charging */
+ }
+
+ /*
+ * The combined system and battery resistance is the delta between Vsys
+ * and Vbatt divided by Ibatt.
+ */
+ ocpc->rsys_mo = ((ocpc->vsys_aux_mv - ocpc->vsys_mv) * 1000) /
+ ocpc->isys_ma;
+ ocpc->rbatt_mo = ((ocpc->vsys_mv - battery->voltage) * 1000) /
+ battery->current;
+ ocpc->combined_rsys_rbatt_mo = ocpc->rsys_mo + ocpc->rbatt_mo;
+ CPRINTS_DBG("Rsys: %dmOhm Rbatt: %dmOhm", ocpc->rsys_mo,
+ ocpc->rbatt_mo);
+
+ return EC_SUCCESS;
+}
+
int ocpc_config_secondary_charger(int *desired_input_current,
struct ocpc_data *ocpc,
int voltage_mv, int current_ma)
@@ -71,6 +97,7 @@ int ocpc_config_secondary_charger(int *desired_input_current,
static int prev_limited;
int chgnum;
enum ec_error_list result;
+ static int iterations;
/*
* There's nothing to do if we're not using this charger. Should
@@ -100,8 +127,10 @@ int ocpc_config_secondary_charger(int *desired_input_current,
return result;
}
- if (ocpc->last_vsys == OCPC_UNINIT)
+ if (ocpc->last_vsys == OCPC_UNINIT) {
ph = PHASE_UNKNOWN;
+ iterations = 0;
+ }
if (current_ma == 0) {
vsys_target = voltage_mv;
@@ -118,6 +147,27 @@ int ocpc_config_secondary_charger(int *desired_input_current,
ocpc_get_adcs(ocpc);
charger_get_params(&charger);
+
+ /*
+ * If the system is in S5/G3, we can calculate the board and battery
+ * resistances.
+ */
+ if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) {
+ /*
+ * In the first few iterations of the loop, charging isn't
+ * stable/correct so making the calculation then leads to some
+ * strange values throwing off the loop even more. However,
+ * after those initial iterations it then begins to behave as
+ * expected. From there onwards, the resistance values aren't
+ * changing _too_ rapidly. This is why we calculate with every
+ * modulo 4 interval.
+ */
+ iterations++;
+ if (!(iterations % 4))
+ ocpc_calc_resistances(ocpc, &batt);
+ iterations %= 5;
+ }
+
/* Set our current target accordingly. */
if (batt.voltage < batt.desired_voltage) {
if (ph < PHASE_CV_TRIP)
@@ -167,13 +217,7 @@ int ocpc_config_secondary_charger(int *desired_input_current,
CPRINTS_DBG("batt.current = %dmA", batt.current);
CPRINTS_DBG("i_ma = %dmA", i_ma);
- /*
- * Assuming that our combined Rsys + Rbatt resistance is correct, this
- * should be enough to reach our desired i_ma. If it's not, our PID
- * loop will help us get there.
- */
- min_vsys_target = (i_ma * ocpc->combined_rsys_rbatt_mo) / 1000;
- min_vsys_target += MIN(batt.voltage, batt.desired_voltage);
+ min_vsys_target = MIN(batt.voltage, batt.desired_voltage);
CPRINTS_DBG("min_vsys_target = %d", min_vsys_target);
/* Obtain the drive from our PID controller. */
@@ -248,9 +292,15 @@ void ocpc_get_adcs(struct ocpc_data *ocpc)
if (!charger_get_input_current(CHARGER_PRIMARY, &val))
ocpc->primary_ibus_ma = val;
+ val = 0;
+ if (!charger_get_voltage(CHARGER_PRIMARY, &val))
+ ocpc->vsys_mv = val;
+
if (board_get_charger_chip_count() <= CHARGER_SECONDARY) {
ocpc->secondary_vbus_mv = 0;
ocpc->secondary_ibus_ma = 0;
+ ocpc->vsys_aux_mv = 0;
+ ocpc->isys_ma = 0;
return;
}
@@ -261,6 +311,14 @@ void ocpc_get_adcs(struct ocpc_data *ocpc)
val = 0;
if (!charger_get_input_current(CHARGER_SECONDARY, &val))
ocpc->secondary_ibus_ma = val;
+
+ val = 0;
+ if (!charger_get_voltage(CHARGER_SECONDARY, &val))
+ ocpc->vsys_aux_mv = val;
+
+ val = 0;
+ if (!charger_get_current(CHARGER_SECONDARY, &val))
+ ocpc->isys_ma = val;
}
__overridable void ocpc_get_pid_constants(int *kp, int *kp_div,