summaryrefslogtreecommitdiff
path: root/baseboard/kukui/charger_mt6370.c
diff options
context:
space:
mode:
Diffstat (limited to 'baseboard/kukui/charger_mt6370.c')
-rw-r--r--baseboard/kukui/charger_mt6370.c366
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);
-}