diff mbox series

[09/14,v1] usb: typec: tcpm: Add support for Sink Fast Role SWAP(FRS)

Message ID 20200825042210.300632-10-badhri@google.com (mailing list archive)
State Superseded
Headers show
Series TCPM support for FRS and AutoDischarge Disconnect | expand

Commit Message

Badhri Jagan Sridharan Aug. 25, 2020, 4:22 a.m. UTC
PD 3.0 spec defines a new mechanism for power role swap called
Fast role swap. This change enables TCPM to support FRS when
acting as sink.

Once the explicit contract is negotiated, sink port is
expected to query the source port for sink caps to
determine whether the source is FRS capable.
Bits 23 & 24 of fixed pdo of the sink caps from the source, when
set, indicates the current needed by the source when fast role
swap is in progress(Implicit contract phasae). 0 indicates that
the source does not support Fast Role Swap.

Upon receiving the FRS signal from the source,
TCPC(TCPM_FRS_EVENT) informs TCPM to start the Fast role swap sequence.

1. TCPM sends FRS PD message: FR_SWAP_SEND
2. If response is not received within the expiry of
   SenderResponseTimer, Error recovery is triggered.:
   FR_SWAP_SEND_TIMEOUT
3. Upon receipt of the accept message, TCPM waits for
   PSSourceOffTimer for PS_READY message from the partner:
   FR_SWAP_SNK_SRC_NEW_SINK_READY.

TCPC is expected to autonomously turn on vbus once the FRS
signal is received and vbus voltage falls below vsafe5v within
tSrcFrSwap. This is different from traditional power role swap
where the vbus sourcing is turned on by TCPM.

4. By this time, TCPC most likely would have started to
   source vbus, TCPM waits for tSrcFrSwap to see  if the
   lower level TCPC driver signals TCPM_SOURCING_VBUS event:
   FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED.
5. When TCPC signals sourcing vbus, TCPM sends PS_READY msg and
   changes the CC pin from Rd to Rp. This is the end of fast
   role swap sequence and TCPM initiates the sequnce to negotiate
   explicit contract by transitioning into SRC_STARTUP after
   SwapSrcStart.

The code is written based on the sequence described in "Figure 8-107:
Dual-role Port in Sink to Source Fast Role Swap State Diagram" of
USB Power Delivery Specification Revision 3.0, Version 1.2.

Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
 drivers/usb/typec/tcpm/tcpm.c | 191 +++++++++++++++++++++++++++++++++-
 include/linux/usb/pd.h        |  20 ++--
 include/linux/usb/tcpm.h      |   8 +-
 include/linux/usb/typec.h     |  13 +++
 4 files changed, 220 insertions(+), 12 deletions(-)

Comments

kernel test robot Aug. 26, 2020, 12:42 p.m. UTC | #1
Hi Badhri,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on usb/usb-testing]
[also build test WARNING on robh/for-next v5.9-rc2 next-20200826]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Badhri-Jagan-Sridharan/TCPM-support-for-FRS-and-AutoDischarge-Disconnect/20200825-122527
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
config: arm-randconfig-r005-20200826 (attached as .config)
compiler: arm-linux-gnueabi-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arm 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/usb/typec/tcpm/tcpm.c: In function 'run_state_machine':
>> drivers/usb/typec/tcpm/tcpm.c:3684:3: warning: this statement may fall through [-Wimplicit-fallthrough=]
    3684 |   tcpm_swap_complete(port, port->swap_status);
         |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/usb/typec/tcpm/tcpm.c:3685:2: note: here
    3685 |  case FR_SWAP_CANCEL:
         |  ^~~~
   At top level:
   drivers/usb/typec/tcpm/tcpm.c:1618:39: warning: 'tcpm_altmode_ops' defined but not used [-Wunused-const-variable=]
    1618 | static const struct typec_altmode_ops tcpm_altmode_ops = {
         |                                       ^~~~~~~~~~~~~~~~

# https://github.com/0day-ci/linux/commit/a8727cbd1e6baa15662e368128ac96b196fe540f
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Badhri-Jagan-Sridharan/TCPM-support-for-FRS-and-AutoDischarge-Disconnect/20200825-122527
git checkout a8727cbd1e6baa15662e368128ac96b196fe540f
vim +3684 drivers/usb/typec/tcpm/tcpm.c

fce042f02ef03c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-15  2982  
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  2983  static void run_state_machine(struct tcpm_port *port)
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  2984  {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  2985  	int ret;
fce042f02ef03c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-15  2986  	enum typec_pwr_opmode opmode;
131c7d12ef21e1 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  2987  	unsigned int msecs;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  2988  
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  2989  	port->enter_state = port->state;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  2990  	switch (port->state) {
7893f9e1c26d1f drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-04-16  2991  	case TOGGLING:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  2992  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  2993  	/* SRC states */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  2994  	case SRC_UNATTACHED:
b17dd57118fee7 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-08-10  2995  		if (!port->non_pd_role_swap)
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  2996  			tcpm_swap_complete(port, -ENOTCONN);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  2997  		tcpm_src_detach(port);
7893f9e1c26d1f drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-04-16  2998  		if (tcpm_start_toggling(port, tcpm_rp_cc(port))) {
7893f9e1c26d1f drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-04-16  2999  			tcpm_set_state(port, TOGGLING, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3000  			break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3001  		}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3002  		tcpm_set_cc(port, tcpm_rp_cc(port));
9b0ae69909c281 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3003  		if (port->port_type == TYPEC_PORT_DRP)
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3004  			tcpm_set_state(port, SNK_UNATTACHED, PD_T_DRP_SNK);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3005  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3006  	case SRC_ATTACH_WAIT:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3007  		if (tcpm_port_is_debug(port))
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3008  			tcpm_set_state(port, DEBUG_ACC_ATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3009  				       PD_T_CC_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3010  		else if (tcpm_port_is_audio(port))
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3011  			tcpm_set_state(port, AUDIO_ACC_ATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3012  				       PD_T_CC_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3013  		else if (tcpm_port_is_source(port))
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3014  			tcpm_set_state(port,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3015  				       tcpm_try_snk(port) ? SNK_TRY
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3016  							  : SRC_ATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3017  				       PD_T_CC_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3018  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3019  
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3020  	case SNK_TRY:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3021  		port->try_snk_count++;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3022  		/*
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3023  		 * Requirements:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3024  		 * - Do not drive vconn or vbus
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3025  		 * - Terminate CC pins (both) to Rd
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3026  		 * Action:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3027  		 * - Wait for tDRPTry (PD_T_DRP_TRY).
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3028  		 *   Until then, ignore any state changes.
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3029  		 */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3030  		tcpm_set_cc(port, TYPEC_CC_RD);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3031  		tcpm_set_state(port, SNK_TRY_WAIT, PD_T_DRP_TRY);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3032  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3033  	case SNK_TRY_WAIT:
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3034  		if (tcpm_port_is_sink(port)) {
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3035  			tcpm_set_state(port, SNK_TRY_WAIT_DEBOUNCE, 0);
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3036  		} else {
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3037  			tcpm_set_state(port, SRC_TRYWAIT, 0);
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3038  			port->max_wait = 0;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3039  		}
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3040  		break;
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3041  	case SNK_TRY_WAIT_DEBOUNCE:
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3042  		tcpm_set_state(port, SNK_TRY_WAIT_DEBOUNCE_CHECK_VBUS,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3043  			       PD_T_PD_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3044  		break;
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3045  	case SNK_TRY_WAIT_DEBOUNCE_CHECK_VBUS:
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3046  		if (port->vbus_present && tcpm_port_is_sink(port)) {
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3047  			tcpm_set_state(port, SNK_ATTACHED, 0);
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3048  		} else {
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3049  			tcpm_set_state(port, SRC_TRYWAIT, 0);
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3050  			port->max_wait = 0;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3051  		}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3052  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3053  	case SRC_TRYWAIT:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3054  		tcpm_set_cc(port, tcpm_rp_cc(port));
02d5be466b68f6 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3055  		if (port->max_wait == 0) {
02d5be466b68f6 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3056  			port->max_wait = jiffies +
02d5be466b68f6 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3057  					 msecs_to_jiffies(PD_T_DRP_TRY);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3058  			tcpm_set_state(port, SRC_TRYWAIT_UNATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3059  				       PD_T_DRP_TRY);
02d5be466b68f6 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3060  		} else {
02d5be466b68f6 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3061  			if (time_is_after_jiffies(port->max_wait))
02d5be466b68f6 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3062  				tcpm_set_state(port, SRC_TRYWAIT_UNATTACHED,
02d5be466b68f6 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3063  					       jiffies_to_msecs(port->max_wait -
02d5be466b68f6 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3064  								jiffies));
02d5be466b68f6 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3065  			else
02d5be466b68f6 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3066  				tcpm_set_state(port, SNK_UNATTACHED, 0);
02d5be466b68f6 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3067  		}
02d5be466b68f6 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3068  		break;
02d5be466b68f6 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3069  	case SRC_TRYWAIT_DEBOUNCE:
02d5be466b68f6 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3070  		tcpm_set_state(port, SRC_ATTACHED, PD_T_CC_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3071  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3072  	case SRC_TRYWAIT_UNATTACHED:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3073  		tcpm_set_state(port, SNK_UNATTACHED, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3074  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3075  
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3076  	case SRC_ATTACHED:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3077  		ret = tcpm_src_attach(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3078  		tcpm_set_state(port, SRC_UNATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3079  			       ret < 0 ? 0 : PD_T_PS_SOURCE_ON);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3080  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3081  	case SRC_STARTUP:
fce042f02ef03c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-15  3082  		opmode =  tcpm_get_pwr_opmode(tcpm_rp_cc(port));
fce042f02ef03c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-15  3083  		typec_set_pwr_opmode(port->typec_port, opmode);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3084  		port->pwr_opmode = TYPEC_PWR_MODE_USB;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3085  		port->caps_count = 0;
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3086  		port->negotiated_rev = PD_MAX_REV;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3087  		port->message_id = 0;
5fec4b54d0bf6c drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3088  		port->rx_msgid = -1;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3089  		port->explicit_contract = false;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3090  		tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3091  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3092  	case SRC_SEND_CAPABILITIES:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3093  		port->caps_count++;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3094  		if (port->caps_count > PD_N_CAPS_COUNT) {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3095  			tcpm_set_state(port, SRC_READY, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3096  			break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3097  		}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3098  		ret = tcpm_pd_send_source_caps(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3099  		if (ret < 0) {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3100  			tcpm_set_state(port, SRC_SEND_CAPABILITIES,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3101  				       PD_T_SEND_SOURCE_CAP);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3102  		} else {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3103  			/*
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3104  			 * Per standard, we should clear the reset counter here.
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3105  			 * However, that can result in state machine hang-ups.
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3106  			 * Reset it only in READY state to improve stability.
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3107  			 */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3108  			/* port->hard_reset_count = 0; */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3109  			port->caps_count = 0;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3110  			port->pd_capable = true;
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3111  			tcpm_set_state_cond(port, SRC_SEND_CAPABILITIES_TIMEOUT,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3112  					    PD_T_SEND_SOURCE_CAP);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3113  		}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3114  		break;
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3115  	case SRC_SEND_CAPABILITIES_TIMEOUT:
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3116  		/*
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3117  		 * Error recovery for a PD_DATA_SOURCE_CAP reply timeout.
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3118  		 *
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3119  		 * PD 2.0 sinks are supposed to accept src-capabilities with a
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3120  		 * 3.0 header and simply ignore any src PDOs which the sink does
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3121  		 * not understand such as PPS but some 2.0 sinks instead ignore
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3122  		 * the entire PD_DATA_SOURCE_CAP message, causing contract
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3123  		 * negotiation to fail.
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3124  		 *
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3125  		 * After PD_N_HARD_RESET_COUNT hard-reset attempts, we try
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3126  		 * sending src-capabilities with a lower PD revision to
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3127  		 * make these broken sinks work.
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3128  		 */
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3129  		if (port->hard_reset_count < PD_N_HARD_RESET_COUNT) {
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3130  			tcpm_set_state(port, HARD_RESET_SEND, 0);
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3131  		} else if (port->negotiated_rev > PD_REV20) {
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3132  			port->negotiated_rev--;
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3133  			port->hard_reset_count = 0;
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3134  			tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3135  		} else {
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3136  			tcpm_set_state(port, hard_reset_state(port), 0);
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3137  		}
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-03-16  3138  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3139  	case SRC_NEGOTIATE_CAPABILITIES:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3140  		ret = tcpm_pd_check_request(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3141  		if (ret < 0) {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3142  			tcpm_pd_send_control(port, PD_CTRL_REJECT);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3143  			if (!port->explicit_contract) {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3144  				tcpm_set_state(port,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3145  					       SRC_WAIT_NEW_CAPABILITIES, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3146  			} else {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3147  				tcpm_set_state(port, SRC_READY, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3148  			}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3149  		} else {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3150  			tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3151  			tcpm_set_state(port, SRC_TRANSITION_SUPPLY,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3152  				       PD_T_SRC_TRANSITION);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3153  		}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3154  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3155  	case SRC_TRANSITION_SUPPLY:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3156  		/* XXX: regulator_set_voltage(vbus, ...) */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3157  		tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3158  		port->explicit_contract = true;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3159  		typec_set_pwr_opmode(port->typec_port, TYPEC_PWR_MODE_PD);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3160  		port->pwr_opmode = TYPEC_PWR_MODE_PD;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3161  		tcpm_set_state_cond(port, SRC_READY, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3162  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3163  	case SRC_READY:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3164  #if 1
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3165  		port->hard_reset_count = 0;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3166  #endif
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3167  		port->try_src_count = 0;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3168  
3113bf1a5da35f drivers/staging/typec/tcpm.c  Guenter Roeck          2017-08-10  3169  		tcpm_swap_complete(port, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3170  		tcpm_typec_connect(port);
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3171  
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3172  		tcpm_check_send_discover(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3173  		/*
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3174  		 * 6.3.5
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3175  		 * Sending ping messages is not necessary if
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3176  		 * - the source operates at vSafe5V
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3177  		 * or
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3178  		 * - The system is not operating in PD mode
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3179  		 * or
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3180  		 * - Both partners are connected using a Type-C connector
f451ac9e4c6dd2 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3181  		 *
f451ac9e4c6dd2 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3182  		 * There is no actual need to send PD messages since the local
f451ac9e4c6dd2 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3183  		 * port type-c and the spec does not clearly say whether PD is
f451ac9e4c6dd2 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3184  		 * possible when type-c is connected to Type-A/B
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3185  		 */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3186  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3187  	case SRC_WAIT_NEW_CAPABILITIES:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3188  		/* Nothing to do... */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3189  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3190  
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3191  	/* SNK states */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3192  	case SNK_UNATTACHED:
b17dd57118fee7 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-08-10  3193  		if (!port->non_pd_role_swap)
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3194  			tcpm_swap_complete(port, -ENOTCONN);
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3195  		tcpm_pps_complete(port, -ENOTCONN);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3196  		tcpm_snk_detach(port);
7893f9e1c26d1f drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-04-16  3197  		if (tcpm_start_toggling(port, TYPEC_CC_RD)) {
7893f9e1c26d1f drivers/usb/typec/tcpm/tcpm.c Hans de Goede          2019-04-16  3198  			tcpm_set_state(port, TOGGLING, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3199  			break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3200  		}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3201  		tcpm_set_cc(port, TYPEC_CC_RD);
9b0ae69909c281 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3202  		if (port->port_type == TYPEC_PORT_DRP)
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3203  			tcpm_set_state(port, SRC_UNATTACHED, PD_T_DRP_SRC);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3204  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3205  	case SNK_ATTACH_WAIT:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3206  		if ((port->cc1 == TYPEC_CC_OPEN &&
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3207  		     port->cc2 != TYPEC_CC_OPEN) ||
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3208  		    (port->cc1 != TYPEC_CC_OPEN &&
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3209  		     port->cc2 == TYPEC_CC_OPEN))
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3210  			tcpm_set_state(port, SNK_DEBOUNCED,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3211  				       PD_T_CC_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3212  		else if (tcpm_port_is_disconnected(port))
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3213  			tcpm_set_state(port, SNK_UNATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3214  				       PD_T_PD_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3215  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3216  	case SNK_DEBOUNCED:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3217  		if (tcpm_port_is_disconnected(port))
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3218  			tcpm_set_state(port, SNK_UNATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3219  				       PD_T_PD_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3220  		else if (port->vbus_present)
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3221  			tcpm_set_state(port,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3222  				       tcpm_try_src(port) ? SRC_TRY
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3223  							  : SNK_ATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3224  				       0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3225  		else
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3226  			/* Wait for VBUS, but not forever */
56277035c294ec drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3227  			tcpm_set_state(port, PORT_RESET, PD_T_PS_SOURCE_ON);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3228  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3229  
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3230  	case SRC_TRY:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3231  		port->try_src_count++;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3232  		tcpm_set_cc(port, tcpm_rp_cc(port));
131c7d12ef21e1 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3233  		port->max_wait = 0;
131c7d12ef21e1 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3234  		tcpm_set_state(port, SRC_TRY_WAIT, 0);
131c7d12ef21e1 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3235  		break;
131c7d12ef21e1 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3236  	case SRC_TRY_WAIT:
131c7d12ef21e1 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3237  		if (port->max_wait == 0) {
131c7d12ef21e1 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3238  			port->max_wait = jiffies +
131c7d12ef21e1 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3239  					 msecs_to_jiffies(PD_T_DRP_TRY);
131c7d12ef21e1 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3240  			msecs = PD_T_DRP_TRY;
131c7d12ef21e1 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3241  		} else {
131c7d12ef21e1 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3242  			if (time_is_after_jiffies(port->max_wait))
131c7d12ef21e1 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3243  				msecs = jiffies_to_msecs(port->max_wait -
131c7d12ef21e1 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3244  							 jiffies);
131c7d12ef21e1 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3245  			else
131c7d12ef21e1 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3246  				msecs = 0;
131c7d12ef21e1 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3247  		}
131c7d12ef21e1 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3248  		tcpm_set_state(port, SNK_TRYWAIT, msecs);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3249  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3250  	case SRC_TRY_DEBOUNCE:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3251  		tcpm_set_state(port, SRC_ATTACHED, PD_T_PD_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3252  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3253  	case SNK_TRYWAIT:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3254  		tcpm_set_cc(port, TYPEC_CC_RD);
af450ebb500ad2 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3255  		tcpm_set_state(port, SNK_TRYWAIT_VBUS, PD_T_CC_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3256  		break;
af450ebb500ad2 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3257  	case SNK_TRYWAIT_VBUS:
af450ebb500ad2 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3258  		/*
af450ebb500ad2 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3259  		 * TCPM stays in this state indefinitely until VBUS
af450ebb500ad2 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3260  		 * is detected as long as Rp is not detected for
af450ebb500ad2 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3261  		 * more than a time period of tPDDebounce.
af450ebb500ad2 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3262  		 */
af450ebb500ad2 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3263  		if (port->vbus_present && tcpm_port_is_sink(port)) {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3264  			tcpm_set_state(port, SNK_ATTACHED, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3265  			break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3266  		}
af450ebb500ad2 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3267  		if (!tcpm_port_is_sink(port))
af450ebb500ad2 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3268  			tcpm_set_state(port, SNK_TRYWAIT_DEBOUNCE, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3269  		break;
af450ebb500ad2 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3270  	case SNK_TRYWAIT_DEBOUNCE:
af450ebb500ad2 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3271  		tcpm_set_state(port, SNK_UNATTACHED, PD_T_PD_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3272  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3273  	case SNK_ATTACHED:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3274  		ret = tcpm_snk_attach(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3275  		if (ret < 0)
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3276  			tcpm_set_state(port, SNK_UNATTACHED, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3277  		else
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3278  			tcpm_set_state(port, SNK_STARTUP, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3279  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3280  	case SNK_STARTUP:
fce042f02ef03c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-15  3281  		opmode =  tcpm_get_pwr_opmode(port->polarity ?
fce042f02ef03c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-15  3282  					      port->cc2 : port->cc1);
fce042f02ef03c drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-15  3283  		typec_set_pwr_opmode(port->typec_port, opmode);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3284  		port->pwr_opmode = TYPEC_PWR_MODE_USB;
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3285  		port->negotiated_rev = PD_MAX_REV;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3286  		port->message_id = 0;
5fec4b54d0bf6c drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3287  		port->rx_msgid = -1;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3288  		port->explicit_contract = false;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3289  		tcpm_set_state(port, SNK_DISCOVERY, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3290  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3291  	case SNK_DISCOVERY:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3292  		if (port->vbus_present) {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3293  			tcpm_set_current_limit(port,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3294  					       tcpm_get_current_limit(port),
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3295  					       5000);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3296  			tcpm_set_charge(port, true);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3297  			tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3298  			break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3299  		}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3300  		/*
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3301  		 * For DRP, timeouts differ. Also, handling is supposed to be
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3302  		 * different and much more complex (dead battery detection;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3303  		 * see USB power delivery specification, section 8.3.3.6.1.5.1).
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3304  		 */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3305  		tcpm_set_state(port, hard_reset_state(port),
9b0ae69909c281 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3306  			       port->port_type == TYPEC_PORT_DRP ?
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3307  					PD_T_DB_DETECT : PD_T_NO_RESPONSE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3308  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3309  	case SNK_DISCOVERY_DEBOUNCE:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3310  		tcpm_set_state(port, SNK_DISCOVERY_DEBOUNCE_DONE,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3311  			       PD_T_CC_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3312  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3313  	case SNK_DISCOVERY_DEBOUNCE_DONE:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3314  		if (!tcpm_port_is_disconnected(port) &&
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3315  		    tcpm_port_is_sink(port) &&
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3316  		    time_is_after_jiffies(port->delayed_runtime)) {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3317  			tcpm_set_state(port, SNK_DISCOVERY,
9578bcd0bb487b drivers/usb/typec/tcpm.c      Dan Carpenter          2018-06-07  3318  				       jiffies_to_msecs(port->delayed_runtime -
9578bcd0bb487b drivers/usb/typec/tcpm.c      Dan Carpenter          2018-06-07  3319  							jiffies));
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3320  			break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3321  		}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3322  		tcpm_set_state(port, unattached_state(port), 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3323  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3324  	case SNK_WAIT_CAPABILITIES:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3325  		ret = port->tcpc->set_pd_rx(port->tcpc, true);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3326  		if (ret < 0) {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3327  			tcpm_set_state(port, SNK_READY, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3328  			break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3329  		}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3330  		/*
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3331  		 * If VBUS has never been low, and we time out waiting
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3332  		 * for source cap, try a soft reset first, in case we
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3333  		 * were already in a stable contract before this boot.
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3334  		 * Do this only once.
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3335  		 */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3336  		if (port->vbus_never_low) {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3337  			port->vbus_never_low = false;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3338  			tcpm_set_state(port, SOFT_RESET_SEND,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3339  				       PD_T_SINK_WAIT_CAP);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3340  		} else {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3341  			tcpm_set_state(port, hard_reset_state(port),
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3342  				       PD_T_SINK_WAIT_CAP);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3343  		}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3344  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3345  	case SNK_NEGOTIATE_CAPABILITIES:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3346  		port->pd_capable = true;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3347  		port->hard_reset_count = 0;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3348  		ret = tcpm_pd_send_request(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3349  		if (ret < 0) {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3350  			/* Let the Source send capabilities again. */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3351  			tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3352  		} else {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3353  			tcpm_set_state_cond(port, hard_reset_state(port),
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3354  					    PD_T_SENDER_RESPONSE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3355  		}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3356  		break;
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3357  	case SNK_NEGOTIATE_PPS_CAPABILITIES:
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3358  		ret = tcpm_pd_send_pps_request(port);
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3359  		if (ret < 0) {
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3360  			port->pps_status = ret;
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3361  			/*
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3362  			 * If this was called due to updates to sink
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3363  			 * capabilities, and pps is no longer valid, we should
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3364  			 * safely fall back to a standard PDO.
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3365  			 */
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3366  			if (port->update_sink_caps)
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3367  				tcpm_set_state(port, SNK_NEGOTIATE_CAPABILITIES, 0);
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3368  			else
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3369  				tcpm_set_state(port, SNK_READY, 0);
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3370  		} else {
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3371  			tcpm_set_state_cond(port, hard_reset_state(port),
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3372  					    PD_T_SENDER_RESPONSE);
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3373  		}
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3374  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3375  	case SNK_TRANSITION_SINK:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3376  	case SNK_TRANSITION_SINK_VBUS:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3377  		tcpm_set_state(port, hard_reset_state(port),
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3378  			       PD_T_PS_TRANSITION);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3379  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3380  	case SNK_READY:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3381  		port->try_snk_count = 0;
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3382  		port->update_sink_caps = false;
8bf05746cffa34 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-17  3383  		if (port->explicit_contract) {
8bf05746cffa34 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-17  3384  			typec_set_pwr_opmode(port->typec_port,
8bf05746cffa34 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-17  3385  					     TYPEC_PWR_MODE_PD);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3386  			port->pwr_opmode = TYPEC_PWR_MODE_PD;
8bf05746cffa34 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-17  3387  		}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3388  
3113bf1a5da35f drivers/staging/typec/tcpm.c  Guenter Roeck          2017-08-10  3389  		tcpm_swap_complete(port, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3390  		tcpm_typec_connect(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3391  		tcpm_check_send_discover(port);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3392  		mod_delayed_work(port->wq, &port->enable_frs, msecs_to_jiffies(0));
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3393  		tcpm_pps_complete(port, port->pps_status);
f2a8aa053c1761 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3394  		power_supply_changed(port->psy);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3395  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3396  
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3397  	/* Accessory states */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3398  	case ACC_UNATTACHED:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3399  		tcpm_acc_detach(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3400  		tcpm_set_state(port, SRC_UNATTACHED, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3401  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3402  	case DEBUG_ACC_ATTACHED:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3403  	case AUDIO_ACC_ATTACHED:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3404  		ret = tcpm_acc_attach(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3405  		if (ret < 0)
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3406  			tcpm_set_state(port, ACC_UNATTACHED, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3407  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3408  	case AUDIO_ACC_DEBOUNCE:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3409  		tcpm_set_state(port, ACC_UNATTACHED, PD_T_CC_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3410  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3411  
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3412  	/* Hard_Reset states */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3413  	case HARD_RESET_SEND:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3414  		tcpm_pd_transmit(port, TCPC_TX_HARD_RESET, NULL);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3415  		tcpm_set_state(port, HARD_RESET_START, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3416  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3417  	case HARD_RESET_START:
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3418  		port->sink_cap_done = false;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3419  		if (port->tcpc->enable_frs)
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3420  			port->tcpc->enable_frs(port->tcpc, false);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3421  		port->hard_reset_count++;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3422  		port->tcpc->set_pd_rx(port->tcpc, false);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3423  		tcpm_unregister_altmodes(port);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3424  		port->nr_sink_caps = 0;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3425  		port->send_discover = true;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3426  		if (port->pwr_role == TYPEC_SOURCE)
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3427  			tcpm_set_state(port, SRC_HARD_RESET_VBUS_OFF,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3428  				       PD_T_PS_HARD_RESET);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3429  		else
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3430  			tcpm_set_state(port, SNK_HARD_RESET_SINK_OFF, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3431  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3432  	case SRC_HARD_RESET_VBUS_OFF:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3433  		tcpm_set_vconn(port, true);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3434  		tcpm_set_vbus(port, false);
23b5f73266e59a drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01  3435  		tcpm_set_roles(port, port->self_powered, TYPEC_SOURCE,
6ecc632d4b35d2 drivers/usb/typec/tcpm/tcpm.c Li Jun                 2020-02-14  3436  			       tcpm_data_role_for_source(port));
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3437  		tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, PD_T_SRC_RECOVER);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3438  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3439  	case SRC_HARD_RESET_VBUS_ON:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3440  		tcpm_set_vbus(port, true);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3441  		port->tcpc->set_pd_rx(port->tcpc, true);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3442  		tcpm_set_attached_state(port, true);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3443  		tcpm_set_state(port, SRC_UNATTACHED, PD_T_PS_SOURCE_ON);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3444  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3445  	case SNK_HARD_RESET_SINK_OFF:
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3446  		memset(&port->pps_data, 0, sizeof(port->pps_data));
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3447  		tcpm_set_vconn(port, false);
157c0f2f641a99 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01  3448  		if (port->pd_capable)
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3449  			tcpm_set_charge(port, false);
23b5f73266e59a drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01  3450  		tcpm_set_roles(port, port->self_powered, TYPEC_SINK,
6ecc632d4b35d2 drivers/usb/typec/tcpm/tcpm.c Li Jun                 2020-02-14  3451  			       tcpm_data_role_for_sink(port));
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3452  		/*
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3453  		 * VBUS may or may not toggle, depending on the adapter.
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3454  		 * If it doesn't toggle, transition to SNK_HARD_RESET_SINK_ON
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3455  		 * directly after timeout.
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3456  		 */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3457  		tcpm_set_state(port, SNK_HARD_RESET_SINK_ON, PD_T_SAFE_0V);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3458  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3459  	case SNK_HARD_RESET_WAIT_VBUS:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3460  		/* Assume we're disconnected if VBUS doesn't come back. */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3461  		tcpm_set_state(port, SNK_UNATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3462  			       PD_T_SRC_RECOVER_MAX + PD_T_SRC_TURN_ON);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3463  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3464  	case SNK_HARD_RESET_SINK_ON:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3465  		/* Note: There is no guarantee that VBUS is on in this state */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3466  		/*
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3467  		 * XXX:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3468  		 * The specification suggests that dual mode ports in sink
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3469  		 * mode should transition to state PE_SRC_Transition_to_default.
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3470  		 * See USB power delivery specification chapter 8.3.3.6.1.3.
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3471  		 * This would mean to to
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3472  		 * - turn off VCONN, reset power supply
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3473  		 * - request hardware reset
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3474  		 * - turn on VCONN
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3475  		 * - Transition to state PE_Src_Startup
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3476  		 * SNK only ports shall transition to state Snk_Startup
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3477  		 * (see chapter 8.3.3.3.8).
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3478  		 * Similar, dual-mode ports in source mode should transition
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3479  		 * to PE_SNK_Transition_to_default.
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3480  		 */
157c0f2f641a99 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01  3481  		if (port->pd_capable) {
157c0f2f641a99 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01  3482  			tcpm_set_current_limit(port,
157c0f2f641a99 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01  3483  					       tcpm_get_current_limit(port),
157c0f2f641a99 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01  3484  					       5000);
157c0f2f641a99 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01  3485  			tcpm_set_charge(port, true);
157c0f2f641a99 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01  3486  		}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3487  		tcpm_set_attached_state(port, true);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3488  		tcpm_set_state(port, SNK_STARTUP, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3489  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3490  
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3491  	/* Soft_Reset states */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3492  	case SOFT_RESET:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3493  		port->message_id = 0;
5fec4b54d0bf6c drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3494  		port->rx_msgid = -1;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3495  		tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3496  		if (port->pwr_role == TYPEC_SOURCE)
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3497  			tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3498  		else
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3499  			tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3500  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3501  	case SOFT_RESET_SEND:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3502  		port->message_id = 0;
5fec4b54d0bf6c drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3503  		port->rx_msgid = -1;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3504  		if (tcpm_pd_send_control(port, PD_CTRL_SOFT_RESET))
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3505  			tcpm_set_state_cond(port, hard_reset_state(port), 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3506  		else
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3507  			tcpm_set_state_cond(port, hard_reset_state(port),
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3508  					    PD_T_SENDER_RESPONSE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3509  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3510  
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3511  	/* DR_Swap states */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3512  	case DR_SWAP_SEND:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3513  		tcpm_pd_send_control(port, PD_CTRL_DR_SWAP);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3514  		tcpm_set_state_cond(port, DR_SWAP_SEND_TIMEOUT,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3515  				    PD_T_SENDER_RESPONSE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3516  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3517  	case DR_SWAP_ACCEPT:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3518  		tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3519  		tcpm_set_state_cond(port, DR_SWAP_CHANGE_DR, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3520  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3521  	case DR_SWAP_SEND_TIMEOUT:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3522  		tcpm_swap_complete(port, -ETIMEDOUT);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3523  		tcpm_set_state(port, ready_state(port), 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3524  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3525  	case DR_SWAP_CHANGE_DR:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3526  		if (port->data_role == TYPEC_HOST) {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3527  			tcpm_unregister_altmodes(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3528  			tcpm_set_roles(port, true, port->pwr_role,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3529  				       TYPEC_DEVICE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3530  		} else {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3531  			tcpm_set_roles(port, true, port->pwr_role,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3532  				       TYPEC_HOST);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3533  			port->send_discover = true;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3534  		}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3535  		tcpm_set_state(port, ready_state(port), 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3536  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3537  
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3538  	case FR_SWAP_SEND:
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3539  		if (tcpm_pd_send_control(port, PD_CTRL_FR_SWAP)) {
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3540  			tcpm_set_state(port, ERROR_RECOVERY, 0);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3541  			break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3542  		}
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3543  		tcpm_set_state_cond(port, FR_SWAP_SEND_TIMEOUT, PD_T_SENDER_RESPONSE);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3544  		break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3545  	case FR_SWAP_SEND_TIMEOUT:
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3546  		tcpm_set_state(port, ERROR_RECOVERY, 0);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3547  		break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3548  	case FR_SWAP_SNK_SRC_TRANSITION_TO_OFF:
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3549  		tcpm_set_state(port, ERROR_RECOVERY, PD_T_PS_SOURCE_OFF);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3550  		break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3551  	case FR_SWAP_SNK_SRC_NEW_SINK_READY:
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3552  		if (port->vbus_source)
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3553  			tcpm_set_state(port, FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED, 0);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3554  		else
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3555  			tcpm_set_state(port, ERROR_RECOVERY, PD_T_RECEIVER_RESPONSE);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3556  		break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3557  	case FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED:
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3558  		tcpm_set_pwr_role(port, TYPEC_SOURCE);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3559  		if (tcpm_pd_send_control(port, PD_CTRL_PS_RDY)) {
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3560  			tcpm_set_state(port, ERROR_RECOVERY, 0);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3561  			break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3562  		}
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3563  		tcpm_set_cc(port, tcpm_rp_cc(port));
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3564  		tcpm_set_state(port, SRC_STARTUP, PD_T_SWAP_SRC_START);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3565  		break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3566  
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3567  	/* PR_Swap states */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3568  	case PR_SWAP_ACCEPT:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3569  		tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3570  		tcpm_set_state(port, PR_SWAP_START, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3571  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3572  	case PR_SWAP_SEND:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3573  		tcpm_pd_send_control(port, PD_CTRL_PR_SWAP);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3574  		tcpm_set_state_cond(port, PR_SWAP_SEND_TIMEOUT,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3575  				    PD_T_SENDER_RESPONSE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3576  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3577  	case PR_SWAP_SEND_TIMEOUT:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3578  		tcpm_swap_complete(port, -ETIMEDOUT);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3579  		tcpm_set_state(port, ready_state(port), 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3580  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3581  	case PR_SWAP_START:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3582  		if (port->pwr_role == TYPEC_SOURCE)
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3583  			tcpm_set_state(port, PR_SWAP_SRC_SNK_TRANSITION_OFF,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3584  				       PD_T_SRC_TRANSITION);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3585  		else
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3586  			tcpm_set_state(port, PR_SWAP_SNK_SRC_SINK_OFF, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3587  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3588  	case PR_SWAP_SRC_SNK_TRANSITION_OFF:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3589  		tcpm_set_vbus(port, false);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3590  		port->explicit_contract = false;
b965b6317ff147 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3591  		/* allow time for Vbus discharge, must be < tSrcSwapStdby */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3592  		tcpm_set_state(port, PR_SWAP_SRC_SNK_SOURCE_OFF,
b965b6317ff147 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3593  			       PD_T_SRCSWAPSTDBY);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3594  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3595  	case PR_SWAP_SRC_SNK_SOURCE_OFF:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3596  		tcpm_set_cc(port, TYPEC_CC_RD);
b965b6317ff147 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3597  		/* allow CC debounce */
b965b6317ff147 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3598  		tcpm_set_state(port, PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED,
b965b6317ff147 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3599  			       PD_T_CC_DEBOUNCE);
b965b6317ff147 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3600  		break;
b965b6317ff147 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3601  	case PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED:
050161ea3268ad drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3602  		/*
050161ea3268ad drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3603  		 * USB-PD standard, 6.2.1.4, Port Power Role:
050161ea3268ad drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3604  		 * "During the Power Role Swap Sequence, for the initial Source
050161ea3268ad drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3605  		 * Port, the Port Power Role field shall be set to Sink in the
050161ea3268ad drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3606  		 * PS_RDY Message indicating that the initial Source’s power
050161ea3268ad drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3607  		 * supply is turned off"
050161ea3268ad drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3608  		 */
050161ea3268ad drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3609  		tcpm_set_pwr_role(port, TYPEC_SINK);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3610  		if (tcpm_pd_send_control(port, PD_CTRL_PS_RDY)) {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3611  			tcpm_set_state(port, ERROR_RECOVERY, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3612  			break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3613  		}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3614  		tcpm_set_state_cond(port, SNK_UNATTACHED, PD_T_PS_SOURCE_ON);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3615  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3616  	case PR_SWAP_SRC_SNK_SINK_ON:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3617  		tcpm_set_state(port, SNK_STARTUP, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3618  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3619  	case PR_SWAP_SNK_SRC_SINK_OFF:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3620  		tcpm_set_charge(port, false);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3621  		tcpm_set_state(port, hard_reset_state(port),
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3622  			       PD_T_PS_SOURCE_OFF);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3623  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3624  	case PR_SWAP_SNK_SRC_SOURCE_ON:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3625  		tcpm_set_cc(port, tcpm_rp_cc(port));
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3626  		tcpm_set_vbus(port, true);
b965b6317ff147 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3627  		/*
b965b6317ff147 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3628  		 * allow time VBUS ramp-up, must be < tNewSrc
b965b6317ff147 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3629  		 * Also, this window overlaps with CC debounce as well.
b965b6317ff147 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3630  		 * So, Wait for the max of two which is PD_T_NEWSRC
b965b6317ff147 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3631  		 */
b965b6317ff147 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3632  		tcpm_set_state(port, PR_SWAP_SNK_SRC_SOURCE_ON_VBUS_RAMPED_UP,
b965b6317ff147 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3633  			       PD_T_NEWSRC);
b965b6317ff147 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3634  		break;
b965b6317ff147 drivers/staging/typec/tcpm.c  Badhri Jagan Sridharan 2017-08-28  3635  	case PR_SWAP_SNK_SRC_SOURCE_ON_VBUS_RAMPED_UP:
050161ea3268ad drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3636  		/*
050161ea3268ad drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3637  		 * USB PD standard, 6.2.1.4:
050161ea3268ad drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3638  		 * "Subsequent Messages initiated by the Policy Engine,
050161ea3268ad drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3639  		 * such as the PS_RDY Message sent to indicate that Vbus
050161ea3268ad drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3640  		 * is ready, will have the Port Power Role field set to
050161ea3268ad drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3641  		 * Source."
050161ea3268ad drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3642  		 */
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3643  		tcpm_set_pwr_role(port, TYPEC_SOURCE);
050161ea3268ad drivers/staging/typec/tcpm.c  Guenter Roeck          2017-05-09  3644  		tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3645  		tcpm_set_state(port, SRC_STARTUP, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3646  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3647  
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3648  	case VCONN_SWAP_ACCEPT:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3649  		tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3650  		tcpm_set_state(port, VCONN_SWAP_START, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3651  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3652  	case VCONN_SWAP_SEND:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3653  		tcpm_pd_send_control(port, PD_CTRL_VCONN_SWAP);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3654  		tcpm_set_state(port, VCONN_SWAP_SEND_TIMEOUT,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3655  			       PD_T_SENDER_RESPONSE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3656  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3657  	case VCONN_SWAP_SEND_TIMEOUT:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3658  		tcpm_swap_complete(port, -ETIMEDOUT);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3659  		tcpm_set_state(port, ready_state(port), 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3660  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3661  	case VCONN_SWAP_START:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3662  		if (port->vconn_role == TYPEC_SOURCE)
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3663  			tcpm_set_state(port, VCONN_SWAP_WAIT_FOR_VCONN, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3664  		else
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3665  			tcpm_set_state(port, VCONN_SWAP_TURN_ON_VCONN, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3666  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3667  	case VCONN_SWAP_WAIT_FOR_VCONN:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3668  		tcpm_set_state(port, hard_reset_state(port),
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3669  			       PD_T_VCONN_SOURCE_ON);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3670  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3671  	case VCONN_SWAP_TURN_ON_VCONN:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3672  		tcpm_set_vconn(port, true);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3673  		tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3674  		tcpm_set_state(port, ready_state(port), 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3675  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3676  	case VCONN_SWAP_TURN_OFF_VCONN:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3677  		tcpm_set_vconn(port, false);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3678  		tcpm_set_state(port, ready_state(port), 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3679  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3680  
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3681  	case DR_SWAP_CANCEL:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3682  	case PR_SWAP_CANCEL:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3683  	case VCONN_SWAP_CANCEL:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27 @3684  		tcpm_swap_complete(port, port->swap_status);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3685  	case FR_SWAP_CANCEL:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3686  		if (port->pwr_role == TYPEC_SOURCE)
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3687  			tcpm_set_state(port, SRC_READY, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3688  		else
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3689  			tcpm_set_state(port, SNK_READY, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3690  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3691  
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3692  	case BIST_RX:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3693  		switch (BDO_MODE_MASK(port->bist_request)) {
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3694  		case BDO_MODE_CARRIER2:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3695  			tcpm_pd_transmit(port, TCPC_TX_BIST_MODE_2, NULL);
6e1c2241f4cecf drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-07-15  3696  			tcpm_set_state(port, unattached_state(port),
6e1c2241f4cecf drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-07-15  3697  				       PD_T_BIST_CONT_MODE);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3698  			break;
b2dcfefc43f783 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-07-15  3699  		case BDO_MODE_TESTDATA:
b2dcfefc43f783 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-07-15  3700  			if (port->tcpc->set_bist_data) {
b2dcfefc43f783 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-07-15  3701  				tcpm_log(port, "Enable BIST MODE TESTDATA");
b2dcfefc43f783 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-07-15  3702  				port->tcpc->set_bist_data(port->tcpc, true);
b2dcfefc43f783 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-07-15  3703  			}
b2dcfefc43f783 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-07-15  3704  			break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3705  		default:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3706  			break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3707  		}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3708  		break;
64f7c494a3c02b drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3709  	case GET_STATUS_SEND:
64f7c494a3c02b drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3710  		tcpm_pd_send_control(port, PD_CTRL_GET_STATUS);
64f7c494a3c02b drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3711  		tcpm_set_state(port, GET_STATUS_SEND_TIMEOUT,
64f7c494a3c02b drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3712  			       PD_T_SENDER_RESPONSE);
64f7c494a3c02b drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3713  		break;
64f7c494a3c02b drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3714  	case GET_STATUS_SEND_TIMEOUT:
64f7c494a3c02b drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3715  		tcpm_set_state(port, ready_state(port), 0);
64f7c494a3c02b drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3716  		break;
64f7c494a3c02b drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3717  	case GET_PPS_STATUS_SEND:
64f7c494a3c02b drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3718  		tcpm_pd_send_control(port, PD_CTRL_GET_PPS_STATUS);
64f7c494a3c02b drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3719  		tcpm_set_state(port, GET_PPS_STATUS_SEND_TIMEOUT,
64f7c494a3c02b drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3720  			       PD_T_SENDER_RESPONSE);
64f7c494a3c02b drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3721  		break;
64f7c494a3c02b drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3722  	case GET_PPS_STATUS_SEND_TIMEOUT:
64f7c494a3c02b drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3723  		tcpm_set_state(port, ready_state(port), 0);
64f7c494a3c02b drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3724  		break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3725  	case GET_SINK_CAP:
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3726  		tcpm_pd_send_control(port, PD_CTRL_GET_SINK_CAP);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3727  		tcpm_set_state(port, GET_SINK_CAP_TIMEOUT, PD_T_SENDER_RESPONSE);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3728  		break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3729  	case GET_SINK_CAP_TIMEOUT:
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3730  		port->sink_cap_done = true;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3731  		tcpm_set_state(port, ready_state(port), 0);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24  3732  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3733  	case ERROR_RECOVERY:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3734  		tcpm_swap_complete(port, -EPROTO);
2eadc33f40d4c5 drivers/usb/typec/tcpm.c      Adam Thomson           2018-04-23  3735  		tcpm_pps_complete(port, -EPROTO);
b17dd57118fee7 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-08-10  3736  		tcpm_set_state(port, PORT_RESET, 0);
b17dd57118fee7 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-08-10  3737  		break;
b17dd57118fee7 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-08-10  3738  	case PORT_RESET:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3739  		tcpm_reset_port(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3740  		tcpm_set_cc(port, TYPEC_CC_OPEN);
b17dd57118fee7 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-08-10  3741  		tcpm_set_state(port, PORT_RESET_WAIT_OFF,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3742  			       PD_T_ERROR_RECOVERY);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3743  		break;
b17dd57118fee7 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-08-10  3744  	case PORT_RESET_WAIT_OFF:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3745  		tcpm_set_state(port,
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3746  			       tcpm_default_state(port),
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3747  			       port->vbus_present ? PD_T_PS_SOURCE_OFF : 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3748  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3749  	default:
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3750  		WARN(1, "Unexpected port state %d\n", port->state);
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3751  		break;
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3752  	}
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3753  }
f0690a25a140b8 drivers/staging/typec/tcpm.c  Guenter Roeck          2017-04-27  3754  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 3ef37202ee37..6ea4613af905 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -103,6 +103,13 @@ 
 	S(VCONN_SWAP_TURN_ON_VCONN),		\
 	S(VCONN_SWAP_TURN_OFF_VCONN),		\
 						\
+	S(FR_SWAP_SEND),			\
+	S(FR_SWAP_SEND_TIMEOUT),		\
+	S(FR_SWAP_SNK_SRC_TRANSITION_TO_OFF),			\
+	S(FR_SWAP_SNK_SRC_NEW_SINK_READY),		\
+	S(FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED),	\
+	S(FR_SWAP_CANCEL),			\
+						\
 	S(SNK_TRY),				\
 	S(SNK_TRY_WAIT),			\
 	S(SNK_TRY_WAIT_DEBOUNCE),               \
@@ -124,6 +131,9 @@ 
 	S(GET_PPS_STATUS_SEND),			\
 	S(GET_PPS_STATUS_SEND_TIMEOUT),		\
 						\
+	S(GET_SINK_CAP),			\
+	S(GET_SINK_CAP_TIMEOUT),		\
+						\
 	S(ERROR_RECOVERY),			\
 	S(PORT_RESET),				\
 	S(PORT_RESET_WAIT_OFF)
@@ -172,6 +182,8 @@  enum adev_actions {
 #define TCPM_CC_EVENT		BIT(0)
 #define TCPM_VBUS_EVENT		BIT(1)
 #define TCPM_RESET_EVENT	BIT(2)
+#define TCPM_FRS_EVENT		BIT(3)
+#define TCPM_SOURCING_VBUS	BIT(4)
 
 #define LOG_BUFFER_ENTRIES	1024
 #define LOG_BUFFER_ENTRY_SIZE	128
@@ -181,6 +193,8 @@  enum adev_actions {
 #define SVID_DISCOVERY_MAX	16
 #define ALTMODE_DISCOVERY_MAX	(SVID_DISCOVERY_MAX * MODE_DISCOVERY_MAX)
 
+#define GET_SINK_CAP_RETRY_MS	100
+
 struct pd_mode_data {
 	int svid_index;		/* current SVID index		*/
 	int nsvids;
@@ -256,6 +270,7 @@  struct tcpm_port {
 	struct work_struct event_work;
 	struct delayed_work state_machine;
 	struct delayed_work vdm_state_machine;
+	struct delayed_work enable_frs;
 	bool state_machine_running;
 
 	struct completion tx_complete;
@@ -330,6 +345,12 @@  struct tcpm_port {
 	/* port belongs to a self powered device */
 	bool self_powered;
 
+	/* FRS */
+	enum frs_typec_current frs_current;
+
+	/* Sink caps have been queried */
+	bool sink_cap_done;
+
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *dentry;
 	struct mutex logbuffer_lock;	/* log buffer access lock */
@@ -1646,6 +1667,9 @@  static void tcpm_pd_data_request(struct tcpm_port *port,
 	unsigned int cnt = pd_header_cnt_le(msg->header);
 	unsigned int rev = pd_header_rev_le(msg->header);
 	unsigned int i;
+	enum frs_typec_current frs_current;
+	bool frs_enable;
+	int ret;
 
 	switch (type) {
 	case PD_DATA_SOURCE_CAP:
@@ -1715,7 +1739,21 @@  static void tcpm_pd_data_request(struct tcpm_port *port,
 		/* We don't do anything with this at the moment... */
 		for (i = 0; i < cnt; i++)
 			port->sink_caps[i] = le32_to_cpu(msg->payload[i]);
+
+		frs_current = (port->sink_caps[0] & PDO_FIXED_FRS_CURR_MASK) >>
+			PDO_FIXED_FRS_CURR_SHIFT;
+		frs_enable = frs_current && (frs_current <= port->typec_caps.frs_current);
+		tcpm_log(port,
+			 "Port partner FRS capable partner_frs_current:%u port_frs_current:%u enable:%c",
+			 frs_current, port->typec_caps.frs_current, frs_enable ? 'y' : 'n');
+		if (frs_enable) {
+			ret  = port->tcpc->enable_frs(port->tcpc, true);
+			tcpm_log(port, "Enable FRS %s, ret:%d\n", ret ? "fail" : "success", ret);
+		}
+
 		port->nr_sink_caps = cnt;
+		port->sink_cap_done = true;
+		tcpm_set_state(port, SNK_READY, 0);
 		break;
 	case PD_DATA_VENDOR_DEF:
 		tcpm_handle_vdm_request(port, msg->payload, cnt);
@@ -1810,6 +1848,9 @@  static void tcpm_pd_ctrl_request(struct tcpm_port *port,
 		case VCONN_SWAP_WAIT_FOR_VCONN:
 			tcpm_set_state(port, VCONN_SWAP_TURN_OFF_VCONN, 0);
 			break;
+		case FR_SWAP_SNK_SRC_TRANSITION_TO_OFF:
+			tcpm_set_state(port, FR_SWAP_SNK_SRC_NEW_SINK_READY, 0);
+			break;
 		default:
 			break;
 		}
@@ -1849,6 +1890,13 @@  static void tcpm_pd_ctrl_request(struct tcpm_port *port,
 					     -EAGAIN : -EOPNOTSUPP);
 			tcpm_set_state(port, VCONN_SWAP_CANCEL, 0);
 			break;
+		case FR_SWAP_SEND:
+			tcpm_set_state(port, FR_SWAP_CANCEL, 0);
+			break;
+		case GET_SINK_CAP:
+			port->sink_cap_done = true;
+			tcpm_set_state(port, ready_state(port), 0);
+			break;
 		default:
 			break;
 		}
@@ -1883,6 +1931,9 @@  static void tcpm_pd_ctrl_request(struct tcpm_port *port,
 		case VCONN_SWAP_SEND:
 			tcpm_set_state(port, VCONN_SWAP_START, 0);
 			break;
+		case FR_SWAP_SEND:
+			tcpm_set_state(port, FR_SWAP_SNK_SRC_TRANSITION_TO_OFF, 0);
+			break;
 		default:
 			break;
 		}
@@ -2783,6 +2834,10 @@  static void tcpm_reset_port(struct tcpm_port *port)
 	port->try_src_count = 0;
 	port->try_snk_count = 0;
 	port->usb_type = POWER_SUPPLY_USB_TYPE_C;
+	port->nr_sink_caps = 0;
+	port->sink_cap_done = false;
+	if (port->tcpc->enable_frs)
+		port->tcpc->enable_frs(port->tcpc, false);
 
 	power_supply_changed(port->psy);
 }
@@ -3334,10 +3389,9 @@  static void run_state_machine(struct tcpm_port *port)
 		tcpm_swap_complete(port, 0);
 		tcpm_typec_connect(port);
 		tcpm_check_send_discover(port);
+		mod_delayed_work(port->wq, &port->enable_frs, msecs_to_jiffies(0));
 		tcpm_pps_complete(port, port->pps_status);
-
 		power_supply_changed(port->psy);
-
 		break;
 
 	/* Accessory states */
@@ -3361,9 +3415,13 @@  static void run_state_machine(struct tcpm_port *port)
 		tcpm_set_state(port, HARD_RESET_START, 0);
 		break;
 	case HARD_RESET_START:
+		port->sink_cap_done = false;
+		if (port->tcpc->enable_frs)
+			port->tcpc->enable_frs(port->tcpc, false);
 		port->hard_reset_count++;
 		port->tcpc->set_pd_rx(port->tcpc, false);
 		tcpm_unregister_altmodes(port);
+		port->nr_sink_caps = 0;
 		port->send_discover = true;
 		if (port->pwr_role == TYPEC_SOURCE)
 			tcpm_set_state(port, SRC_HARD_RESET_VBUS_OFF,
@@ -3477,6 +3535,35 @@  static void run_state_machine(struct tcpm_port *port)
 		tcpm_set_state(port, ready_state(port), 0);
 		break;
 
+	case FR_SWAP_SEND:
+		if (tcpm_pd_send_control(port, PD_CTRL_FR_SWAP)) {
+			tcpm_set_state(port, ERROR_RECOVERY, 0);
+			break;
+		}
+		tcpm_set_state_cond(port, FR_SWAP_SEND_TIMEOUT, PD_T_SENDER_RESPONSE);
+		break;
+	case FR_SWAP_SEND_TIMEOUT:
+		tcpm_set_state(port, ERROR_RECOVERY, 0);
+		break;
+	case FR_SWAP_SNK_SRC_TRANSITION_TO_OFF:
+		tcpm_set_state(port, ERROR_RECOVERY, PD_T_PS_SOURCE_OFF);
+		break;
+	case FR_SWAP_SNK_SRC_NEW_SINK_READY:
+		if (port->vbus_source)
+			tcpm_set_state(port, FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED, 0);
+		else
+			tcpm_set_state(port, ERROR_RECOVERY, PD_T_RECEIVER_RESPONSE);
+		break;
+	case FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED:
+		tcpm_set_pwr_role(port, TYPEC_SOURCE);
+		if (tcpm_pd_send_control(port, PD_CTRL_PS_RDY)) {
+			tcpm_set_state(port, ERROR_RECOVERY, 0);
+			break;
+		}
+		tcpm_set_cc(port, tcpm_rp_cc(port));
+		tcpm_set_state(port, SRC_STARTUP, PD_T_SWAP_SRC_START);
+		break;
+
 	/* PR_Swap states */
 	case PR_SWAP_ACCEPT:
 		tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
@@ -3595,6 +3682,7 @@  static void run_state_machine(struct tcpm_port *port)
 	case PR_SWAP_CANCEL:
 	case VCONN_SWAP_CANCEL:
 		tcpm_swap_complete(port, port->swap_status);
+	case FR_SWAP_CANCEL:
 		if (port->pwr_role == TYPEC_SOURCE)
 			tcpm_set_state(port, SRC_READY, 0);
 		else
@@ -3634,6 +3722,14 @@  static void run_state_machine(struct tcpm_port *port)
 	case GET_PPS_STATUS_SEND_TIMEOUT:
 		tcpm_set_state(port, ready_state(port), 0);
 		break;
+	case GET_SINK_CAP:
+		tcpm_pd_send_control(port, PD_CTRL_GET_SINK_CAP);
+		tcpm_set_state(port, GET_SINK_CAP_TIMEOUT, PD_T_SENDER_RESPONSE);
+		break;
+	case GET_SINK_CAP_TIMEOUT:
+		port->sink_cap_done = true;
+		tcpm_set_state(port, ready_state(port), 0);
+		break;
 	case ERROR_RECOVERY:
 		tcpm_swap_complete(port, -EPROTO);
 		tcpm_pps_complete(port, -EPROTO);
@@ -3850,6 +3946,13 @@  static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
 		 * Ignore it.
 		 */
 		break;
+	case FR_SWAP_SEND:
+	case FR_SWAP_SEND_TIMEOUT:
+	case FR_SWAP_SNK_SRC_TRANSITION_TO_OFF:
+	case FR_SWAP_SNK_SRC_NEW_SINK_READY:
+	case FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED:
+		/* Do nothing, CC change expected */
+		break;
 
 	case PORT_RESET:
 	case PORT_RESET_WAIT_OFF:
@@ -3920,6 +4023,9 @@  static void _tcpm_pd_vbus_on(struct tcpm_port *port)
 	case SRC_TRY_DEBOUNCE:
 		/* Do nothing, waiting for sink detection */
 		break;
+	case FR_SWAP_SNK_SRC_NEW_SINK_READY:
+		tcpm_set_state(port, FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED, 0);
+		break;
 
 	case PORT_RESET:
 	case PORT_RESET_WAIT_OFF:
@@ -3995,6 +4101,14 @@  static void _tcpm_pd_vbus_off(struct tcpm_port *port)
 		 */
 		break;
 
+	case FR_SWAP_SEND:
+	case FR_SWAP_SEND_TIMEOUT:
+	case FR_SWAP_SNK_SRC_TRANSITION_TO_OFF:
+	case FR_SWAP_SNK_SRC_NEW_SINK_READY:
+	case FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED:
+		/* Do nothing, vbus drop expected */
+		break;
+
 	default:
 		if (port->pwr_role == TYPEC_SINK &&
 		    port->attached)
@@ -4049,6 +4163,25 @@  static void tcpm_pd_event_handler(struct work_struct *work)
 			if (port->tcpc->get_cc(port->tcpc, &cc1, &cc2) == 0)
 				_tcpm_cc_change(port, cc1, cc2);
 		}
+		if (events & TCPM_FRS_EVENT) {
+			if (port->state == SNK_READY)
+				tcpm_set_state(port, FR_SWAP_SEND, 0);
+			else
+				tcpm_log(port, "Discarding FRS_SIGNAL! Not in sink ready");
+		}
+		if (events & TCPM_SOURCING_VBUS) {
+			tcpm_log(port, "sourcing vbus");
+			/*
+			 * In fast role swap case TCPC autonomously sources vbus. Set vbus_source
+			 * true as TCPM wouldn't have called tcpm_set_vbus.
+			 *
+			 * When vbus is sourced on the command on TCPM i.e. TCPM called
+			 * tcpm_set_vbus to source vbus, vbus_source would already be true.
+			 */
+			port->vbus_source = true;
+			_tcpm_pd_vbus_on(port);
+		}
+
 		spin_lock(&port->pd_event_lock);
 	}
 	spin_unlock(&port->pd_event_lock);
@@ -4082,6 +4215,50 @@  void tcpm_pd_hard_reset(struct tcpm_port *port)
 }
 EXPORT_SYMBOL_GPL(tcpm_pd_hard_reset);
 
+void tcpm_sink_frs(struct tcpm_port *port)
+{
+	spin_lock(&port->pd_event_lock);
+	port->pd_events = TCPM_FRS_EVENT;
+	spin_unlock(&port->pd_event_lock);
+	queue_work(port->wq, &port->event_work);
+}
+EXPORT_SYMBOL_GPL(tcpm_sink_frs);
+
+void tcpm_sourcing_vbus(struct tcpm_port *port)
+{
+	spin_lock(&port->pd_event_lock);
+	port->pd_events = TCPM_SOURCING_VBUS;
+	spin_unlock(&port->pd_event_lock);
+	queue_work(port->wq, &port->event_work);
+}
+EXPORT_SYMBOL_GPL(tcpm_sourcing_vbus);
+
+static void tcpm_enable_frs(struct work_struct *work)
+{
+	struct tcpm_port *port = container_of(work, struct tcpm_port, enable_frs.work);
+
+	mutex_lock(&port->lock);
+	/* Not FRS capable */
+	if (!port->connected || port->port_type != TYPEC_PORT_DRP ||
+	    port->pwr_opmode != TYPEC_PWR_MODE_PD ||
+	    !port->tcpc->enable_frs ||
+	    /* Sink caps queried */
+	    port->sink_cap_done || port->negotiated_rev < PD_REV30)
+		goto unlock;
+
+	/* Send when the state machine is idle */
+	if (port->state != SNK_READY || port->vdm_state != VDM_STATE_DONE || port->send_discover)
+		goto resched;
+
+	tcpm_set_state(port, GET_SINK_CAP, 0);
+	port->sink_cap_done = true;
+
+resched:
+	mod_delayed_work(port->wq, &port->enable_frs, msecs_to_jiffies(GET_SINK_CAP_RETRY_MS));
+unlock:
+	mutex_unlock(&port->lock);
+}
+
 static int tcpm_dr_set(struct typec_port *p, enum typec_data_role data)
 {
 	struct tcpm_port *port = typec_get_drvdata(p);
@@ -4489,7 +4666,7 @@  static int tcpm_fw_get_caps(struct tcpm_port *port,
 {
 	const char *cap_str;
 	int ret;
-	u32 mw;
+	u32 mw, frs_current;
 
 	if (!fwnode)
 		return -EINVAL;
@@ -4558,6 +4735,13 @@  static int tcpm_fw_get_caps(struct tcpm_port *port,
 
 	port->self_powered = fwnode_property_read_bool(fwnode, "self-powered");
 
+	/* FRS can only be supported byb DRP ports */
+	if (port->port_type == TYPEC_PORT_DRP) {
+		ret = fwnode_property_read_u32(fwnode, "frs-typec-current", &frs_current);
+		if (ret >= 0 && frs_current <= FRS_5V_3A)
+			port->typec_caps.frs_current = frs_current;
+	}
+
 	return 0;
 }
 
@@ -4813,6 +4997,7 @@  struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
 	INIT_DELAYED_WORK(&port->state_machine, tcpm_state_machine_work);
 	INIT_DELAYED_WORK(&port->vdm_state_machine, vdm_state_machine_work);
 	INIT_WORK(&port->event_work, tcpm_pd_event_handler);
+	INIT_DELAYED_WORK(&port->enable_frs, tcpm_enable_frs);
 
 	spin_lock_init(&port->pd_event_lock);
 
diff --git a/include/linux/usb/pd.h b/include/linux/usb/pd.h
index b6c233e79bd4..5d8a29c683a4 100644
--- a/include/linux/usb/pd.h
+++ b/include/linux/usb/pd.h
@@ -219,14 +219,16 @@  enum pd_pdo_type {
 #define PDO_CURR_MASK		0x3ff
 #define PDO_PWR_MASK		0x3ff
 
-#define PDO_FIXED_DUAL_ROLE	BIT(29)	/* Power role swap supported */
-#define PDO_FIXED_SUSPEND	BIT(28) /* USB Suspend supported (Source) */
-#define PDO_FIXED_HIGHER_CAP	BIT(28) /* Requires more than vSafe5V (Sink) */
-#define PDO_FIXED_EXTPOWER	BIT(27) /* Externally powered */
-#define PDO_FIXED_USB_COMM	BIT(26) /* USB communications capable */
-#define PDO_FIXED_DATA_SWAP	BIT(25) /* Data role swap supported */
-#define PDO_FIXED_VOLT_SHIFT	10	/* 50mV units */
-#define PDO_FIXED_CURR_SHIFT	0	/* 10mA units */
+#define PDO_FIXED_DUAL_ROLE		BIT(29)	/* Power role swap supported */
+#define PDO_FIXED_SUSPEND		BIT(28) /* USB Suspend supported (Source) */
+#define PDO_FIXED_HIGHER_CAP		BIT(28) /* Requires more than vSafe5V (Sink) */
+#define PDO_FIXED_EXTPOWER		BIT(27) /* Externally powered */
+#define PDO_FIXED_USB_COMM		BIT(26) /* USB communications capable */
+#define PDO_FIXED_DATA_SWAP		BIT(25) /* Data role swap supported */
+#define PDO_FIXED_FRS_CURR_MASK		(BIT(24) | BIT(23)) /* FR_Swap Current (Sink) */
+#define PDO_FIXED_FRS_CURR_SHIFT	23
+#define PDO_FIXED_VOLT_SHIFT		10	/* 50mV units */
+#define PDO_FIXED_CURR_SHIFT		0	/* 10mA units */
 
 #define PDO_FIXED_VOLT(mv)	((((mv) / 50) & PDO_VOLT_MASK) << PDO_FIXED_VOLT_SHIFT)
 #define PDO_FIXED_CURR(ma)	((((ma) / 10) & PDO_CURR_MASK) << PDO_FIXED_CURR_SHIFT)
@@ -454,6 +456,7 @@  static inline unsigned int rdo_max_power(u32 rdo)
 #define PD_T_DB_DETECT		10000	/* 10 - 15 seconds */
 #define PD_T_SEND_SOURCE_CAP	150	/* 100 - 200 ms */
 #define PD_T_SENDER_RESPONSE	60	/* 24 - 30 ms, relaxed */
+#define PD_T_RECEIVER_RESPONSE	15	/* 15ms max */
 #define PD_T_SOURCE_ACTIVITY	45
 #define PD_T_SINK_ACTIVITY	135
 #define PD_T_SINK_WAIT_CAP	240
@@ -473,6 +476,7 @@  static inline unsigned int rdo_max_power(u32 rdo)
 #define PD_T_ERROR_RECOVERY	100	/* minimum 25 is insufficient */
 #define PD_T_SRCSWAPSTDBY      625     /* Maximum of 650ms */
 #define PD_T_NEWSRC            250     /* Maximum of 275ms */
+#define PD_T_SWAP_SRC_START	20	/* Minimum of 20ms */
 
 #define PD_T_DRP_TRY		100	/* 75 - 150 ms */
 #define PD_T_DRP_TRYWAIT	600	/* 400 - 800 ms */
diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h
index 89f58760cf48..09762d26fa0c 100644
--- a/include/linux/usb/tcpm.h
+++ b/include/linux/usb/tcpm.h
@@ -78,8 +78,11 @@  enum tcpm_transmit_type {
  *		automatically if a connection is established.
  * @try_role:	Optional; called to set a preferred role
  * @pd_transmit:Called to transmit PD message
- * @mux:	Pointer to multiplexer data
  * @set_bist_data: Turn on/off bist data mode for compliance testing
+ * @enable_frs:
+ *		Optional; Called to enable/disable PD 3.0 fast role swap.
+ *		Enabling frs is accessory dependent as not all PD3.0
+ *		accessories support fast role swap.
  */
 struct tcpc_dev {
 	struct fwnode_handle *fwnode;
@@ -105,6 +108,7 @@  struct tcpc_dev {
 	int (*pd_transmit)(struct tcpc_dev *dev, enum tcpm_transmit_type type,
 			   const struct pd_message *msg);
 	int (*set_bist_data)(struct tcpc_dev *dev, bool on);
+	int (*enable_frs)(struct tcpc_dev *dev, bool enable);
 };
 
 struct tcpm_port;
@@ -114,6 +118,8 @@  void tcpm_unregister_port(struct tcpm_port *port);
 
 void tcpm_vbus_change(struct tcpm_port *port);
 void tcpm_cc_change(struct tcpm_port *port);
+void tcpm_sink_frs(struct tcpm_port *port);
+void tcpm_sourcing_vbus(struct tcpm_port *port);
 void tcpm_pd_receive(struct tcpm_port *port,
 		     const struct pd_message *msg);
 void tcpm_pd_transmit_complete(struct tcpm_port *port,
diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h
index 9cb1bec94b71..2ec7451a14ab 100644
--- a/include/linux/usb/typec.h
+++ b/include/linux/usb/typec.h
@@ -204,6 +204,18 @@  struct typec_operations {
 			     enum typec_port_type type);
 };
 
+/*
+ * Initial current capability of the new source when vSafe5V is applied during PD3.0 Fast Role Swap.
+ * Based on "Table 6-14 Fixed Supply PDO - Sink" of "USB Power Delivery Specification Revision 3.0,
+ * Version 1.2"
+ */
+enum frs_typec_current {
+	FRS_NOT_SUPPORTED,
+	FRS_DEFAULT_POWER,
+	FRS_5V_1P5A,
+	FRS_5V_3A,
+};
+
 /*
  * struct typec_capability - USB Type-C Port Capabilities
  * @type: Supported power role of the port
@@ -226,6 +238,7 @@  struct typec_capability {
 	int			prefer_role;
 	enum typec_accessory	accessory[TYPEC_MAX_ACCESSORY];
 	unsigned int		orientation_aware:1;
+	enum frs_typec_current	frs_current;
 
 	struct fwnode_handle	*fwnode;
 	void			*driver_data;