summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/ryu/board.h1
-rw-r--r--common/charge_manager.c73
-rw-r--r--common/usb_pd_policy.c8
-rw-r--r--common/usb_pd_protocol.c13
-rw-r--r--include/config.h3
-rw-r--r--include/ec_commands.h12
-rw-r--r--include/usb_pd.h9
-rw-r--r--util/ectool.c34
8 files changed, 130 insertions, 23 deletions
diff --git a/board/ryu/board.h b/board/ryu/board.h
index 4d8111b79c..3a22f811c9 100644
--- a/board/ryu/board.h
+++ b/board/ryu/board.h
@@ -22,6 +22,7 @@
/* Optional features */
#undef CONFIG_CMD_HASH
#define CONFIG_CHARGE_MANAGER
+#define CONFIG_CHARGE_MANAGER_EXTERNAL_POWER_LIMIT
#define CONFIG_CHARGE_RAMP_HW
#define CONFIG_FORCE_CONSOLE_RESUME
#define CONFIG_STM_HWTIMER32
diff --git a/common/charge_manager.c b/common/charge_manager.c
index 4e21bdf2bd..ef74438368 100644
--- a/common/charge_manager.c
+++ b/common/charge_manager.c
@@ -855,3 +855,76 @@ DECLARE_CONSOLE_COMMAND(chgoverride, command_charge_port_override,
"[port | -1 | -2]",
"Force charging from a given port (-1 = off, -2 = disable charging)",
NULL);
+
+#ifdef CONFIG_CHARGE_MANAGER_EXTERNAL_POWER_LIMIT
+static void charge_manager_set_external_power_limit(int current_lim,
+ int voltage_lim)
+{
+ int port;
+
+ if (current_lim == EC_POWER_LIMIT_NONE)
+ current_lim = CHARGE_CEIL_NONE;
+ if (voltage_lim == EC_POWER_LIMIT_NONE)
+ voltage_lim = PD_MAX_VOLTAGE_MV;
+
+ for (port = 0; port < CONFIG_USB_PD_PORT_COUNT; ++port) {
+ charge_manager_set_ceil(port, CEIL_REQUESTOR_HOST, current_lim);
+ pd_set_external_voltage_limit(port, voltage_lim);
+ }
+}
+
+/*
+ * On transition out of S0, disable all external power limits, in case AP
+ * failed to clear them.
+ */
+static void charge_manager_external_power_limit_off(void)
+{
+ charge_manager_set_external_power_limit(EC_POWER_LIMIT_NONE,
+ EC_POWER_LIMIT_NONE);
+}
+DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, charge_manager_external_power_limit_off,
+ HOOK_PRIO_DEFAULT);
+
+static int hc_external_power_limit(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_external_power_limit_v1 *p = args->params;
+
+ charge_manager_set_external_power_limit(p->current_lim,
+ p->voltage_lim);
+
+ return EC_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_EXTERNAL_POWER_LIMIT,
+ hc_external_power_limit,
+ EC_VER_MASK(1));
+
+static int command_external_power_limit(int argc, char **argv)
+{
+ int max_current;
+ int max_voltage;
+ char *e;
+
+ if (argc >= 2) {
+ max_current = strtoi(argv[1], &e, 10);
+ if (*e)
+ return EC_ERROR_PARAM1;
+ } else
+ max_current = EC_POWER_LIMIT_NONE;
+
+ if (argc >= 3) {
+ max_voltage = strtoi(argv[2], &e, 10);
+ if (*e)
+ return EC_ERROR_PARAM1;
+ } else
+ max_voltage = EC_POWER_LIMIT_NONE;
+
+ charge_manager_set_external_power_limit(max_current, max_voltage);
+ ccprintf("max req: %dmA %dmV\n", max_current, max_voltage);
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(chglim, command_external_power_limit,
+ "[max_current (mA)] [max_voltage (mV)]",
+ "Set max charger current / voltage",
+ NULL);
+#endif /* CONFIG_CHARGE_MANAGER_EXTERNAL_POWER_LIMIT */
diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c
index 16a9fefa7a..91bbdb15e4 100644
--- a/common/usb_pd_policy.c
+++ b/common/usb_pd_policy.c
@@ -34,7 +34,7 @@ static int rw_flash_changed = 1;
#ifdef CONFIG_USB_PD_DUAL_ROLE
/* Cap on the max voltage requested as a sink (in millivolts) */
-static unsigned max_request_mv = -1; /* no cap */
+static unsigned max_request_mv = PD_MAX_VOLTAGE_MV; /* no cap */
/**
* Find PDO index that offers the most amount of power and stays within
@@ -53,10 +53,6 @@ static int pd_find_pdo_index(int cnt, uint32_t *src_caps, int max_mv)
int cur_mv;
#endif
- /* max_mv of -1 represents max limit */
- if (max_mv == -1)
- max_mv = PD_MAX_VOLTAGE_MV;
-
/* max voltage is always limited by this boards max request */
max_mv = MIN(max_mv, PD_MAX_VOLTAGE_MV);
@@ -155,7 +151,7 @@ void pd_process_source_cap(int port, int cnt, uint32_t *src_caps)
int pdo_index;
/* Get max power info that we could request */
- pdo_index = pd_find_pdo_index(cnt, src_caps, -1);
+ pdo_index = pd_find_pdo_index(cnt, src_caps, PD_MAX_VOLTAGE_MV);
if (pdo_index < 0)
pdo_index = 0;
pd_extract_pdo_power(src_caps[pdo_index], &ma, &mv);
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index b124ad0245..b6507baa5c 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -2725,6 +2725,19 @@ void pd_request_source_voltage(int port, int mv)
task_wake(PD_PORT_TO_TASK_ID(port));
}
+
+void pd_set_external_voltage_limit(int port, int mv)
+{
+ pd_set_max_voltage(mv);
+
+ if (pd[port].task_state == PD_STATE_SNK_READY ||
+ pd[port].task_state == PD_STATE_SNK_TRANSITION) {
+ /* Set flag to send new power request in pd_task */
+ pd[port].new_power_request = 1;
+ task_wake(PD_PORT_TO_TASK_ID(port));
+ }
+}
+
#endif /* CONFIG_USB_PD_DUAL_ROLE */
static int command_pd(int argc, char **argv)
diff --git a/include/config.h b/include/config.h
index b718941a12..4685c89f59 100644
--- a/include/config.h
+++ b/include/config.h
@@ -247,6 +247,9 @@
/* Compile charge manager */
#undef CONFIG_CHARGE_MANAGER
+/* Handle the external power limit host command in charge manager */
+#undef CONFIG_CHARGE_MANAGER_EXTERNAL_POWER_LIMIT
+
/* Compile input current ramping support */
#undef CONFIG_CHARGE_RAMP
diff --git a/include/ec_commands.h b/include/ec_commands.h
index f64ffd6eac..fa820b7ebb 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -2842,14 +2842,18 @@ struct ec_params_current_limit {
} __packed;
/*
- * Set maximum external power current.
+ * Set maximum external voltage / current.
*/
-#define EC_CMD_EXT_POWER_CURRENT_LIMIT 0xa2
+#define EC_CMD_EXTERNAL_POWER_LIMIT 0xa2
-struct ec_params_ext_power_current_limit {
- uint32_t limit; /* in mA */
+/* Command v0 is used only on Spring and is obsolete + unsupported */
+struct ec_params_external_power_limit_v1 {
+ uint16_t current_lim; /* in mA, or EC_POWER_LIMIT_NONE to clear limit */
+ uint16_t voltage_lim; /* in mV, or EC_POWER_LIMIT_NONE to clear limit */
} __packed;
+#define EC_POWER_LIMIT_NONE 0xffff
+
/*****************************************************************************/
/* Smart battery pass-through */
diff --git a/include/usb_pd.h b/include/usb_pd.h
index 5b42b687e0..6ca88bb55a 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -947,6 +947,15 @@ int pd_set_power_supply_ready(int port);
void pd_request_source_voltage(int port, int mv);
/**
+ * Set a voltage limit from the PD source.
+ *
+ * If the source is currently active, it triggers a new negotiation.
+ * @param port USB-C port number
+ * @param mv limit voltage in millivolts.
+ */
+void pd_set_external_voltage_limit(int port, int mv);
+
+/**
* Set the PD input current limit.
*
* @param port USB-C port number
diff --git a/util/ectool.c b/util/ectool.c
index 8fa08b4b10..c6a40f4b34 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -43,8 +43,6 @@ static struct option long_opts[] = {
const char help_str[] =
"Commands:\n"
- " extpwrcurrentlimit\n"
- " Set the maximum external power current\n"
" autofanctrl <on>\n"
" Turn on automatic fan speed control.\n"
" backlight <enabled>\n"
@@ -93,6 +91,8 @@ const char help_str[] =
" Sets the SMI mask for EC host events\n"
" eventsetwakemask <mask>\n"
" Sets the wake mask for EC host events\n"
+ " extpwrlimit\n"
+ " Set the maximum external power limit\n"
" fanduty <percent>\n"
" Forces the fan PWM to a constant duty cycle\n"
" flasherase <offset> <size>\n"
@@ -4829,26 +4829,34 @@ int cmd_lcd_backlight(int argc, char *argv[])
}
-int cmd_ext_power_current_limit(int argc, char *argv[])
+int cmd_ext_power_limit(int argc, char *argv[])
{
- struct ec_params_ext_power_current_limit p;
- int rv;
+ /* Version 1 is used, no support for obsolete version 0 */
+ struct ec_params_external_power_limit_v1 p;
char *e;
- if (argc != 2) {
- fprintf(stderr, "Usage: %s <max_current_mA>\n", argv[0]);
+ if (argc != 3) {
+ fprintf(stderr,
+ "Usage: %s <max_current_mA> <max_voltage_mV>\n",
+ argv[0]);
return -1;
}
- p.limit = strtol(argv[1], &e, 0);
+ p.current_lim = strtol(argv[1], &e, 0);
if (e && *e) {
- fprintf(stderr, "Bad value.\n");
+ fprintf(stderr, "Bad param1.\n");
return -1;
}
- rv = ec_command(EC_CMD_EXT_POWER_CURRENT_LIMIT, 0, &p, sizeof(p),
- NULL, 0);
- return rv;
+ p.voltage_lim = strtol(argv[2], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad param2.\n");
+ return -1;
+ }
+
+ /* Send version 1 of command */
+ return ec_command(EC_CMD_EXTERNAL_POWER_LIMIT, 1, &p, sizeof(p),
+ NULL, 0);
}
@@ -6315,7 +6323,6 @@ int cmd_pd_write_log(int argc, char *argv[])
/* NULL-terminated list of commands */
const struct command commands[] = {
- {"extpwrcurrentlimit", cmd_ext_power_current_limit},
{"autofanctrl", cmd_thermal_auto_fan_ctrl},
{"backlight", cmd_lcd_backlight},
{"battery", cmd_battery},
@@ -6340,6 +6347,7 @@ const struct command commands[] = {
{"eventsetscimask", cmd_host_event_set_sci_mask},
{"eventsetsmimask", cmd_host_event_set_smi_mask},
{"eventsetwakemask", cmd_host_event_set_wake_mask},
+ {"extpwrlimit", cmd_ext_power_limit},
{"fanduty", cmd_fanduty},
{"flasherase", cmd_flash_erase},
{"flashprotect", cmd_flash_protect},