From 9a96e2945938d3bd3b9983264fc51f90e3417c23 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Wed, 26 Sep 2018 16:23:52 +0100 Subject: [PATCH] UPSTREAM: usb: typec: fusb302: Resolve fixed power role contract setup When the controller is configured for a fixed power role (Source only or Sink only), attach does not proceed within the TCPM state machine as there is no CC event generated by this driver to update the CC line status. To rectify this, when CC is configured as Source or Sink we now make use of the hardware's automatic fixed Source or Sink toggling mechanism, which detects attaches in the same way as for DRP toggling. In this way the result of toggling is handled in the same way by the 'fusb302_handle_togdone()' function, and CC events are generated as expected for TCPM allowing a contract to be established. Change-Id: I736243adf0ddc9a11c00aa02be07c7039d26811d Signed-off-by: Adam Thomson Reviewed-by: Guenter Roeck Reviewed-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman Signed-off-by: Frank Wang (cherry picked from commit ea3b4d5523bc8d3e955075d3716af536d6212cc7) --- drivers/usb/typec/tcpm/fusb302.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index e61a5531850f..6adeca36a3e4 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -681,6 +681,7 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc) int ret = 0; bool pull_up, pull_down; u8 rd_mda; + enum toggling_mode mode; mutex_lock(&chip->lock); switch (cc) { @@ -766,6 +767,29 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc) chip->intr_comp_chng = false; } fusb302_log(chip, "cc := %s", typec_cc_status_name[cc]); + + /* Enable detection for fixed SNK or SRC only roles */ + switch (cc) { + case TYPEC_CC_RD: + mode = TOGGLING_MODE_SNK; + break; + case TYPEC_CC_RP_DEF: + case TYPEC_CC_RP_1_5: + case TYPEC_CC_RP_3_0: + mode = TOGGLING_MODE_SRC; + break; + default: + mode = TOGGLING_MODE_OFF; + break; + } + + if (mode != TOGGLING_MODE_OFF) { + ret = fusb302_set_toggling(chip, mode); + if (ret < 0) + fusb302_log(chip, + "cannot set fixed role toggling mode, ret=%d", + ret); + } done: mutex_unlock(&chip->lock);