Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f83e3150 authored by Hemant Kumar's avatar Hemant Kumar Committed by Jack Pham
Browse files

usb: pd: Support revision 3.0 in sink-only mode



commit 07040df2790e ("usb: pd: policy_engine: Handle spec revision
properly") changed the spec revision handling to be 2.0 mode unless
a programmable power supply is seen. Extend this via a module
parameter to allow PD 3.0 in sink-only mode regardless of PPS when
a 3.0 source is connected.

Since the revision of the source is first encountered when
receiving the Source Capabilities message, this information is
lost by the time pd_eval_src_caps() is called. So bring back the
handling in phy_msg_received() removed in commit 07040df2790e ("usb:
pd: policy_engine: Handle spec revision properly").

Change-Id: I0485224aeadcffbfaecd0c7942c6dbcd9ddd3813
Signed-off-by: default avatarHemant Kumar <hemantk@codeaurora.org>
parent b3b1b701
Loading
Loading
Loading
Loading
+27 −7
Original line number Diff line number Diff line
@@ -38,6 +38,10 @@ static bool disable_usb_pd;
module_param(disable_usb_pd, bool, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(disable_usb_pd, "Disable USB PD for USB3.1 compliance testing");

static bool rev3_sink_only;
module_param(rev3_sink_only, bool, 0644);
MODULE_PARM_DESC(rev3_sink_only, "Enable power delivery rev3.0 sink only mode");

enum usbpd_state {
	PE_UNKNOWN,
	PE_ERROR_RECOVERY,
@@ -670,7 +674,7 @@ static int pd_select_pdo(struct usbpd *pd, int pdo_pos, int uv, int ua)

static int pd_eval_src_caps(struct usbpd *pd)
{
	int obj_cnt;
	int i;
	union power_supply_propval val;
	u32 first_pdo = pd->received_pdos[0];

@@ -687,11 +691,20 @@ static int pd_eval_src_caps(struct usbpd *pd)
	power_supply_set_property(pd->usb_psy,
			POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED, &val);

	for (obj_cnt = 1; obj_cnt < PD_MAX_DATA_OBJ; obj_cnt++) {
		if ((PD_SRC_PDO_TYPE(pd->received_pdos[obj_cnt]) ==
	if (pd->spec_rev == USBPD_REV_30 && !rev3_sink_only) {
		bool pps_found = false;

		/* downgrade to 2.0 if no PPS */
		for (i = 1; i < PD_MAX_DATA_OBJ; i++) {
			if ((PD_SRC_PDO_TYPE(pd->received_pdos[i]) ==
					PD_SRC_PDO_TYPE_AUGMENTED) &&
				!PD_APDO_PPS(pd->received_pdos[obj_cnt]))
			pd->spec_rev = USBPD_REV_30;
				!PD_APDO_PPS(pd->received_pdos[i])) {
				pps_found = true;
				break;
			}
		}
		if (!pps_found)
			pd->spec_rev = USBPD_REV_20;
	}

	/* Select the first PDO (vSafe5V) immediately. */
@@ -1034,6 +1047,8 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
		power_supply_set_property(pd->usb_psy,
				POWER_SUPPLY_PROP_TYPEC_POWER_ROLE, &val);

		/* support only PD 2.0 as a source */
		pd->spec_rev = USBPD_REV_20;
		pd_reset_protocol(pd);

		if (!pd->in_pr_swap) {
@@ -1204,6 +1219,11 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
		if (!val.intval || disable_usb_pd)
			break;

		/*
		 * support up to PD 3.0 as a sink; if source is 2.0
		 * phy_msg_received() will handle the downgrade.
		 */
		pd->spec_rev = USBPD_REV_30;
		pd_reset_protocol(pd);

		if (!pd->in_pr_swap) {
@@ -1909,6 +1929,8 @@ static void usbpd_sm(struct work_struct *w)
		/* set due to dual_role class "mode" change */
		if (pd->forced_pr != POWER_SUPPLY_TYPEC_PR_NONE)
			val.intval = pd->forced_pr;
		else if (rev3_sink_only)
			val.intval = POWER_SUPPLY_TYPEC_PR_SINK;
		else
			/* Set CC back to DRP toggle */
			val.intval = POWER_SUPPLY_TYPEC_PR_DUAL;
@@ -3910,8 +3932,6 @@ struct usbpd *usbpd_create(struct device *parent)
		pd->dual_role->drv_data = pd;
	}

	/* default support as PD 2.0 source or sink */
	pd->spec_rev = USBPD_REV_20;
	pd->current_pr = PR_NONE;
	pd->current_dr = DR_NONE;
	list_add_tail(&pd->instance, &_usbpd);