static int cros_usbpd_charger_get_power_info()

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;
}