From f416f6095a5303befe022911eea05e96da3fce57 Mon Sep 17 00:00:00 2001 From: Zhuohao Lee Date: Sat, 19 Jan 2019 17:03:10 +0800 Subject: usb_port_power_smart: turn on/off charging mode during system suspend This patch adds a feature to allow the userspace program turns on/off the usb type-a charging mode during system suspend. BUG=b:121438672 BRANCH=firmware-rammus-11275 TEST=make -j buildall ectool usbchargemode 0 0x2 0, CDP works in S0 and S0ix ectool usbchargemode 0 0x2 1, CDP works in S0 but not in S0ix Change-Id: Icb8ab1b3f1beb671fbd02f441bf40284ba74e097 Signed-off-by: Zhuohao Lee Reviewed-on: https://chromium-review.googlesource.com/1424040 Reviewed-by: Jett Rink (cherry picked from commit 9670696203029efa87b0871073e149b7ba8619c2) Reviewed-on: https://chromium-review.googlesource.com/c/1460291 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1561470 Reviewed-by: Diana Z Commit-Queue: Marco Chen Tested-by: Marco Chen --- common/acpi.c | 3 +- common/usb_port_power_dumb.c | 6 ++-- common/usb_port_power_smart.c | 69 ++++++++++++++++++++++++++++++++----------- include/ec_commands.h | 3 +- include/usb_charge.h | 15 ++++++++-- util/ectool.c | 17 +++++++++-- 6 files changed, 86 insertions(+), 27 deletions(-) diff --git a/common/acpi.c b/common/acpi.c index 924a180cb8..e33ac17bb0 100644 --- a/common/acpi.c +++ b/common/acpi.c @@ -362,7 +362,8 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr) if (mode_field & 1) mode = USB_CHARGE_MODE_ENABLED; - if (usb_charge_set_mode(i, mode)) { + if (usb_charge_set_mode(i, mode, + USB_ALLOW_SUSPEND_CHARGE)) { CPRINTS("ERROR: could not set charge " "mode of USB port p%d to %d", i, mode); diff --git a/common/usb_port_power_dumb.c b/common/usb_port_power_dumb.c index a37fb84c3f..ea6904c97f 100644 --- a/common/usb_port_power_dumb.c +++ b/common/usb_port_power_dumb.c @@ -47,7 +47,8 @@ static void usb_port_all_ports_off(void) /*****************************************************************************/ /* Host commands */ -int usb_charge_set_mode(int port_id, enum usb_charge_mode mode) +int usb_charge_set_mode(int port_id, enum usb_charge_mode mode, + enum usb_suspend_charge inhibit_charge) { CPRINTS("USB port p%d %d", port_id, mode); @@ -72,7 +73,8 @@ static int usb_port_command_set_mode(struct host_cmd_handler_args *args) { const struct ec_params_usb_charge_set_mode *p = args->params; - if (usb_charge_set_mode(p->usb_port_id, p->mode) != EC_SUCCESS) + if (usb_charge_set_mode(p->usb_port_id, p->mode, + p->inhibit_charge) != EC_SUCCESS) return EC_RES_ERROR; return EC_RES_SUCCESS; diff --git a/common/usb_port_power_smart.c b/common/usb_port_power_smart.c index 0d1b18d820..8da655f331 100644 --- a/common/usb_port_power_smart.c +++ b/common/usb_port_power_smart.c @@ -25,7 +25,10 @@ #define CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE USB_CHARGE_MODE_SDP2 #endif -static uint8_t charge_mode[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT]; +static struct { + uint8_t mode:7; + uint8_t inhibit_charging_in_suspend:1; +} charge_mode[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT]; /* GPIOs to enable/disable USB ports. Board specific. */ extern const int usb_port_enable[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT]; @@ -91,12 +94,13 @@ static void usb_charge_all_ports_ctrl(enum usb_charge_mode mode) int i; for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++) - usb_charge_set_mode(i, mode); + usb_charge_set_mode(i, mode, USB_ALLOW_SUSPEND_CHARGE); } -int usb_charge_set_mode(int port_id, enum usb_charge_mode mode) +int usb_charge_set_mode(int port_id, enum usb_charge_mode mode, + enum usb_suspend_charge inhibit_charge) { - CPRINTS("USB charge p%d m%d", port_id, mode); + CPRINTS("USB charge p%d m%d i%d", port_id, mode, inhibit_charge); if (port_id >= CONFIG_USB_PORT_POWER_SMART_PORT_COUNT) return EC_ERROR_INVAL; @@ -125,7 +129,8 @@ int usb_charge_set_mode(int port_id, enum usb_charge_mode mode) return EC_ERROR_UNKNOWN; } - charge_mode[port_id] = mode; + charge_mode[port_id].mode = mode; + charge_mode[port_id].inhibit_charging_in_suspend = inhibit_charge; return EC_SUCCESS; } @@ -136,17 +141,18 @@ int usb_charge_set_mode(int port_id, enum usb_charge_mode mode) static int command_set_mode(int argc, char **argv) { int port_id = -1; - int mode = -1; + int mode = -1, inhibit_charge = 0; char *e; int i; if (argc == 1) { for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++) - ccprintf("Port %d: %d\n", i, charge_mode[i]); + ccprintf("Port %d: %d,%d\n", i, charge_mode[i].mode, + charge_mode[i].inhibit_charging_in_suspend); return EC_SUCCESS; } - if (argc != 3) + if (argc != 3 && argc != 4) return EC_ERROR_PARAM_COUNT; port_id = strtoi(argv[1], &e, 0); @@ -158,17 +164,26 @@ static int command_set_mode(int argc, char **argv) if (*e || mode < 0 || mode >= USB_CHARGE_MODE_COUNT) return EC_ERROR_PARAM2; - return usb_charge_set_mode(port_id, mode); + if (argc == 4) { + inhibit_charge = strtoi(argv[3], &e, 0); + if (*e || (inhibit_charge != 0 && inhibit_charge != 1)) + return EC_ERROR_PARAM3; + } + + return usb_charge_set_mode(port_id, mode, inhibit_charge); } DECLARE_CONSOLE_COMMAND(usbchargemode, command_set_mode, - "[ <0 | 1 | 2 | 3>]", + "[ <0 | 1 | 2 | 3> [<0 | 1>]]", "Set USB charge mode"); /* * Modes: - * 0=Disabled. - * 1=Standard downstream port. - * 2=Charging downstream port, BC 1.2. - * 3=Dedicated charging port, BC 1.2. + * 0 = Disabled. + * 1 = Standard downstream port. + * 2 = Charging downstream port, BC 1.2. + * 3 = Dedicated charging port, BC 1.2. + * Inhibit Charge: + * 0 = Enable charging during system suspend + * 1 = Disable charging during system suspend */ /*****************************************************************************/ @@ -178,7 +193,8 @@ static int usb_charge_command_set_mode(struct host_cmd_handler_args *args) { const struct ec_params_usb_charge_set_mode *p = args->params; - if (usb_charge_set_mode(p->usb_port_id, p->mode) != EC_SUCCESS) + if (usb_charge_set_mode(p->usb_port_id, p->mode, + p->inhibit_charge) != EC_SUCCESS) return EC_RES_ERROR; return EC_RES_SUCCESS; @@ -212,17 +228,36 @@ static void usb_charge_init(void) } for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++) - usb_charge_set_mode(i, prev[i]); + usb_charge_set_mode(i, prev[i], USB_ALLOW_SUSPEND_CHARGE); } DECLARE_HOOK(HOOK_INIT, usb_charge_init, HOOK_PRIO_DEFAULT); static void usb_charge_resume(void) { + int i; + /* Turn on USB ports on as we go into S0 from S3 or S5. */ - usb_charge_all_ports_ctrl(CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE); + for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++) + usb_charge_set_mode(i, + CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE, + charge_mode[i].inhibit_charging_in_suspend); } DECLARE_HOOK(HOOK_CHIPSET_RESUME, usb_charge_resume, HOOK_PRIO_DEFAULT); +static void usb_charge_suspend(void) +{ + int i; + + /* + * Inhibit charging during suspend if the inhibit_charging_in_suspend + * is set to 1. + */ + for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++) + if (charge_mode[i].inhibit_charging_in_suspend) + usb_charge_set_enabled(i, 0 /* disabled */); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, usb_charge_suspend, HOOK_PRIO_DEFAULT); + static void usb_charge_shutdown(void) { /* Turn on USB ports off as we go back to S5. */ diff --git a/include/ec_commands.h b/include/ec_commands.h index 2becaecdce..ac7e3ba022 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -2848,7 +2848,8 @@ struct ec_params_config_power_button { struct ec_params_usb_charge_set_mode { uint8_t usb_port_id; - uint8_t mode; + uint8_t mode:7; + uint8_t inhibit_charge:1; } __ec_align1; /*****************************************************************************/ diff --git a/include/usb_charge.h b/include/usb_charge.h index 1de3372434..6dfb8bd98b 100644 --- a/include/usb_charge.h +++ b/include/usb_charge.h @@ -30,14 +30,23 @@ enum usb_charge_mode { USB_CHARGE_MODE_COUNT }; +enum usb_suspend_charge { + /* Enable charging in suspend */ + USB_ALLOW_SUSPEND_CHARGE, + /* Disable charging in suspend */ + USB_DISALLOW_SUSPEND_CHARGE +}; + /** * Set USB charge mode for the port. * - * @param usb_port_id Port to set. - * @param mode New mode for port. + * @param usb_port_id Port to set. + * @param mode New mode for port. + * @param inhibit_charge Inhibit charging during system suspend. * @return EC_SUCCESS, or non-zero if error. */ -int usb_charge_set_mode(int usb_port_id, enum usb_charge_mode mode); +int usb_charge_set_mode(int usb_port_id, enum usb_charge_mode mode, + enum usb_suspend_charge inhibit_charge); #ifdef HAS_TASK_USB_CHG_P0 #define USB_CHG_EVENT_BC12 TASK_EVENT_CUSTOM(1) diff --git a/util/ectool.c b/util/ectool.c index 64bbf86c67..15d04424af 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -4922,9 +4922,10 @@ int cmd_usb_charge_set_mode(int argc, char *argv[]) char *e; int rv; - if (argc != 3) { + if (argc != 3 && argc != 4) { fprintf(stderr, - "Usage: %s \n", argv[0]); + "Usage: %s \n", + argv[0]); return -1; } p.usb_port_id = strtol(argv[1], &e, 0); @@ -4937,8 +4938,18 @@ int cmd_usb_charge_set_mode(int argc, char *argv[]) fprintf(stderr, "Bad mode ID.\n"); return -1; } + p.inhibit_charge = 0; + if (argc == 4) { + p.inhibit_charge = strtol(argv[3], &e, 0); + if ((e && *e) || (p.inhibit_charge != 0 && + p.inhibit_charge != 1)) { + fprintf(stderr, "Bad value\n"); + return -1; + } + } - printf("Setting port %d to mode %d...\n", p.usb_port_id, p.mode); + printf("Setting port %d to mode %d inhibit_charge %d...\n", + p.usb_port_id, p.mode, p.inhibit_charge); rv = ec_command(EC_CMD_USB_CHARGE_SET_MODE, 0, &p, sizeof(p), NULL, 0); -- cgit v1.2.1