summaryrefslogtreecommitdiff
path: root/board/servo_v4p1
diff options
context:
space:
mode:
authorJan Dabros <jsd@semihalf.com>2020-12-15 13:55:12 +0100
committerCommit Bot <commit-bot@chromium.org>2021-01-14 14:40:19 +0000
commit4f8c2db072fb4a8a99ccdc9fa557f122582f8173 (patch)
treebfcae95e7f847a03281f696217f8c707e6afddc3 /board/servo_v4p1
parent4ccfbe2d22b5c7f65a182dfb5bb35fe033799a2f (diff)
downloadchrome-ec-4f8c2db072fb4a8a99ccdc9fa557f122582f8173.tar.gz
servo_v4p1: Add driver for power management
Depending on the power source and loads, the servo_v4p1 may have insufficient wattage available. New driver gathers information about available inputs, monitors power consumed and sets alert when a threshold is crossed. For servo_v4p1 there are two main power sources - host USBC port and servo charger port. Host connection operates on 5V and may allow up to 500mA(USB2.0), 900mA(USB3.0), 1500mA(BC1.2 or USB-C) or 3000mA(USB-C). Servo charger port currently offers only standard USB-C wattage - 1500mA/5V or 3000mA/5V. There is a possibility that in future PD will be enabled on this port, thus enabling higher wattages. Algorithm queries host connection capabilities (including BC1.2) and servo charger port connection settings, with charger port being always a primary selection. INAXX chip is used to monitor level of consumed power and notification is send to the user, when threshold is reached. In future servod should be used as a channel for alerts notification. BUG=b:144776402 BRANCH=master TEST=Test various connections for input power to servo_v4p1 - USB2.0 host/cable, USB3.0, BC1.2 enabled/disabled, servo charger with different Rp/Rd settings, also hot plugging servo charger. Provide different loads to servo - pendrives, DUT connection and DisplayPort. Monitor power used by servo and loads (either by external power meter or compile-in INA_CMD). When threshold is reached, one should see "System full power threshold exceeded" on the servo console. Default threshold is set to 90% of power. For example on USB2.0 connection (500mA at max) and assuming 5V is provided to VCC rail, warning should appear when drawing 500mA * 9/10 = 450m. Keep in mind though that actual alert is configured on power over limit mode (not current), thus there may be some differences when there is no ideal 5V on a tested connection. Signed-off-by: Jan Dabros <jsd@semihalf.com> Change-Id: I1099192fa7475b51922e9dcb272f812d1547f311 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2592495 Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
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