diff options
Diffstat (limited to 'baseboard/kukui/charger_mt6370.c')
-rw-r--r-- | baseboard/kukui/charger_mt6370.c | 366 |
1 files changed, 0 insertions, 366 deletions
diff --git a/baseboard/kukui/charger_mt6370.c b/baseboard/kukui/charger_mt6370.c deleted file mode 100644 index 327b567db6..0000000000 --- a/baseboard/kukui/charger_mt6370.c +++ /dev/null @@ -1,366 +0,0 @@ -/* Copyright 2019 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. - */ - -#include "charge_manager.h" -#include "charge_state_v2.h" -#include "charger_mt6370.h" -#include "console.h" -#include "driver/charger/rt946x.h" -#include "driver/tcpm/mt6370.h" -#include "hooks.h" -#include "power.h" -#include "timer.h" -#include "usb_common.h" -#include "usb_pd.h" -#include "util.h" - -#define BAT_LEVEL_PD_LIMIT 85 -#define SYSTEM_PLT_MW 3500 -/* - * b/143318064: Prefer a voltage above 5V to force it picks a voltage - * above 5V at first. If PREFER_MV is 5V, when desired power is around - * 15W ~ 11W, it would pick 5V/3A initially, and mt6370 can only sink - * around 10W, and cause a low charging efficiency. - */ -#define PREVENT_CURRENT_DROP_MV 6000 -#define DEFAULT_PREFER_MV 5000 -/* - * We empirically chose 300mA as the limit for when buck inefficiency is - * noticeable. - */ -#define STABLE_CURRENT_DELTA 300 - -struct pd_pref_config_t pd_pref_config = { - .mv = PREVENT_CURRENT_DROP_MV, - .cv = 70, - .plt_mw = SYSTEM_PLT_MW, - .type = PD_PREFER_BUCK, -}; - -static void update_plt_suspend(void) -{ - pd_pref_config.plt_mw = 0; -} -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, update_plt_suspend, HOOK_PRIO_DEFAULT); - -static void update_plt_resume(void) -{ - pd_pref_config.plt_mw = SYSTEM_PLT_MW; -} -DECLARE_HOOK(HOOK_CHIPSET_RESUME, update_plt_resume, HOOK_PRIO_DEFAULT); - -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) - -/* wait time to evaluate charger thermal status */ -static timestamp_t thermal_wait_until; -/* input current bound when charger throttled */ -static int throttled_ma = PD_MAX_CURRENT_MA; -/* charge_ma in last board_set_charge_limit call */ -static int prev_charge_limit; -/* charge_mv in last board_set_charge_limit call */ -static int prev_charge_mv; - -#ifndef CONFIG_BATTERY_SMART -int board_cut_off_battery(void) -{ - /* The cut-off procedure is recommended by Richtek. b/116682788 */ - rt946x_por_reset(); - mt6370_vconn_discharge(0); - rt946x_cutoff_battery(); - - return EC_SUCCESS; -} -#endif - -static void board_set_charge_limit_throttle(int charge_ma, int charge_mv) -{ - charge_set_input_current_limit( - MIN(throttled_ma, MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT)), - charge_mv); -} - -static void battery_thermal_control(struct charge_state_data *curr) -{ - int input_current, jc_temp; - static int skip_reset; - /* - * mt6370's input current setting is 50mA step, use 50 as well for - * easy value mapping. - */ - const int k_p = 50; - - if (charge_manager_get_charger_voltage() == 5000 || - curr->state != ST_CHARGE) { - /* We already set the charge limit, do not reset it again. */ - if (skip_reset) - return; - skip_reset = 1; - thermal_wait_until.val = 0; - throttled_ma = PD_MAX_CURRENT_MA; - board_set_charge_limit_throttle(prev_charge_limit, - prev_charge_mv); - return; - } - - skip_reset = 0; - - if (thermal_wait_until.val == 0) - goto thermal_exit; - - if (get_time().val < thermal_wait_until.val) - return; - - /* If we fail to read adc, skip for this cycle. */ - if (rt946x_get_adc(MT6370_ADC_TEMP_JC, &jc_temp)) - return; - - /* If we fail to read input curr limit, skip for this cycle. */ - if (charger_get_input_current_limit(CHARGER_SOLO, &input_current)) - return; - - /* - * If input current limit is maximum, and we are under thermal budget, - * just skip. - */ - if (input_current == PD_MAX_CURRENT_MA && - jc_temp < thermal_bound.target + thermal_bound.err) - return; - - /* If the temp is within +- err, thermal is under control */ - if (jc_temp < thermal_bound.target + thermal_bound.err && - jc_temp > thermal_bound.target - thermal_bound.err) - return; - - /* - * PID algorithm (https://en.wikipedia.org/wiki/PID_controller), - * and operates on only P value. - */ - throttled_ma = MIN( - PD_MAX_CURRENT_MA, - /* - * Should not pass the previously set input current by - * charger manager. This value might be related the charger's - * capability. - */ - MIN(prev_charge_limit, - input_current + k_p * (thermal_bound.target - jc_temp))); - - /* If the input current doesn't change, just skip. */ - if (throttled_ma != input_current) - board_set_charge_limit_throttle(throttled_ma, prev_charge_mv); - -thermal_exit: - thermal_wait_until.val = get_time().val + (3 * SECOND); -} - -int command_jc(int argc, char **argv) -{ - static int prev_jc_temp; - int jc_temp; - - if (rt946x_get_adc(MT6370_ADC_TEMP_JC, &jc_temp)) - jc_temp = prev_jc_temp; - - ccprintf("JC Temp: %d\n", jc_temp); - prev_jc_temp = jc_temp; - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(jc, command_jc, "", "mt6370 junction temp"); - -/* - * b/143318064: A workwround for mt6370 bad buck efficiency. - * If the delta of VBUS and VBAT(on krane, desired voltage 4.4V) is too small - * (i.e. < 500mV), the buck throughput will be bounded, and causing that we - * can't drain 5V/3A when battery SoC above around 40%. - * This function watches battery current. If we see battery current drops after - * switching from high voltage to 5V (This will happen if we enable - * CONFIG_USB_PD_PREFER_MV and set prefer votage to 5V), the charger will lost - * power due to the inefficiency (e.g. switch from 9V/1.67A = 15W to 5V/3A, - * but mt6370 would only sink less than 5V/2.4A = 12W), and we will request a - * higher voltage PDO to prevent a slow charging time. - */ -static void battery_desired_curr_dynamic(struct charge_state_data *curr) -{ - static int prev_stable_current = CHARGE_CURRENT_UNINITIALIZED; - static int prev_supply_voltage; - int supply_voltage; - int stable_current; - int delta_current; - - if (curr->state != ST_CHARGE) { - prev_supply_voltage = 0; - prev_stable_current = CHARGE_CURRENT_UNINITIALIZED; - /* - * Always force higher voltage on first PD negotiation. - * When desired power is around 15W ~ 11W, PD would pick - * 5V/3A initially, but mt6370 can't drain that much, and - * causes a low charging efficiency. - */ - pd_pref_config.mv = PREVENT_CURRENT_DROP_MV; - return; - } - - supply_voltage = charge_manager_get_charger_voltage(); - stable_current = charge_get_stable_current(); - - if (!charge_is_current_stable()) - return; - - if (!prev_supply_voltage) - goto update_charge; - - delta_current = prev_stable_current - stable_current; - if (curr->batt.state_of_charge >= pd_pref_config.cv && - supply_voltage == DEFAULT_PREFER_MV && - prev_supply_voltage > supply_voltage && - delta_current > STABLE_CURRENT_DELTA) { - /* Raise perfer voltage above 5000mV */ - pd_pref_config.mv = PREVENT_CURRENT_DROP_MV; - /* - * Delay stable current evaluation for 5 mins if we see a - * current drop. It's a reasonable waiting time since that - * the battery desired current can't catch the gap that fast - * in the period. - */ - charge_reset_stable_current_us(5 * MINUTE); - /* Rewrite the stable current to re-evalute desired watt */ - charge_set_stable_current(prev_stable_current); - - /* - * do not alter current by thermal if we just raising PD - * voltage - */ - thermal_wait_until.val = get_time().val + (10 * SECOND); - } else { - pd_pref_config.mv = DEFAULT_PREFER_MV; - /* - * If the power supply is plugged while battery full, - * the stable_current will always be 0 such that we are unable - * to switch to 5V. We force evaluating PDO to switch to 5V. - */ - if (prev_supply_voltage == supply_voltage && !stable_current && - !prev_stable_current && - supply_voltage != DEFAULT_PREFER_MV && - charge_manager_get_supplier() == CHARGE_SUPPLIER_PD) - pd_set_new_power_request( - charge_manager_get_active_charge_port()); - } - -update_charge: - prev_supply_voltage = supply_voltage; - prev_stable_current = stable_current; -} - -#ifdef CONFIG_BATTERY_SMART -static void charge_enable_eoc_and_te(void) -{ - rt946x_enable_charge_eoc(1); - rt946x_enable_charge_termination(1); -} -DECLARE_DEFERRED(charge_enable_eoc_and_te); -#endif - -void mt6370_charger_profile_override(struct charge_state_data *curr) -{ - static int previous_chg_limit_mv; - int chg_limit_mv = pd_get_max_voltage(); - - battery_desired_curr_dynamic(curr); - - battery_thermal_control(curr); - -#ifdef CONFIG_BATTERY_SMART - /* - * SMP battery uses HW pre-charge circuit and pre-charge current is - * limited to ~50mA. Once the charge current is lower than IEOC level - * within CHG_TEDG_EOC, and TE is enabled, the charging power path will - * be turned off. Disable EOC and TE when battery stays over discharge - * state, otherwise enable EOC and TE. - */ - if (!(curr->batt.flags & BATT_FLAG_BAD_VOLTAGE)) { - const struct battery_info *batt_info = battery_get_info(); - static int normal_charge_lock, over_discharge_lock; - - if (curr->batt.voltage < batt_info->voltage_min) { - normal_charge_lock = 0; - - if (!over_discharge_lock && curr->state == ST_CHARGE) { - over_discharge_lock = 1; - rt946x_enable_charge_eoc(0); - rt946x_enable_charge_termination(0); - } - } else { - over_discharge_lock = 0; - - if (!normal_charge_lock) { - normal_charge_lock = 1; - /* - * b/148045048: When the battery is activated - * in shutdown mode, the adapter cannot boot - * DUT automatically. It's a workaround to - * delay 4.5 second to enable charger EOC - * and TE function. - */ - hook_call_deferred( - &charge_enable_eoc_and_te_data, - (4.5 * SECOND)); - } - } - } -#endif - - /* Limit input (=VBUS) to 5V when soc > 85% and charge current < 1A. */ - if (!(curr->batt.flags & BATT_FLAG_BAD_CURRENT) && - charge_get_percent() > BAT_LEVEL_PD_LIMIT && - curr->batt.current < 1000 && power_get_state() != POWER_S0) - chg_limit_mv = 5500; - else - chg_limit_mv = PD_MAX_VOLTAGE_MV; - - if (chg_limit_mv != previous_chg_limit_mv) - CPRINTS("VBUS limited to %dmV", chg_limit_mv); - previous_chg_limit_mv = chg_limit_mv; - - /* Pull down VBUS */ - if (pd_get_max_voltage() != chg_limit_mv) - pd_set_external_voltage_limit(0, chg_limit_mv); - - /* - * When the charger says it's done charging, even if fuel gauge says - * SOC < BATTERY_LEVEL_NEAR_FULL, we'll overwrite SOC with - * BATTERY_LEVEL_NEAR_FULL. So we can ensure both Chrome OS UI - * and battery LED indicate full charge. - * - * Enable this hack on on-board gauge only (b/142097561) - */ - if (IS_ENABLED(CONFIG_BATTERY_MAX17055) && rt946x_is_charge_done()) { - curr->batt.state_of_charge = MAX(BATTERY_LEVEL_NEAR_FULL, - curr->batt.state_of_charge); - } - -} - -#ifndef CONFIG_BATTERY_SMART -static void board_charge_termination(void) -{ - static uint8_t te; - /* Enable charge termination when we are sure battery is present. */ - if (!te && battery_is_present() == BP_YES) { - if (!rt946x_enable_charge_termination(1)) - te = 1; - } -} -DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, - board_charge_termination, - HOOK_PRIO_DEFAULT); -#endif - -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - prev_charge_limit = charge_ma; - prev_charge_mv = charge_mv; - board_set_charge_limit_throttle(charge_ma, charge_mv); -} |