summaryrefslogtreecommitdiff
path: root/board/servo_v4p1
diff options
context:
space:
mode:
Diffstat (limited to 'board/servo_v4p1')
-rw-r--r--board/servo_v4p1/board.c19
-rw-r--r--board/servo_v4p1/build.mk1
-rw-r--r--board/servo_v4p1/ina231s.c16
-rw-r--r--board/servo_v4p1/ina231s.h6
-rw-r--r--board/servo_v4p1/power_mgmt.c70
-rw-r--r--board/servo_v4p1/power_mgmt.h16
-rw-r--r--board/servo_v4p1/usb_tc_snk_sm.c30
-rw-r--r--board/servo_v4p1/usb_tc_snk_sm.h12
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