diff options
Diffstat (limited to 'common/charge_ramp_sw.c')
-rw-r--r-- | common/charge_ramp_sw.c | 383 |
1 files changed, 0 insertions, 383 deletions
diff --git a/common/charge_ramp_sw.c b/common/charge_ramp_sw.c deleted file mode 100644 index bfd6db057b..0000000000 --- a/common/charge_ramp_sw.c +++ /dev/null @@ -1,383 +0,0 @@ -/* Copyright 2017 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. - */ - -/* Charge input current limit ramp module for Chrome EC */ - -#include "charge_manager.h" -#include "charge_ramp.h" -#include "charge_state.h" -#include "common.h" -#include "console.h" -#include "ec_commands.h" -#include "task.h" -#include "timer.h" -#include "usb_pd.h" -#include "util.h" - -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) - -/* Number of times to ramp current searching for limit before stable charging */ -#define RAMP_COUNT 3 - -/* Maximum allowable time charger can be unplugged to be considered an OCP */ -#define OC_RECOVER_MAX_TIME (SECOND) - -/* Delay for running state machine when board is not consuming full current */ -#define CURRENT_DRAW_DELAY (5*SECOND) - -/* Current ramp increment */ -#define RAMP_CURR_INCR_MA 64 -#define RAMP_CURR_DELAY (500*MSEC) -#define RAMP_CURR_START_MA 500 - -/* How much to backoff the input current limit when limit has been found */ -#define RAMP_ICL_BACKOFF (2*RAMP_CURR_INCR_MA) - -/* Interval at which VBUS voltage is monitored in stable state */ -#define STABLE_VBUS_MONITOR_INTERVAL (SECOND) - -/* Time to delay for stablizing the charging current */ -#define STABLIZE_DELAY (5*SECOND) - -enum chg_ramp_state { - CHG_RAMP_DISCONNECTED, - CHG_RAMP_CHARGE_DETECT_DELAY, - CHG_RAMP_OVERCURRENT_DETECT, - CHG_RAMP_RAMP, - CHG_RAMP_STABILIZE, - CHG_RAMP_STABLE, -}; -static enum chg_ramp_state ramp_st; - -struct oc_info { - timestamp_t ts; - int oc_detected; - int sup; - int icl; -}; - -/* OCP info for each over-current */ -static struct oc_info oc_info[CONFIG_USB_PD_PORT_MAX_COUNT][RAMP_COUNT]; -static int oc_info_idx[CONFIG_USB_PD_PORT_MAX_COUNT]; -#define ACTIVE_OC_INFO (oc_info[active_port][oc_info_idx[active_port]]) - -/* Active charging information */ -static int active_port = CHARGE_PORT_NONE; -static int active_sup; -static int active_icl; -static int active_vtg; -static timestamp_t reg_time; - -static int stablize_port; -static int stablize_sup; - -/* Maximum/minimum input current limit for active charger */ -static int max_icl; -static int min_icl; - -void chg_ramp_charge_supplier_change(int port, int supplier, int current, - timestamp_t registration_time, int voltage) -{ - /* - * If the last active port was a valid port and the port - * has changed, then this may have been an over-current. - */ - if (active_port != CHARGE_PORT_NONE && - port != active_port) { - if (oc_info_idx[active_port] == RAMP_COUNT - 1) - oc_info_idx[active_port] = 0; - else - oc_info_idx[active_port]++; - ACTIVE_OC_INFO.ts = get_time(); - ACTIVE_OC_INFO.sup = active_sup; - ACTIVE_OC_INFO.icl = active_icl; - } - - /* Set new active port, set ramp state, and wake ramp task */ - active_port = port; - active_sup = supplier; - active_vtg = voltage; - - /* Set min and max input current limit based on if ramp is allowed */ - if (chg_ramp_allowed(active_port, active_sup)) { - min_icl = RAMP_CURR_START_MA; - max_icl = chg_ramp_max(active_port, active_sup, current); - } else { - min_icl = max_icl = current; - } - - reg_time = registration_time; - if (ramp_st != CHG_RAMP_STABILIZE) { - ramp_st = (active_port == CHARGE_PORT_NONE) ? - CHG_RAMP_DISCONNECTED : CHG_RAMP_CHARGE_DETECT_DELAY; - CPRINTS("Ramp reset: st%d", ramp_st); - task_wake(TASK_ID_CHG_RAMP); - } -} - -int chg_ramp_get_current_limit(void) -{ - /* - * If we are ramping or stable, then use the active input - * current limit. Otherwise, use the minimum input current - * limit. - */ - switch (ramp_st) { - case CHG_RAMP_RAMP: - case CHG_RAMP_STABILIZE: - case CHG_RAMP_STABLE: - return active_icl; - default: - return min_icl; - } -} - -int chg_ramp_is_detected(void) -{ - /* Charger detected (charge detect delay has passed) */ - return ramp_st > CHG_RAMP_CHARGE_DETECT_DELAY; -} - -int chg_ramp_is_stable(void) -{ - return ramp_st == CHG_RAMP_STABLE; -} - -void chg_ramp_task(void *u) -{ - int task_wait_time = -1; - int i, lim; - uint64_t detect_end_time_us = 0, time_us; - int last_active_port = CHARGE_PORT_NONE; - - enum chg_ramp_state ramp_st_prev = CHG_RAMP_DISCONNECTED, - ramp_st_new = CHG_RAMP_DISCONNECTED; - int active_icl_new; - - /* Clear last OCP supplier to guarantee we ramp on first connect */ - for (i = 0; i < board_get_usb_pd_port_count(); i++) - oc_info[i][0].sup = CHARGE_SUPPLIER_NONE; - - /* - * Sleep until chg_ramp_charge_supplier_change is called to avoid - * setting input current limit to zero. chg_ramp_charge_supplier_change - * won't be called until charge_manager is ready to call - * board_set_charge_limit by itself (if there is no chg_ramp_task). - */ - if (!IS_ENABLED(TEST_BUILD)) - task_wait_event(-1); - - while (1) { - ramp_st_new = ramp_st; - active_icl_new = active_icl; - switch (ramp_st) { - case CHG_RAMP_DISCONNECTED: - /* Do nothing */ - task_wait_time = -1; - break; - case CHG_RAMP_CHARGE_DETECT_DELAY: - /* Delay for charge_manager to determine supplier */ - /* - * On entry to state, or if port changes, check - * timestamps to determine if this was likely an - * OC event (check if we lost VBUS and it came back - * within OC_RECOVER_MAX_TIME). - */ - if (ramp_st_prev != ramp_st || - active_port != last_active_port) { - last_active_port = active_port; - if (reg_time.val < - ACTIVE_OC_INFO.ts.val + - OC_RECOVER_MAX_TIME) { - ACTIVE_OC_INFO.oc_detected = 1; - } else { - for (i = 0; i < RAMP_COUNT; ++i) - oc_info[active_port][i]. - oc_detected = 0; - } - detect_end_time_us = get_time().val + - CHARGE_DETECT_DELAY; - task_wait_time = CHARGE_DETECT_DELAY; - break; - } - - /* If detect delay has not passed, set wait time */ - time_us = get_time().val; - if (time_us < detect_end_time_us) { - task_wait_time = detect_end_time_us - time_us; - break; - } - - /* Detect delay is over, fall through to next state */ - ramp_st_new = CHG_RAMP_OVERCURRENT_DETECT; - /* notify host of power info change */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); - case CHG_RAMP_OVERCURRENT_DETECT: - /* Check if we should ramp or go straight to stable */ - task_wait_time = SECOND; - - /* Skip ramp for specific suppliers */ - if (!chg_ramp_allowed(active_port, active_sup)) { - active_icl_new = min_icl; - ramp_st_new = CHG_RAMP_STABLE; - break; - } - - /* - * If we are not drawing full charge, then don't ramp, - * just wait in this state, until we are. - */ - if (!charge_is_consuming_full_input_current()) { - task_wait_time = CURRENT_DRAW_DELAY; - break; - } - - /* - * Compare recent OCP events, if all info matches, - * then we don't need to ramp anymore. - */ - for (i = 0; i < RAMP_COUNT; i++) { - if (oc_info[active_port][i].sup != active_sup || - !oc_info[active_port][i].oc_detected) - break; - } - - if (i == RAMP_COUNT) { - /* Found OC threshold! */ - active_icl_new = ACTIVE_OC_INFO.icl - - RAMP_ICL_BACKOFF; - ramp_st_new = CHG_RAMP_STABLE; - } else { - /* - * Need to ramp to find OC threshold, start - * at the minimum input current limit. - */ - active_icl_new = min_icl; - ramp_st_new = CHG_RAMP_RAMP; - } - break; - case CHG_RAMP_RAMP: - /* Keep ramping until we find the limit */ - task_wait_time = RAMP_CURR_DELAY; - - /* Pause ramping if we are not drawing full current */ - if (!charge_is_consuming_full_input_current()) { - task_wait_time = CURRENT_DRAW_DELAY; - break; - } - - /* If VBUS is sagging a lot, then stop ramping */ - if (board_is_vbus_too_low(active_port, - CHG_RAMP_VBUS_RAMPING)) { - CPRINTS("VBUS low"); - active_icl_new = MAX(min_icl, active_icl - - RAMP_ICL_BACKOFF); - ramp_st_new = CHG_RAMP_STABILIZE; - task_wait_time = STABLIZE_DELAY; - stablize_port = active_port; - stablize_sup = active_sup; - break; - } - - /* Ramp the current limit if we haven't reached max */ - if (active_icl == max_icl) - ramp_st_new = CHG_RAMP_STABLE; - else if (active_icl + RAMP_CURR_INCR_MA > max_icl) - active_icl_new = max_icl; - else - active_icl_new = active_icl + RAMP_CURR_INCR_MA; - break; - case CHG_RAMP_STABILIZE: - /* Wait for current to stabilize after ramp is done */ - /* Use default delay for exiting this state */ - task_wait_time = SECOND; - if (active_port == stablize_port && - active_sup == stablize_sup) { - ramp_st_new = CHG_RAMP_STABLE; - break; - } - - ramp_st_new = active_port == CHARGE_PORT_NONE ? - CHG_RAMP_DISCONNECTED : - CHG_RAMP_CHARGE_DETECT_DELAY; - break; - case CHG_RAMP_STABLE: - /* Maintain input current limit */ - /* On entry log charging stats */ - if (ramp_st_prev != ramp_st) { -#ifdef CONFIG_USB_PD_LOGGING - charge_manager_save_log(active_port); -#endif - /* notify host of power info change */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); - } - - /* Keep an eye on VBUS and restart ramping if it dips */ - if (chg_ramp_allowed(active_port, active_sup) && - board_is_vbus_too_low(active_port, - CHG_RAMP_VBUS_STABLE)) { - CPRINTS("VBUS low; Re-ramp"); - max_icl = MAX(min_icl, - max_icl - RAMP_ICL_BACKOFF); - active_icl_new = min_icl; - ramp_st_new = CHG_RAMP_RAMP; - } - task_wait_time = STABLE_VBUS_MONITOR_INTERVAL; - break; - } - - ramp_st_prev = ramp_st; - ramp_st = ramp_st_new; - active_icl = active_icl_new; - - /* Skip setting limit if status is stable twice in a row */ - if (ramp_st_prev != CHG_RAMP_STABLE || - ramp_st != CHG_RAMP_STABLE) { - CPRINTS("Ramp p%d st%d %dmA %dmA", - active_port, ramp_st, min_icl, active_icl); - /* Set the input current limit */ - lim = chg_ramp_get_current_limit(); - board_set_charge_limit(active_port, active_sup, lim, - lim, active_vtg); - } - - if (ramp_st == CHG_RAMP_STABILIZE) - /* - * When in stabilize state, supplier/port may change - * and we don't want to wake up task until we have - * slept this amount of time. - */ - usleep(task_wait_time); - else - task_wait_event(task_wait_time); - } -} - -#ifdef CONFIG_CMD_CHGRAMP -static int command_chgramp(int argc, char **argv) -{ - int i; - int port; - - ccprintf("Chg Ramp:\nState: %d\nMin ICL: %d\nActive ICL: %d\n", - ramp_st, min_icl, active_icl); - - for (port = 0; port < board_get_usb_pd_port_count(); port++) { - ccprintf("Port %d:\n", port); - ccprintf(" OC idx:%d\n", oc_info_idx[port]); - for (i = 0; i < RAMP_COUNT; i++) { - ccprintf(" OC %d: s%d oc_det%d icl%d\n", i, - oc_info[port][i].sup, - oc_info[port][i].oc_detected, - oc_info[port][i].icl); - } - } - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(chgramp, command_chgramp, - "", - "Dump charge ramp state info"); -#endif |