diff options
author | Alec Berg <alecaberg@chromium.org> | 2014-10-15 13:09:38 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-10-30 04:31:34 +0000 |
commit | 498abf833cad27c5014cdb2d1511f3860703ba82 (patch) | |
tree | bee810af95220991f45cca57b52eebbee9da3ef4 | |
parent | cfbb9e51b2abfd562af865c0b11362d48d799cfd (diff) | |
download | chrome-ec-498abf833cad27c5014cdb2d1511f3860703ba82.tar.gz |
samus_pd: add host command to get type-c port power info
Get type-c port power info including power role, charger type,
and charging info. Also added host command to get number of type-c
ports.
Also adds new charging suppliers for pericom identified chargers
including DCP, CDP, SDP, proprietary, and other chargers. Priority
of these for charging is set in samus board file.
BUG=chrome-os-partner:32650
BRANCH=samus
TEST=run 'ectool --name=cros_pd usbpdpower' and verify correct
status with minimuffin, zinger, and type-C to type-A adapter.
Change-Id: I1dabbe7de4185a23df5684a5ea9a2d944f1f6ff5
Signed-off-by: Alec Berg <alecaberg@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/223523
Tested-by: Shawn Nematbakhsh <shawnn@chromium.org>
Reviewed-by: Shawn Nematbakhsh <shawnn@chromium.org>
Reviewed-by: Patrick Georgi <pgeorgi@chromium.org>
Reviewed-by: Todd Broch <tbroch@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r-- | board/samus_pd/board.c | 50 | ||||
-rw-r--r-- | board/samus_pd/board.h | 6 | ||||
-rw-r--r-- | common/charge_manager.c | 97 | ||||
-rw-r--r-- | common/usb_pd_protocol.c | 12 | ||||
-rw-r--r-- | driver/pi3usb9281.h | 2 | ||||
-rw-r--r-- | include/ec_commands.h | 39 | ||||
-rw-r--r-- | include/usb.h | 2 | ||||
-rw-r--r-- | util/ectool.c | 83 |
8 files changed, 281 insertions, 10 deletions
diff --git a/board/samus_pd/board.c b/board/samus_pd/board.c index d57ce4704f..736b28360e 100644 --- a/board/samus_pd/board.c +++ b/board/samus_pd/board.c @@ -48,7 +48,11 @@ BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); const int supplier_priority[] = { [CHARGE_SUPPLIER_PD] = 0, [CHARGE_SUPPLIER_TYPEC] = 1, - [CHARGE_SUPPLIER_BC12] = 1, + [CHARGE_SUPPLIER_PROPRIETARY] = 1, + [CHARGE_SUPPLIER_BC12_DCP] = 1, + [CHARGE_SUPPLIER_BC12_CDP] = 2, + [CHARGE_SUPPLIER_BC12_SDP] = 3, + [CHARGE_SUPPLIER_OTHER] = 3 }; BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT); @@ -72,23 +76,40 @@ static void board_usb_charger_update(int port) { int device_type, charger_status; struct charge_port_info charge; + int type; charge.voltage = USB_BC12_CHARGE_VOLTAGE; /* Read interrupt register to clear*/ pi3usb9281_get_interrupts(port); + + /* Set device type */ device_type = pi3usb9281_get_device_type(port); charger_status = pi3usb9281_get_charger_status(port); + if (PI3USB9281_CHG_STATUS_ANY(charger_status)) + type = CHARGE_SUPPLIER_PROPRIETARY; + else if (device_type & PI3USB9281_TYPE_CDP) + type = CHARGE_SUPPLIER_BC12_CDP; + else if (device_type & PI3USB9281_TYPE_DCP) + type = CHARGE_SUPPLIER_BC12_DCP; + else if (device_type & PI3USB9281_TYPE_SDP) + type = CHARGE_SUPPLIER_BC12_SDP; + else + type = CHARGE_SUPPLIER_OTHER; /* Attachment: decode + update available charge */ - if (device_type || (charger_status & 0x1f)) + if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) { charge.current = pi3usb9281_get_ilim(device_type, charger_status); - /* Detachment: update available charge to 0 */ - else + charge_manager_update(type, port, &charge); + } else { /* Detachment: update available charge to 0 */ charge.current = 0; - - charge_manager_update(CHARGE_SUPPLIER_BC12, port, &charge); - + charge_manager_update(CHARGE_SUPPLIER_PROPRIETARY, port, + &charge); + charge_manager_update(CHARGE_SUPPLIER_BC12_CDP, port, &charge); + charge_manager_update(CHARGE_SUPPLIER_BC12_DCP, port, &charge); + charge_manager_update(CHARGE_SUPPLIER_BC12_SDP, port, &charge); + charge_manager_update(CHARGE_SUPPLIER_OTHER, port, &charge); + } } /* Pericom USB deferred tasks -- called after USB device insert / removal */ @@ -176,9 +197,10 @@ void board_config_pre_init(void) /* Initialize board. */ static void board_init(void) { - int pd_enable; + int pd_enable, i; int slp_s5 = gpio_get_level(GPIO_PCH_SLP_S5_L); int slp_s3 = gpio_get_level(GPIO_PCH_SLP_S3_L); + struct charge_port_info charge; /* * Enable CC lines after all GPIO have been initialized. Note, it is @@ -191,6 +213,18 @@ static void board_init(void) gpio_enable_interrupt(GPIO_USB_C0_VBUS_WAKE); gpio_enable_interrupt(GPIO_USB_C1_VBUS_WAKE); + /* Initialize all pericom charge suppliers to 0 */ + charge.voltage = USB_BC12_CHARGE_VOLTAGE; + charge.current = 0; + for (i = 0; i < PD_PORT_COUNT; i++) { + charge_manager_update(CHARGE_SUPPLIER_PROPRIETARY, i, + &charge); + charge_manager_update(CHARGE_SUPPLIER_BC12_CDP, i, &charge); + charge_manager_update(CHARGE_SUPPLIER_BC12_DCP, i, &charge); + charge_manager_update(CHARGE_SUPPLIER_BC12_SDP, i, &charge); + charge_manager_update(CHARGE_SUPPLIER_OTHER, i, &charge); + } + /* Enable pericom BC1.2 interrupts. */ gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); diff --git a/board/samus_pd/board.h b/board/samus_pd/board.h index 82e1993fa8..62805b6c07 100644 --- a/board/samus_pd/board.h +++ b/board/samus_pd/board.h @@ -90,7 +90,11 @@ enum pwm_channel { enum charge_supplier { CHARGE_SUPPLIER_PD, CHARGE_SUPPLIER_TYPEC, - CHARGE_SUPPLIER_BC12, + CHARGE_SUPPLIER_BC12_DCP, + CHARGE_SUPPLIER_BC12_CDP, + CHARGE_SUPPLIER_BC12_SDP, + CHARGE_SUPPLIER_PROPRIETARY, + CHARGE_SUPPLIER_OTHER, CHARGE_SUPPLIER_COUNT }; diff --git a/common/charge_manager.c b/common/charge_manager.c index af648f2cfd..01552a7144 100644 --- a/common/charge_manager.c +++ b/common/charge_manager.c @@ -6,6 +6,8 @@ #include "charge_manager.h" #include "console.h" #include "hooks.h" +#include "host_command.h" +#include "usb_pd.h" #include "usb_pd_config.h" #include "util.h" @@ -18,6 +20,7 @@ static struct charge_port_info available_charge[CHARGE_SUPPLIER_COUNT] /* Store current state of port enable / charge current. */ static int charge_port = CHARGE_PORT_NONE; static int charge_current = CHARGE_CURRENT_UNINITIALIZED; +static int charge_supplier = CHARGE_SUPPLIER_NONE; /** * Initialize available charge. Run before board init, so board init can @@ -113,6 +116,7 @@ static void charge_manager_refresh(void) board_set_active_charge_port(new_port); charge_current = new_charge_current; + charge_supplier = new_supplier; charge_port = new_port; } } @@ -154,3 +158,96 @@ void charge_manager_update(int supplier, hook_call_deferred(charge_manager_refresh, 0); } } + +static int hc_pd_power_info(struct host_cmd_handler_args *args) +{ + const struct ec_params_usb_pd_power_info *p = args->params; + struct ec_response_usb_pd_power_info *r = args->response; + int port = p->port; + int sup = CHARGE_SUPPLIER_NONE; + int i; + + /* If host is asking for the charging port, set port appropriately */ + if (port == PD_POWER_CHARGING_PORT) + port = charge_port; + + /* Determine supplier information to show */ + if (port == charge_port) { + sup = charge_supplier; + } else { + /* Find highest priority supplier */ + for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i) { + if (available_charge[i][port].current > 0 && + available_charge[i][port].voltage > 0 && + (sup == CHARGE_SUPPLIER_NONE || + supplier_priority[i] < + supplier_priority[sup] || + (supplier_priority[i] == + supplier_priority[sup] && + POWER(available_charge[i][port]) > + POWER(available_charge[sup] + [port])))) + sup = i; + } + } + + /* Fill in power role */ + if (charge_port == port) + r->role = USB_PD_PORT_POWER_SINK; + else if (sup != CHARGE_SUPPLIER_NONE) + r->role = USB_PD_PORT_POWER_SINK_NOT_CHARGING; + else if (pd_is_connected(port) && pd_get_role(port) == PD_ROLE_SOURCE) + r->role = USB_PD_PORT_POWER_SOURCE; + else + r->role = USB_PD_PORT_POWER_DISCONNECTED; + + if (sup == CHARGE_SUPPLIER_NONE) { + r->type = USB_CHG_TYPE_NONE; + r->voltage_max = 0; + r->voltage_now = 0; + r->current_max = 0; + r->max_power = 0; + } else { + switch (sup) { + case CHARGE_SUPPLIER_PD: + r->type = USB_CHG_TYPE_PD; + break; + case CHARGE_SUPPLIER_TYPEC: + r->type = USB_CHG_TYPE_C; + break; + case CHARGE_SUPPLIER_PROPRIETARY: + r->type = USB_CHG_TYPE_PROPRIETARY; + break; + case CHARGE_SUPPLIER_BC12_DCP: + r->type = USB_CHG_TYPE_BC12_DCP; + break; + case CHARGE_SUPPLIER_BC12_CDP: + r->type = USB_CHG_TYPE_BC12_CDP; + break; + case CHARGE_SUPPLIER_BC12_SDP: + r->type = USB_CHG_TYPE_BC12_SDP; + break; + default: + r->type = USB_CHG_TYPE_OTHER; + } + r->voltage_max = available_charge[sup][port].voltage; + r->current_max = available_charge[sup][port].current; + r->max_power = POWER(available_charge[sup][port]); + + /* + * If we are sourcing power, or sinking but not charging, then + * VBUS must be 5V. If we are charging, then read VBUS ADC. + */ + if (r->role == USB_PD_PORT_POWER_SOURCE || + r->role == USB_PD_PORT_POWER_SINK_NOT_CHARGING) + r->voltage_now = 5000; + else + r->voltage_now = adc_read_channel(ADC_BOOSTIN); + } + + args->response_size = sizeof(*r); + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_POWER_INFO, + hc_pd_power_info, + EC_VER_MASK(0)); diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 24cdf8e264..34ef385621 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -1985,6 +1985,18 @@ DECLARE_CONSOLE_COMMAND(typec, command_typec, NULL); #endif /* CONFIG_USBC_SS_MUX */ +static int hc_pd_ports(struct host_cmd_handler_args *args) +{ + struct ec_response_usb_pd_ports *r = args->response; + r->num_ports = PD_PORT_COUNT; + + args->response_size = sizeof(*r); + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_PORTS, + hc_pd_ports, + EC_VER_MASK(0)); + static const enum pd_dual_role_states dual_role_map[USB_PD_CTRL_ROLE_COUNT] = { [USB_PD_CTRL_ROLE_TOGGLE_ON] = PD_DRP_TOGGLE_ON, [USB_PD_CTRL_ROLE_TOGGLE_OFF] = PD_DRP_TOGGLE_OFF, diff --git a/driver/pi3usb9281.h b/driver/pi3usb9281.h index d26295b846..392c02ae52 100644 --- a/driver/pi3usb9281.h +++ b/driver/pi3usb9281.h @@ -46,6 +46,8 @@ #define PI3USB9281_CHG_APPLE_1A (1 << 2) #define PI3USB9281_CHG_APPLE_2A (1 << 3) #define PI3USB9281_CHG_APPLE_2_4A (1 << 4) +/* Check if charge status has any connection */ +#define PI3USB9281_CHG_STATUS_ANY(x) (((x) & 0x1f) > 1) /* Read PI3USB9281 register. */ uint8_t pi3usb9281_read(uint8_t chip_idx, uint8_t reg); diff --git a/include/ec_commands.h b/include/ec_commands.h index 52a0996b91..07bf6a5a43 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -2734,6 +2734,45 @@ struct ec_response_usb_pd_control { uint8_t state; } __packed; +#define EC_CMD_USB_PD_PORTS 0x102 + +struct ec_response_usb_pd_ports { + uint8_t num_ports; +} __packed; + +#define EC_CMD_USB_PD_POWER_INFO 0x103 + +#define PD_POWER_CHARGING_PORT 0xff +struct ec_params_usb_pd_power_info { + uint8_t port; +} __packed; + +enum usb_chg_type { + USB_CHG_TYPE_NONE, + USB_CHG_TYPE_PD, + USB_CHG_TYPE_C, + USB_CHG_TYPE_PROPRIETARY, + USB_CHG_TYPE_BC12_DCP, + USB_CHG_TYPE_BC12_CDP, + USB_CHG_TYPE_BC12_SDP, + USB_CHG_TYPE_OTHER +}; +enum usb_power_roles { + USB_PD_PORT_POWER_DISCONNECTED, + USB_PD_PORT_POWER_SOURCE, + USB_PD_PORT_POWER_SINK, + USB_PD_PORT_POWER_SINK_NOT_CHARGING, +}; + +struct ec_response_usb_pd_power_info { + uint8_t role; + uint8_t type; + uint16_t voltage_max; + uint16_t voltage_now; + uint16_t current_max; + uint32_t max_power; +} __packed; + /* Write USB-PD device FW */ #define EC_CMD_USB_PD_FW_UPDATE 0x110 diff --git a/include/usb.h b/include/usb.h index bf2bb8fd6a..df6426fc64 100644 --- a/include/usb.h +++ b/include/usb.h @@ -190,7 +190,7 @@ struct usb_endpoint_descriptor { #define USB_REQ_SET_INTERFACE 0x0B #define USB_REQ_SYNCH_FRAME 0x0C -#define USB_BC12_CHARGE_VOLTAGE 5000 /* mA */ +#define USB_BC12_CHARGE_VOLTAGE 5000 /* mV */ /* Helpers for descriptors */ diff --git a/util/ectool.c b/util/ectool.c index 2823ede20d..e9f0195077 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -191,6 +191,8 @@ const char help_str[] = " usbpd <port> <auto | " "[toggle|toggle-off|sink|source] [none|usb|dp|dock]>\n" " Control USB PD/type-C\n" + " usbpdpower\n" + " Get USB PD power information\n" " version\n" " Prints EC version\n" " wireless <flags> [<mask> [<suspend_flags> <suspend_mask>]]\n" @@ -2880,6 +2882,86 @@ int cmd_usb_pd(int argc, char *argv[]) return (rv < 0 ? rv : 0); } +int cmd_usb_pd_power(int argc, char *argv[]) +{ + struct ec_params_usb_pd_power_info p; + struct ec_response_usb_pd_power_info *r = + (struct ec_response_usb_pd_power_info *)ec_inbuf; + int num_ports, i, rv; + + rv = ec_command(EC_CMD_USB_PD_PORTS, 0, NULL, 0, + ec_inbuf, ec_max_insize); + if (rv < 0) + return rv; + num_ports = ((struct ec_response_usb_pd_ports *)r)->num_ports; + + for (i = 0; i < num_ports; i++) { + p.port = i; + rv = ec_command(EC_CMD_USB_PD_POWER_INFO, 0, + &p, sizeof(p), + ec_inbuf, ec_max_insize); + if (rv < 0) + return rv; + + printf("Port %d:\n Power role: ", i); + switch (r->role) { + case USB_PD_PORT_POWER_DISCONNECTED: + printf("Disconnected\n"); + break; + case USB_PD_PORT_POWER_SOURCE: + printf("Source\n"); + break; + case USB_PD_PORT_POWER_SINK: + printf("Sink\n"); + break; + case USB_PD_PORT_POWER_SINK_NOT_CHARGING: + printf("Sink (not charging)\n"); + break; + default: + printf("Unknown\n"); + } + + printf(" Charger type: "); + switch (r->type) { + case USB_CHG_TYPE_PD: + printf("PD\n"); + break; + case USB_CHG_TYPE_C: + printf("Type-c\n"); + break; + case USB_CHG_TYPE_PROPRIETARY: + printf("Proprietary\n"); + break; + case USB_CHG_TYPE_BC12_DCP: + printf("BC1.2 DCP\n"); + break; + case USB_CHG_TYPE_BC12_CDP: + printf("BC1.2 CDP\n"); + break; + case USB_CHG_TYPE_BC12_SDP: + printf("BC1.2 SDP\n"); + break; + case USB_CHG_TYPE_OTHER: + printf("Other\n"); + break; + default: + printf("None\n"); + } + + printf(" Max charging voltage: %dmV\n", + r->voltage_max); + printf(" Current charging voltage: %dmV\n", + r->voltage_now); + printf(" Max input current: %dmA\n", + r->current_max); + printf(" Max input power: %dmW\n", + r->max_power); + + printf("\n"); + } + + return 0; +} int cmd_kbpress(int argc, char *argv[]) { @@ -5096,6 +5178,7 @@ const struct command commands[] = { {"usbchargemode", cmd_usb_charge_set_mode}, {"usbmux", cmd_usb_mux}, {"usbpd", cmd_usb_pd}, + {"usbpdpower", cmd_usb_pd_power}, {"version", cmd_version}, {"wireless", cmd_wireless}, {NULL, NULL} |