summaryrefslogtreecommitdiff
path: root/common/ocpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/ocpc.c')
-rw-r--r--common/ocpc.c767
1 files changed, 0 insertions, 767 deletions
diff --git a/common/ocpc.c b/common/ocpc.c
deleted file mode 100644
index 3bc2a265d3..0000000000
--- a/common/ocpc.c
+++ /dev/null
@@ -1,767 +0,0 @@
-/* Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/* OCPC - One Charger IC Per Type-C module */
-
-#include "battery.h"
-#include "battery_fuel_gauge.h"
-#include "charge_manager.h"
-#include "charge_state_v2.h"
-#include "charger.h"
-#include "common.h"
-#include "console.h"
-#include "hooks.h"
-#include "math_util.h"
-#include "ocpc.h"
-#include "timer.h"
-#include "usb_pd.h"
-#include "util.h"
-
-/*
- * These constants were chosen by tuning the PID loop to reduce oscillations and
- * minimize overshoot.
- */
-#define KP 1
-#define KP_DIV 4
-#define KI 1
-#define KI_DIV 15
-#define KD 1
-#define KD_DIV 10
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_CHARGER, outstr)
-#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args)
-#define CPRINT_VIZ(format, args...) \
-do { \
- if (viz_output) \
- cprintf(CC_CHARGER, format, ## args); \
-} while (0)
-#define CPRINTS_DBG(format, args...) \
-do { \
- if (debug_output) \
- cprints(CC_CHARGER, format, ## args); \
-} while (0)
-#define CPRINTF_DBG(format, args...) \
-do { \
- if (debug_output) \
- cprintf(CC_CHARGER, format, ## args); \
-} while (0)
-
-
-/* Code refactor will be needed if more than 2 charger chips are present */
-BUILD_ASSERT(CHARGER_NUM == 2);
-
-static int k_p = KP;
-static int k_i = KI;
-static int k_d = KD;
-static int k_p_div = KP_DIV;
-static int k_i_div = KI_DIV;
-static int k_d_div = KD_DIV;
-static int debug_output;
-static int viz_output;
-
-#define NUM_RESISTANCE_SAMPLES 8
-#define COMBINED_IDX 0
-#define RBATT_IDX 1
-#define RSYS_IDX 2
-static int resistance_tbl[NUM_RESISTANCE_SAMPLES][3] = {
- /* Rsys+Rbatt Rbatt Rsys */
- {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0},
- {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0},
- {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0},
- {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0},
- {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0},
- {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0},
- {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0},
- {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0},
-};
-static int resistance_tbl_idx;
-static int mean_resistance[3];
-static int stddev_resistance[3];
-static int ub[3];
-static int lb[3];
-
-enum phase {
- PHASE_UNKNOWN = -1,
- PHASE_PRECHARGE,
- PHASE_CC,
- PHASE_CV_TRIP,
- PHASE_CV_COMPLETE,
-};
-
-__overridable void board_ocpc_init(struct ocpc_data *ocpc)
-{
-}
-
-static enum ec_error_list ocpc_precharge_enable(bool enable);
-
-static void calc_resistance_stats(struct ocpc_data *ocpc)
-{
- int i;
- int j;
- int sum;
- int cols = 3;
- int act_chg = ocpc->active_chg_chip;
-
- /* Only perform separate stats on Rsys and Rbatt if necessary. */
- if ((ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP))
- cols = 1;
-
- /* Calculate mean */
- for (i = 0; i < cols; i++) {
- sum = 0;
- for (j = 0; j < NUM_RESISTANCE_SAMPLES; j++) {
- sum += resistance_tbl[j][i];
- CPRINTF_DBG("%d ", resistance_tbl[j][i]);
- }
- CPRINTF_DBG("\n");
-
- mean_resistance[i] = sum / NUM_RESISTANCE_SAMPLES;
-
- /* Calculate standard deviation */
- sum = 0;
- for (j = 0; j < NUM_RESISTANCE_SAMPLES; j++)
- sum += POW2(resistance_tbl[j][i] - mean_resistance[i]);
-
- stddev_resistance[i] = fp_sqrtf(INT_TO_FP(sum /
- NUM_RESISTANCE_SAMPLES));
- stddev_resistance[i] = FP_TO_INT(stddev_resistance[i]);
- /*
- * Don't let our stddev collapse to 0 to continually consider
- * new values.
- */
- stddev_resistance[i] = MAX(stddev_resistance[i], 1);
- CPRINTS_DBG("%d: mean: %d stddev: %d", i, mean_resistance[i],
- stddev_resistance[i]);
- lb[i] = MAX(0, mean_resistance[i] - (3 * stddev_resistance[i]));
- ub[i] = mean_resistance[i] + (3 * stddev_resistance[i]);
- }
-}
-
-static bool is_within_range(struct ocpc_data *ocpc, int combined, int rbatt,
- int rsys)
-{
- int act_chg = ocpc->active_chg_chip;
- bool valid;
-
- /* Discard measurements not within a 6 std. dev. window. */
- if ((ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP)) {
- /* We only know the combined Rsys+Rbatt */
- valid = (combined > 0) &&
- (combined <= ub[COMBINED_IDX]) &&
- (combined >= lb[COMBINED_IDX]);
- } else {
- valid = (rsys <= ub[RSYS_IDX]) && (rsys >= lb[RSYS_IDX]) &&
- (rbatt <= ub[RBATT_IDX]) && (rbatt >= lb[RBATT_IDX]) &&
- (rsys > 0) && (rbatt > 0);
- }
-
- if (!valid)
- CPRINTS_DBG("Discard Rc:%d Rb:%d Rs:%d", combined, rbatt, rsys);
-
- return valid;
-}
-
-enum ec_error_list ocpc_calc_resistances(struct ocpc_data *ocpc,
- struct batt_params *battery)
-{
- int act_chg = ocpc->active_chg_chip;
- static bool seeded;
- static int initial_samples;
- int combined;
- int rsys = -1;
- int rbatt = -1;
-
- /*
- * In order to actually calculate the resistance, we need to make sure
- * we're actually charging the battery at a significant rate. The LSB
- * of a charger IC can be as high as 96mV. Assuming a resistance of 60
- * mOhms, we would need a current of 1666mA to have a voltage delta of
- * 100mV.
- */
- if ((battery->current <= 1666) ||
- (!(ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP) &&
- (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.
- */
- if ((ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP)) {
- /*
- * There's no provision to measure Isys, so we cannot separate
- * out Rsys from Rbatt.
- */
- combined = ((ocpc->vsys_aux_mv - battery->voltage) * 1000) /
- battery->current;
- } else {
- rsys = ((ocpc->vsys_aux_mv - ocpc->vsys_mv) * 1000) /
- ocpc->isys_ma;
- rbatt = ((ocpc->vsys_mv - battery->voltage) * 1000) /
- battery->current;
- combined = rsys + rbatt;
- }
-
- /* Discard measurements not within a 6 std dev window. */
- if ((!seeded) ||
- (seeded && is_within_range(ocpc, combined, rbatt, rsys))) {
- if (!(ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP)) {
- resistance_tbl[resistance_tbl_idx][RSYS_IDX] =
- MAX(rsys, 0);
- resistance_tbl[resistance_tbl_idx][RBATT_IDX] =
- MAX(rbatt, CONFIG_OCPC_DEF_RBATT_MOHMS);
- }
- resistance_tbl[resistance_tbl_idx][COMBINED_IDX] =
- MAX(combined, CONFIG_OCPC_DEF_RBATT_MOHMS);
- calc_resistance_stats(ocpc);
- resistance_tbl_idx = (resistance_tbl_idx + 1) %
- NUM_RESISTANCE_SAMPLES;
- }
-
- if (seeded) {
- ocpc->combined_rsys_rbatt_mo =
- MAX(mean_resistance[COMBINED_IDX],
- CONFIG_OCPC_DEF_RBATT_MOHMS);
-
- if (!(ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP)) {
- ocpc->rsys_mo = mean_resistance[RSYS_IDX];
- ocpc->rbatt_mo = MAX(mean_resistance[RBATT_IDX],
- CONFIG_OCPC_DEF_RBATT_MOHMS);
- CPRINTS_DBG("Rsys: %dmOhm Rbatt: %dmOhm",
- ocpc->rsys_mo, ocpc->rbatt_mo);
- }
-
- CPRINTS_DBG("Rsys+Rbatt: %dmOhm", ocpc->combined_rsys_rbatt_mo);
- } else {
- seeded = ++initial_samples >= (2 * NUM_RESISTANCE_SAMPLES) ?
- true : false;
- }
-
- return EC_SUCCESS;
-}
-
-int ocpc_config_secondary_charger(int *desired_input_current,
- struct ocpc_data *ocpc,
- int voltage_mv, int current_ma)
-{
- int rv = EC_SUCCESS;
- struct batt_params batt;
- const struct battery_info *batt_info;
- struct charger_params charger;
- int vsys_target = 0;
- int drive = 0;
- int i_ma = 0;
- static int i_ma_CC_CV;
- int min_vsys_target;
- int error = 0;
- int derivative = 0;
- static enum phase ph;
- static int prev_limited;
- int chgnum;
- enum ec_error_list result;
- static int iterations;
- int i_step;
- static timestamp_t delay;
- int i, step, loc;
- bool icl_reached = false;
- static timestamp_t precharge_exit;
-
- /*
- * There's nothing to do if we're not using this charger. Should
- * there be more than two charger ICs in the future, the following check
- * should change to ensure that only the active charger IC is acted
- * upon.
- */
- chgnum = charge_get_active_chg_chip();
- if (chgnum != CHARGER_SECONDARY)
- return EC_ERROR_INVAL;
-
- batt_info = battery_get_info();
-
- if (current_ma == 0) {
- vsys_target = voltage_mv;
- goto set_vsys;
- }
-
- /*
- * Check to see if the charge FET is disabled. If it's disabled, the
- * charging loop is broken and increasing VSYS will not actually help.
- * Therefore, don't make any changes at this time.
- */
- if (battery_is_charge_fet_disabled() &&
- (battery_get_disconnect_state() == BATTERY_NOT_DISCONNECTED)) {
- CPRINTS("CFET disabled; not changing VSYS!");
-
- /*
- * Let's check back in 5 seconds to see if the CFET is enabled
- * now. Note that if this continues to occur, we'll keep
- * pushing this out.
- */
- delay = get_time();
- delay.val += (5 * SECOND);
- return EC_ERROR_INVALID_CONFIG;
- }
-
- /*
- * The CFET status changed recently, wait until it's no longer disabled
- * for awhile before modifying VSYS. This could be the fuel gauge
- * performing some impedence calculations.
- */
- if (!timestamp_expired(delay, NULL))
- return EC_ERROR_BUSY;
-
- result = charger_set_vsys_compensation(chgnum, ocpc, current_ma,
- voltage_mv);
- switch (result) {
- case EC_SUCCESS:
- /* No further action required, so we're done here. */
- return EC_SUCCESS;
-
- case EC_ERROR_UNIMPLEMENTED:
- /* Let's get to work */
- break;
-
- default:
- /* Something went wrong configuring the auxiliary charger IC. */
- CPRINTS("Failed to set VSYS compensation! (%d) (result: %d)",
- chgnum, result);
- return result;
- }
-
- if (ocpc->last_vsys == OCPC_UNINIT) {
- ph = PHASE_UNKNOWN;
- precharge_exit.val = 0;
- iterations = 0;
- }
-
-
- /*
- * We need to induce a current flow that matches the requested current
- * by raising VSYS. Let's start by getting the latest data that we
- * know of.
- */
- batt_info = battery_get_info();
- battery_get_params(&batt);
- 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 |
- CHIPSET_STATE_ANY_SUSPEND)) {
- /*
- * 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.desired_voltage) {
- if (((batt.voltage < batt_info->voltage_min) ||
- ((batt.voltage < batt_info->voltage_normal) &&
- (current_ma <= batt_info->precharge_current))) &&
- (ph != PHASE_PRECHARGE)) {
- /*
- * If the charger IC doesn't support the linear charge
- * feature, proceed to the CC phase.
- */
- result = ocpc_precharge_enable(true);
- if (result == EC_ERROR_UNIMPLEMENTED) {
- ph = PHASE_CC;
- } else if (result == EC_SUCCESS) {
- CPRINTS("OCPC: Enabling linear precharge");
- ph = PHASE_PRECHARGE;
- i_ma = current_ma;
- }
- } else if (batt.voltage < batt.desired_voltage) {
- if ((ph == PHASE_PRECHARGE) &&
- (current_ma >
- batt_info->precharge_current)) {
- /*
- * Precharge phase is complete. Now set the
- * target VSYS to the battery voltage to prevent
- * a large current spike during the transition.
- */
- /*
- * If we'd like to exit precharge, let's wait a
- * short delay.
- */
- if (!precharge_exit.val) {
- CPRINTS("OCPC: Preparing to exit "
- "precharge");
- precharge_exit = get_time();
- precharge_exit.val += 3 * SECOND;
- }
- if (timestamp_expired(precharge_exit, NULL)) {
- CPRINTS("OCPC: Precharge complete");
- charger_set_voltage(CHARGER_SECONDARY,
- batt.voltage);
- ocpc->last_vsys = batt.voltage;
- ocpc_precharge_enable(false);
- ph = PHASE_CC;
- precharge_exit.val = 0;
- }
- }
-
- if ((ph != PHASE_PRECHARGE) && (ph < PHASE_CV_TRIP))
- ph = PHASE_CC;
- i_ma = current_ma;
- } else {
- /*
- * Once the battery voltage reaches the desired voltage,
- * we should note that we've reached the CV step and set
- * VSYS to the desired CV + offset.
- */
- i_ma = batt.current;
- ph = ph == PHASE_CC ? PHASE_CV_TRIP : PHASE_CV_COMPLETE;
- if (ph == PHASE_CV_TRIP)
- i_ma_CC_CV = batt.current;
-
- }
- }
-
- /* Ensure our target is not negative. */
- i_ma = MAX(i_ma, 0);
-
- /* Convert desired mA to what the charger could actually regulate to. */
- i_step = (int)charger_get_info()->current_step;
- i_ma = (i_ma / i_step) * i_step;
-
- /*
- * We'll use our current target and our combined Rsys+Rbatt to seed our
- * VSYS target. However, we'll use a PID loop to correct the error and
- * help drive VSYS to what it _should_ be in order to reach our current
- * target. The first time through this function, we won't make any
- * corrections in order to determine our initial error.
- */
- if (ocpc->last_vsys != OCPC_UNINIT) {
- error = i_ma - batt.current;
- /* Add some hysteresis. */
- if (ABS(error) < (i_step / 2))
- error = 0;
-
- /* Make a note if we're significantly over target. */
- if (error < -100)
- CPRINTS("OCPC: over target %dmA", error * -1);
-
- derivative = error - ocpc->last_error;
- ocpc->last_error = error;
- ocpc->integral += error;
- if (ocpc->integral > 500)
- ocpc->integral = 500;
- }
-
- CPRINTS_DBG("phase = %d", ph);
- CPRINTS_DBG("error = %dmA", error);
- CPRINTS_DBG("derivative = %d", derivative);
- CPRINTS_DBG("integral = %d", ocpc->integral);
- CPRINTS_DBG("batt.voltage = %dmV", batt.voltage);
- CPRINTS_DBG("batt.desired_voltage = %dmV", batt.desired_voltage);
- CPRINTS_DBG("batt.desired_current = %dmA", batt.desired_current);
- CPRINTS_DBG("batt.current = %dmA", batt.current);
- CPRINTS_DBG("i_ma = %dmA", i_ma);
-
- 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. */
- if ((ocpc->last_vsys != OCPC_UNINIT) &&
- (ph > PHASE_PRECHARGE)) {
- drive = (k_p * error / k_p_div) +
- (k_i * ocpc->integral / k_i_div) +
- (k_d * derivative / k_d_div);
- /*
- * Let's limit upward transitions to 10mV. It's okay to reduce
- * VSYS rather quickly, but we'll be conservative on
- * increasing VSYS.
- */
- if (drive > 10)
- drive = 10;
- CPRINTS_DBG("drive = %d", drive);
- }
-
- /*
- * For the pre-charge phase, simply keep the VSYS target at the desired
- * voltage.
- */
- if (ph == PHASE_PRECHARGE)
- vsys_target = batt.desired_voltage;
-
- /*
- * Adjust our VSYS target by applying the calculated drive. Note that
- * we won't apply our drive the first time through this function such
- * that we can determine our initial error.
- */
- if ((ocpc->last_vsys != OCPC_UNINIT) && (ph > PHASE_PRECHARGE))
- vsys_target = ocpc->last_vsys + drive;
-
- /*
- * Once we're in the CV region, all we need to do is keep VSYS at the
- * desired voltage.
- */
- if (ph == PHASE_CV_TRIP) {
- vsys_target = batt.desired_voltage +
- ((i_ma_CC_CV *
- ocpc->combined_rsys_rbatt_mo) / 1000);
- CPRINTS_DBG("i_ma_CC_CV = %d", i_ma_CC_CV);
- }
- if (ph == PHASE_CV_COMPLETE)
- vsys_target = batt.desired_voltage +
- ((batt_info->precharge_current *
- ocpc->combined_rsys_rbatt_mo) / 1000);
-
- /*
- * Ensure VSYS is no higher than the specified maximum battery voltage
- * plus the voltage drop across the system.
- */
- vsys_target = CLAMP(vsys_target, min_vsys_target,
- batt_info->voltage_max +
- (i_ma * ocpc->combined_rsys_rbatt_mo / 1000));
-
- /* If we're input current limited, we cannot increase VSYS any more. */
- CPRINTS_DBG("OCPC: Inst. Input Current: %dmA (Limit: %dmA)",
- ocpc->secondary_ibus_ma, *desired_input_current);
-
- if (charger_is_icl_reached(chgnum, &icl_reached) != EC_SUCCESS) {
- /*
- * If the charger doesn't support telling us, assume that the
- * input current limit is reached if we're consuming more than
- * 95% of the limit.
- */
- if (ocpc->secondary_ibus_ma >=
- (*desired_input_current * 95 / 100))
- icl_reached = true;
- }
-
- if (icl_reached && (vsys_target > ocpc->last_vsys) &&
- (ocpc->last_vsys != OCPC_UNINIT)) {
- if (!prev_limited)
- CPRINTS("Input limited! Not increasing VSYS");
- prev_limited = 1;
- return rv;
- }
- prev_limited = 0;
-
-set_vsys:
- /* VSYS should never be below the battery's min voltage. */
- vsys_target = MAX(vsys_target, batt_info->voltage_min);
- /* To reduce spam, only print when we change VSYS significantly. */
- if ((ABS(vsys_target - ocpc->last_vsys) > 10) || debug_output)
- CPRINTS("OCPC: Target VSYS: %dmV", vsys_target);
- charger_set_voltage(CHARGER_SECONDARY, vsys_target);
- ocpc->last_vsys = vsys_target;
-
- /*
- * Print a visualization graph of the actual current vs. the target.
- * Each position represents 5% of the target current.
- */
- if (i_ma != 0) {
- step = 5 * i_ma / 100;
- loc = error / step;
- loc = CLAMP(loc, -10, 10);
- CPRINT_VIZ("[");
- for (i = -10; i <= 10; i++) {
- if (i == 0)
- CPRINT_VIZ(loc == 0 ? "#" : "|");
- else
- CPRINT_VIZ(i == loc ? "o" : "-");
- }
- CPRINT_VIZ("] (actual)%dmA (desired)%dmA\n", batt.current,
- i_ma);
- }
-
- return rv;
-}
-
-void ocpc_get_adcs(struct ocpc_data *ocpc)
-{
- int val;
-
- val = 0;
- if (!charger_get_vbus_voltage(CHARGER_PRIMARY, &val))
- ocpc->primary_vbus_mv = val;
-
- val = 0;
- if (!charger_get_input_current(CHARGER_PRIMARY, &val))
- ocpc->primary_ibus_ma = val;
-
- val = 0;
- if (!charger_get_actual_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;
- }
-
- val = 0;
- if (!charger_get_vbus_voltage(CHARGER_SECONDARY, &val))
- ocpc->secondary_vbus_mv = val;
-
- val = 0;
- if (!charger_get_input_current(CHARGER_SECONDARY, &val))
- ocpc->secondary_ibus_ma = val;
-
- val = 0;
- if (!charger_get_actual_voltage(CHARGER_SECONDARY, &val))
- ocpc->vsys_aux_mv = val;
-
- val = 0;
- if (!charger_get_actual_current(CHARGER_SECONDARY, &val))
- ocpc->isys_ma = val;
-}
-
-__overridable void ocpc_get_pid_constants(int *kp, int *kp_div,
- int *ki, int *ki_div,
- int *kd, int *kd_div)
-{
-}
-
-static enum ec_error_list ocpc_precharge_enable(bool enable)
-{
- /* Enable linear charging on the primary charger IC. */
- int rv = charger_enable_linear_charge(CHARGER_PRIMARY, enable);
-
- if (rv)
- CPRINTS("OCPC: Failed to %sble linear charge!", enable ? "ena"
- : "dis");
-
- return rv;
-}
-
-void ocpc_reset(struct ocpc_data *ocpc)
-{
- struct batt_params batt;
-
- battery_get_params(&batt);
- ocpc->integral = 0;
- ocpc->last_error = 0;
- ocpc->last_vsys = OCPC_UNINIT;
-
- /*
- * Initialize the VSYS target on the aux chargers to the current battery
- * voltage to avoid a large spike.
- */
- if (ocpc->active_chg_chip > CHARGER_PRIMARY && batt.voltage > 0) {
- CPRINTS("OCPC: C%d Init VSYS to %dmV", ocpc->active_chg_chip,
- batt.voltage);
- charger_set_voltage(ocpc->active_chg_chip, batt.voltage);
- }
-
- /*
- * See(b:191347747) When linear precharge is enabled, it may affect
- * the charging behavior from the primary charger IC. Therefore as
- * a part of the reset process, we need to disable linear precharge.
- */
- ocpc_precharge_enable(false);
-}
-
-static void ocpc_set_pid_constants(void)
-{
- ocpc_get_pid_constants(&k_p, &k_p_div, &k_i, &k_i_div, &k_d, &k_d_div);
-}
-DECLARE_HOOK(HOOK_INIT, ocpc_set_pid_constants, HOOK_PRIO_DEFAULT);
-
-void ocpc_init(struct ocpc_data *ocpc)
-{
- /*
- * We can start off assuming that the board resistance is 0 ohms
- * and later on, we can update this value if we charge the
- * system in suspend or off.
- */
- ocpc->combined_rsys_rbatt_mo = CONFIG_OCPC_DEF_RBATT_MOHMS;
- ocpc->rbatt_mo = CONFIG_OCPC_DEF_RBATT_MOHMS;
-
- board_ocpc_init(ocpc);
-}
-
-static int command_ocpcdebug(int argc, char **argv)
-{
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- if (!strncmp(argv[1], "ena", 3)) {
- debug_output = true;
- viz_output = false;
- } else if (!strncmp(argv[1], "dis", 3)) {
- debug_output = false;
- viz_output = false;
- } else if (!strncmp(argv[1], "viz", 3)) {
- debug_output = false;
- viz_output = true;
- } else if (!strncmp(argv[1], "all", 3)) {
- debug_output = true;
- viz_output = true;
- } else {
- return EC_ERROR_PARAM1;
- }
-
- return EC_SUCCESS;
-}
-DECLARE_SAFE_CONSOLE_COMMAND(ocpcdebug, command_ocpcdebug,
- "<enable/viz/all/disable",
- "Enable/disable debug prints for OCPC data. "
- "Enable turns on text debug, viz shows a graph."
- "Each segment is 5% of current target. All shows"
- " both. Disable shows no debug output.");
-
-static int command_ocpcpid(int argc, char **argv)
-{
- int *num, *denom;
-
- if (argc == 4) {
- switch (argv[1][0]) {
- case 'p':
- num = &k_p;
- denom = &k_p_div;
- break;
-
- case 'i':
- num = &k_i;
- denom = &k_i_div;
- break;
-
- case 'd':
- num = &k_d;
- denom = &k_d_div;
- break;
- default:
- return EC_ERROR_PARAM1;
- }
-
- *num = atoi(argv[2]);
- *denom = atoi(argv[3]);
- }
-
- /* Print the current constants */
- ccprintf("Kp = %d / %d\n", k_p, k_p_div);
- ccprintf("Ki = %d / %d\n", k_i, k_i_div);
- ccprintf("Kd = %d / %d\n", k_d, k_d_div);
- return EC_SUCCESS;
-}
-DECLARE_SAFE_CONSOLE_COMMAND(ocpcpid, command_ocpcpid,
- "[<k/p/d> <numerator> <denominator>]",
- "Show/Set PID constants for OCPC PID loop");