diff options
-rw-r--r-- | board/servo_v4p1/board.c | 19 | ||||
-rw-r--r-- | board/servo_v4p1/build.mk | 1 | ||||
-rw-r--r-- | board/servo_v4p1/ina231s.c | 16 | ||||
-rw-r--r-- | board/servo_v4p1/ina231s.h | 6 | ||||
-rw-r--r-- | board/servo_v4p1/power_mgmt.c | 70 | ||||
-rw-r--r-- | board/servo_v4p1/power_mgmt.h | 16 | ||||
-rw-r--r-- | board/servo_v4p1/usb_tc_snk_sm.c | 30 | ||||
-rw-r--r-- | board/servo_v4p1/usb_tc_snk_sm.h | 12 |
8 files changed, 170 insertions, 0 deletions
diff --git a/board/servo_v4p1/board.c b/board/servo_v4p1/board.c index 2d8725f206..6ffbfbad97 100644 --- a/board/servo_v4p1/board.c +++ b/board/servo_v4p1/board.c @@ -21,6 +21,7 @@ #include "ioexpanders.h" #include "pathsel.h" #include "pi3usb9201.h" +#include "power_mgmt.h" #include "queue_policies.h" #include "registers.h" #include "spi.h" @@ -387,6 +388,14 @@ int board_get_version(void) return board_id_det(); } +#ifdef SECTION_IS_RO +static void evaluate_input_power_def(void) +{ + evaluate_input_power(); +} +DECLARE_DEFERRED(evaluate_input_power_def); +#endif + static void board_init(void) { /* USB to serial queues */ @@ -420,6 +429,16 @@ static void board_init(void) init_ina231s(); init_fusb302b(1); + /* + * Get data about available input power. Add additional check after a + * delay, since we need to wait for USB2/USB3 enumeration on host hub + * as well as I2C interface of this hub needs to be initialized. + * 3 seconds is experimentally selected value, by this time hub should + * be up and running. + */ + evaluate_input_power(); + hook_call_deferred(&evaluate_input_power_def_data, 3 * SECOND); + /* Enable DUT USB2.0 pair. */ gpio_set_level(GPIO_FASTBOOT_DUTHUB_MUX_EN_L, 0); diff --git a/board/servo_v4p1/build.mk b/board/servo_v4p1/build.mk index a8d22ccbc3..1b89435d3c 100644 --- a/board/servo_v4p1/build.mk +++ b/board/servo_v4p1/build.mk @@ -29,5 +29,6 @@ board-ro+=usb_pd_policy.o board-ro+=fusb302b.o board-ro+=usb_sm.o board-ro+=usb_tc_snk_sm.o +board-ro+=power_mgmt.o all_deps=$(patsubst ro,,$(def_all_deps)) diff --git a/board/servo_v4p1/ina231s.c b/board/servo_v4p1/ina231s.c index 3382686f3f..bd5355b052 100644 --- a/board/servo_v4p1/ina231s.c +++ b/board/servo_v4p1/ina231s.c @@ -67,3 +67,19 @@ int sr_chg_power(void) { return ina2xx_get_power(SR_CHG_IDX); } + +int set_sr_chg_power_limit(int limit) +{ + int enable; + int rv; + + /* Configure PowerOverLimit alert */ + enable = ina2xx_get_mask(SR_CHG_IDX); + enable |= 0x800; + + rv = ina2xx_set_alert(SR_CHG_IDX, limit / 25); + if (rv) + return rv; + + return ina2xx_set_mask(SR_CHG_IDX, enable); +} diff --git a/board/servo_v4p1/ina231s.h b/board/servo_v4p1/ina231s.h index 9c3804e769..e830c9c505 100644 --- a/board/servo_v4p1/ina231s.h +++ b/board/servo_v4p1/ina231s.h @@ -56,4 +56,10 @@ int sr_chg_current(void); */ int sr_chg_power(void); +/* + * Set power limit on servo charger input to `limit` milliWatts, + * configure interrupt + */ +int set_sr_chg_power_limit(int limit); + #endif /* __CROS_EC_INA231S_H */ diff --git a/board/servo_v4p1/power_mgmt.c b/board/servo_v4p1/power_mgmt.c new file mode 100644 index 0000000000..b6d1024eaf --- /dev/null +++ b/board/servo_v4p1/power_mgmt.c @@ -0,0 +1,70 @@ +/* Copyright 2021 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 "console.h" +#include "gl3590.h" +#include "ina231s.h" +#include "ioexpanders.h" +#include "system.h" +#include "usb_tc_snk_sm.h" +#include "util.h" +#include "pwr_defs.h" + +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) + +/* + * Power alert threshold, defines what is the trigger level for used power in + * relation to all available input power in percentages. + */ +#define PWR_ALERT_TH (90) + +/* Cache previous power in milliwatts in order to detect changes */ +static int old_pwr_mw; + +static int is_bc12_enabled(void) +{ + return get_host_chrg_det(); +} + +void evaluate_input_power(void) +{ + struct pwr_con_t host_hub_pwr = {0}, bc12_pwr = {0}, srv_chg_pwr = {0}; + struct pwr_con_t *available_pwr; + + if (gl3590_ufp_pwr(0, &host_hub_pwr)) { + CPRINTF("Cannot get host connection power data, assuming " + "5V/500mA\n"); + host_hub_pwr.volts = 5; + host_hub_pwr.milli_amps = 500; + } + + if (is_bc12_enabled()) { + bc12_pwr.volts = 5; + bc12_pwr.milli_amps = 1500; + } + + /* + * It is possible that we will get less power from servo charger port + * than from the host connection, however the design of power + * multiplexer circuit doesn't allow to switch back from alternate + * supply. That's why once enabled, servo charger power will be always + * used. + */ + if (get_alternate_port_pwr(&srv_chg_pwr)) { + available_pwr = pwr_con_to_milliwatts(&host_hub_pwr) > + pwr_con_to_milliwatts(&bc12_pwr) ? + &host_hub_pwr : &bc12_pwr; + } else { + available_pwr = &srv_chg_pwr; + } + + if (pwr_con_to_milliwatts(available_pwr) != old_pwr_mw) { + CPRINTF("Servo now powered %dV/%dmA\n", available_pwr->volts, + available_pwr->milli_amps); + set_sr_chg_power_limit(pwr_con_to_milliwatts(available_pwr) * + PWR_ALERT_TH / 100); + old_pwr_mw = pwr_con_to_milliwatts(available_pwr); + } +} diff --git a/board/servo_v4p1/power_mgmt.h b/board/servo_v4p1/power_mgmt.h new file mode 100644 index 0000000000..6c8871e63b --- /dev/null +++ b/board/servo_v4p1/power_mgmt.h @@ -0,0 +1,16 @@ +/* Copyright 2021 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. + */ + +#ifndef __CROS_EC_POWER_MGMT_H +#define __CROS_EC_POWER_MGMT_H + +/* + * Method for getting current platform input power capabilities and configuring + * alert interrupt when programmed power threshold is exceeded. This function + * should be invoked every time the input power may change its value. + */ +void evaluate_input_power(void); + +#endif diff --git a/board/servo_v4p1/usb_tc_snk_sm.c b/board/servo_v4p1/usb_tc_snk_sm.c index f9a3966434..0889d05db6 100644 --- a/board/servo_v4p1/usb_tc_snk_sm.c +++ b/board/servo_v4p1/usb_tc_snk_sm.c @@ -7,12 +7,15 @@ #include "console.h" #include "fusb302b.h" #include "ioexpanders.h" +#include "pwr_defs.h" +#include "power_mgmt.h" #include "system.h" #include "task.h" #include "usb_common.h" #include "usb_pd.h" #include "usb_sm.h" #include "usb_tc_sm.h" +#include "usb_tc_snk_sm.h" #define EVT_TIMEOUT_NEVER (-1) #define EVT_TIMEOUT_5MS (5 * MSEC) @@ -85,6 +88,28 @@ static void restart_tc_sm(enum usb_tc_state start_state) tc.evt_timeout = EVT_TIMEOUT_NEVER; } +int get_alternate_port_pwr(struct pwr_con_t *pwr) +{ + enum tcpc_cc_voltage_status cc; + + cc = tc.polarity ? tc.cc2 : tc.cc1; + + pwr->volts = 5; + + if (cc == TYPEC_CC_VOLT_RP_1_5) { + pwr->milli_amps = 1500; + } else if (cc == TYPEC_CC_VOLT_RP_3_0) { + pwr->milli_amps = 3000; + } else if (cc == TYPEC_CC_VOLT_RP_DEF) { + pwr->milli_amps = 900; + } else { + pwr->milli_amps = 0; + return -1; + } + + return 0; +} + /* * Private Functions */ @@ -145,6 +170,9 @@ static void sink_power_sub_states(void) tc.cc_debounce = 0; print_alt_power(); + + /* Update board power configuration */ + evaluate_input_power(); } /* @@ -219,6 +247,8 @@ static void tc_attach_wait_snk_run(int port) static void tc_attached_snk_entry(int port) { print_alt_power(); + /* Update board power configuration */ + evaluate_input_power(); tc.evt_timeout = EVT_TIMEOUT_NEVER; tc.cc_debounce = 0; diff --git a/board/servo_v4p1/usb_tc_snk_sm.h b/board/servo_v4p1/usb_tc_snk_sm.h new file mode 100644 index 0000000000..c501c01012 --- /dev/null +++ b/board/servo_v4p1/usb_tc_snk_sm.h @@ -0,0 +1,12 @@ +/* Copyright 2021 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. + */ + +#ifndef __CROS_EC_USB_TC_SNK_SM_H +#define __CROS_EC_USB_TC_SNK_SM_H + +/* Function to retrieve state of servo charger port */ +int get_alternate_port_pwr(struct pwr_con_t *pwr); + +#endif |