in supply/cros_usbpd-charger.c [183:305]
static int cros_usbpd_charger_get_power_info(struct port_data *port)
{
struct charger_data *charger = port->charger;
struct ec_response_usb_pd_power_info resp;
struct ec_params_usb_pd_power_info req;
int last_psy_status, last_psy_usb_type;
struct device *dev = charger->dev;
int ret;
req.port = port->port_number;
ret = cros_usbpd_charger_ec_command(charger, 0,
EC_CMD_USB_PD_POWER_INFO,
&req, sizeof(req),
&resp, sizeof(resp));
if (ret < 0) {
dev_err(dev, "Unable to query PD power info (err:0x%x)\n", ret);
return ret;
}
last_psy_status = port->psy_status;
last_psy_usb_type = port->psy_usb_type;
switch (resp.role) {
case USB_PD_PORT_POWER_DISCONNECTED:
port->psy_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
port->psy_online = 0;
break;
case USB_PD_PORT_POWER_SOURCE:
port->psy_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
port->psy_online = 0;
break;
case USB_PD_PORT_POWER_SINK:
port->psy_status = POWER_SUPPLY_STATUS_CHARGING;
port->psy_online = 1;
break;
case USB_PD_PORT_POWER_SINK_NOT_CHARGING:
port->psy_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
port->psy_online = 1;
break;
default:
dev_err(dev, "Unknown role %d\n", resp.role);
break;
}
port->psy_voltage_max_design = resp.meas.voltage_max;
port->psy_voltage_now = resp.meas.voltage_now;
port->psy_current_max = resp.meas.current_max;
port->psy_power_max = resp.max_power;
switch (resp.type) {
case USB_CHG_TYPE_BC12_SDP:
case USB_CHG_TYPE_VBUS:
port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
break;
case USB_CHG_TYPE_NONE:
/*
* For dual-role devices when we are a source, the firmware
* reports the type as NONE. Report such chargers as type
* USB_PD_DRP.
*/
if (resp.role == USB_PD_PORT_POWER_SOURCE && resp.dualrole)
port->psy_usb_type = POWER_SUPPLY_USB_TYPE_PD_DRP;
else
port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
break;
case USB_CHG_TYPE_OTHER:
case USB_CHG_TYPE_PROPRIETARY:
port->psy_usb_type = POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID;
break;
case USB_CHG_TYPE_C:
port->psy_usb_type = POWER_SUPPLY_USB_TYPE_C;
break;
case USB_CHG_TYPE_BC12_DCP:
port->psy_usb_type = POWER_SUPPLY_USB_TYPE_DCP;
break;
case USB_CHG_TYPE_BC12_CDP:
port->psy_usb_type = POWER_SUPPLY_USB_TYPE_CDP;
break;
case USB_CHG_TYPE_PD:
if (resp.dualrole)
port->psy_usb_type = POWER_SUPPLY_USB_TYPE_PD_DRP;
else
port->psy_usb_type = POWER_SUPPLY_USB_TYPE_PD;
break;
case USB_CHG_TYPE_UNKNOWN:
/*
* While the EC is trying to determine the type of charger that
* has been plugged in, it will report the charger type as
* unknown. Additionally since the power capabilities are
* unknown, report the max current and voltage as zero.
*/
port->psy_usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN;
port->psy_voltage_max_design = 0;
port->psy_current_max = 0;
break;
default:
dev_err(dev, "Port %d: default case!\n", port->port_number);
port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
}
if (cros_usbpd_charger_port_is_dedicated(port))
port->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
else
port->psy_desc.type = POWER_SUPPLY_TYPE_USB;
dev_dbg(dev,
"Port %d: type=%d vmax=%d vnow=%d cmax=%d clim=%d pmax=%d\n",
port->port_number, resp.type, resp.meas.voltage_max,
resp.meas.voltage_now, resp.meas.current_max,
resp.meas.current_lim, resp.max_power);
/*
* If power supply type or status changed, explicitly call
* power_supply_changed. This results in udev event getting generated
* and allows user mode apps to react quicker instead of waiting for
* their next poll of power supply status.
*/
if (last_psy_usb_type != port->psy_usb_type ||
last_psy_status != port->psy_status)
power_supply_changed(port->psy);
return 0;
}