Exemple #1
0
/**
 * Perform cleanup operations on an override port, when switching to a
 * different port. This involves switching the port from sink to source,
 * if applicable.
 */
static void charge_manager_cleanup_override_port(int port)
{
	if (port < 0 || port >= CONFIG_USB_PD_PORT_COUNT)
		return;

	if (dualrole_capability[port] == CAP_DUALROLE &&
	    pd_get_role(port) == PD_ROLE_SINK)
		pd_request_power_swap(port);
}
Exemple #2
0
/**
 * Attempt to switch to power source on port if applicable.
 */
static void charge_manager_switch_to_source(int port)
{
	if (port < 0 || port >= CONFIG_USB_PD_PORT_COUNT)
		return;

	/* If connected to dual-role device, then ask for a swap */
	if (dualrole_capability[port] == CAP_DUALROLE &&
	    pd_get_role(port) == PD_ROLE_SINK)
		pd_request_power_swap(port);
}
Exemple #3
0
/**
 * Select an 'override port', a port which is always the preferred charge port.
 * Returns EC_SUCCESS on success, ec_error_list status on failure.
 *
 * @param port			Charge port to select as override, or
 *				OVERRIDE_OFF to select no override port,
 *				or OVERRIDE_DONT_CHARGE to specifc that no
 *				charge port should be selected.
 */
int charge_manager_set_override(int port)
{
	int retval = EC_SUCCESS;

	ASSERT(port >= OVERRIDE_DONT_CHARGE && port < CONFIG_USB_PD_PORT_COUNT);

	CPRINTS("Charge Override: %d", port);

	/* Supersede any pending delayed overrides. */
	if (delayed_override_port != OVERRIDE_OFF) {
		if (delayed_override_port != port)
			charge_manager_cleanup_override_port(
				delayed_override_port);

		delayed_override_port = OVERRIDE_OFF;
		hook_call_deferred(
			charge_override_timeout, -1);
	}

	/* Set the override port if it's a sink. */
	if (port < 0 || pd_get_role(port) == PD_ROLE_SINK) {
		if (override_port != port) {
			charge_manager_cleanup_override_port(override_port);
			override_port = port;
			if (charge_manager_is_seeded())
				hook_call_deferred(charge_manager_refresh, 0);
		}
	}
	/*
	 * If the attached device is capable of being a sink, request a
	 * power swap and set the delayed override for swap completion.
	 */
	else if (pd_get_role(port) != PD_ROLE_SINK &&
		 dualrole_capability[port] == CAP_DUALROLE) {
		delayed_override_deadline.val = get_time().val +
						POWER_SWAP_TIMEOUT;
		delayed_override_port = port;
		hook_call_deferred(
			charge_override_timeout,
			POWER_SWAP_TIMEOUT);
		pd_request_power_swap(port);
	/* Can't charge from requested port -- return error. */
	} else
		retval = EC_ERROR_INVAL;

	return retval;
}
Exemple #4
0
void pd_check_pr_role(int port, int pr_role, int flags)
{
	/*
	 * If partner is dual-role power and dualrole toggling is on, consider
	 * if a power swap is necessary.
	 */
	if ((flags & PD_FLAGS_PARTNER_DR_POWER) &&
	    pd_get_dual_role() == PD_DRP_TOGGLE_ON) {
		/*
		 * If we are source and partner is externally powered,
		 * swap to become a sink.
		 */
		if ((flags & PD_FLAGS_PARTNER_EXTPOWER) &&
		    pr_role == PD_ROLE_SOURCE)
			pd_request_power_swap(port);
	}
}
Exemple #5
0
/**
 * Select an 'override port', a port which is always the preferred charge port.
 * Returns EC_SUCCESS on success, ec_error_list status on failure.
 *
 * @param port			Charge port to select as override, or
 *				OVERRIDE_OFF to select no override port,
 *				or OVERRIDE_DONT_CHARGE to specifc that no
 *				charge port should be selected.
 */
int charge_manager_set_override(int port)
{
	int retval = EC_SUCCESS;

	ASSERT(port >= OVERRIDE_DONT_CHARGE && port < CONFIG_USB_PD_PORT_COUNT);

	CPRINTS("Charge Override: %d", port);

	/*
	 * If attempting to change the override port, then return
	 * error. Since we may be in the middle of a power swap on
	 * the original override port, it's too complicated to
	 * guarantee that the original override port is switched back
	 * to source.
	 */
	if (delayed_override_port != OVERRIDE_OFF)
		return EC_ERROR_BUSY;

	/* Set the override port if it's a sink. */
	if (port < 0 || pd_get_role(port) == PD_ROLE_SINK) {
		if (override_port != port) {
			override_port = port;
			if (charge_manager_is_seeded())
				hook_call_deferred(charge_manager_refresh, 0);
		}
	}
	/*
	 * If the attached device is capable of being a sink, request a
	 * power swap and set the delayed override for swap completion.
	 */
	else if (pd_get_role(port) != PD_ROLE_SINK &&
		 dualrole_capability[port] == CAP_DUALROLE) {
		delayed_override_deadline.val = get_time().val +
						POWER_SWAP_TIMEOUT;
		delayed_override_port = port;
		hook_call_deferred(
			charge_override_timeout,
			POWER_SWAP_TIMEOUT);
		pd_request_power_swap(port);
	/* Can't charge from requested port -- return error. */
	} else
		retval = EC_ERROR_INVAL;

	return retval;
}