summaryrefslogtreecommitdiff
path: root/common/charge_ramp_sw.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/charge_ramp_sw.c')
-rw-r--r--common/charge_ramp_sw.c383
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