diff options
| author | Hemant Kumar <hemantk@codeaurora.org> | 2017-07-20 13:51:49 -0700 |
|---|---|---|
| committer | Jack Pham <jackp@codeaurora.org> | 2018-01-17 17:55:15 -0800 |
| commit | f83e315016ed98567696797b7cb2168a61950a32 (patch) | |
| tree | 435225cad01898fd98a0b860a2075c20b50aeb75 | |
| parent | b3b1b7012ce3bdd728f867114e08053b8b7b4fe7 (diff) | |
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: Hemant Kumar <hemantk@codeaurora.org>
| -rw-r--r-- | drivers/usb/pd/policy_engine.c | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index 77a1627ac5f2..f2383b62a68b 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -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); |
