mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-11 18:35:28 +00:00
charge_manager: Log charge-related change events
Add the charging events to the PD event log FIFO and add an ectool to retrieve/decode them. BUG=chrome-os-partner:33248 TEST=Manual on Samus. Run `ectool --name cros_pd pdlog`, verify that all log entries are dumped and the content matches expectation. BRANCH=Samus Change-Id: I65dd5696cc0487856ab42aff24134bcdfa1a8219 Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/238093 Commit-Queue: Vincent Palatin <vpalatin@chromium.org> Trybot-Ready: Vincent Palatin <vpalatin@chromium.org> Tested-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Alec Berg <alecaberg@chromium.org>
This commit is contained in:
committed by
ChromeOS Commit Bot
parent
4e75e20f4e
commit
bd85bc4636
@@ -88,6 +88,134 @@ static int charge_manager_is_seeded(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef TEST_CHARGE_MANAGER
|
||||
/**
|
||||
* Fills passed power_info structure with current info about the passed port.
|
||||
*/
|
||||
static void charge_manager_fill_power_info(int port,
|
||||
struct ec_response_usb_pd_power_info *r)
|
||||
{
|
||||
int sup = CHARGE_SUPPLIER_NONE;
|
||||
int i;
|
||||
|
||||
/* 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 (pd_is_connected(port) && pd_get_role(port) == PD_ROLE_SOURCE)
|
||||
r->role = USB_PD_PORT_POWER_SOURCE;
|
||||
else if (sup != CHARGE_SUPPLIER_NONE)
|
||||
r->role = USB_PD_PORT_POWER_SINK_NOT_CHARGING;
|
||||
else
|
||||
r->role = USB_PD_PORT_POWER_DISCONNECTED;
|
||||
|
||||
/* Is port partner dual-role capable */
|
||||
r->dualrole = pd_get_partner_dualrole_capable(port);
|
||||
|
||||
if (sup == CHARGE_SUPPLIER_NONE ||
|
||||
r->role == USB_PD_PORT_POWER_SOURCE) {
|
||||
r->type = USB_CHG_TYPE_NONE;
|
||||
r->meas.voltage_max = 0;
|
||||
r->meas.voltage_now = r->role == USB_PD_PORT_POWER_SOURCE ? 5000
|
||||
: 0;
|
||||
r->meas.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->meas.voltage_max = available_charge[sup][port].voltage;
|
||||
r->meas.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_SINK_NOT_CHARGING)
|
||||
r->meas.voltage_now = 5000;
|
||||
else
|
||||
r->meas.voltage_now = adc_read_channel(ADC_VBUS);
|
||||
}
|
||||
}
|
||||
#endif /* TEST_CHARGE_MANAGER */
|
||||
|
||||
#ifdef CONFIG_USB_PD_LOGGING
|
||||
/**
|
||||
* Saves a power state log entry with the current info about the passed port.
|
||||
*/
|
||||
static void charge_manager_save_log(int port)
|
||||
{
|
||||
uint16_t flags = 0;
|
||||
struct ec_response_usb_pd_power_info pinfo;
|
||||
uint16_t voltage_now;
|
||||
static uint16_t last_voltage[PD_PORT_COUNT];
|
||||
static uint16_t last_flags[PD_PORT_COUNT];
|
||||
|
||||
charge_manager_fill_power_info(port, &pinfo);
|
||||
|
||||
/* Flags are stored in the data field */
|
||||
if (port == override_port)
|
||||
flags |= CHARGE_FLAGS_OVERRIDE;
|
||||
if (port == delayed_override_port)
|
||||
flags |= CHARGE_FLAGS_DELAYED_OVERRIDE;
|
||||
flags |= pinfo.role | (pinfo.type << CHARGE_FLAGS_TYPE_SHIFT) |
|
||||
(pinfo.dualrole ? CHARGE_FLAGS_DUAL_ROLE : 0);
|
||||
|
||||
/*
|
||||
* Check for a log change, not considering timestamp. Also, ignore
|
||||
* voltage_now fluctuations of < 500mV.
|
||||
*/
|
||||
voltage_now = pinfo.meas.voltage_now;
|
||||
if (last_flags[port] == flags &&
|
||||
voltage_now < last_voltage[port] + 500 &&
|
||||
last_voltage[port] < voltage_now + 500)
|
||||
return;
|
||||
last_voltage[port] = voltage_now;
|
||||
last_flags[port] = flags;
|
||||
|
||||
pd_log_event(PD_EVENT_MCU_CHARGE,
|
||||
PD_LOG_PORT_SIZE(port, sizeof(pinfo.meas)),
|
||||
flags, &pinfo.meas);
|
||||
}
|
||||
#endif /* CONFIG_USB_PD_LOGGING */
|
||||
|
||||
/**
|
||||
* Perform cleanup operations on an override port, when switching to a
|
||||
* different port. This involves switching the port from sink to source,
|
||||
@@ -283,6 +411,12 @@ static void charge_manager_refresh(void)
|
||||
charge_supplier = new_supplier;
|
||||
charge_port = new_port;
|
||||
|
||||
#ifdef CONFIG_USB_PD_LOGGING
|
||||
/* Log possible charge state changes. */
|
||||
for (i = 0; i < PD_PORT_COUNT; ++i)
|
||||
charge_manager_save_log(i);
|
||||
#endif
|
||||
|
||||
/* New power requests must be set only after updating the globals. */
|
||||
if (updated_new_port != CHARGE_PORT_NONE)
|
||||
pd_set_new_power_request(updated_new_port);
|
||||
@@ -443,89 +577,12 @@ 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 (pd_is_connected(port) && pd_get_role(port) == PD_ROLE_SOURCE)
|
||||
r->role = USB_PD_PORT_POWER_SOURCE;
|
||||
else if (sup != CHARGE_SUPPLIER_NONE)
|
||||
r->role = USB_PD_PORT_POWER_SINK_NOT_CHARGING;
|
||||
else
|
||||
r->role = USB_PD_PORT_POWER_DISCONNECTED;
|
||||
|
||||
/* Is port partner dual-role capable */
|
||||
r->dualrole = pd_get_partner_dualrole_capable(port);
|
||||
|
||||
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_VBUS);
|
||||
}
|
||||
charge_manager_fill_power_info(port, r);
|
||||
|
||||
args->response_size = sizeof(*r);
|
||||
return EC_RES_SUCCESS;
|
||||
|
||||
171
util/ectool.c
171
util/ectool.c
@@ -6,6 +6,7 @@
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -137,6 +138,8 @@ const char help_str[] =
|
||||
" Prints saved panic info\n"
|
||||
" pause_in_s5 [on|off]\n"
|
||||
" Whether or not the AP should pause in S5 on shutdown\n"
|
||||
" pdlog\n"
|
||||
" Prints the PD event log entries\n"
|
||||
" port80flood\n"
|
||||
" Rapidly write bytes to port 80\n"
|
||||
" port80read\n"
|
||||
@@ -2965,6 +2968,65 @@ int cmd_usb_pd(int argc, char *argv[])
|
||||
return (rv < 0 ? rv : 0);
|
||||
}
|
||||
|
||||
static void print_pd_power_info(struct ec_response_usb_pd_power_info *r)
|
||||
{
|
||||
printf("Power role: ");
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
if (r->role != USB_PD_PORT_POWER_DISCONNECTED) {
|
||||
printf(" %s\n", r->dualrole ?
|
||||
"Dual-role device" : "Dedicated charger");
|
||||
}
|
||||
|
||||
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->meas.voltage_max);
|
||||
printf(" Current charging voltage: %dmV\n", r->meas.voltage_now);
|
||||
printf(" Max input current: %dmA\n", r->meas.current_max);
|
||||
printf(" Max input power: %dmW\n", r->max_power / 1000);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int cmd_usb_pd_power(int argc, char *argv[])
|
||||
{
|
||||
struct ec_params_usb_pd_power_info p;
|
||||
@@ -2986,66 +3048,8 @@ int cmd_usb_pd_power(int argc, char *argv[])
|
||||
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");
|
||||
}
|
||||
|
||||
if (r->role != USB_PD_PORT_POWER_DISCONNECTED) {
|
||||
printf(" %s\n", r->dualrole ?
|
||||
"Dual-role device" : "Dedicated charger");
|
||||
}
|
||||
|
||||
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 / 1000);
|
||||
|
||||
printf("\n");
|
||||
printf("Port %d:\n", i);
|
||||
print_pd_power_info(r);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -5232,6 +5236,52 @@ int cmd_charge_port_override(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_pd_log(int argc, char *argv[])
|
||||
{
|
||||
union {
|
||||
struct ec_response_pd_log r;
|
||||
uint32_t words[8]; /* space for the payload */
|
||||
} u;
|
||||
struct ec_response_usb_pd_power_info pinfo;
|
||||
int rv;
|
||||
|
||||
while (1) {
|
||||
rv = ec_command(EC_CMD_PD_GET_LOG_ENTRY, 0,
|
||||
NULL, 0, &u, sizeof(u));
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
if (u.r.type == PD_EVENT_NO_ENTRY) {
|
||||
printf("--- END OF LOG ---\n");
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Port: %d, %"PRIu64" ms ago : ",
|
||||
PD_LOG_PORT(u.r.size_port),
|
||||
(uint64_t)(u.r.timestamp << PD_LOG_TIMESTAMP_SHIFT)
|
||||
/ 1000);
|
||||
if (u.r.type == PD_EVENT_MCU_CHARGE) {
|
||||
if (u.r.data & CHARGE_FLAGS_OVERRIDE)
|
||||
printf("override ");
|
||||
if (u.r.data & CHARGE_FLAGS_DELAYED_OVERRIDE)
|
||||
printf("pending_override ");
|
||||
printf("\n");
|
||||
memcpy(&pinfo.meas, u.r.payload,
|
||||
sizeof(struct usb_chg_measures));
|
||||
pinfo.dualrole = !!(u.r.data & CHARGE_FLAGS_DUAL_ROLE);
|
||||
pinfo.role = u.r.data & CHARGE_FLAGS_ROLE_MASK;
|
||||
pinfo.type = (u.r.data & CHARGE_FLAGS_TYPE_MASK)
|
||||
>> CHARGE_FLAGS_TYPE_SHIFT;
|
||||
pinfo.max_power = 0;
|
||||
print_pd_power_info(&pinfo);
|
||||
} else { /* Unknown type */
|
||||
printf(" event %02x\n", u.r.type);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* NULL-terminated list of commands */
|
||||
const struct command commands[] = {
|
||||
{"extpwrcurrentlimit", cmd_ext_power_current_limit},
|
||||
@@ -5285,6 +5335,7 @@ const struct command commands[] = {
|
||||
{"panicinfo", cmd_panic_info},
|
||||
{"pause_in_s5", cmd_s5},
|
||||
{"port80read", cmd_port80_read},
|
||||
{"pdlog", cmd_pd_log},
|
||||
{"powerinfo", cmd_power_info},
|
||||
{"protoinfo", cmd_proto_info},
|
||||
{"pstoreinfo", cmd_pstore_info},
|
||||
|
||||
Reference in New Issue
Block a user