1*a2c81616SWang Jie // SPDX-License-Identifier: GPL-2.0+
2*a2c81616SWang Jie /*
3*a2c81616SWang Jie * Copyright 2015-2017 Google, Inc
4*a2c81616SWang Jie *
5*a2c81616SWang Jie * USB Power Delivery protocol stack.
6*a2c81616SWang Jie */
7*a2c81616SWang Jie
8*a2c81616SWang Jie #include <asm/io.h>
9*a2c81616SWang Jie #include <common.h>
10*a2c81616SWang Jie #include <dm.h>
11*a2c81616SWang Jie #include <asm/gpio.h>
12*a2c81616SWang Jie #include <irq-generic.h>
13*a2c81616SWang Jie #include <rk_timer_irq.h>
14*a2c81616SWang Jie #include <power/power_delivery/tcpm.h>
15*a2c81616SWang Jie #include <power/power_delivery/pd_vdo.h>
16*a2c81616SWang Jie
17*a2c81616SWang Jie #define FOREACH_STATE(S) \
18*a2c81616SWang Jie S(INVALID_STATE), \
19*a2c81616SWang Jie S(TOGGLING), \
20*a2c81616SWang Jie S(SRC_UNATTACHED), \
21*a2c81616SWang Jie S(SRC_ATTACH_WAIT), \
22*a2c81616SWang Jie S(SRC_ATTACHED), \
23*a2c81616SWang Jie S(SRC_STARTUP), \
24*a2c81616SWang Jie S(SRC_SEND_CAPABILITIES), \
25*a2c81616SWang Jie S(SRC_SEND_CAPABILITIES_TIMEOUT), \
26*a2c81616SWang Jie S(SRC_NEGOTIATE_CAPABILITIES), \
27*a2c81616SWang Jie S(SRC_TRANSITION_SUPPLY), \
28*a2c81616SWang Jie S(SRC_READY), \
29*a2c81616SWang Jie S(SRC_WAIT_NEW_CAPABILITIES), \
30*a2c81616SWang Jie \
31*a2c81616SWang Jie S(SNK_UNATTACHED), \
32*a2c81616SWang Jie S(SNK_ATTACH_WAIT), \
33*a2c81616SWang Jie S(SNK_DEBOUNCED), \
34*a2c81616SWang Jie S(SNK_ATTACHED), \
35*a2c81616SWang Jie S(SNK_STARTUP), \
36*a2c81616SWang Jie S(SNK_DISCOVERY), \
37*a2c81616SWang Jie S(SNK_DISCOVERY_DEBOUNCE), \
38*a2c81616SWang Jie S(SNK_DISCOVERY_DEBOUNCE_DONE), \
39*a2c81616SWang Jie S(SNK_WAIT_CAPABILITIES), \
40*a2c81616SWang Jie S(SNK_NEGOTIATE_CAPABILITIES), \
41*a2c81616SWang Jie S(SNK_NEGOTIATE_PPS_CAPABILITIES), \
42*a2c81616SWang Jie S(SNK_TRANSITION_SINK), \
43*a2c81616SWang Jie S(SNK_TRANSITION_SINK_VBUS), \
44*a2c81616SWang Jie S(SNK_READY), \
45*a2c81616SWang Jie \
46*a2c81616SWang Jie S(ACC_UNATTACHED), \
47*a2c81616SWang Jie S(DEBUG_ACC_ATTACHED), \
48*a2c81616SWang Jie S(AUDIO_ACC_ATTACHED), \
49*a2c81616SWang Jie S(AUDIO_ACC_DEBOUNCE), \
50*a2c81616SWang Jie \
51*a2c81616SWang Jie S(HARD_RESET_SEND), \
52*a2c81616SWang Jie S(HARD_RESET_START), \
53*a2c81616SWang Jie S(SRC_HARD_RESET_VBUS_OFF), \
54*a2c81616SWang Jie S(SRC_HARD_RESET_VBUS_ON), \
55*a2c81616SWang Jie S(SNK_HARD_RESET_SINK_OFF), \
56*a2c81616SWang Jie S(SNK_HARD_RESET_WAIT_VBUS), \
57*a2c81616SWang Jie S(SNK_HARD_RESET_SINK_ON), \
58*a2c81616SWang Jie \
59*a2c81616SWang Jie S(SOFT_RESET), \
60*a2c81616SWang Jie S(SRC_SOFT_RESET_WAIT_SNK_TX), \
61*a2c81616SWang Jie S(SNK_SOFT_RESET), \
62*a2c81616SWang Jie S(SOFT_RESET_SEND), \
63*a2c81616SWang Jie \
64*a2c81616SWang Jie S(DR_SWAP_ACCEPT), \
65*a2c81616SWang Jie S(DR_SWAP_SEND), \
66*a2c81616SWang Jie S(DR_SWAP_SEND_TIMEOUT), \
67*a2c81616SWang Jie S(DR_SWAP_CANCEL), \
68*a2c81616SWang Jie S(DR_SWAP_CHANGE_DR), \
69*a2c81616SWang Jie \
70*a2c81616SWang Jie S(PR_SWAP_ACCEPT), \
71*a2c81616SWang Jie S(PR_SWAP_SEND), \
72*a2c81616SWang Jie S(PR_SWAP_SEND_TIMEOUT), \
73*a2c81616SWang Jie S(PR_SWAP_CANCEL), \
74*a2c81616SWang Jie S(PR_SWAP_START), \
75*a2c81616SWang Jie S(PR_SWAP_SRC_SNK_TRANSITION_OFF), \
76*a2c81616SWang Jie S(PR_SWAP_SRC_SNK_SOURCE_OFF), \
77*a2c81616SWang Jie S(PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED), \
78*a2c81616SWang Jie S(PR_SWAP_SRC_SNK_SINK_ON), \
79*a2c81616SWang Jie S(PR_SWAP_SNK_SRC_SINK_OFF), \
80*a2c81616SWang Jie S(PR_SWAP_SNK_SRC_SOURCE_ON), \
81*a2c81616SWang Jie S(PR_SWAP_SNK_SRC_SOURCE_ON_VBUS_RAMPED_UP), \
82*a2c81616SWang Jie \
83*a2c81616SWang Jie S(VCONN_SWAP_ACCEPT), \
84*a2c81616SWang Jie S(VCONN_SWAP_SEND), \
85*a2c81616SWang Jie S(VCONN_SWAP_SEND_TIMEOUT), \
86*a2c81616SWang Jie S(VCONN_SWAP_CANCEL), \
87*a2c81616SWang Jie S(VCONN_SWAP_START), \
88*a2c81616SWang Jie S(VCONN_SWAP_WAIT_FOR_VCONN), \
89*a2c81616SWang Jie S(VCONN_SWAP_TURN_ON_VCONN), \
90*a2c81616SWang Jie S(VCONN_SWAP_TURN_OFF_VCONN), \
91*a2c81616SWang Jie \
92*a2c81616SWang Jie S(FR_SWAP_SEND), \
93*a2c81616SWang Jie S(FR_SWAP_SEND_TIMEOUT), \
94*a2c81616SWang Jie S(FR_SWAP_SNK_SRC_TRANSITION_TO_OFF), \
95*a2c81616SWang Jie S(FR_SWAP_SNK_SRC_NEW_SINK_READY), \
96*a2c81616SWang Jie S(FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED), \
97*a2c81616SWang Jie S(FR_SWAP_CANCEL), \
98*a2c81616SWang Jie \
99*a2c81616SWang Jie S(SNK_TRY), \
100*a2c81616SWang Jie S(SNK_TRY_WAIT), \
101*a2c81616SWang Jie S(SNK_TRY_WAIT_DEBOUNCE), \
102*a2c81616SWang Jie S(SNK_TRY_WAIT_DEBOUNCE_CHECK_VBUS), \
103*a2c81616SWang Jie S(SRC_TRYWAIT), \
104*a2c81616SWang Jie S(SRC_TRYWAIT_DEBOUNCE), \
105*a2c81616SWang Jie S(SRC_TRYWAIT_UNATTACHED), \
106*a2c81616SWang Jie \
107*a2c81616SWang Jie S(SRC_TRY), \
108*a2c81616SWang Jie S(SRC_TRY_WAIT), \
109*a2c81616SWang Jie S(SRC_TRY_DEBOUNCE), \
110*a2c81616SWang Jie S(SNK_TRYWAIT), \
111*a2c81616SWang Jie S(SNK_TRYWAIT_DEBOUNCE), \
112*a2c81616SWang Jie S(SNK_TRYWAIT_VBUS), \
113*a2c81616SWang Jie S(BIST_RX), \
114*a2c81616SWang Jie \
115*a2c81616SWang Jie S(GET_STATUS_SEND), \
116*a2c81616SWang Jie S(GET_STATUS_SEND_TIMEOUT), \
117*a2c81616SWang Jie S(GET_PPS_STATUS_SEND), \
118*a2c81616SWang Jie S(GET_PPS_STATUS_SEND_TIMEOUT), \
119*a2c81616SWang Jie \
120*a2c81616SWang Jie S(GET_SINK_CAP), \
121*a2c81616SWang Jie S(GET_SINK_CAP_TIMEOUT), \
122*a2c81616SWang Jie \
123*a2c81616SWang Jie S(ERROR_RECOVERY), \
124*a2c81616SWang Jie S(PORT_RESET), \
125*a2c81616SWang Jie S(PORT_RESET_WAIT_OFF), \
126*a2c81616SWang Jie \
127*a2c81616SWang Jie S(AMS_START), \
128*a2c81616SWang Jie S(CHUNK_NOT_SUPP)
129*a2c81616SWang Jie
130*a2c81616SWang Jie #define FOREACH_AMS(S) \
131*a2c81616SWang Jie S(NONE_AMS), \
132*a2c81616SWang Jie S(POWER_NEGOTIATION), \
133*a2c81616SWang Jie S(GOTOMIN), \
134*a2c81616SWang Jie S(SOFT_RESET_AMS), \
135*a2c81616SWang Jie S(HARD_RESET), \
136*a2c81616SWang Jie S(CABLE_RESET), \
137*a2c81616SWang Jie S(GET_SOURCE_CAPABILITIES), \
138*a2c81616SWang Jie S(GET_SINK_CAPABILITIES), \
139*a2c81616SWang Jie S(POWER_ROLE_SWAP), \
140*a2c81616SWang Jie S(FAST_ROLE_SWAP), \
141*a2c81616SWang Jie S(DATA_ROLE_SWAP), \
142*a2c81616SWang Jie S(VCONN_SWAP), \
143*a2c81616SWang Jie S(SOURCE_ALERT), \
144*a2c81616SWang Jie S(GETTING_SOURCE_EXTENDED_CAPABILITIES),\
145*a2c81616SWang Jie S(GETTING_SOURCE_SINK_STATUS), \
146*a2c81616SWang Jie S(GETTING_BATTERY_CAPABILITIES), \
147*a2c81616SWang Jie S(GETTING_BATTERY_STATUS), \
148*a2c81616SWang Jie S(GETTING_MANUFACTURER_INFORMATION), \
149*a2c81616SWang Jie S(SECURITY), \
150*a2c81616SWang Jie S(FIRMWARE_UPDATE), \
151*a2c81616SWang Jie S(DISCOVER_IDENTITY), \
152*a2c81616SWang Jie S(SOURCE_STARTUP_CABLE_PLUG_DISCOVER_IDENTITY), \
153*a2c81616SWang Jie S(DISCOVER_SVIDS), \
154*a2c81616SWang Jie S(DISCOVER_MODES), \
155*a2c81616SWang Jie S(DFP_TO_UFP_ENTER_MODE), \
156*a2c81616SWang Jie S(DFP_TO_UFP_EXIT_MODE), \
157*a2c81616SWang Jie S(DFP_TO_CABLE_PLUG_ENTER_MODE), \
158*a2c81616SWang Jie S(DFP_TO_CABLE_PLUG_EXIT_MODE), \
159*a2c81616SWang Jie S(ATTENTION), \
160*a2c81616SWang Jie S(BIST), \
161*a2c81616SWang Jie S(UNSTRUCTURED_VDMS), \
162*a2c81616SWang Jie S(STRUCTURED_VDMS), \
163*a2c81616SWang Jie S(COUNTRY_INFO), \
164*a2c81616SWang Jie S(COUNTRY_CODES)
165*a2c81616SWang Jie
166*a2c81616SWang Jie #define GENERATE_ENUM(e) e
167*a2c81616SWang Jie #define GENERATE_STRING(s) #s
168*a2c81616SWang Jie #define TCPM_POLL_EVENT_TIME_OUT 2000
169*a2c81616SWang Jie
170*a2c81616SWang Jie enum tcpm_state {
171*a2c81616SWang Jie FOREACH_STATE(GENERATE_ENUM)
172*a2c81616SWang Jie };
173*a2c81616SWang Jie
174*a2c81616SWang Jie static const char * const tcpm_states[] = {
175*a2c81616SWang Jie FOREACH_STATE(GENERATE_STRING)
176*a2c81616SWang Jie };
177*a2c81616SWang Jie
178*a2c81616SWang Jie enum tcpm_ams {
179*a2c81616SWang Jie FOREACH_AMS(GENERATE_ENUM)
180*a2c81616SWang Jie };
181*a2c81616SWang Jie
182*a2c81616SWang Jie static const char * const tcpm_ams_str[] = {
183*a2c81616SWang Jie FOREACH_AMS(GENERATE_STRING)
184*a2c81616SWang Jie };
185*a2c81616SWang Jie
186*a2c81616SWang Jie enum vdm_states {
187*a2c81616SWang Jie VDM_STATE_ERR_BUSY = -3,
188*a2c81616SWang Jie VDM_STATE_ERR_SEND = -2,
189*a2c81616SWang Jie VDM_STATE_ERR_TMOUT = -1,
190*a2c81616SWang Jie VDM_STATE_DONE = 0,
191*a2c81616SWang Jie /* Anything >0 represents an active state */
192*a2c81616SWang Jie VDM_STATE_READY = 1,
193*a2c81616SWang Jie VDM_STATE_BUSY = 2,
194*a2c81616SWang Jie VDM_STATE_WAIT_RSP_BUSY = 3,
195*a2c81616SWang Jie VDM_STATE_SEND_MESSAGE = 4,
196*a2c81616SWang Jie };
197*a2c81616SWang Jie
198*a2c81616SWang Jie enum pd_msg_request {
199*a2c81616SWang Jie PD_MSG_NONE = 0,
200*a2c81616SWang Jie PD_MSG_CTRL_REJECT,
201*a2c81616SWang Jie PD_MSG_CTRL_WAIT,
202*a2c81616SWang Jie PD_MSG_CTRL_NOT_SUPP,
203*a2c81616SWang Jie PD_MSG_DATA_SINK_CAP,
204*a2c81616SWang Jie PD_MSG_DATA_SOURCE_CAP,
205*a2c81616SWang Jie };
206*a2c81616SWang Jie
207*a2c81616SWang Jie enum adev_actions {
208*a2c81616SWang Jie ADEV_NONE = 0,
209*a2c81616SWang Jie ADEV_NOTIFY_USB_AND_QUEUE_VDM,
210*a2c81616SWang Jie ADEV_QUEUE_VDM,
211*a2c81616SWang Jie ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL,
212*a2c81616SWang Jie ADEV_ATTENTION,
213*a2c81616SWang Jie };
214*a2c81616SWang Jie
215*a2c81616SWang Jie /*
216*a2c81616SWang Jie * Initial current capability of the new source when vSafe5V is applied during PD3.0 Fast Role Swap.
217*a2c81616SWang Jie * Based on "Table 6-14 Fixed Supply PDO - Sink" of "USB Power Delivery Specification Revision 3.0,
218*a2c81616SWang Jie * Version 1.2"
219*a2c81616SWang Jie */
220*a2c81616SWang Jie enum frs_typec_current {
221*a2c81616SWang Jie FRS_NOT_SUPPORTED,
222*a2c81616SWang Jie FRS_DEFAULT_POWER,
223*a2c81616SWang Jie FRS_5V_1P5A,
224*a2c81616SWang Jie FRS_5V_3A,
225*a2c81616SWang Jie };
226*a2c81616SWang Jie
227*a2c81616SWang Jie /* Events from low level driver */
228*a2c81616SWang Jie
229*a2c81616SWang Jie #define TCPM_CC_EVENT BIT(0)
230*a2c81616SWang Jie #define TCPM_VBUS_EVENT BIT(1)
231*a2c81616SWang Jie #define TCPM_RESET_EVENT BIT(2)
232*a2c81616SWang Jie #define TCPM_FRS_EVENT BIT(3)
233*a2c81616SWang Jie #define TCPM_SOURCING_VBUS BIT(4)
234*a2c81616SWang Jie
235*a2c81616SWang Jie #define LOG_BUFFER_ENTRIES 1024
236*a2c81616SWang Jie #define LOG_BUFFER_ENTRY_SIZE 128
237*a2c81616SWang Jie
238*a2c81616SWang Jie /* Alternate mode support */
239*a2c81616SWang Jie
240*a2c81616SWang Jie #define SVID_DISCOVERY_MAX 16
241*a2c81616SWang Jie #define ALTMODE_DISCOVERY_MAX (SVID_DISCOVERY_MAX * MODE_DISCOVERY_MAX)
242*a2c81616SWang Jie
243*a2c81616SWang Jie #define GET_SINK_CAP_RETRY_MS 100
244*a2c81616SWang Jie #define SEND_DISCOVER_RETRY_MS 100
245*a2c81616SWang Jie
246*a2c81616SWang Jie /*
247*a2c81616SWang Jie * @min_volt: Actual min voltage at the local port
248*a2c81616SWang Jie * @req_min_volt: Requested min voltage to the port partner
249*a2c81616SWang Jie * @max_volt: Actual max voltage at the local port
250*a2c81616SWang Jie * @req_max_volt: Requested max voltage to the port partner
251*a2c81616SWang Jie * @max_curr: Actual max current at the local port
252*a2c81616SWang Jie * @req_max_curr: Requested max current of the port partner
253*a2c81616SWang Jie * @req_out_volt: Requested output voltage to the port partner
254*a2c81616SWang Jie * @req_op_curr: Requested operating current to the port partner
255*a2c81616SWang Jie * @supported: Parter has atleast one APDO hence supports PPS
256*a2c81616SWang Jie * @active: PPS mode is active
257*a2c81616SWang Jie */
258*a2c81616SWang Jie struct pd_pps_data {
259*a2c81616SWang Jie u32 min_volt;
260*a2c81616SWang Jie u32 req_min_volt;
261*a2c81616SWang Jie u32 max_volt;
262*a2c81616SWang Jie u32 req_max_volt;
263*a2c81616SWang Jie u32 max_curr;
264*a2c81616SWang Jie u32 req_max_curr;
265*a2c81616SWang Jie u32 req_out_volt;
266*a2c81616SWang Jie u32 req_op_curr;
267*a2c81616SWang Jie bool supported;
268*a2c81616SWang Jie bool active;
269*a2c81616SWang Jie };
270*a2c81616SWang Jie
271*a2c81616SWang Jie enum power_supply_usb_type {
272*a2c81616SWang Jie POWER_SUPPLY_USB_TYPE_UNKNOWN = 0,
273*a2c81616SWang Jie POWER_SUPPLY_USB_TYPE_SDP, /* Standard Downstream Port */
274*a2c81616SWang Jie POWER_SUPPLY_USB_TYPE_DCP, /* Dedicated Charging Port */
275*a2c81616SWang Jie POWER_SUPPLY_USB_TYPE_CDP, /* Charging Downstream Port */
276*a2c81616SWang Jie POWER_SUPPLY_USB_TYPE_ACA, /* Accessory Charger Adapters */
277*a2c81616SWang Jie POWER_SUPPLY_USB_TYPE_C, /* Type C Port */
278*a2c81616SWang Jie POWER_SUPPLY_USB_TYPE_PD, /* Power Delivery Port */
279*a2c81616SWang Jie POWER_SUPPLY_USB_TYPE_PD_DRP, /* PD Dual Role Port */
280*a2c81616SWang Jie POWER_SUPPLY_USB_TYPE_PD_PPS, /* PD Programmable Power Supply */
281*a2c81616SWang Jie POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID, /* Apple Charging Method */
282*a2c81616SWang Jie };
283*a2c81616SWang Jie
284*a2c81616SWang Jie struct tcpm_port {
285*a2c81616SWang Jie struct udevice *dev;
286*a2c81616SWang Jie struct typec_capability typec_caps;
287*a2c81616SWang Jie struct tcpc_dev *tcpc;
288*a2c81616SWang Jie
289*a2c81616SWang Jie enum typec_role vconn_role;
290*a2c81616SWang Jie enum typec_role pwr_role;
291*a2c81616SWang Jie enum typec_data_role data_role;
292*a2c81616SWang Jie enum typec_pwr_opmode pwr_opmode;
293*a2c81616SWang Jie
294*a2c81616SWang Jie struct usb_pd_identity partner_ident;
295*a2c81616SWang Jie struct typec_partner_desc partner_desc;
296*a2c81616SWang Jie struct typec_partner *partner;
297*a2c81616SWang Jie
298*a2c81616SWang Jie enum typec_cc_status cc_req;
299*a2c81616SWang Jie
300*a2c81616SWang Jie enum typec_cc_status cc1;
301*a2c81616SWang Jie enum typec_cc_status cc2;
302*a2c81616SWang Jie enum typec_cc_polarity polarity;
303*a2c81616SWang Jie
304*a2c81616SWang Jie bool attached;
305*a2c81616SWang Jie bool connected;
306*a2c81616SWang Jie int poll_event_cnt;
307*a2c81616SWang Jie enum typec_port_type port_type;
308*a2c81616SWang Jie
309*a2c81616SWang Jie /*
310*a2c81616SWang Jie * Set to true when vbus is greater than VSAFE5V min.
311*a2c81616SWang Jie * Set to false when vbus falls below vSinkDisconnect max threshold.
312*a2c81616SWang Jie */
313*a2c81616SWang Jie bool vbus_present;
314*a2c81616SWang Jie
315*a2c81616SWang Jie /*
316*a2c81616SWang Jie * Set to true when vbus is less than VSAFE0V max.
317*a2c81616SWang Jie * Set to false when vbus is greater than VSAFE0V max.
318*a2c81616SWang Jie */
319*a2c81616SWang Jie bool vbus_vsafe0v;
320*a2c81616SWang Jie
321*a2c81616SWang Jie bool vbus_never_low;
322*a2c81616SWang Jie bool vbus_source;
323*a2c81616SWang Jie bool vbus_charge;
324*a2c81616SWang Jie
325*a2c81616SWang Jie /* Set to true when Discover_Identity Command is expected to be sent in Ready states. */
326*a2c81616SWang Jie bool send_discover;
327*a2c81616SWang Jie bool op_vsafe5v;
328*a2c81616SWang Jie
329*a2c81616SWang Jie int try_role;
330*a2c81616SWang Jie int try_snk_count;
331*a2c81616SWang Jie int try_src_count;
332*a2c81616SWang Jie
333*a2c81616SWang Jie enum pd_msg_request queued_message;
334*a2c81616SWang Jie
335*a2c81616SWang Jie enum tcpm_state enter_state;
336*a2c81616SWang Jie enum tcpm_state prev_state;
337*a2c81616SWang Jie enum tcpm_state state;
338*a2c81616SWang Jie enum tcpm_state delayed_state;
339*a2c81616SWang Jie unsigned long delay_ms;
340*a2c81616SWang Jie
341*a2c81616SWang Jie spinlock_t pd_event_lock;
342*a2c81616SWang Jie u32 pd_events;
343*a2c81616SWang Jie
344*a2c81616SWang Jie bool state_machine_running;
345*a2c81616SWang Jie /* Set to true when VDM State Machine has following actions. */
346*a2c81616SWang Jie bool vdm_sm_running;
347*a2c81616SWang Jie
348*a2c81616SWang Jie bool tx_complete;
349*a2c81616SWang Jie enum tcpm_transmit_status tx_status;
350*a2c81616SWang Jie
351*a2c81616SWang Jie struct mutex swap_lock; /* swap command lock */
352*a2c81616SWang Jie bool swap_pending;
353*a2c81616SWang Jie bool non_pd_role_swap;
354*a2c81616SWang Jie int swap_status;
355*a2c81616SWang Jie
356*a2c81616SWang Jie unsigned int negotiated_rev;
357*a2c81616SWang Jie unsigned int message_id;
358*a2c81616SWang Jie unsigned int caps_count;
359*a2c81616SWang Jie unsigned int hard_reset_count;
360*a2c81616SWang Jie bool pd_capable;
361*a2c81616SWang Jie bool explicit_contract;
362*a2c81616SWang Jie unsigned int rx_msgid;
363*a2c81616SWang Jie
364*a2c81616SWang Jie /* Partner capabilities/requests */
365*a2c81616SWang Jie u32 sink_request;
366*a2c81616SWang Jie u32 source_caps[PDO_MAX_OBJECTS];
367*a2c81616SWang Jie unsigned int nr_source_caps;
368*a2c81616SWang Jie u32 sink_caps[PDO_MAX_OBJECTS];
369*a2c81616SWang Jie unsigned int nr_sink_caps;
370*a2c81616SWang Jie
371*a2c81616SWang Jie /*
372*a2c81616SWang Jie * whether to wait for the Type-C device to send the DR_SWAP Message flag
373*a2c81616SWang Jie * For Type-C device with Dual-Role Power and Dual-Role Data, the port side
374*a2c81616SWang Jie * is used as sink + ufp, then the tcpm framework needs to wait for Type-C
375*a2c81616SWang Jie * device to initiate DR_swap Message.
376*a2c81616SWang Jie */
377*a2c81616SWang Jie bool wait_dr_swap_Message;
378*a2c81616SWang Jie
379*a2c81616SWang Jie /* Local capabilities */
380*a2c81616SWang Jie u32 src_pdo[PDO_MAX_OBJECTS];
381*a2c81616SWang Jie unsigned int nr_src_pdo;
382*a2c81616SWang Jie u32 snk_pdo[PDO_MAX_OBJECTS];
383*a2c81616SWang Jie unsigned int nr_snk_pdo;
384*a2c81616SWang Jie u32 snk_vdo_v1[VDO_MAX_OBJECTS];
385*a2c81616SWang Jie unsigned int nr_snk_vdo_v1;
386*a2c81616SWang Jie u32 snk_vdo[VDO_MAX_OBJECTS];
387*a2c81616SWang Jie unsigned int nr_snk_vdo;
388*a2c81616SWang Jie
389*a2c81616SWang Jie unsigned int operating_snk_mw;
390*a2c81616SWang Jie bool update_sink_caps;
391*a2c81616SWang Jie
392*a2c81616SWang Jie /* Requested current / voltage to the port partner */
393*a2c81616SWang Jie u32 req_current_limit;
394*a2c81616SWang Jie u32 req_supply_voltage;
395*a2c81616SWang Jie /* Actual current / voltage limit of the local port */
396*a2c81616SWang Jie u32 current_limit;
397*a2c81616SWang Jie u32 supply_voltage;
398*a2c81616SWang Jie
399*a2c81616SWang Jie enum power_supply_usb_type usb_type;
400*a2c81616SWang Jie
401*a2c81616SWang Jie u32 bist_request;
402*a2c81616SWang Jie
403*a2c81616SWang Jie /* PD state for Vendor Defined Messages */
404*a2c81616SWang Jie enum vdm_states vdm_state;
405*a2c81616SWang Jie u32 vdm_retries;
406*a2c81616SWang Jie /* next Vendor Defined Message to send */
407*a2c81616SWang Jie u32 vdo_data[VDO_MAX_SIZE];
408*a2c81616SWang Jie u8 vdo_count;
409*a2c81616SWang Jie /* VDO to retry if UFP responder replied busy */
410*a2c81616SWang Jie u32 vdo_retry;
411*a2c81616SWang Jie
412*a2c81616SWang Jie /* PPS */
413*a2c81616SWang Jie struct pd_pps_data pps_data;
414*a2c81616SWang Jie bool pps_pending;
415*a2c81616SWang Jie int pps_status;
416*a2c81616SWang Jie
417*a2c81616SWang Jie /* Deadline in jiffies to exit src_try_wait state */
418*a2c81616SWang Jie unsigned long max_wait;
419*a2c81616SWang Jie
420*a2c81616SWang Jie /* port belongs to a self powered device */
421*a2c81616SWang Jie bool self_powered;
422*a2c81616SWang Jie
423*a2c81616SWang Jie /* Sink FRS */
424*a2c81616SWang Jie enum frs_typec_current new_source_frs_current;
425*a2c81616SWang Jie
426*a2c81616SWang Jie /* Sink caps have been queried */
427*a2c81616SWang Jie bool sink_cap_done;
428*a2c81616SWang Jie
429*a2c81616SWang Jie /* Port is still in tCCDebounce */
430*a2c81616SWang Jie bool debouncing;
431*a2c81616SWang Jie
432*a2c81616SWang Jie /* Collision Avoidance and Atomic Message Sequence */
433*a2c81616SWang Jie enum tcpm_state upcoming_state;
434*a2c81616SWang Jie enum tcpm_ams ams;
435*a2c81616SWang Jie enum tcpm_ams next_ams;
436*a2c81616SWang Jie bool in_ams;
437*a2c81616SWang Jie
438*a2c81616SWang Jie /* Auto vbus discharge status */
439*a2c81616SWang Jie bool auto_vbus_discharge_enabled;
440*a2c81616SWang Jie
441*a2c81616SWang Jie /*
442*a2c81616SWang Jie * When set, port requests PD_P_SNK_STDBY_MW upon entering SNK_DISCOVERY and
443*a2c81616SWang Jie * the actual currrent limit after RX of PD_CTRL_PSRDY for PD link,
444*a2c81616SWang Jie * SNK_READY for non-pd link.
445*a2c81616SWang Jie */
446*a2c81616SWang Jie bool slow_charger_loop;
447*a2c81616SWang Jie #ifdef CONFIG_DEBUG_FS
448*a2c81616SWang Jie struct dentry *dentry;
449*a2c81616SWang Jie struct mutex logbuffer_lock; /* log buffer access lock */
450*a2c81616SWang Jie int logbuffer_head;
451*a2c81616SWang Jie int logbuffer_tail;
452*a2c81616SWang Jie u8 *logbuffer[LOG_BUFFER_ENTRIES];
453*a2c81616SWang Jie #endif
454*a2c81616SWang Jie };
455*a2c81616SWang Jie
456*a2c81616SWang Jie struct pd_rx_event {
457*a2c81616SWang Jie struct tcpm_port *port;
458*a2c81616SWang Jie struct pd_message msg;
459*a2c81616SWang Jie };
460*a2c81616SWang Jie
461*a2c81616SWang Jie static const char * const pd_rev[] = {
462*a2c81616SWang Jie [PD_REV10] = "rev1",
463*a2c81616SWang Jie [PD_REV20] = "rev2",
464*a2c81616SWang Jie [PD_REV30] = "rev3",
465*a2c81616SWang Jie };
466*a2c81616SWang Jie
467*a2c81616SWang Jie #define tcpm_cc_is_sink(cc) \
468*a2c81616SWang Jie ((cc) == TYPEC_CC_RP_DEF || (cc) == TYPEC_CC_RP_1_5 || \
469*a2c81616SWang Jie (cc) == TYPEC_CC_RP_3_0)
470*a2c81616SWang Jie
471*a2c81616SWang Jie #define tcpm_port_is_sink(port) \
472*a2c81616SWang Jie ((tcpm_cc_is_sink((port)->cc1) && !tcpm_cc_is_sink((port)->cc2)) || \
473*a2c81616SWang Jie (tcpm_cc_is_sink((port)->cc2) && !tcpm_cc_is_sink((port)->cc1)))
474*a2c81616SWang Jie
475*a2c81616SWang Jie #define tcpm_cc_is_source(cc) ((cc) == TYPEC_CC_RD)
476*a2c81616SWang Jie #define tcpm_cc_is_audio(cc) ((cc) == TYPEC_CC_RA)
477*a2c81616SWang Jie #define tcpm_cc_is_open(cc) ((cc) == TYPEC_CC_OPEN)
478*a2c81616SWang Jie
479*a2c81616SWang Jie #define tcpm_port_is_source(port) \
480*a2c81616SWang Jie ((tcpm_cc_is_source((port)->cc1) && \
481*a2c81616SWang Jie !tcpm_cc_is_source((port)->cc2)) || \
482*a2c81616SWang Jie (tcpm_cc_is_source((port)->cc2) && \
483*a2c81616SWang Jie !tcpm_cc_is_source((port)->cc1)))
484*a2c81616SWang Jie
485*a2c81616SWang Jie #define tcpm_port_is_debug(port) \
486*a2c81616SWang Jie (tcpm_cc_is_source((port)->cc1) && tcpm_cc_is_source((port)->cc2))
487*a2c81616SWang Jie
488*a2c81616SWang Jie #define tcpm_port_is_audio(port) \
489*a2c81616SWang Jie (tcpm_cc_is_audio((port)->cc1) && tcpm_cc_is_audio((port)->cc2))
490*a2c81616SWang Jie
491*a2c81616SWang Jie #define tcpm_port_is_audio_detached(port) \
492*a2c81616SWang Jie ((tcpm_cc_is_audio((port)->cc1) && tcpm_cc_is_open((port)->cc2)) || \
493*a2c81616SWang Jie (tcpm_cc_is_audio((port)->cc2) && tcpm_cc_is_open((port)->cc1)))
494*a2c81616SWang Jie
495*a2c81616SWang Jie #define tcpm_try_snk(port) \
496*a2c81616SWang Jie ((port)->try_snk_count == 0 && (port)->try_role == TYPEC_SINK && \
497*a2c81616SWang Jie (port)->port_type == TYPEC_PORT_DRP)
498*a2c81616SWang Jie
499*a2c81616SWang Jie #define tcpm_try_src(port) \
500*a2c81616SWang Jie ((port)->try_src_count == 0 && (port)->try_role == TYPEC_SOURCE && \
501*a2c81616SWang Jie (port)->port_type == TYPEC_PORT_DRP)
502*a2c81616SWang Jie
503*a2c81616SWang Jie #define tcpm_data_role_for_source(port) \
504*a2c81616SWang Jie ((port)->typec_caps.data == TYPEC_PORT_UFP ? \
505*a2c81616SWang Jie TYPEC_DEVICE : TYPEC_HOST)
506*a2c81616SWang Jie
507*a2c81616SWang Jie #define tcpm_data_role_for_sink(port) \
508*a2c81616SWang Jie ((port)->typec_caps.data == TYPEC_PORT_DFP ? \
509*a2c81616SWang Jie TYPEC_HOST : TYPEC_DEVICE)
510*a2c81616SWang Jie
tcpm_default_state(struct tcpm_port * port)511*a2c81616SWang Jie static enum tcpm_state tcpm_default_state(struct tcpm_port *port)
512*a2c81616SWang Jie {
513*a2c81616SWang Jie if (port->port_type == TYPEC_PORT_DRP) {
514*a2c81616SWang Jie if (port->try_role == TYPEC_SINK)
515*a2c81616SWang Jie return SNK_UNATTACHED;
516*a2c81616SWang Jie else if (port->try_role == TYPEC_SOURCE)
517*a2c81616SWang Jie return SRC_UNATTACHED;
518*a2c81616SWang Jie /* Fall through to return SRC_UNATTACHED */
519*a2c81616SWang Jie } else if (port->port_type == TYPEC_PORT_SNK) {
520*a2c81616SWang Jie return SNK_UNATTACHED;
521*a2c81616SWang Jie }
522*a2c81616SWang Jie return SRC_UNATTACHED;
523*a2c81616SWang Jie }
524*a2c81616SWang Jie
tcpm_port_is_disconnected(struct tcpm_port * port)525*a2c81616SWang Jie static bool tcpm_port_is_disconnected(struct tcpm_port *port)
526*a2c81616SWang Jie {
527*a2c81616SWang Jie return (!port->attached && port->cc1 == TYPEC_CC_OPEN &&
528*a2c81616SWang Jie port->cc2 == TYPEC_CC_OPEN) ||
529*a2c81616SWang Jie (port->attached && ((port->polarity == TYPEC_POLARITY_CC1 &&
530*a2c81616SWang Jie port->cc1 == TYPEC_CC_OPEN) ||
531*a2c81616SWang Jie (port->polarity == TYPEC_POLARITY_CC2 &&
532*a2c81616SWang Jie port->cc2 == TYPEC_CC_OPEN)));
533*a2c81616SWang Jie }
534*a2c81616SWang Jie
tcpm_set_cc(struct tcpm_port * port,enum typec_cc_status cc)535*a2c81616SWang Jie static void tcpm_set_cc(struct tcpm_port *port, enum typec_cc_status cc)
536*a2c81616SWang Jie {
537*a2c81616SWang Jie debug("%s: cc = %d", __func__, cc);
538*a2c81616SWang Jie port->cc_req = cc;
539*a2c81616SWang Jie port->tcpc->set_cc(port->tcpc, cc);
540*a2c81616SWang Jie }
541*a2c81616SWang Jie
542*a2c81616SWang Jie /*
543*a2c81616SWang Jie * Determine RP value to set based on maximum current supported
544*a2c81616SWang Jie * by a port if configured as source.
545*a2c81616SWang Jie * Returns CC value to report to link partner.
546*a2c81616SWang Jie */
tcpm_rp_cc(struct tcpm_port * port)547*a2c81616SWang Jie static enum typec_cc_status tcpm_rp_cc(struct tcpm_port *port)
548*a2c81616SWang Jie {
549*a2c81616SWang Jie const u32 *src_pdo = port->src_pdo;
550*a2c81616SWang Jie int nr_pdo = port->nr_src_pdo;
551*a2c81616SWang Jie int i;
552*a2c81616SWang Jie
553*a2c81616SWang Jie /*
554*a2c81616SWang Jie * Search for first entry with matching voltage.
555*a2c81616SWang Jie * It should report the maximum supported current.
556*a2c81616SWang Jie */
557*a2c81616SWang Jie for (i = 0; i < nr_pdo; i++) {
558*a2c81616SWang Jie const u32 pdo = src_pdo[i];
559*a2c81616SWang Jie
560*a2c81616SWang Jie if (pdo_type(pdo) == PDO_TYPE_FIXED &&
561*a2c81616SWang Jie pdo_fixed_voltage(pdo) == 5000) {
562*a2c81616SWang Jie unsigned int curr = pdo_max_current(pdo);
563*a2c81616SWang Jie
564*a2c81616SWang Jie if (curr >= 3000)
565*a2c81616SWang Jie return TYPEC_CC_RP_3_0;
566*a2c81616SWang Jie else if (curr >= 1500)
567*a2c81616SWang Jie return TYPEC_CC_RP_1_5;
568*a2c81616SWang Jie return TYPEC_CC_RP_DEF;
569*a2c81616SWang Jie }
570*a2c81616SWang Jie }
571*a2c81616SWang Jie
572*a2c81616SWang Jie return TYPEC_CC_RP_DEF;
573*a2c81616SWang Jie }
574*a2c81616SWang Jie
tcpm_pd_transmit(struct tcpm_port * port,enum tcpm_transmit_type type,const struct pd_message * msg)575*a2c81616SWang Jie static int tcpm_pd_transmit(struct tcpm_port *port,
576*a2c81616SWang Jie enum tcpm_transmit_type type,
577*a2c81616SWang Jie const struct pd_message *msg)
578*a2c81616SWang Jie {
579*a2c81616SWang Jie int ret;
580*a2c81616SWang Jie int timeout = PD_T_TCPC_TX_TIMEOUT;
581*a2c81616SWang Jie
582*a2c81616SWang Jie if (msg)
583*a2c81616SWang Jie debug("PD TX, header: %#x\n", le16_to_cpu(msg->header));
584*a2c81616SWang Jie else
585*a2c81616SWang Jie debug("PD TX, type: %#x\n", type);
586*a2c81616SWang Jie
587*a2c81616SWang Jie port->tx_complete = false;
588*a2c81616SWang Jie ret = port->tcpc->pd_transmit(port->tcpc, type, msg, port->negotiated_rev);
589*a2c81616SWang Jie if (ret < 0)
590*a2c81616SWang Jie return ret;
591*a2c81616SWang Jie
592*a2c81616SWang Jie while ((timeout > 0) && (!port->tx_complete)) {
593*a2c81616SWang Jie port->tcpc->poll_event(port->tcpc);
594*a2c81616SWang Jie udelay(1000);
595*a2c81616SWang Jie timeout--;
596*a2c81616SWang Jie }
597*a2c81616SWang Jie
598*a2c81616SWang Jie if (!timeout) {
599*a2c81616SWang Jie printf("%s: pd transmit data timeout\n", __func__);
600*a2c81616SWang Jie return -ETIMEDOUT;
601*a2c81616SWang Jie }
602*a2c81616SWang Jie
603*a2c81616SWang Jie switch (port->tx_status) {
604*a2c81616SWang Jie case TCPC_TX_SUCCESS:
605*a2c81616SWang Jie port->message_id = (port->message_id + 1) & PD_HEADER_ID_MASK;
606*a2c81616SWang Jie break;
607*a2c81616SWang Jie case TCPC_TX_DISCARDED:
608*a2c81616SWang Jie ret = -EAGAIN;
609*a2c81616SWang Jie break;
610*a2c81616SWang Jie case TCPC_TX_FAILED:
611*a2c81616SWang Jie default:
612*a2c81616SWang Jie ret = -EIO;
613*a2c81616SWang Jie break;
614*a2c81616SWang Jie }
615*a2c81616SWang Jie
616*a2c81616SWang Jie return ret;
617*a2c81616SWang Jie }
618*a2c81616SWang Jie
tcpm_pd_transmit_complete(struct tcpm_port * port,enum tcpm_transmit_status status)619*a2c81616SWang Jie void tcpm_pd_transmit_complete(struct tcpm_port *port,
620*a2c81616SWang Jie enum tcpm_transmit_status status)
621*a2c81616SWang Jie {
622*a2c81616SWang Jie debug("%s: PD TX complete, status: %u\n", __func__, status);
623*a2c81616SWang Jie port->poll_event_cnt = 0;
624*a2c81616SWang Jie port->tx_status = status;
625*a2c81616SWang Jie port->tx_complete = true;
626*a2c81616SWang Jie }
627*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpm_pd_transmit_complete);
628*a2c81616SWang Jie
tcpm_set_polarity(struct tcpm_port * port,enum typec_cc_polarity polarity)629*a2c81616SWang Jie static int tcpm_set_polarity(struct tcpm_port *port,
630*a2c81616SWang Jie enum typec_cc_polarity polarity)
631*a2c81616SWang Jie {
632*a2c81616SWang Jie int ret;
633*a2c81616SWang Jie
634*a2c81616SWang Jie debug("%s: polarity %d\n", __func__, polarity);
635*a2c81616SWang Jie
636*a2c81616SWang Jie ret = port->tcpc->set_polarity(port->tcpc, polarity);
637*a2c81616SWang Jie if (ret < 0)
638*a2c81616SWang Jie return ret;
639*a2c81616SWang Jie
640*a2c81616SWang Jie port->polarity = polarity;
641*a2c81616SWang Jie
642*a2c81616SWang Jie return 0;
643*a2c81616SWang Jie }
644*a2c81616SWang Jie
tcpm_set_vconn(struct tcpm_port * port,bool enable)645*a2c81616SWang Jie static int tcpm_set_vconn(struct tcpm_port *port, bool enable)
646*a2c81616SWang Jie {
647*a2c81616SWang Jie int ret;
648*a2c81616SWang Jie
649*a2c81616SWang Jie debug("%s: vconn = %d\n", __func__, enable);
650*a2c81616SWang Jie
651*a2c81616SWang Jie ret = port->tcpc->set_vconn(port->tcpc, enable);
652*a2c81616SWang Jie if (!ret)
653*a2c81616SWang Jie port->vconn_role = enable ? TYPEC_SOURCE : TYPEC_SINK;
654*a2c81616SWang Jie
655*a2c81616SWang Jie return ret;
656*a2c81616SWang Jie }
657*a2c81616SWang Jie
tcpm_get_current_limit(struct tcpm_port * port)658*a2c81616SWang Jie static u32 tcpm_get_current_limit(struct tcpm_port *port)
659*a2c81616SWang Jie {
660*a2c81616SWang Jie enum typec_cc_status cc;
661*a2c81616SWang Jie u32 limit;
662*a2c81616SWang Jie
663*a2c81616SWang Jie cc = port->polarity ? port->cc2 : port->cc1;
664*a2c81616SWang Jie switch (cc) {
665*a2c81616SWang Jie case TYPEC_CC_RP_1_5:
666*a2c81616SWang Jie limit = 1500;
667*a2c81616SWang Jie break;
668*a2c81616SWang Jie case TYPEC_CC_RP_3_0:
669*a2c81616SWang Jie limit = 3000;
670*a2c81616SWang Jie break;
671*a2c81616SWang Jie case TYPEC_CC_RP_DEF:
672*a2c81616SWang Jie default:
673*a2c81616SWang Jie if (port->tcpc->get_current_limit)
674*a2c81616SWang Jie limit = port->tcpc->get_current_limit(port->tcpc);
675*a2c81616SWang Jie else
676*a2c81616SWang Jie limit = 0;
677*a2c81616SWang Jie break;
678*a2c81616SWang Jie }
679*a2c81616SWang Jie
680*a2c81616SWang Jie return limit;
681*a2c81616SWang Jie }
682*a2c81616SWang Jie
tcpm_set_current_limit(struct tcpm_port * port,u32 max_ma,u32 mv)683*a2c81616SWang Jie static int tcpm_set_current_limit(struct tcpm_port *port, u32 max_ma, u32 mv)
684*a2c81616SWang Jie {
685*a2c81616SWang Jie int ret = -EOPNOTSUPP;
686*a2c81616SWang Jie
687*a2c81616SWang Jie debug("Setting voltage/current limit %u mV %u mA\n", mv, max_ma);
688*a2c81616SWang Jie
689*a2c81616SWang Jie port->supply_voltage = mv;
690*a2c81616SWang Jie port->current_limit = max_ma;
691*a2c81616SWang Jie
692*a2c81616SWang Jie if (port->tcpc->set_current_limit)
693*a2c81616SWang Jie ret = port->tcpc->set_current_limit(port->tcpc, max_ma, mv);
694*a2c81616SWang Jie
695*a2c81616SWang Jie return ret;
696*a2c81616SWang Jie }
697*a2c81616SWang Jie
tcpm_set_attached_state(struct tcpm_port * port,bool attached)698*a2c81616SWang Jie static int tcpm_set_attached_state(struct tcpm_port *port, bool attached)
699*a2c81616SWang Jie {
700*a2c81616SWang Jie return port->tcpc->set_roles(port->tcpc, attached, port->pwr_role,
701*a2c81616SWang Jie port->data_role);
702*a2c81616SWang Jie }
703*a2c81616SWang Jie
tcpm_set_roles(struct tcpm_port * port,bool attached,enum typec_role role,enum typec_data_role data)704*a2c81616SWang Jie static int tcpm_set_roles(struct tcpm_port *port, bool attached,
705*a2c81616SWang Jie enum typec_role role, enum typec_data_role data)
706*a2c81616SWang Jie {
707*a2c81616SWang Jie #if 0
708*a2c81616SWang Jie enum typec_orientation orientation;
709*a2c81616SWang Jie enum usb_role usb_role;
710*a2c81616SWang Jie #endif
711*a2c81616SWang Jie int ret;
712*a2c81616SWang Jie
713*a2c81616SWang Jie #if 0
714*a2c81616SWang Jie if (port->polarity == TYPEC_POLARITY_CC1)
715*a2c81616SWang Jie orientation = TYPEC_ORIENTATION_NORMAL;
716*a2c81616SWang Jie else
717*a2c81616SWang Jie orientation = TYPEC_ORIENTATION_REVERSE;
718*a2c81616SWang Jie
719*a2c81616SWang Jie if (data == TYPEC_HOST)
720*a2c81616SWang Jie usb_role = USB_ROLE_HOST;
721*a2c81616SWang Jie else
722*a2c81616SWang Jie usb_role = USB_ROLE_DEVICE;
723*a2c81616SWang Jie
724*a2c81616SWang Jie ret = tcpm_mux_set(port, TYPEC_STATE_USB, usb_role, orientation);
725*a2c81616SWang Jie if (ret < 0)
726*a2c81616SWang Jie return ret;
727*a2c81616SWang Jie #endif
728*a2c81616SWang Jie
729*a2c81616SWang Jie ret = port->tcpc->set_roles(port->tcpc, attached, role, data);
730*a2c81616SWang Jie if (ret < 0)
731*a2c81616SWang Jie return ret;
732*a2c81616SWang Jie
733*a2c81616SWang Jie port->pwr_role = role;
734*a2c81616SWang Jie port->data_role = data;
735*a2c81616SWang Jie #if 0
736*a2c81616SWang Jie typec_set_data_role(port->typec_port, data);
737*a2c81616SWang Jie typec_set_pwr_role(port->typec_port, role);
738*a2c81616SWang Jie #endif
739*a2c81616SWang Jie
740*a2c81616SWang Jie return 0;
741*a2c81616SWang Jie }
742*a2c81616SWang Jie
tcpm_pd_send_source_caps(struct tcpm_port * port)743*a2c81616SWang Jie static int tcpm_pd_send_source_caps(struct tcpm_port *port)
744*a2c81616SWang Jie {
745*a2c81616SWang Jie struct pd_message msg;
746*a2c81616SWang Jie int i;
747*a2c81616SWang Jie
748*a2c81616SWang Jie memset(&msg, 0, sizeof(msg));
749*a2c81616SWang Jie
750*a2c81616SWang Jie if (!port->nr_src_pdo) {
751*a2c81616SWang Jie /* No source capabilities defined, sink only */
752*a2c81616SWang Jie msg.header = PD_HEADER_LE(PD_CTRL_REJECT,
753*a2c81616SWang Jie port->pwr_role,
754*a2c81616SWang Jie port->data_role,
755*a2c81616SWang Jie port->negotiated_rev,
756*a2c81616SWang Jie port->message_id, 0);
757*a2c81616SWang Jie } else {
758*a2c81616SWang Jie msg.header = PD_HEADER_LE(PD_DATA_SOURCE_CAP,
759*a2c81616SWang Jie port->pwr_role,
760*a2c81616SWang Jie port->data_role,
761*a2c81616SWang Jie port->negotiated_rev,
762*a2c81616SWang Jie port->message_id,
763*a2c81616SWang Jie port->nr_src_pdo);
764*a2c81616SWang Jie }
765*a2c81616SWang Jie
766*a2c81616SWang Jie for (i = 0; i < port->nr_src_pdo; i++)
767*a2c81616SWang Jie msg.payload[i] = cpu_to_le32(port->src_pdo[i]);
768*a2c81616SWang Jie
769*a2c81616SWang Jie return tcpm_pd_transmit(port, TCPC_TX_SOP, &msg);
770*a2c81616SWang Jie }
771*a2c81616SWang Jie
tcpm_pd_send_sink_caps(struct tcpm_port * port)772*a2c81616SWang Jie static int tcpm_pd_send_sink_caps(struct tcpm_port *port)
773*a2c81616SWang Jie {
774*a2c81616SWang Jie struct pd_message msg;
775*a2c81616SWang Jie unsigned int i;
776*a2c81616SWang Jie
777*a2c81616SWang Jie memset(&msg, 0, sizeof(msg));
778*a2c81616SWang Jie
779*a2c81616SWang Jie if (!port->nr_snk_pdo) {
780*a2c81616SWang Jie /* No sink capabilities defined, source only */
781*a2c81616SWang Jie msg.header = PD_HEADER_LE(PD_CTRL_REJECT,
782*a2c81616SWang Jie port->pwr_role,
783*a2c81616SWang Jie port->data_role,
784*a2c81616SWang Jie port->negotiated_rev,
785*a2c81616SWang Jie port->message_id, 0);
786*a2c81616SWang Jie } else {
787*a2c81616SWang Jie msg.header = PD_HEADER_LE(PD_DATA_SINK_CAP,
788*a2c81616SWang Jie port->pwr_role,
789*a2c81616SWang Jie port->data_role,
790*a2c81616SWang Jie port->negotiated_rev,
791*a2c81616SWang Jie port->message_id,
792*a2c81616SWang Jie port->nr_snk_pdo);
793*a2c81616SWang Jie }
794*a2c81616SWang Jie
795*a2c81616SWang Jie for (i = 0; i < port->nr_snk_pdo; i++)
796*a2c81616SWang Jie msg.payload[i] = cpu_to_le32(port->snk_pdo[i]);
797*a2c81616SWang Jie
798*a2c81616SWang Jie return tcpm_pd_transmit(port, TCPC_TX_SOP, &msg);
799*a2c81616SWang Jie }
800*a2c81616SWang Jie
801*a2c81616SWang Jie static void tcpm_state_machine(struct tcpm_port *port);
802*a2c81616SWang Jie static void tcpm_timer_uninit(struct tcpm_port *port);
tcpm_timer_irq(int irq,void * data)803*a2c81616SWang Jie static void tcpm_timer_irq(int irq, void *data)
804*a2c81616SWang Jie {
805*a2c81616SWang Jie struct tcpm_port *port = data;
806*a2c81616SWang Jie
807*a2c81616SWang Jie writel(TIMER_CLR_INT, TIMER_BASE + TIMER_INTSTATUS);
808*a2c81616SWang Jie tcpm_timer_uninit(port);
809*a2c81616SWang Jie tcpm_state_machine(port);
810*a2c81616SWang Jie }
811*a2c81616SWang Jie
tcpm_timer_init(struct tcpm_port * port,uint32_t ms)812*a2c81616SWang Jie static void tcpm_timer_init(struct tcpm_port *port, uint32_t ms)
813*a2c81616SWang Jie {
814*a2c81616SWang Jie uint64_t period = 24000ULL * ms;
815*a2c81616SWang Jie
816*a2c81616SWang Jie /* Disable before conifg */
817*a2c81616SWang Jie writel(0, TIMER_BASE + TIMER_CTRL);
818*a2c81616SWang Jie
819*a2c81616SWang Jie /* Config */
820*a2c81616SWang Jie writel((uint32_t)period, TIMER_BASE + TIMER_LOAD_COUNT0);
821*a2c81616SWang Jie writel((uint32_t)(period >> 32), TIMER_BASE + TIMER_LOAD_COUNT1);
822*a2c81616SWang Jie writel(TIMER_CLR_INT, TIMER_BASE + TIMER_INTSTATUS);
823*a2c81616SWang Jie writel(TIMER_EN | TIMER_INT_EN, TIMER_BASE + TIMER_CTRL);
824*a2c81616SWang Jie
825*a2c81616SWang Jie /* IRQ */
826*a2c81616SWang Jie irq_install_handler(TIMER_IRQ,
827*a2c81616SWang Jie (interrupt_handler_t *)tcpm_timer_irq, port);
828*a2c81616SWang Jie irq_handler_enable(TIMER_IRQ);
829*a2c81616SWang Jie }
830*a2c81616SWang Jie
tcpm_timer_uninit(struct tcpm_port * port)831*a2c81616SWang Jie static void tcpm_timer_uninit(struct tcpm_port *port)
832*a2c81616SWang Jie {
833*a2c81616SWang Jie writel(0, TIMER_BASE + TIMER_CTRL);
834*a2c81616SWang Jie
835*a2c81616SWang Jie irq_handler_disable(TIMER_IRQ);
836*a2c81616SWang Jie irq_free_handler(TIMER_IRQ);
837*a2c81616SWang Jie }
838*a2c81616SWang Jie
mod_tcpm_delayed_work(struct tcpm_port * port,unsigned int delay_ms)839*a2c81616SWang Jie static void mod_tcpm_delayed_work(struct tcpm_port *port, unsigned int delay_ms)
840*a2c81616SWang Jie {
841*a2c81616SWang Jie if (delay_ms) {
842*a2c81616SWang Jie tcpm_timer_init(port, delay_ms);
843*a2c81616SWang Jie } else {
844*a2c81616SWang Jie tcpm_timer_uninit(port);
845*a2c81616SWang Jie tcpm_state_machine(port);
846*a2c81616SWang Jie }
847*a2c81616SWang Jie }
848*a2c81616SWang Jie
tcpm_set_state(struct tcpm_port * port,enum tcpm_state state,unsigned int delay_ms)849*a2c81616SWang Jie static void tcpm_set_state(struct tcpm_port *port, enum tcpm_state state,
850*a2c81616SWang Jie unsigned int delay_ms)
851*a2c81616SWang Jie {
852*a2c81616SWang Jie debug("%s: line = %d, delay_ms = %d, set state = %s\n",
853*a2c81616SWang Jie __func__, __LINE__, delay_ms, tcpm_states[state]);
854*a2c81616SWang Jie
855*a2c81616SWang Jie if (delay_ms) {
856*a2c81616SWang Jie debug("pending state change %s -> %s @ %u ms [%s]\n",
857*a2c81616SWang Jie tcpm_states[port->state], tcpm_states[state], delay_ms,
858*a2c81616SWang Jie pd_rev[port->negotiated_rev]);
859*a2c81616SWang Jie port->delayed_state = state;
860*a2c81616SWang Jie mod_tcpm_delayed_work(port, delay_ms);
861*a2c81616SWang Jie port->delay_ms = delay_ms;
862*a2c81616SWang Jie } else {
863*a2c81616SWang Jie debug("state change %s -> %s\n",
864*a2c81616SWang Jie tcpm_states[port->state], tcpm_states[state]);
865*a2c81616SWang Jie port->delayed_state = INVALID_STATE;
866*a2c81616SWang Jie port->prev_state = port->state;
867*a2c81616SWang Jie port->state = state;
868*a2c81616SWang Jie /*
869*a2c81616SWang Jie * Don't re-queue the state machine work item if we're currently
870*a2c81616SWang Jie * in the state machine and we're immediately changing states.
871*a2c81616SWang Jie * tcpm_state_machine_work() will continue running the state
872*a2c81616SWang Jie * machine.
873*a2c81616SWang Jie */
874*a2c81616SWang Jie if (!port->state_machine_running)
875*a2c81616SWang Jie mod_tcpm_delayed_work(port, 0);
876*a2c81616SWang Jie }
877*a2c81616SWang Jie }
878*a2c81616SWang Jie
tcpm_set_state_cond(struct tcpm_port * port,enum tcpm_state state,unsigned int delay_ms)879*a2c81616SWang Jie static void tcpm_set_state_cond(struct tcpm_port *port, enum tcpm_state state,
880*a2c81616SWang Jie unsigned int delay_ms)
881*a2c81616SWang Jie {
882*a2c81616SWang Jie if (port->enter_state == port->state)
883*a2c81616SWang Jie tcpm_set_state(port, state, delay_ms);
884*a2c81616SWang Jie else
885*a2c81616SWang Jie debug("skipped %sstate change %s -> %s [%u ms], context state %s [%s %s]\n",
886*a2c81616SWang Jie delay_ms ? "delayed " : "",
887*a2c81616SWang Jie tcpm_states[port->state], tcpm_states[state],
888*a2c81616SWang Jie delay_ms, tcpm_states[port->enter_state],
889*a2c81616SWang Jie pd_rev[port->negotiated_rev], tcpm_ams_str[port->ams]);
890*a2c81616SWang Jie }
891*a2c81616SWang Jie
tcpm_queue_message(struct tcpm_port * port,enum pd_msg_request message)892*a2c81616SWang Jie static void tcpm_queue_message(struct tcpm_port *port,
893*a2c81616SWang Jie enum pd_msg_request message)
894*a2c81616SWang Jie {
895*a2c81616SWang Jie port->queued_message = message;
896*a2c81616SWang Jie mod_tcpm_delayed_work(port, 0);
897*a2c81616SWang Jie }
898*a2c81616SWang Jie
899*a2c81616SWang Jie #if 0
900*a2c81616SWang Jie static void tcpm_pd_handle_msg(struct tcpm_port *port,
901*a2c81616SWang Jie enum pd_msg_request message,
902*a2c81616SWang Jie enum tcpm_ams ams);
903*a2c81616SWang Jie #endif
904*a2c81616SWang Jie
905*a2c81616SWang Jie enum pdo_err {
906*a2c81616SWang Jie PDO_NO_ERR,
907*a2c81616SWang Jie PDO_ERR_NO_VSAFE5V,
908*a2c81616SWang Jie PDO_ERR_VSAFE5V_NOT_FIRST,
909*a2c81616SWang Jie PDO_ERR_PDO_TYPE_NOT_IN_ORDER,
910*a2c81616SWang Jie PDO_ERR_FIXED_NOT_SORTED,
911*a2c81616SWang Jie PDO_ERR_VARIABLE_BATT_NOT_SORTED,
912*a2c81616SWang Jie PDO_ERR_DUPE_PDO,
913*a2c81616SWang Jie PDO_ERR_PPS_APDO_NOT_SORTED,
914*a2c81616SWang Jie PDO_ERR_DUPE_PPS_APDO,
915*a2c81616SWang Jie };
916*a2c81616SWang Jie
917*a2c81616SWang Jie static const char * const pdo_err_msg[] = {
918*a2c81616SWang Jie [PDO_ERR_NO_VSAFE5V] =
919*a2c81616SWang Jie " err: source/sink caps should atleast have vSafe5V",
920*a2c81616SWang Jie [PDO_ERR_VSAFE5V_NOT_FIRST] =
921*a2c81616SWang Jie " err: vSafe5V Fixed Supply Object Shall always be the first object",
922*a2c81616SWang Jie [PDO_ERR_PDO_TYPE_NOT_IN_ORDER] =
923*a2c81616SWang Jie " err: PDOs should be in the following order: Fixed; Battery; Variable",
924*a2c81616SWang Jie [PDO_ERR_FIXED_NOT_SORTED] =
925*a2c81616SWang Jie " err: Fixed supply pdos should be in increasing order of their fixed voltage",
926*a2c81616SWang Jie [PDO_ERR_VARIABLE_BATT_NOT_SORTED] =
927*a2c81616SWang Jie " err: Variable/Battery supply pdos should be in increasing order of their minimum voltage",
928*a2c81616SWang Jie [PDO_ERR_DUPE_PDO] =
929*a2c81616SWang Jie " err: Variable/Batt supply pdos cannot have same min/max voltage",
930*a2c81616SWang Jie [PDO_ERR_PPS_APDO_NOT_SORTED] =
931*a2c81616SWang Jie " err: Programmable power supply apdos should be in increasing order of their maximum voltage",
932*a2c81616SWang Jie [PDO_ERR_DUPE_PPS_APDO] =
933*a2c81616SWang Jie " err: Programmable power supply apdos cannot have same min/max voltage and max current",
934*a2c81616SWang Jie };
935*a2c81616SWang Jie
tcpm_caps_err(struct tcpm_port * port,const u32 * pdo,unsigned int nr_pdo)936*a2c81616SWang Jie static enum pdo_err tcpm_caps_err(struct tcpm_port *port, const u32 *pdo,
937*a2c81616SWang Jie unsigned int nr_pdo)
938*a2c81616SWang Jie {
939*a2c81616SWang Jie unsigned int i;
940*a2c81616SWang Jie
941*a2c81616SWang Jie /* Should at least contain vSafe5v */
942*a2c81616SWang Jie if (nr_pdo < 1)
943*a2c81616SWang Jie return PDO_ERR_NO_VSAFE5V;
944*a2c81616SWang Jie
945*a2c81616SWang Jie /* The vSafe5V Fixed Supply Object Shall always be the first object */
946*a2c81616SWang Jie if (pdo_type(pdo[0]) != PDO_TYPE_FIXED ||
947*a2c81616SWang Jie pdo_fixed_voltage(pdo[0]) != VSAFE5V)
948*a2c81616SWang Jie return PDO_ERR_VSAFE5V_NOT_FIRST;
949*a2c81616SWang Jie
950*a2c81616SWang Jie for (i = 1; i < nr_pdo; i++) {
951*a2c81616SWang Jie if (pdo_type(pdo[i]) < pdo_type(pdo[i - 1])) {
952*a2c81616SWang Jie return PDO_ERR_PDO_TYPE_NOT_IN_ORDER;
953*a2c81616SWang Jie } else if (pdo_type(pdo[i]) == pdo_type(pdo[i - 1])) {
954*a2c81616SWang Jie enum pd_pdo_type type = pdo_type(pdo[i]);
955*a2c81616SWang Jie
956*a2c81616SWang Jie switch (type) {
957*a2c81616SWang Jie /*
958*a2c81616SWang Jie * The remaining Fixed Supply Objects, if
959*a2c81616SWang Jie * present, shall be sent in voltage order;
960*a2c81616SWang Jie * lowest to highest.
961*a2c81616SWang Jie */
962*a2c81616SWang Jie case PDO_TYPE_FIXED:
963*a2c81616SWang Jie if (pdo_fixed_voltage(pdo[i]) <=
964*a2c81616SWang Jie pdo_fixed_voltage(pdo[i - 1]))
965*a2c81616SWang Jie return PDO_ERR_FIXED_NOT_SORTED;
966*a2c81616SWang Jie break;
967*a2c81616SWang Jie /*
968*a2c81616SWang Jie * The Battery Supply Objects and Variable
969*a2c81616SWang Jie * supply, if present shall be sent in Minimum
970*a2c81616SWang Jie * Voltage order; lowest to highest.
971*a2c81616SWang Jie */
972*a2c81616SWang Jie case PDO_TYPE_VAR:
973*a2c81616SWang Jie case PDO_TYPE_BATT:
974*a2c81616SWang Jie if (pdo_min_voltage(pdo[i]) <
975*a2c81616SWang Jie pdo_min_voltage(pdo[i - 1]))
976*a2c81616SWang Jie return PDO_ERR_VARIABLE_BATT_NOT_SORTED;
977*a2c81616SWang Jie else if ((pdo_min_voltage(pdo[i]) ==
978*a2c81616SWang Jie pdo_min_voltage(pdo[i - 1])) &&
979*a2c81616SWang Jie (pdo_max_voltage(pdo[i]) ==
980*a2c81616SWang Jie pdo_max_voltage(pdo[i - 1])))
981*a2c81616SWang Jie return PDO_ERR_DUPE_PDO;
982*a2c81616SWang Jie break;
983*a2c81616SWang Jie /*
984*a2c81616SWang Jie * The Programmable Power Supply APDOs, if present,
985*a2c81616SWang Jie * shall be sent in Maximum Voltage order;
986*a2c81616SWang Jie * lowest to highest.
987*a2c81616SWang Jie */
988*a2c81616SWang Jie case PDO_TYPE_APDO:
989*a2c81616SWang Jie if (pdo_apdo_type(pdo[i]) != APDO_TYPE_PPS)
990*a2c81616SWang Jie break;
991*a2c81616SWang Jie
992*a2c81616SWang Jie if (pdo_pps_apdo_max_voltage(pdo[i]) <
993*a2c81616SWang Jie pdo_pps_apdo_max_voltage(pdo[i - 1]))
994*a2c81616SWang Jie return PDO_ERR_PPS_APDO_NOT_SORTED;
995*a2c81616SWang Jie else if (pdo_pps_apdo_min_voltage(pdo[i]) ==
996*a2c81616SWang Jie pdo_pps_apdo_min_voltage(pdo[i - 1]) &&
997*a2c81616SWang Jie pdo_pps_apdo_max_voltage(pdo[i]) ==
998*a2c81616SWang Jie pdo_pps_apdo_max_voltage(pdo[i - 1]) &&
999*a2c81616SWang Jie pdo_pps_apdo_max_current(pdo[i]) ==
1000*a2c81616SWang Jie pdo_pps_apdo_max_current(pdo[i - 1]))
1001*a2c81616SWang Jie return PDO_ERR_DUPE_PPS_APDO;
1002*a2c81616SWang Jie break;
1003*a2c81616SWang Jie default:
1004*a2c81616SWang Jie printf("%s: Unknown pdo type\n", __func__);
1005*a2c81616SWang Jie }
1006*a2c81616SWang Jie }
1007*a2c81616SWang Jie }
1008*a2c81616SWang Jie
1009*a2c81616SWang Jie return PDO_NO_ERR;
1010*a2c81616SWang Jie }
1011*a2c81616SWang Jie
tcpm_validate_caps(struct tcpm_port * port,const u32 * pdo,unsigned int nr_pdo)1012*a2c81616SWang Jie static int tcpm_validate_caps(struct tcpm_port *port, const u32 *pdo,
1013*a2c81616SWang Jie unsigned int nr_pdo)
1014*a2c81616SWang Jie {
1015*a2c81616SWang Jie enum pdo_err err_index = tcpm_caps_err(port, pdo, nr_pdo);
1016*a2c81616SWang Jie
1017*a2c81616SWang Jie if (err_index != PDO_NO_ERR) {
1018*a2c81616SWang Jie printf("%s", pdo_err_msg[err_index]);
1019*a2c81616SWang Jie return -EINVAL;
1020*a2c81616SWang Jie }
1021*a2c81616SWang Jie
1022*a2c81616SWang Jie return 0;
1023*a2c81616SWang Jie }
1024*a2c81616SWang Jie
1025*a2c81616SWang Jie /*
1026*a2c81616SWang Jie * PD (data, control) command handling functions
1027*a2c81616SWang Jie */
ready_state(struct tcpm_port * port)1028*a2c81616SWang Jie static inline enum tcpm_state ready_state(struct tcpm_port *port)
1029*a2c81616SWang Jie {
1030*a2c81616SWang Jie if (port->pwr_role == TYPEC_SOURCE)
1031*a2c81616SWang Jie return SRC_READY;
1032*a2c81616SWang Jie else
1033*a2c81616SWang Jie return SNK_READY;
1034*a2c81616SWang Jie }
1035*a2c81616SWang Jie
1036*a2c81616SWang Jie static int tcpm_pd_send_control(struct tcpm_port *port,
1037*a2c81616SWang Jie enum pd_ctrl_msg_type type);
1038*a2c81616SWang Jie
1039*a2c81616SWang Jie #if 0
1040*a2c81616SWang Jie static void tcpm_pd_handle_msg(struct tcpm_port *port,
1041*a2c81616SWang Jie enum pd_msg_request message,
1042*a2c81616SWang Jie enum tcpm_ams ams)
1043*a2c81616SWang Jie {
1044*a2c81616SWang Jie switch (port->state) {
1045*a2c81616SWang Jie case SRC_READY:
1046*a2c81616SWang Jie case SNK_READY:
1047*a2c81616SWang Jie port->ams = ams;
1048*a2c81616SWang Jie tcpm_queue_message(port, message);
1049*a2c81616SWang Jie break;
1050*a2c81616SWang Jie /* PD 3.0 Spec 8.3.3.4.1.1 and 6.8.1 */
1051*a2c81616SWang Jie case SNK_TRANSITION_SINK:
1052*a2c81616SWang Jie case SNK_TRANSITION_SINK_VBUS:
1053*a2c81616SWang Jie case SRC_TRANSITION_SUPPLY:
1054*a2c81616SWang Jie tcpm_set_state(port, HARD_RESET_SEND, 0);
1055*a2c81616SWang Jie break;
1056*a2c81616SWang Jie default:
1057*a2c81616SWang Jie if (!tcpm_ams_interruptible(port)) {
1058*a2c81616SWang Jie tcpm_set_state(port, port->pwr_role == TYPEC_SOURCE ?
1059*a2c81616SWang Jie SRC_SOFT_RESET_WAIT_SNK_TX :
1060*a2c81616SWang Jie SNK_SOFT_RESET,
1061*a2c81616SWang Jie 0);
1062*a2c81616SWang Jie } else {
1063*a2c81616SWang Jie port->next_ams = ams;
1064*a2c81616SWang Jie tcpm_set_state(port, ready_state(port), 0);
1065*a2c81616SWang Jie /* 6.8.1 process the Message */
1066*a2c81616SWang Jie tcpm_queue_message(port, message);
1067*a2c81616SWang Jie }
1068*a2c81616SWang Jie break;
1069*a2c81616SWang Jie }
1070*a2c81616SWang Jie }
1071*a2c81616SWang Jie #endif
1072*a2c81616SWang Jie
tcpm_pd_data_request(struct tcpm_port * port,const struct pd_message * msg)1073*a2c81616SWang Jie static void tcpm_pd_data_request(struct tcpm_port *port,
1074*a2c81616SWang Jie const struct pd_message *msg)
1075*a2c81616SWang Jie {
1076*a2c81616SWang Jie enum pd_data_msg_type type = pd_header_type_le(msg->header);
1077*a2c81616SWang Jie unsigned int cnt = pd_header_cnt_le(msg->header);
1078*a2c81616SWang Jie unsigned int rev = pd_header_rev_le(msg->header);
1079*a2c81616SWang Jie unsigned int i;
1080*a2c81616SWang Jie
1081*a2c81616SWang Jie switch (type) {
1082*a2c81616SWang Jie case PD_DATA_SOURCE_CAP:
1083*a2c81616SWang Jie for (i = 0; i < cnt; i++)
1084*a2c81616SWang Jie port->source_caps[i] = le32_to_cpu(msg->payload[i]);
1085*a2c81616SWang Jie
1086*a2c81616SWang Jie port->nr_source_caps = cnt;
1087*a2c81616SWang Jie
1088*a2c81616SWang Jie tcpm_validate_caps(port, port->source_caps,
1089*a2c81616SWang Jie port->nr_source_caps);
1090*a2c81616SWang Jie
1091*a2c81616SWang Jie /*
1092*a2c81616SWang Jie * Adjust revision in subsequent message headers, as required,
1093*a2c81616SWang Jie * to comply with 6.2.1.1.5 of the USB PD 3.0 spec. We don't
1094*a2c81616SWang Jie * support Rev 1.0 so just do nothing in that scenario.
1095*a2c81616SWang Jie */
1096*a2c81616SWang Jie if (rev == PD_REV10) {
1097*a2c81616SWang Jie break;
1098*a2c81616SWang Jie }
1099*a2c81616SWang Jie
1100*a2c81616SWang Jie if (rev < PD_MAX_REV)
1101*a2c81616SWang Jie port->negotiated_rev = rev;
1102*a2c81616SWang Jie
1103*a2c81616SWang Jie if ((pdo_type(port->source_caps[0]) == PDO_TYPE_FIXED) &&
1104*a2c81616SWang Jie (port->source_caps[0] & PDO_FIXED_DUAL_ROLE) &&
1105*a2c81616SWang Jie (port->source_caps[0] & PDO_FIXED_DATA_SWAP)) {
1106*a2c81616SWang Jie /* Dual role power and data, eg: self-powered Type-C */
1107*a2c81616SWang Jie port->wait_dr_swap_Message = true;
1108*a2c81616SWang Jie } else {
1109*a2c81616SWang Jie /* Non-Dual role power, eg: adapter */
1110*a2c81616SWang Jie port->wait_dr_swap_Message = false;
1111*a2c81616SWang Jie }
1112*a2c81616SWang Jie
1113*a2c81616SWang Jie /*
1114*a2c81616SWang Jie * This message may be received even if VBUS is not
1115*a2c81616SWang Jie * present. This is quite unexpected; see USB PD
1116*a2c81616SWang Jie * specification, sections 8.3.3.6.3.1 and 8.3.3.6.3.2.
1117*a2c81616SWang Jie * However, at the same time, we must be ready to
1118*a2c81616SWang Jie * receive this message and respond to it 15ms after
1119*a2c81616SWang Jie * receiving PS_RDY during power swap operations, no matter
1120*a2c81616SWang Jie * if VBUS is available or not (USB PD specification,
1121*a2c81616SWang Jie * section 6.5.9.2).
1122*a2c81616SWang Jie * So we need to accept the message either way,
1123*a2c81616SWang Jie * but be prepared to keep waiting for VBUS after it was
1124*a2c81616SWang Jie * handled.
1125*a2c81616SWang Jie */
1126*a2c81616SWang Jie tcpm_set_state(port, SNK_NEGOTIATE_CAPABILITIES, 0);
1127*a2c81616SWang Jie break;
1128*a2c81616SWang Jie case PD_DATA_REQUEST:
1129*a2c81616SWang Jie /*
1130*a2c81616SWang Jie * Adjust revision in subsequent message headers, as required,
1131*a2c81616SWang Jie * to comply with 6.2.1.1.5 of the USB PD 3.0 spec. We don't
1132*a2c81616SWang Jie * support Rev 1.0 so just reject in that scenario.
1133*a2c81616SWang Jie */
1134*a2c81616SWang Jie if (rev == PD_REV10) {
1135*a2c81616SWang Jie tcpm_queue_message(port, PD_MSG_CTRL_REJECT);
1136*a2c81616SWang Jie break;
1137*a2c81616SWang Jie }
1138*a2c81616SWang Jie
1139*a2c81616SWang Jie if (rev < PD_MAX_REV)
1140*a2c81616SWang Jie port->negotiated_rev = rev;
1141*a2c81616SWang Jie
1142*a2c81616SWang Jie port->sink_request = le32_to_cpu(msg->payload[0]);
1143*a2c81616SWang Jie
1144*a2c81616SWang Jie tcpm_set_state(port, SRC_NEGOTIATE_CAPABILITIES, 0);
1145*a2c81616SWang Jie break;
1146*a2c81616SWang Jie case PD_DATA_SINK_CAP:
1147*a2c81616SWang Jie /* We don't do anything with this at the moment... */
1148*a2c81616SWang Jie for (i = 0; i < cnt; i++)
1149*a2c81616SWang Jie port->sink_caps[i] = le32_to_cpu(msg->payload[i]);
1150*a2c81616SWang Jie
1151*a2c81616SWang Jie port->nr_sink_caps = cnt;
1152*a2c81616SWang Jie break;
1153*a2c81616SWang Jie default:
1154*a2c81616SWang Jie break;
1155*a2c81616SWang Jie }
1156*a2c81616SWang Jie }
1157*a2c81616SWang Jie
tcpm_pd_ctrl_request(struct tcpm_port * port,const struct pd_message * msg)1158*a2c81616SWang Jie static void tcpm_pd_ctrl_request(struct tcpm_port *port,
1159*a2c81616SWang Jie const struct pd_message *msg)
1160*a2c81616SWang Jie {
1161*a2c81616SWang Jie enum pd_ctrl_msg_type type = pd_header_type_le(msg->header);
1162*a2c81616SWang Jie enum tcpm_state next_state;
1163*a2c81616SWang Jie
1164*a2c81616SWang Jie switch (type) {
1165*a2c81616SWang Jie case PD_CTRL_GOOD_CRC:
1166*a2c81616SWang Jie case PD_CTRL_PING:
1167*a2c81616SWang Jie break;
1168*a2c81616SWang Jie case PD_CTRL_GET_SOURCE_CAP:
1169*a2c81616SWang Jie switch (port->state) {
1170*a2c81616SWang Jie case SRC_READY:
1171*a2c81616SWang Jie case SNK_READY:
1172*a2c81616SWang Jie tcpm_queue_message(port, PD_MSG_DATA_SOURCE_CAP);
1173*a2c81616SWang Jie break;
1174*a2c81616SWang Jie default:
1175*a2c81616SWang Jie tcpm_queue_message(port, PD_MSG_CTRL_REJECT);
1176*a2c81616SWang Jie break;
1177*a2c81616SWang Jie }
1178*a2c81616SWang Jie break;
1179*a2c81616SWang Jie case PD_CTRL_GET_SINK_CAP:
1180*a2c81616SWang Jie switch (port->state) {
1181*a2c81616SWang Jie case SRC_READY:
1182*a2c81616SWang Jie case SNK_READY:
1183*a2c81616SWang Jie tcpm_queue_message(port, PD_MSG_DATA_SINK_CAP);
1184*a2c81616SWang Jie break;
1185*a2c81616SWang Jie default:
1186*a2c81616SWang Jie tcpm_queue_message(port, PD_MSG_CTRL_REJECT);
1187*a2c81616SWang Jie break;
1188*a2c81616SWang Jie }
1189*a2c81616SWang Jie break;
1190*a2c81616SWang Jie case PD_CTRL_GOTO_MIN:
1191*a2c81616SWang Jie break;
1192*a2c81616SWang Jie case PD_CTRL_PS_RDY:
1193*a2c81616SWang Jie switch (port->state) {
1194*a2c81616SWang Jie case SNK_TRANSITION_SINK:
1195*a2c81616SWang Jie if (port->vbus_present) {
1196*a2c81616SWang Jie tcpm_set_current_limit(port,
1197*a2c81616SWang Jie port->req_current_limit,
1198*a2c81616SWang Jie port->req_supply_voltage);
1199*a2c81616SWang Jie port->explicit_contract = true;
1200*a2c81616SWang Jie tcpm_set_state(port, SNK_READY, 0);
1201*a2c81616SWang Jie } else {
1202*a2c81616SWang Jie /*
1203*a2c81616SWang Jie * Seen after power swap. Keep waiting for VBUS
1204*a2c81616SWang Jie * in a transitional state.
1205*a2c81616SWang Jie */
1206*a2c81616SWang Jie tcpm_set_state(port,
1207*a2c81616SWang Jie SNK_TRANSITION_SINK_VBUS, 0);
1208*a2c81616SWang Jie }
1209*a2c81616SWang Jie break;
1210*a2c81616SWang Jie default:
1211*a2c81616SWang Jie break;
1212*a2c81616SWang Jie }
1213*a2c81616SWang Jie break;
1214*a2c81616SWang Jie case PD_CTRL_REJECT:
1215*a2c81616SWang Jie case PD_CTRL_WAIT:
1216*a2c81616SWang Jie case PD_CTRL_NOT_SUPP:
1217*a2c81616SWang Jie switch (port->state) {
1218*a2c81616SWang Jie case SNK_NEGOTIATE_CAPABILITIES:
1219*a2c81616SWang Jie /* USB PD specification, Figure 8-43 */
1220*a2c81616SWang Jie if (port->explicit_contract)
1221*a2c81616SWang Jie next_state = SNK_READY;
1222*a2c81616SWang Jie else
1223*a2c81616SWang Jie next_state = SNK_WAIT_CAPABILITIES;
1224*a2c81616SWang Jie
1225*a2c81616SWang Jie tcpm_set_state(port, next_state, 0);
1226*a2c81616SWang Jie break;
1227*a2c81616SWang Jie case SNK_NEGOTIATE_PPS_CAPABILITIES:
1228*a2c81616SWang Jie /* Revert data back from any requested PPS updates */
1229*a2c81616SWang Jie port->pps_data.req_out_volt = port->supply_voltage;
1230*a2c81616SWang Jie port->pps_data.req_op_curr = port->current_limit;
1231*a2c81616SWang Jie port->pps_status = (type == PD_CTRL_WAIT ?
1232*a2c81616SWang Jie -EAGAIN : -EOPNOTSUPP);
1233*a2c81616SWang Jie tcpm_set_state(port, SNK_READY, 0);
1234*a2c81616SWang Jie break;
1235*a2c81616SWang Jie default:
1236*a2c81616SWang Jie break;
1237*a2c81616SWang Jie }
1238*a2c81616SWang Jie break;
1239*a2c81616SWang Jie case PD_CTRL_ACCEPT:
1240*a2c81616SWang Jie switch (port->state) {
1241*a2c81616SWang Jie case SNK_NEGOTIATE_CAPABILITIES:
1242*a2c81616SWang Jie port->pps_data.active = false;
1243*a2c81616SWang Jie tcpm_set_state(port, SNK_TRANSITION_SINK, 0);
1244*a2c81616SWang Jie break;
1245*a2c81616SWang Jie case SNK_NEGOTIATE_PPS_CAPABILITIES:
1246*a2c81616SWang Jie port->pps_data.active = true;
1247*a2c81616SWang Jie /* ???? */
1248*a2c81616SWang Jie port->pps_data.min_volt = port->pps_data.req_min_volt;
1249*a2c81616SWang Jie port->pps_data.max_volt = port->pps_data.req_max_volt;
1250*a2c81616SWang Jie port->pps_data.max_curr = port->pps_data.req_max_curr;
1251*a2c81616SWang Jie port->req_supply_voltage = port->pps_data.req_out_volt;
1252*a2c81616SWang Jie port->req_current_limit = port->pps_data.req_op_curr;
1253*a2c81616SWang Jie tcpm_set_state(port, SNK_TRANSITION_SINK, 0);
1254*a2c81616SWang Jie break;
1255*a2c81616SWang Jie case SOFT_RESET_SEND:
1256*a2c81616SWang Jie port->message_id = 0;
1257*a2c81616SWang Jie port->rx_msgid = -1;
1258*a2c81616SWang Jie if (port->pwr_role == TYPEC_SOURCE)
1259*a2c81616SWang Jie next_state = SRC_SEND_CAPABILITIES;
1260*a2c81616SWang Jie else
1261*a2c81616SWang Jie next_state = SNK_WAIT_CAPABILITIES;
1262*a2c81616SWang Jie tcpm_set_state(port, next_state, 0);
1263*a2c81616SWang Jie break;
1264*a2c81616SWang Jie default:
1265*a2c81616SWang Jie break;
1266*a2c81616SWang Jie }
1267*a2c81616SWang Jie break;
1268*a2c81616SWang Jie case PD_CTRL_SOFT_RESET:
1269*a2c81616SWang Jie tcpm_set_state(port, SOFT_RESET, 0);
1270*a2c81616SWang Jie break;
1271*a2c81616SWang Jie case PD_CTRL_DR_SWAP:
1272*a2c81616SWang Jie if (port->port_type != TYPEC_PORT_DRP) {
1273*a2c81616SWang Jie tcpm_queue_message(port, PD_MSG_CTRL_REJECT);
1274*a2c81616SWang Jie break;
1275*a2c81616SWang Jie }
1276*a2c81616SWang Jie /*
1277*a2c81616SWang Jie * XXX
1278*a2c81616SWang Jie * 6.3.9: If an alternate mode is active, a request to swap
1279*a2c81616SWang Jie * alternate modes shall trigger a port reset.
1280*a2c81616SWang Jie */
1281*a2c81616SWang Jie switch (port->state) {
1282*a2c81616SWang Jie case SRC_READY:
1283*a2c81616SWang Jie case SNK_READY:
1284*a2c81616SWang Jie #if 0
1285*a2c81616SWang Jie if (port->vdm_sm_running) {
1286*a2c81616SWang Jie tcpm_queue_message(port, PD_MSG_CTRL_WAIT);
1287*a2c81616SWang Jie break;
1288*a2c81616SWang Jie }
1289*a2c81616SWang Jie #endif
1290*a2c81616SWang Jie tcpm_set_state(port, DR_SWAP_ACCEPT, 0);
1291*a2c81616SWang Jie break;
1292*a2c81616SWang Jie default:
1293*a2c81616SWang Jie tcpm_queue_message(port, PD_MSG_CTRL_WAIT);
1294*a2c81616SWang Jie break;
1295*a2c81616SWang Jie }
1296*a2c81616SWang Jie break;
1297*a2c81616SWang Jie case PD_CTRL_PR_SWAP:
1298*a2c81616SWang Jie case PD_CTRL_VCONN_SWAP:
1299*a2c81616SWang Jie case PD_CTRL_GET_SOURCE_CAP_EXT:
1300*a2c81616SWang Jie case PD_CTRL_GET_STATUS:
1301*a2c81616SWang Jie case PD_CTRL_FR_SWAP:
1302*a2c81616SWang Jie case PD_CTRL_GET_PPS_STATUS:
1303*a2c81616SWang Jie case PD_CTRL_GET_COUNTRY_CODES:
1304*a2c81616SWang Jie /* Currently not supported */
1305*a2c81616SWang Jie printf("Currently not supported type %#x \n", type);
1306*a2c81616SWang Jie tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
1307*a2c81616SWang Jie break;
1308*a2c81616SWang Jie default:
1309*a2c81616SWang Jie printf("Unrecognized ctrl message type %#x\n", type);
1310*a2c81616SWang Jie break;
1311*a2c81616SWang Jie }
1312*a2c81616SWang Jie }
1313*a2c81616SWang Jie
1314*a2c81616SWang Jie #if 0
1315*a2c81616SWang Jie static void tcpm_pd_ext_msg_request(struct tcpm_port *port,
1316*a2c81616SWang Jie const struct pd_message *msg)
1317*a2c81616SWang Jie {
1318*a2c81616SWang Jie enum pd_ext_msg_type type = pd_header_type_le(msg->header);
1319*a2c81616SWang Jie unsigned int data_size = pd_ext_header_data_size_le(msg->ext_msg.header);
1320*a2c81616SWang Jie
1321*a2c81616SWang Jie if (!(le16_to_cpu(msg->ext_msg.header) & PD_EXT_HDR_CHUNKED)) {
1322*a2c81616SWang Jie tcpm_pd_handle_msg(port, PD_MSG_CTRL_NOT_SUPP, NONE_AMS);
1323*a2c81616SWang Jie printf("Unchunked extended messages unsupported\n");
1324*a2c81616SWang Jie return;
1325*a2c81616SWang Jie }
1326*a2c81616SWang Jie
1327*a2c81616SWang Jie if (data_size > PD_EXT_MAX_CHUNK_DATA) {
1328*a2c81616SWang Jie tcpm_pd_handle_state(port, CHUNK_NOT_SUPP, NONE_AMS, PD_T_CHUNK_NOT_SUPP);
1329*a2c81616SWang Jie printf("Chunk handling not yet supported\n");
1330*a2c81616SWang Jie return;
1331*a2c81616SWang Jie }
1332*a2c81616SWang Jie
1333*a2c81616SWang Jie switch (type) {
1334*a2c81616SWang Jie case PD_EXT_STATUS:
1335*a2c81616SWang Jie case PD_EXT_PPS_STATUS:
1336*a2c81616SWang Jie tcpm_set_state(port, ready_state(port), 0);
1337*a2c81616SWang Jie }
1338*a2c81616SWang Jie break;
1339*a2c81616SWang Jie case PD_EXT_SOURCE_CAP_EXT:
1340*a2c81616SWang Jie case PD_EXT_GET_BATT_CAP:
1341*a2c81616SWang Jie case PD_EXT_GET_BATT_STATUS:
1342*a2c81616SWang Jie case PD_EXT_BATT_CAP:
1343*a2c81616SWang Jie case PD_EXT_GET_MANUFACTURER_INFO:
1344*a2c81616SWang Jie case PD_EXT_MANUFACTURER_INFO:
1345*a2c81616SWang Jie case PD_EXT_SECURITY_REQUEST:
1346*a2c81616SWang Jie case PD_EXT_SECURITY_RESPONSE:
1347*a2c81616SWang Jie case PD_EXT_FW_UPDATE_REQUEST:
1348*a2c81616SWang Jie case PD_EXT_FW_UPDATE_RESPONSE:
1349*a2c81616SWang Jie case PD_EXT_COUNTRY_INFO:
1350*a2c81616SWang Jie case PD_EXT_COUNTRY_CODES:
1351*a2c81616SWang Jie tcpm_pd_handle_msg(port, PD_MSG_CTRL_NOT_SUPP, NONE_AMS);
1352*a2c81616SWang Jie break;
1353*a2c81616SWang Jie default:
1354*a2c81616SWang Jie tcpm_pd_handle_msg(port, PD_MSG_CTRL_NOT_SUPP, NONE_AMS);
1355*a2c81616SWang Jie printf("Unrecognized extended message type %#x\n", type);
1356*a2c81616SWang Jie break;
1357*a2c81616SWang Jie }
1358*a2c81616SWang Jie }
1359*a2c81616SWang Jie #endif
1360*a2c81616SWang Jie
tcpm_pd_rx_handler(struct tcpm_port * port,struct pd_rx_event * event)1361*a2c81616SWang Jie static void tcpm_pd_rx_handler(struct tcpm_port *port,
1362*a2c81616SWang Jie struct pd_rx_event *event)
1363*a2c81616SWang Jie {
1364*a2c81616SWang Jie const struct pd_message *msg = &event->msg;
1365*a2c81616SWang Jie unsigned int cnt = pd_header_cnt_le(msg->header);
1366*a2c81616SWang Jie
1367*a2c81616SWang Jie debug("PD RX, header: %#x [%d]\n", le16_to_cpu(msg->header),
1368*a2c81616SWang Jie port->attached);
1369*a2c81616SWang Jie
1370*a2c81616SWang Jie if (port->attached) {
1371*a2c81616SWang Jie enum pd_ctrl_msg_type type = pd_header_type_le(msg->header);
1372*a2c81616SWang Jie unsigned int msgid = pd_header_msgid_le(msg->header);
1373*a2c81616SWang Jie
1374*a2c81616SWang Jie /*
1375*a2c81616SWang Jie * USB PD standard, 6.6.1.2:
1376*a2c81616SWang Jie * "... if MessageID value in a received Message is the
1377*a2c81616SWang Jie * same as the stored value, the receiver shall return a
1378*a2c81616SWang Jie * GoodCRC Message with that MessageID value and drop
1379*a2c81616SWang Jie * the Message (this is a retry of an already received
1380*a2c81616SWang Jie * Message). Note: this shall not apply to the Soft_Reset
1381*a2c81616SWang Jie * Message which always has a MessageID value of zero."
1382*a2c81616SWang Jie */
1383*a2c81616SWang Jie if (msgid == port->rx_msgid && type != PD_CTRL_SOFT_RESET)
1384*a2c81616SWang Jie goto done;
1385*a2c81616SWang Jie port->rx_msgid = msgid;
1386*a2c81616SWang Jie
1387*a2c81616SWang Jie /*
1388*a2c81616SWang Jie * If both ends believe to be DFP/host, we have a data role
1389*a2c81616SWang Jie * mismatch.
1390*a2c81616SWang Jie */
1391*a2c81616SWang Jie if (!!(le16_to_cpu(msg->header) & PD_HEADER_DATA_ROLE) ==
1392*a2c81616SWang Jie (port->data_role == TYPEC_HOST)) {
1393*a2c81616SWang Jie printf("Data role mismatch, initiating error recovery\n");
1394*a2c81616SWang Jie tcpm_set_state(port, ERROR_RECOVERY, 0);
1395*a2c81616SWang Jie } else {
1396*a2c81616SWang Jie if (cnt)
1397*a2c81616SWang Jie tcpm_pd_data_request(port, msg);
1398*a2c81616SWang Jie else
1399*a2c81616SWang Jie tcpm_pd_ctrl_request(port, msg);
1400*a2c81616SWang Jie }
1401*a2c81616SWang Jie }
1402*a2c81616SWang Jie
1403*a2c81616SWang Jie done:
1404*a2c81616SWang Jie kfree(event);
1405*a2c81616SWang Jie }
1406*a2c81616SWang Jie
tcpm_pd_receive(struct tcpm_port * port,const struct pd_message * msg)1407*a2c81616SWang Jie void tcpm_pd_receive(struct tcpm_port *port, const struct pd_message *msg)
1408*a2c81616SWang Jie {
1409*a2c81616SWang Jie struct pd_rx_event *event;
1410*a2c81616SWang Jie
1411*a2c81616SWang Jie port->poll_event_cnt = 0;
1412*a2c81616SWang Jie event = kzalloc(sizeof(*event), GFP_ATOMIC);
1413*a2c81616SWang Jie if (!event)
1414*a2c81616SWang Jie return;
1415*a2c81616SWang Jie
1416*a2c81616SWang Jie event->port = port;
1417*a2c81616SWang Jie memcpy(&event->msg, msg, sizeof(*msg));
1418*a2c81616SWang Jie tcpm_pd_rx_handler(port, event);
1419*a2c81616SWang Jie }
1420*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpm_pd_receive);
1421*a2c81616SWang Jie
tcpm_pd_send_control(struct tcpm_port * port,enum pd_ctrl_msg_type type)1422*a2c81616SWang Jie static int tcpm_pd_send_control(struct tcpm_port *port,
1423*a2c81616SWang Jie enum pd_ctrl_msg_type type)
1424*a2c81616SWang Jie {
1425*a2c81616SWang Jie struct pd_message msg;
1426*a2c81616SWang Jie
1427*a2c81616SWang Jie memset(&msg, 0, sizeof(msg));
1428*a2c81616SWang Jie msg.header = PD_HEADER_LE(type, port->pwr_role,
1429*a2c81616SWang Jie port->data_role,
1430*a2c81616SWang Jie port->negotiated_rev,
1431*a2c81616SWang Jie port->message_id, 0);
1432*a2c81616SWang Jie
1433*a2c81616SWang Jie return tcpm_pd_transmit(port, TCPC_TX_SOP, &msg);
1434*a2c81616SWang Jie }
1435*a2c81616SWang Jie
1436*a2c81616SWang Jie /*
1437*a2c81616SWang Jie * Send queued message without affecting state.
1438*a2c81616SWang Jie * Return true if state machine should go back to sleep,
1439*a2c81616SWang Jie * false otherwise.
1440*a2c81616SWang Jie */
tcpm_send_queued_message(struct tcpm_port * port)1441*a2c81616SWang Jie static bool tcpm_send_queued_message(struct tcpm_port *port)
1442*a2c81616SWang Jie {
1443*a2c81616SWang Jie enum pd_msg_request queued_message;
1444*a2c81616SWang Jie
1445*a2c81616SWang Jie do {
1446*a2c81616SWang Jie queued_message = port->queued_message;
1447*a2c81616SWang Jie port->queued_message = PD_MSG_NONE;
1448*a2c81616SWang Jie
1449*a2c81616SWang Jie switch (queued_message) {
1450*a2c81616SWang Jie case PD_MSG_CTRL_WAIT:
1451*a2c81616SWang Jie tcpm_pd_send_control(port, PD_CTRL_WAIT);
1452*a2c81616SWang Jie break;
1453*a2c81616SWang Jie case PD_MSG_CTRL_REJECT:
1454*a2c81616SWang Jie tcpm_pd_send_control(port, PD_CTRL_REJECT);
1455*a2c81616SWang Jie break;
1456*a2c81616SWang Jie case PD_MSG_CTRL_NOT_SUPP:
1457*a2c81616SWang Jie tcpm_pd_send_control(port, PD_CTRL_NOT_SUPP);
1458*a2c81616SWang Jie break;
1459*a2c81616SWang Jie case PD_MSG_DATA_SINK_CAP:
1460*a2c81616SWang Jie tcpm_pd_send_sink_caps(port);
1461*a2c81616SWang Jie break;
1462*a2c81616SWang Jie case PD_MSG_DATA_SOURCE_CAP:
1463*a2c81616SWang Jie tcpm_pd_send_source_caps(port);
1464*a2c81616SWang Jie break;
1465*a2c81616SWang Jie default:
1466*a2c81616SWang Jie break;
1467*a2c81616SWang Jie }
1468*a2c81616SWang Jie } while (port->queued_message != PD_MSG_NONE);
1469*a2c81616SWang Jie
1470*a2c81616SWang Jie #if 0
1471*a2c81616SWang Jie /* ??? */
1472*a2c81616SWang Jie if (port->delayed_state != INVALID_STATE) {
1473*a2c81616SWang Jie if (ktime_after(port->delayed_runtime, ktime_get())) {
1474*a2c81616SWang Jie mod_tcpm_delayed_work(port, ktime_to_ms(ktime_sub(port->delayed_runtime,
1475*a2c81616SWang Jie ktime_get())));
1476*a2c81616SWang Jie return true;
1477*a2c81616SWang Jie }
1478*a2c81616SWang Jie port->delayed_state = INVALID_STATE;
1479*a2c81616SWang Jie }
1480*a2c81616SWang Jie #endif
1481*a2c81616SWang Jie return false;
1482*a2c81616SWang Jie }
1483*a2c81616SWang Jie
tcpm_pd_check_request(struct tcpm_port * port)1484*a2c81616SWang Jie static int tcpm_pd_check_request(struct tcpm_port *port)
1485*a2c81616SWang Jie {
1486*a2c81616SWang Jie u32 pdo, rdo = port->sink_request;
1487*a2c81616SWang Jie unsigned int max, op, pdo_max, index;
1488*a2c81616SWang Jie enum pd_pdo_type type;
1489*a2c81616SWang Jie
1490*a2c81616SWang Jie index = rdo_index(rdo);
1491*a2c81616SWang Jie if (!index || index > port->nr_src_pdo)
1492*a2c81616SWang Jie return -EINVAL;
1493*a2c81616SWang Jie
1494*a2c81616SWang Jie pdo = port->src_pdo[index - 1];
1495*a2c81616SWang Jie type = pdo_type(pdo);
1496*a2c81616SWang Jie switch (type) {
1497*a2c81616SWang Jie case PDO_TYPE_FIXED:
1498*a2c81616SWang Jie case PDO_TYPE_VAR:
1499*a2c81616SWang Jie max = rdo_max_current(rdo);
1500*a2c81616SWang Jie op = rdo_op_current(rdo);
1501*a2c81616SWang Jie pdo_max = pdo_max_current(pdo);
1502*a2c81616SWang Jie
1503*a2c81616SWang Jie if (op > pdo_max)
1504*a2c81616SWang Jie return -EINVAL;
1505*a2c81616SWang Jie if (max > pdo_max && !(rdo & RDO_CAP_MISMATCH))
1506*a2c81616SWang Jie return -EINVAL;
1507*a2c81616SWang Jie
1508*a2c81616SWang Jie if (type == PDO_TYPE_FIXED)
1509*a2c81616SWang Jie debug("Requested %u mV, %u mA for %u / %u mA\n",
1510*a2c81616SWang Jie pdo_fixed_voltage(pdo), pdo_max, op, max);
1511*a2c81616SWang Jie else
1512*a2c81616SWang Jie debug("Requested %u -> %u mV, %u mA for %u / %u mA\n",
1513*a2c81616SWang Jie pdo_min_voltage(pdo), pdo_max_voltage(pdo),
1514*a2c81616SWang Jie pdo_max, op, max);
1515*a2c81616SWang Jie break;
1516*a2c81616SWang Jie case PDO_TYPE_BATT:
1517*a2c81616SWang Jie max = rdo_max_power(rdo);
1518*a2c81616SWang Jie op = rdo_op_power(rdo);
1519*a2c81616SWang Jie pdo_max = pdo_max_power(pdo);
1520*a2c81616SWang Jie
1521*a2c81616SWang Jie if (op > pdo_max)
1522*a2c81616SWang Jie return -EINVAL;
1523*a2c81616SWang Jie if (max > pdo_max && !(rdo & RDO_CAP_MISMATCH))
1524*a2c81616SWang Jie return -EINVAL;
1525*a2c81616SWang Jie printf("Requested %u -> %u mV, %u mW for %u / %u mW\n",
1526*a2c81616SWang Jie pdo_min_voltage(pdo), pdo_max_voltage(pdo),
1527*a2c81616SWang Jie pdo_max, op, max);
1528*a2c81616SWang Jie break;
1529*a2c81616SWang Jie default:
1530*a2c81616SWang Jie return -EINVAL;
1531*a2c81616SWang Jie }
1532*a2c81616SWang Jie
1533*a2c81616SWang Jie port->op_vsafe5v = index == 1;
1534*a2c81616SWang Jie
1535*a2c81616SWang Jie return 0;
1536*a2c81616SWang Jie }
1537*a2c81616SWang Jie
1538*a2c81616SWang Jie #define min_power(x, y) min(pdo_max_power(x), pdo_max_power(y))
1539*a2c81616SWang Jie #define min_current(x, y) min(pdo_max_current(x), pdo_max_current(y))
1540*a2c81616SWang Jie
tcpm_pd_select_pdo(struct tcpm_port * port,int * sink_pdo,int * src_pdo)1541*a2c81616SWang Jie static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo,
1542*a2c81616SWang Jie int *src_pdo)
1543*a2c81616SWang Jie {
1544*a2c81616SWang Jie unsigned int i, j, max_src_mv = 0, min_src_mv = 0, max_mw = 0,
1545*a2c81616SWang Jie max_mv = 0, src_mw = 0, src_ma = 0, max_snk_mv = 0,
1546*a2c81616SWang Jie min_snk_mv = 0;
1547*a2c81616SWang Jie int ret = -EINVAL;
1548*a2c81616SWang Jie
1549*a2c81616SWang Jie port->pps_data.supported = false;
1550*a2c81616SWang Jie port->usb_type = POWER_SUPPLY_USB_TYPE_PD;
1551*a2c81616SWang Jie
1552*a2c81616SWang Jie /*
1553*a2c81616SWang Jie * Select the source PDO providing the most power which has a
1554*a2c81616SWang Jie * matchig sink cap.
1555*a2c81616SWang Jie */
1556*a2c81616SWang Jie for (i = 0; i < port->nr_source_caps; i++) {
1557*a2c81616SWang Jie u32 pdo = port->source_caps[i];
1558*a2c81616SWang Jie enum pd_pdo_type type = pdo_type(pdo);
1559*a2c81616SWang Jie
1560*a2c81616SWang Jie switch (type) {
1561*a2c81616SWang Jie case PDO_TYPE_FIXED:
1562*a2c81616SWang Jie max_src_mv = pdo_fixed_voltage(pdo);
1563*a2c81616SWang Jie min_src_mv = max_src_mv;
1564*a2c81616SWang Jie break;
1565*a2c81616SWang Jie case PDO_TYPE_BATT:
1566*a2c81616SWang Jie case PDO_TYPE_VAR:
1567*a2c81616SWang Jie max_src_mv = pdo_max_voltage(pdo);
1568*a2c81616SWang Jie min_src_mv = pdo_min_voltage(pdo);
1569*a2c81616SWang Jie break;
1570*a2c81616SWang Jie case PDO_TYPE_APDO:
1571*a2c81616SWang Jie if (pdo_apdo_type(pdo) == APDO_TYPE_PPS) {
1572*a2c81616SWang Jie port->pps_data.supported = true;
1573*a2c81616SWang Jie port->usb_type =
1574*a2c81616SWang Jie POWER_SUPPLY_USB_TYPE_PD_PPS;
1575*a2c81616SWang Jie }
1576*a2c81616SWang Jie continue;
1577*a2c81616SWang Jie default:
1578*a2c81616SWang Jie printf("Invalid source PDO type, ignoring\n");
1579*a2c81616SWang Jie continue;
1580*a2c81616SWang Jie }
1581*a2c81616SWang Jie
1582*a2c81616SWang Jie switch (type) {
1583*a2c81616SWang Jie case PDO_TYPE_FIXED:
1584*a2c81616SWang Jie case PDO_TYPE_VAR:
1585*a2c81616SWang Jie src_ma = pdo_max_current(pdo);
1586*a2c81616SWang Jie src_mw = src_ma * min_src_mv / 1000;
1587*a2c81616SWang Jie break;
1588*a2c81616SWang Jie case PDO_TYPE_BATT:
1589*a2c81616SWang Jie src_mw = pdo_max_power(pdo);
1590*a2c81616SWang Jie break;
1591*a2c81616SWang Jie case PDO_TYPE_APDO:
1592*a2c81616SWang Jie continue;
1593*a2c81616SWang Jie default:
1594*a2c81616SWang Jie printf("Invalid source PDO type, ignoring\n");
1595*a2c81616SWang Jie continue;
1596*a2c81616SWang Jie }
1597*a2c81616SWang Jie
1598*a2c81616SWang Jie for (j = 0; j < port->nr_snk_pdo; j++) {
1599*a2c81616SWang Jie pdo = port->snk_pdo[j];
1600*a2c81616SWang Jie
1601*a2c81616SWang Jie switch (pdo_type(pdo)) {
1602*a2c81616SWang Jie case PDO_TYPE_FIXED:
1603*a2c81616SWang Jie max_snk_mv = pdo_fixed_voltage(pdo);
1604*a2c81616SWang Jie min_snk_mv = max_snk_mv;
1605*a2c81616SWang Jie break;
1606*a2c81616SWang Jie case PDO_TYPE_BATT:
1607*a2c81616SWang Jie case PDO_TYPE_VAR:
1608*a2c81616SWang Jie max_snk_mv = pdo_max_voltage(pdo);
1609*a2c81616SWang Jie min_snk_mv = pdo_min_voltage(pdo);
1610*a2c81616SWang Jie break;
1611*a2c81616SWang Jie case PDO_TYPE_APDO:
1612*a2c81616SWang Jie continue;
1613*a2c81616SWang Jie default:
1614*a2c81616SWang Jie printf("Invalid sink PDO type, ignoring\n");
1615*a2c81616SWang Jie continue;
1616*a2c81616SWang Jie }
1617*a2c81616SWang Jie
1618*a2c81616SWang Jie if (max_src_mv <= max_snk_mv &&
1619*a2c81616SWang Jie min_src_mv >= min_snk_mv) {
1620*a2c81616SWang Jie /* Prefer higher voltages if available */
1621*a2c81616SWang Jie if ((src_mw == max_mw && min_src_mv > max_mv) ||
1622*a2c81616SWang Jie src_mw > max_mw) {
1623*a2c81616SWang Jie *src_pdo = i;
1624*a2c81616SWang Jie *sink_pdo = j;
1625*a2c81616SWang Jie max_mw = src_mw;
1626*a2c81616SWang Jie max_mv = min_src_mv;
1627*a2c81616SWang Jie ret = 0;
1628*a2c81616SWang Jie }
1629*a2c81616SWang Jie }
1630*a2c81616SWang Jie }
1631*a2c81616SWang Jie }
1632*a2c81616SWang Jie
1633*a2c81616SWang Jie return ret;
1634*a2c81616SWang Jie }
1635*a2c81616SWang Jie
1636*a2c81616SWang Jie #define min_pps_apdo_current(x, y) \
1637*a2c81616SWang Jie min(pdo_pps_apdo_max_current(x), pdo_pps_apdo_max_current(y))
1638*a2c81616SWang Jie
tcpm_pd_select_pps_apdo(struct tcpm_port * port)1639*a2c81616SWang Jie static unsigned int tcpm_pd_select_pps_apdo(struct tcpm_port *port)
1640*a2c81616SWang Jie {
1641*a2c81616SWang Jie unsigned int i, j, max_mw = 0, max_mv = 0;
1642*a2c81616SWang Jie unsigned int min_src_mv, max_src_mv, src_ma, src_mw;
1643*a2c81616SWang Jie unsigned int min_snk_mv, max_snk_mv;
1644*a2c81616SWang Jie unsigned int max_op_mv;
1645*a2c81616SWang Jie u32 pdo, src, snk;
1646*a2c81616SWang Jie unsigned int src_pdo = 0, snk_pdo = 0;
1647*a2c81616SWang Jie
1648*a2c81616SWang Jie /*
1649*a2c81616SWang Jie * Select the source PPS APDO providing the most power while staying
1650*a2c81616SWang Jie * within the board's limits. We skip the first PDO as this is always
1651*a2c81616SWang Jie * 5V 3A.
1652*a2c81616SWang Jie */
1653*a2c81616SWang Jie for (i = 1; i < port->nr_source_caps; ++i) {
1654*a2c81616SWang Jie pdo = port->source_caps[i];
1655*a2c81616SWang Jie
1656*a2c81616SWang Jie switch (pdo_type(pdo)) {
1657*a2c81616SWang Jie case PDO_TYPE_APDO:
1658*a2c81616SWang Jie if (pdo_apdo_type(pdo) != APDO_TYPE_PPS) {
1659*a2c81616SWang Jie printf("Not PPS APDO (source), ignoring\n");
1660*a2c81616SWang Jie continue;
1661*a2c81616SWang Jie }
1662*a2c81616SWang Jie
1663*a2c81616SWang Jie min_src_mv = pdo_pps_apdo_min_voltage(pdo);
1664*a2c81616SWang Jie max_src_mv = pdo_pps_apdo_max_voltage(pdo);
1665*a2c81616SWang Jie src_ma = pdo_pps_apdo_max_current(pdo);
1666*a2c81616SWang Jie src_mw = (src_ma * max_src_mv) / 1000;
1667*a2c81616SWang Jie
1668*a2c81616SWang Jie /*
1669*a2c81616SWang Jie * Now search through the sink PDOs to find a matching
1670*a2c81616SWang Jie * PPS APDO. Again skip the first sink PDO as this will
1671*a2c81616SWang Jie * always be 5V 3A.
1672*a2c81616SWang Jie */
1673*a2c81616SWang Jie for (j = 1; j < port->nr_snk_pdo; j++) {
1674*a2c81616SWang Jie pdo = port->snk_pdo[j];
1675*a2c81616SWang Jie
1676*a2c81616SWang Jie switch (pdo_type(pdo)) {
1677*a2c81616SWang Jie case PDO_TYPE_APDO:
1678*a2c81616SWang Jie if (pdo_apdo_type(pdo) != APDO_TYPE_PPS) {
1679*a2c81616SWang Jie printf("Not PPS APDO (sink), ignoring\n");
1680*a2c81616SWang Jie continue;
1681*a2c81616SWang Jie }
1682*a2c81616SWang Jie
1683*a2c81616SWang Jie min_snk_mv =
1684*a2c81616SWang Jie pdo_pps_apdo_min_voltage(pdo);
1685*a2c81616SWang Jie max_snk_mv =
1686*a2c81616SWang Jie pdo_pps_apdo_max_voltage(pdo);
1687*a2c81616SWang Jie break;
1688*a2c81616SWang Jie default:
1689*a2c81616SWang Jie printf("Not APDO type (sink), ignoring\n");
1690*a2c81616SWang Jie continue;
1691*a2c81616SWang Jie }
1692*a2c81616SWang Jie
1693*a2c81616SWang Jie if (min_src_mv <= max_snk_mv &&
1694*a2c81616SWang Jie max_src_mv >= min_snk_mv) {
1695*a2c81616SWang Jie max_op_mv = min(max_src_mv, max_snk_mv);
1696*a2c81616SWang Jie src_mw = (max_op_mv * src_ma) / 1000;
1697*a2c81616SWang Jie /* Prefer higher voltages if available */
1698*a2c81616SWang Jie if ((src_mw == max_mw &&
1699*a2c81616SWang Jie max_op_mv > max_mv) ||
1700*a2c81616SWang Jie src_mw > max_mw) {
1701*a2c81616SWang Jie src_pdo = i;
1702*a2c81616SWang Jie snk_pdo = j;
1703*a2c81616SWang Jie max_mw = src_mw;
1704*a2c81616SWang Jie max_mv = max_op_mv;
1705*a2c81616SWang Jie }
1706*a2c81616SWang Jie }
1707*a2c81616SWang Jie }
1708*a2c81616SWang Jie
1709*a2c81616SWang Jie break;
1710*a2c81616SWang Jie default:
1711*a2c81616SWang Jie printf("Not APDO type (source), ignoring\n");
1712*a2c81616SWang Jie continue;
1713*a2c81616SWang Jie }
1714*a2c81616SWang Jie }
1715*a2c81616SWang Jie
1716*a2c81616SWang Jie if (src_pdo) {
1717*a2c81616SWang Jie src = port->source_caps[src_pdo];
1718*a2c81616SWang Jie snk = port->snk_pdo[snk_pdo];
1719*a2c81616SWang Jie
1720*a2c81616SWang Jie port->pps_data.req_min_volt = max(pdo_pps_apdo_min_voltage(src),
1721*a2c81616SWang Jie pdo_pps_apdo_min_voltage(snk));
1722*a2c81616SWang Jie port->pps_data.req_max_volt = min(pdo_pps_apdo_max_voltage(src),
1723*a2c81616SWang Jie pdo_pps_apdo_max_voltage(snk));
1724*a2c81616SWang Jie port->pps_data.req_max_curr = min_pps_apdo_current(src, snk);
1725*a2c81616SWang Jie port->pps_data.req_out_volt = min(port->pps_data.req_max_volt,
1726*a2c81616SWang Jie max(port->pps_data.req_min_volt,
1727*a2c81616SWang Jie port->pps_data.req_out_volt));
1728*a2c81616SWang Jie port->pps_data.req_op_curr = min(port->pps_data.req_max_curr,
1729*a2c81616SWang Jie port->pps_data.req_op_curr);
1730*a2c81616SWang Jie }
1731*a2c81616SWang Jie
1732*a2c81616SWang Jie return src_pdo;
1733*a2c81616SWang Jie }
1734*a2c81616SWang Jie
tcpm_pd_build_request(struct tcpm_port * port,u32 * rdo)1735*a2c81616SWang Jie static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo)
1736*a2c81616SWang Jie {
1737*a2c81616SWang Jie unsigned int mv, ma, mw, flags;
1738*a2c81616SWang Jie unsigned int max_ma, max_mw;
1739*a2c81616SWang Jie enum pd_pdo_type type;
1740*a2c81616SWang Jie u32 pdo, matching_snk_pdo;
1741*a2c81616SWang Jie int src_pdo_index = 0;
1742*a2c81616SWang Jie int snk_pdo_index = 0;
1743*a2c81616SWang Jie int ret;
1744*a2c81616SWang Jie
1745*a2c81616SWang Jie ret = tcpm_pd_select_pdo(port, &snk_pdo_index, &src_pdo_index);
1746*a2c81616SWang Jie if (ret < 0)
1747*a2c81616SWang Jie return ret;
1748*a2c81616SWang Jie
1749*a2c81616SWang Jie pdo = port->source_caps[src_pdo_index];
1750*a2c81616SWang Jie matching_snk_pdo = port->snk_pdo[snk_pdo_index];
1751*a2c81616SWang Jie type = pdo_type(pdo);
1752*a2c81616SWang Jie
1753*a2c81616SWang Jie switch (type) {
1754*a2c81616SWang Jie case PDO_TYPE_FIXED:
1755*a2c81616SWang Jie mv = pdo_fixed_voltage(pdo);
1756*a2c81616SWang Jie break;
1757*a2c81616SWang Jie case PDO_TYPE_BATT:
1758*a2c81616SWang Jie case PDO_TYPE_VAR:
1759*a2c81616SWang Jie mv = pdo_min_voltage(pdo);
1760*a2c81616SWang Jie break;
1761*a2c81616SWang Jie default:
1762*a2c81616SWang Jie printf("Invalid PDO selected!\n");
1763*a2c81616SWang Jie return -EINVAL;
1764*a2c81616SWang Jie }
1765*a2c81616SWang Jie
1766*a2c81616SWang Jie /* Select maximum available current within the sink pdo's limit */
1767*a2c81616SWang Jie if (type == PDO_TYPE_BATT) {
1768*a2c81616SWang Jie mw = min_power(pdo, matching_snk_pdo);
1769*a2c81616SWang Jie ma = 1000 * mw / mv;
1770*a2c81616SWang Jie } else {
1771*a2c81616SWang Jie ma = min_current(pdo, matching_snk_pdo);
1772*a2c81616SWang Jie mw = ma * mv / 1000;
1773*a2c81616SWang Jie }
1774*a2c81616SWang Jie
1775*a2c81616SWang Jie flags = RDO_USB_COMM | RDO_NO_SUSPEND;
1776*a2c81616SWang Jie
1777*a2c81616SWang Jie /* Set mismatch bit if offered power is less than operating power */
1778*a2c81616SWang Jie max_ma = ma;
1779*a2c81616SWang Jie max_mw = mw;
1780*a2c81616SWang Jie if (mw < port->operating_snk_mw) {
1781*a2c81616SWang Jie flags |= RDO_CAP_MISMATCH;
1782*a2c81616SWang Jie if (type == PDO_TYPE_BATT &&
1783*a2c81616SWang Jie (pdo_max_power(matching_snk_pdo) > pdo_max_power(pdo)))
1784*a2c81616SWang Jie max_mw = pdo_max_power(matching_snk_pdo);
1785*a2c81616SWang Jie else if (pdo_max_current(matching_snk_pdo) >
1786*a2c81616SWang Jie pdo_max_current(pdo))
1787*a2c81616SWang Jie max_ma = pdo_max_current(matching_snk_pdo);
1788*a2c81616SWang Jie }
1789*a2c81616SWang Jie
1790*a2c81616SWang Jie debug("cc=%d cc1=%d cc2=%d vbus=%d vconn=%s polarity=%d\n",
1791*a2c81616SWang Jie port->cc_req, port->cc1, port->cc2, port->vbus_source,
1792*a2c81616SWang Jie port->vconn_role == TYPEC_SOURCE ? "source" : "sink",
1793*a2c81616SWang Jie port->polarity);
1794*a2c81616SWang Jie
1795*a2c81616SWang Jie if (type == PDO_TYPE_BATT) {
1796*a2c81616SWang Jie *rdo = RDO_BATT(src_pdo_index + 1, mw, max_mw, flags);
1797*a2c81616SWang Jie
1798*a2c81616SWang Jie printf("Requesting PDO %d: %u mV, %u mW%s\n",
1799*a2c81616SWang Jie src_pdo_index, mv, mw,
1800*a2c81616SWang Jie flags & RDO_CAP_MISMATCH ? " [mismatch]" : "");
1801*a2c81616SWang Jie } else {
1802*a2c81616SWang Jie *rdo = RDO_FIXED(src_pdo_index + 1, ma, max_ma, flags);
1803*a2c81616SWang Jie
1804*a2c81616SWang Jie printf("Requesting PDO %d: %u mV, %u mA%s\n",
1805*a2c81616SWang Jie src_pdo_index, mv, ma,
1806*a2c81616SWang Jie flags & RDO_CAP_MISMATCH ? " [mismatch]" : "");
1807*a2c81616SWang Jie }
1808*a2c81616SWang Jie
1809*a2c81616SWang Jie port->req_current_limit = ma;
1810*a2c81616SWang Jie port->req_supply_voltage = mv;
1811*a2c81616SWang Jie
1812*a2c81616SWang Jie return 0;
1813*a2c81616SWang Jie }
1814*a2c81616SWang Jie
tcpm_pd_send_request(struct tcpm_port * port)1815*a2c81616SWang Jie static int tcpm_pd_send_request(struct tcpm_port *port)
1816*a2c81616SWang Jie {
1817*a2c81616SWang Jie struct pd_message msg;
1818*a2c81616SWang Jie int ret;
1819*a2c81616SWang Jie u32 rdo;
1820*a2c81616SWang Jie
1821*a2c81616SWang Jie ret = tcpm_pd_build_request(port, &rdo);
1822*a2c81616SWang Jie if (ret < 0)
1823*a2c81616SWang Jie return ret;
1824*a2c81616SWang Jie
1825*a2c81616SWang Jie memset(&msg, 0, sizeof(msg));
1826*a2c81616SWang Jie msg.header = PD_HEADER_LE(PD_DATA_REQUEST,
1827*a2c81616SWang Jie port->pwr_role,
1828*a2c81616SWang Jie port->data_role,
1829*a2c81616SWang Jie port->negotiated_rev,
1830*a2c81616SWang Jie port->message_id, 1);
1831*a2c81616SWang Jie msg.payload[0] = cpu_to_le32(rdo);
1832*a2c81616SWang Jie
1833*a2c81616SWang Jie return tcpm_pd_transmit(port, TCPC_TX_SOP, &msg);
1834*a2c81616SWang Jie }
1835*a2c81616SWang Jie
tcpm_pd_build_pps_request(struct tcpm_port * port,u32 * rdo)1836*a2c81616SWang Jie static int tcpm_pd_build_pps_request(struct tcpm_port *port, u32 *rdo)
1837*a2c81616SWang Jie {
1838*a2c81616SWang Jie unsigned int out_mv, op_ma, op_mw, max_mv, max_ma, flags;
1839*a2c81616SWang Jie enum pd_pdo_type type;
1840*a2c81616SWang Jie unsigned int src_pdo_index;
1841*a2c81616SWang Jie u32 pdo;
1842*a2c81616SWang Jie
1843*a2c81616SWang Jie src_pdo_index = tcpm_pd_select_pps_apdo(port);
1844*a2c81616SWang Jie if (!src_pdo_index)
1845*a2c81616SWang Jie return -EOPNOTSUPP;
1846*a2c81616SWang Jie
1847*a2c81616SWang Jie pdo = port->source_caps[src_pdo_index];
1848*a2c81616SWang Jie type = pdo_type(pdo);
1849*a2c81616SWang Jie
1850*a2c81616SWang Jie switch (type) {
1851*a2c81616SWang Jie case PDO_TYPE_APDO:
1852*a2c81616SWang Jie if (pdo_apdo_type(pdo) != APDO_TYPE_PPS) {
1853*a2c81616SWang Jie printf("Invalid APDO selected!\n");
1854*a2c81616SWang Jie return -EINVAL;
1855*a2c81616SWang Jie }
1856*a2c81616SWang Jie max_mv = port->pps_data.req_max_volt;
1857*a2c81616SWang Jie max_ma = port->pps_data.req_max_curr;
1858*a2c81616SWang Jie out_mv = port->pps_data.req_out_volt;
1859*a2c81616SWang Jie op_ma = port->pps_data.req_op_curr;
1860*a2c81616SWang Jie break;
1861*a2c81616SWang Jie default:
1862*a2c81616SWang Jie printf("Invalid PDO selected!\n");
1863*a2c81616SWang Jie return -EINVAL;
1864*a2c81616SWang Jie }
1865*a2c81616SWang Jie
1866*a2c81616SWang Jie flags = RDO_USB_COMM | RDO_NO_SUSPEND;
1867*a2c81616SWang Jie
1868*a2c81616SWang Jie op_mw = (op_ma * out_mv) / 1000;
1869*a2c81616SWang Jie if (op_mw < port->operating_snk_mw) {
1870*a2c81616SWang Jie /*
1871*a2c81616SWang Jie * Try raising current to meet power needs. If that's not enough
1872*a2c81616SWang Jie * then try upping the voltage. If that's still not enough
1873*a2c81616SWang Jie * then we've obviously chosen a PPS APDO which really isn't
1874*a2c81616SWang Jie * suitable so abandon ship.
1875*a2c81616SWang Jie */
1876*a2c81616SWang Jie op_ma = (port->operating_snk_mw * 1000) / out_mv;
1877*a2c81616SWang Jie if ((port->operating_snk_mw * 1000) % out_mv)
1878*a2c81616SWang Jie ++op_ma;
1879*a2c81616SWang Jie op_ma += RDO_PROG_CURR_MA_STEP - (op_ma % RDO_PROG_CURR_MA_STEP);
1880*a2c81616SWang Jie
1881*a2c81616SWang Jie if (op_ma > max_ma) {
1882*a2c81616SWang Jie op_ma = max_ma;
1883*a2c81616SWang Jie out_mv = (port->operating_snk_mw * 1000) / op_ma;
1884*a2c81616SWang Jie if ((port->operating_snk_mw * 1000) % op_ma)
1885*a2c81616SWang Jie ++out_mv;
1886*a2c81616SWang Jie out_mv += RDO_PROG_VOLT_MV_STEP -
1887*a2c81616SWang Jie (out_mv % RDO_PROG_VOLT_MV_STEP);
1888*a2c81616SWang Jie
1889*a2c81616SWang Jie if (out_mv > max_mv) {
1890*a2c81616SWang Jie printf("Invalid PPS APDO selected!\n");
1891*a2c81616SWang Jie return -EINVAL;
1892*a2c81616SWang Jie }
1893*a2c81616SWang Jie }
1894*a2c81616SWang Jie }
1895*a2c81616SWang Jie
1896*a2c81616SWang Jie debug("cc=%d cc1=%d cc2=%d vbus=%d vconn=%s polarity=%d\n",
1897*a2c81616SWang Jie port->cc_req, port->cc1, port->cc2, port->vbus_source,
1898*a2c81616SWang Jie port->vconn_role == TYPEC_SOURCE ? "source" : "sink",
1899*a2c81616SWang Jie port->polarity);
1900*a2c81616SWang Jie
1901*a2c81616SWang Jie *rdo = RDO_PROG(src_pdo_index + 1, out_mv, op_ma, flags);
1902*a2c81616SWang Jie
1903*a2c81616SWang Jie printf("Requesting APDO %d: %u mV, %u mA\n",
1904*a2c81616SWang Jie src_pdo_index, out_mv, op_ma);
1905*a2c81616SWang Jie
1906*a2c81616SWang Jie port->pps_data.req_op_curr = op_ma;
1907*a2c81616SWang Jie port->pps_data.req_out_volt = out_mv;
1908*a2c81616SWang Jie
1909*a2c81616SWang Jie return 0;
1910*a2c81616SWang Jie }
1911*a2c81616SWang Jie
tcpm_pd_send_pps_request(struct tcpm_port * port)1912*a2c81616SWang Jie static int tcpm_pd_send_pps_request(struct tcpm_port *port)
1913*a2c81616SWang Jie {
1914*a2c81616SWang Jie struct pd_message msg;
1915*a2c81616SWang Jie int ret;
1916*a2c81616SWang Jie u32 rdo;
1917*a2c81616SWang Jie
1918*a2c81616SWang Jie ret = tcpm_pd_build_pps_request(port, &rdo);
1919*a2c81616SWang Jie if (ret < 0)
1920*a2c81616SWang Jie return ret;
1921*a2c81616SWang Jie
1922*a2c81616SWang Jie memset(&msg, 0, sizeof(msg));
1923*a2c81616SWang Jie msg.header = PD_HEADER_LE(PD_DATA_REQUEST,
1924*a2c81616SWang Jie port->pwr_role,
1925*a2c81616SWang Jie port->data_role,
1926*a2c81616SWang Jie port->negotiated_rev,
1927*a2c81616SWang Jie port->message_id, 1);
1928*a2c81616SWang Jie msg.payload[0] = cpu_to_le32(rdo);
1929*a2c81616SWang Jie
1930*a2c81616SWang Jie return tcpm_pd_transmit(port, TCPC_TX_SOP, &msg);
1931*a2c81616SWang Jie }
1932*a2c81616SWang Jie
tcpm_set_vbus(struct tcpm_port * port,bool enable)1933*a2c81616SWang Jie static int tcpm_set_vbus(struct tcpm_port *port, bool enable)
1934*a2c81616SWang Jie {
1935*a2c81616SWang Jie int ret;
1936*a2c81616SWang Jie
1937*a2c81616SWang Jie if (enable && port->vbus_charge)
1938*a2c81616SWang Jie return -EINVAL;
1939*a2c81616SWang Jie
1940*a2c81616SWang Jie debug("vbus = %d charge = %d\n", enable, port->vbus_charge);
1941*a2c81616SWang Jie
1942*a2c81616SWang Jie ret = port->tcpc->set_vbus(port->tcpc, enable, port->vbus_charge);
1943*a2c81616SWang Jie if (ret < 0)
1944*a2c81616SWang Jie return ret;
1945*a2c81616SWang Jie
1946*a2c81616SWang Jie port->vbus_source = enable;
1947*a2c81616SWang Jie return 0;
1948*a2c81616SWang Jie }
1949*a2c81616SWang Jie
tcpm_set_charge(struct tcpm_port * port,bool charge)1950*a2c81616SWang Jie static int tcpm_set_charge(struct tcpm_port *port, bool charge)
1951*a2c81616SWang Jie {
1952*a2c81616SWang Jie int ret;
1953*a2c81616SWang Jie
1954*a2c81616SWang Jie if (charge && port->vbus_source)
1955*a2c81616SWang Jie return -EINVAL;
1956*a2c81616SWang Jie
1957*a2c81616SWang Jie if (charge != port->vbus_charge) {
1958*a2c81616SWang Jie debug("vbus = %d charge = %d\n", port->vbus_source, charge);
1959*a2c81616SWang Jie ret = port->tcpc->set_vbus(port->tcpc, port->vbus_source,
1960*a2c81616SWang Jie charge);
1961*a2c81616SWang Jie if (ret < 0)
1962*a2c81616SWang Jie return ret;
1963*a2c81616SWang Jie }
1964*a2c81616SWang Jie port->vbus_charge = charge;
1965*a2c81616SWang Jie return 0;
1966*a2c81616SWang Jie }
1967*a2c81616SWang Jie
tcpm_start_toggling(struct tcpm_port * port,enum typec_cc_status cc)1968*a2c81616SWang Jie static bool tcpm_start_toggling(struct tcpm_port *port, enum typec_cc_status cc)
1969*a2c81616SWang Jie {
1970*a2c81616SWang Jie int ret;
1971*a2c81616SWang Jie
1972*a2c81616SWang Jie if (!port->tcpc->start_toggling)
1973*a2c81616SWang Jie return false;
1974*a2c81616SWang Jie
1975*a2c81616SWang Jie printf("Start toggling\n");
1976*a2c81616SWang Jie ret = port->tcpc->start_toggling(port->tcpc, port->port_type, cc);
1977*a2c81616SWang Jie return ret == 0;
1978*a2c81616SWang Jie }
1979*a2c81616SWang Jie
tcpm_init_vbus(struct tcpm_port * port)1980*a2c81616SWang Jie static int tcpm_init_vbus(struct tcpm_port *port)
1981*a2c81616SWang Jie {
1982*a2c81616SWang Jie int ret;
1983*a2c81616SWang Jie
1984*a2c81616SWang Jie ret = port->tcpc->set_vbus(port->tcpc, false, false);
1985*a2c81616SWang Jie port->vbus_source = false;
1986*a2c81616SWang Jie port->vbus_charge = false;
1987*a2c81616SWang Jie return ret;
1988*a2c81616SWang Jie }
1989*a2c81616SWang Jie
tcpm_init_vconn(struct tcpm_port * port)1990*a2c81616SWang Jie static int tcpm_init_vconn(struct tcpm_port *port)
1991*a2c81616SWang Jie {
1992*a2c81616SWang Jie int ret;
1993*a2c81616SWang Jie
1994*a2c81616SWang Jie ret = port->tcpc->set_vconn(port->tcpc, false);
1995*a2c81616SWang Jie port->vconn_role = TYPEC_SINK;
1996*a2c81616SWang Jie return ret;
1997*a2c81616SWang Jie }
1998*a2c81616SWang Jie
tcpm_typec_connect(struct tcpm_port * port)1999*a2c81616SWang Jie static void tcpm_typec_connect(struct tcpm_port *port)
2000*a2c81616SWang Jie {
2001*a2c81616SWang Jie if (!port->connected) {
2002*a2c81616SWang Jie port->connected = true;
2003*a2c81616SWang Jie }
2004*a2c81616SWang Jie }
2005*a2c81616SWang Jie
tcpm_src_attach(struct tcpm_port * port)2006*a2c81616SWang Jie static int tcpm_src_attach(struct tcpm_port *port)
2007*a2c81616SWang Jie {
2008*a2c81616SWang Jie enum typec_cc_polarity polarity =
2009*a2c81616SWang Jie port->cc2 == TYPEC_CC_RD ? TYPEC_POLARITY_CC2
2010*a2c81616SWang Jie : TYPEC_POLARITY_CC1;
2011*a2c81616SWang Jie int ret;
2012*a2c81616SWang Jie
2013*a2c81616SWang Jie if (port->attached)
2014*a2c81616SWang Jie return 0;
2015*a2c81616SWang Jie
2016*a2c81616SWang Jie ret = tcpm_set_polarity(port, polarity);
2017*a2c81616SWang Jie if (ret < 0)
2018*a2c81616SWang Jie return ret;
2019*a2c81616SWang Jie
2020*a2c81616SWang Jie ret = tcpm_set_roles(port, true, TYPEC_SOURCE, TYPEC_HOST);
2021*a2c81616SWang Jie if (ret < 0)
2022*a2c81616SWang Jie return ret;
2023*a2c81616SWang Jie
2024*a2c81616SWang Jie ret = port->tcpc->set_pd_rx(port->tcpc, true);
2025*a2c81616SWang Jie if (ret < 0)
2026*a2c81616SWang Jie goto out_disable_mux;
2027*a2c81616SWang Jie
2028*a2c81616SWang Jie /*
2029*a2c81616SWang Jie * USB Type-C specification, version 1.2,
2030*a2c81616SWang Jie * chapter 4.5.2.2.8.1 (Attached.SRC Requirements)
2031*a2c81616SWang Jie * Enable VCONN only if the non-RD port is set to RA.
2032*a2c81616SWang Jie */
2033*a2c81616SWang Jie if ((polarity == TYPEC_POLARITY_CC1 && port->cc2 == TYPEC_CC_RA) ||
2034*a2c81616SWang Jie (polarity == TYPEC_POLARITY_CC2 && port->cc1 == TYPEC_CC_RA)) {
2035*a2c81616SWang Jie ret = tcpm_set_vconn(port, true);
2036*a2c81616SWang Jie if (ret < 0)
2037*a2c81616SWang Jie goto out_disable_pd;
2038*a2c81616SWang Jie }
2039*a2c81616SWang Jie
2040*a2c81616SWang Jie ret = tcpm_set_vbus(port, true);
2041*a2c81616SWang Jie if (ret < 0)
2042*a2c81616SWang Jie goto out_disable_vconn;
2043*a2c81616SWang Jie
2044*a2c81616SWang Jie port->pd_capable = false;
2045*a2c81616SWang Jie
2046*a2c81616SWang Jie port->partner = NULL;
2047*a2c81616SWang Jie
2048*a2c81616SWang Jie port->attached = true;
2049*a2c81616SWang Jie port->debouncing = false;
2050*a2c81616SWang Jie //port->send_discover = true;
2051*a2c81616SWang Jie
2052*a2c81616SWang Jie return 0;
2053*a2c81616SWang Jie
2054*a2c81616SWang Jie out_disable_vconn:
2055*a2c81616SWang Jie tcpm_set_vconn(port, false);
2056*a2c81616SWang Jie out_disable_pd:
2057*a2c81616SWang Jie port->tcpc->set_pd_rx(port->tcpc, false);
2058*a2c81616SWang Jie out_disable_mux:
2059*a2c81616SWang Jie printf("CC connected in %s as DFP\n",
2060*a2c81616SWang Jie polarity ? "CC2" : "CC1");
2061*a2c81616SWang Jie return 0;
2062*a2c81616SWang Jie }
2063*a2c81616SWang Jie
tcpm_typec_disconnect(struct tcpm_port * port)2064*a2c81616SWang Jie static void tcpm_typec_disconnect(struct tcpm_port *port)
2065*a2c81616SWang Jie {
2066*a2c81616SWang Jie if (port->connected) {
2067*a2c81616SWang Jie port->partner = NULL;
2068*a2c81616SWang Jie port->connected = false;
2069*a2c81616SWang Jie }
2070*a2c81616SWang Jie }
2071*a2c81616SWang Jie
tcpm_reset_port(struct tcpm_port * port)2072*a2c81616SWang Jie static void tcpm_reset_port(struct tcpm_port *port)
2073*a2c81616SWang Jie {
2074*a2c81616SWang Jie tcpm_timer_uninit(port);
2075*a2c81616SWang Jie tcpm_typec_disconnect(port);
2076*a2c81616SWang Jie port->poll_event_cnt = 0;
2077*a2c81616SWang Jie port->wait_dr_swap_Message = false;
2078*a2c81616SWang Jie port->attached = false;
2079*a2c81616SWang Jie port->pd_capable = false;
2080*a2c81616SWang Jie port->pps_data.supported = false;
2081*a2c81616SWang Jie
2082*a2c81616SWang Jie /*
2083*a2c81616SWang Jie * First Rx ID should be 0; set this to a sentinel of -1 so that
2084*a2c81616SWang Jie * we can check tcpm_pd_rx_handler() if we had seen it before.
2085*a2c81616SWang Jie */
2086*a2c81616SWang Jie port->rx_msgid = -1;
2087*a2c81616SWang Jie
2088*a2c81616SWang Jie port->tcpc->set_pd_rx(port->tcpc, false);
2089*a2c81616SWang Jie tcpm_init_vbus(port); /* also disables charging */
2090*a2c81616SWang Jie tcpm_init_vconn(port);
2091*a2c81616SWang Jie tcpm_set_current_limit(port, 0, 0);
2092*a2c81616SWang Jie tcpm_set_polarity(port, TYPEC_POLARITY_CC1);
2093*a2c81616SWang Jie tcpm_set_attached_state(port, false);
2094*a2c81616SWang Jie port->usb_type = POWER_SUPPLY_USB_TYPE_C;
2095*a2c81616SWang Jie port->nr_sink_caps = 0;
2096*a2c81616SWang Jie port->sink_cap_done = false;
2097*a2c81616SWang Jie }
2098*a2c81616SWang Jie
tcpm_detach(struct tcpm_port * port)2099*a2c81616SWang Jie static void tcpm_detach(struct tcpm_port *port)
2100*a2c81616SWang Jie {
2101*a2c81616SWang Jie if (tcpm_port_is_disconnected(port))
2102*a2c81616SWang Jie port->hard_reset_count = 0;
2103*a2c81616SWang Jie
2104*a2c81616SWang Jie if (!port->attached)
2105*a2c81616SWang Jie return;
2106*a2c81616SWang Jie
2107*a2c81616SWang Jie tcpm_reset_port(port);
2108*a2c81616SWang Jie }
2109*a2c81616SWang Jie
tcpm_src_detach(struct tcpm_port * port)2110*a2c81616SWang Jie static void tcpm_src_detach(struct tcpm_port *port)
2111*a2c81616SWang Jie {
2112*a2c81616SWang Jie tcpm_detach(port);
2113*a2c81616SWang Jie }
2114*a2c81616SWang Jie
tcpm_snk_attach(struct tcpm_port * port)2115*a2c81616SWang Jie static int tcpm_snk_attach(struct tcpm_port *port)
2116*a2c81616SWang Jie {
2117*a2c81616SWang Jie int ret;
2118*a2c81616SWang Jie
2119*a2c81616SWang Jie if (port->attached)
2120*a2c81616SWang Jie return 0;
2121*a2c81616SWang Jie
2122*a2c81616SWang Jie ret = tcpm_set_polarity(port, port->cc2 != TYPEC_CC_OPEN ?
2123*a2c81616SWang Jie TYPEC_POLARITY_CC2 : TYPEC_POLARITY_CC1);
2124*a2c81616SWang Jie if (ret < 0)
2125*a2c81616SWang Jie return ret;
2126*a2c81616SWang Jie
2127*a2c81616SWang Jie ret = tcpm_set_roles(port, true, TYPEC_SINK, TYPEC_DEVICE);
2128*a2c81616SWang Jie if (ret < 0)
2129*a2c81616SWang Jie return ret;
2130*a2c81616SWang Jie
2131*a2c81616SWang Jie port->pd_capable = false;
2132*a2c81616SWang Jie
2133*a2c81616SWang Jie port->partner = NULL;
2134*a2c81616SWang Jie
2135*a2c81616SWang Jie port->attached = true;
2136*a2c81616SWang Jie port->debouncing = false;
2137*a2c81616SWang Jie printf("CC connected in %s as UFP\n",
2138*a2c81616SWang Jie port->cc1 != TYPEC_CC_OPEN ? "CC1" : "CC2");
2139*a2c81616SWang Jie
2140*a2c81616SWang Jie return 0;
2141*a2c81616SWang Jie }
2142*a2c81616SWang Jie
tcpm_snk_detach(struct tcpm_port * port)2143*a2c81616SWang Jie static void tcpm_snk_detach(struct tcpm_port *port)
2144*a2c81616SWang Jie {
2145*a2c81616SWang Jie tcpm_detach(port);
2146*a2c81616SWang Jie }
2147*a2c81616SWang Jie
tcpm_acc_attach(struct tcpm_port * port)2148*a2c81616SWang Jie static int tcpm_acc_attach(struct tcpm_port *port)
2149*a2c81616SWang Jie {
2150*a2c81616SWang Jie int ret;
2151*a2c81616SWang Jie
2152*a2c81616SWang Jie if (port->attached)
2153*a2c81616SWang Jie return 0;
2154*a2c81616SWang Jie
2155*a2c81616SWang Jie ret = tcpm_set_roles(port, true, TYPEC_SOURCE, TYPEC_HOST);
2156*a2c81616SWang Jie if (ret < 0)
2157*a2c81616SWang Jie return ret;
2158*a2c81616SWang Jie
2159*a2c81616SWang Jie port->partner = NULL;
2160*a2c81616SWang Jie
2161*a2c81616SWang Jie tcpm_typec_connect(port);
2162*a2c81616SWang Jie
2163*a2c81616SWang Jie port->attached = true;
2164*a2c81616SWang Jie
2165*a2c81616SWang Jie dev_info(port->dev, "CC connected as Audio Accessory\n");
2166*a2c81616SWang Jie
2167*a2c81616SWang Jie return 0;
2168*a2c81616SWang Jie }
2169*a2c81616SWang Jie
tcpm_acc_detach(struct tcpm_port * port)2170*a2c81616SWang Jie static void tcpm_acc_detach(struct tcpm_port *port)
2171*a2c81616SWang Jie {
2172*a2c81616SWang Jie tcpm_detach(port);
2173*a2c81616SWang Jie }
2174*a2c81616SWang Jie
hard_reset_state(struct tcpm_port * port)2175*a2c81616SWang Jie static inline enum tcpm_state hard_reset_state(struct tcpm_port *port)
2176*a2c81616SWang Jie {
2177*a2c81616SWang Jie if (port->hard_reset_count < PD_N_HARD_RESET_COUNT)
2178*a2c81616SWang Jie return HARD_RESET_SEND;
2179*a2c81616SWang Jie if (port->pd_capable)
2180*a2c81616SWang Jie return ERROR_RECOVERY;
2181*a2c81616SWang Jie if (port->pwr_role == TYPEC_SOURCE)
2182*a2c81616SWang Jie return SRC_UNATTACHED;
2183*a2c81616SWang Jie if (port->state == SNK_WAIT_CAPABILITIES)
2184*a2c81616SWang Jie return SNK_READY;
2185*a2c81616SWang Jie return SNK_UNATTACHED;
2186*a2c81616SWang Jie }
2187*a2c81616SWang Jie
unattached_state(struct tcpm_port * port)2188*a2c81616SWang Jie static inline enum tcpm_state unattached_state(struct tcpm_port *port)
2189*a2c81616SWang Jie {
2190*a2c81616SWang Jie if (port->port_type == TYPEC_PORT_DRP) {
2191*a2c81616SWang Jie if (port->pwr_role == TYPEC_SOURCE)
2192*a2c81616SWang Jie return SRC_UNATTACHED;
2193*a2c81616SWang Jie else
2194*a2c81616SWang Jie return SNK_UNATTACHED;
2195*a2c81616SWang Jie } else if (port->port_type == TYPEC_PORT_SRC) {
2196*a2c81616SWang Jie return SRC_UNATTACHED;
2197*a2c81616SWang Jie }
2198*a2c81616SWang Jie
2199*a2c81616SWang Jie return SNK_UNATTACHED;
2200*a2c81616SWang Jie }
2201*a2c81616SWang Jie
tcpm_is_toggling(struct tcpm_port * port)2202*a2c81616SWang Jie bool tcpm_is_toggling(struct tcpm_port *port)
2203*a2c81616SWang Jie {
2204*a2c81616SWang Jie if (port->port_type == TYPEC_PORT_DRP)
2205*a2c81616SWang Jie return port->state == SRC_UNATTACHED || port->state == SNK_UNATTACHED ||
2206*a2c81616SWang Jie port->state == TOGGLING;
2207*a2c81616SWang Jie
2208*a2c81616SWang Jie return false;
2209*a2c81616SWang Jie }
2210*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpm_is_toggling);
2211*a2c81616SWang Jie
run_state_machine(struct tcpm_port * port)2212*a2c81616SWang Jie static void run_state_machine(struct tcpm_port *port)
2213*a2c81616SWang Jie {
2214*a2c81616SWang Jie int ret;
2215*a2c81616SWang Jie
2216*a2c81616SWang Jie port->enter_state = port->state;
2217*a2c81616SWang Jie switch (port->state) {
2218*a2c81616SWang Jie case TOGGLING:
2219*a2c81616SWang Jie break;
2220*a2c81616SWang Jie /* SRC states */
2221*a2c81616SWang Jie case SRC_UNATTACHED:
2222*a2c81616SWang Jie tcpm_src_detach(port);
2223*a2c81616SWang Jie if (tcpm_start_toggling(port, tcpm_rp_cc(port))) {
2224*a2c81616SWang Jie tcpm_set_state(port, TOGGLING, 0);
2225*a2c81616SWang Jie break;
2226*a2c81616SWang Jie }
2227*a2c81616SWang Jie tcpm_set_cc(port, tcpm_rp_cc(port));
2228*a2c81616SWang Jie if (port->port_type == TYPEC_PORT_DRP)
2229*a2c81616SWang Jie tcpm_set_state(port, SNK_UNATTACHED, PD_T_DRP_SNK);
2230*a2c81616SWang Jie break;
2231*a2c81616SWang Jie case SRC_ATTACH_WAIT:
2232*a2c81616SWang Jie if (tcpm_port_is_debug(port))
2233*a2c81616SWang Jie tcpm_set_state(port, DEBUG_ACC_ATTACHED,
2234*a2c81616SWang Jie PD_T_CC_DEBOUNCE);
2235*a2c81616SWang Jie else if (tcpm_port_is_audio(port))
2236*a2c81616SWang Jie tcpm_set_state(port, AUDIO_ACC_ATTACHED,
2237*a2c81616SWang Jie PD_T_CC_DEBOUNCE);
2238*a2c81616SWang Jie else if (tcpm_port_is_source(port))
2239*a2c81616SWang Jie tcpm_set_state(port, SRC_ATTACHED, PD_T_CC_DEBOUNCE);
2240*a2c81616SWang Jie break;
2241*a2c81616SWang Jie
2242*a2c81616SWang Jie case SRC_ATTACHED:
2243*a2c81616SWang Jie ret = tcpm_src_attach(port);
2244*a2c81616SWang Jie /*
2245*a2c81616SWang Jie * Currently, vbus control is not implemented,
2246*a2c81616SWang Jie * and the SRC detection process cannot be fully implemented.
2247*a2c81616SWang Jie */
2248*a2c81616SWang Jie tcpm_set_state(port, SRC_READY, 0);
2249*a2c81616SWang Jie #if 0
2250*a2c81616SWang Jie tcpm_set_state(port, SRC_UNATTACHED,
2251*a2c81616SWang Jie ret < 0 ? 0 : PD_T_PS_SOURCE_ON);
2252*a2c81616SWang Jie #endif
2253*a2c81616SWang Jie break;
2254*a2c81616SWang Jie case SRC_STARTUP:
2255*a2c81616SWang Jie port->caps_count = 0;
2256*a2c81616SWang Jie port->negotiated_rev = PD_MAX_REV;
2257*a2c81616SWang Jie port->message_id = 0;
2258*a2c81616SWang Jie port->rx_msgid = -1;
2259*a2c81616SWang Jie port->explicit_contract = false;
2260*a2c81616SWang Jie tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
2261*a2c81616SWang Jie break;
2262*a2c81616SWang Jie case SRC_SEND_CAPABILITIES:
2263*a2c81616SWang Jie port->caps_count++;
2264*a2c81616SWang Jie if (port->caps_count > PD_N_CAPS_COUNT) {
2265*a2c81616SWang Jie tcpm_set_state(port, SRC_READY, 0);
2266*a2c81616SWang Jie break;
2267*a2c81616SWang Jie }
2268*a2c81616SWang Jie ret = tcpm_pd_send_source_caps(port);
2269*a2c81616SWang Jie if (ret < 0) {
2270*a2c81616SWang Jie tcpm_set_state(port, SRC_SEND_CAPABILITIES,
2271*a2c81616SWang Jie PD_T_SEND_SOURCE_CAP);
2272*a2c81616SWang Jie } else {
2273*a2c81616SWang Jie /*
2274*a2c81616SWang Jie * Per standard, we should clear the reset counter here.
2275*a2c81616SWang Jie * However, that can result in state machine hang-ups.
2276*a2c81616SWang Jie * Reset it only in READY state to improve stability.
2277*a2c81616SWang Jie */
2278*a2c81616SWang Jie /* port->hard_reset_count = 0; */
2279*a2c81616SWang Jie port->caps_count = 0;
2280*a2c81616SWang Jie port->pd_capable = true;
2281*a2c81616SWang Jie tcpm_set_state_cond(port, SRC_SEND_CAPABILITIES_TIMEOUT,
2282*a2c81616SWang Jie PD_T_SEND_SOURCE_CAP);
2283*a2c81616SWang Jie }
2284*a2c81616SWang Jie break;
2285*a2c81616SWang Jie case SRC_SEND_CAPABILITIES_TIMEOUT:
2286*a2c81616SWang Jie /*
2287*a2c81616SWang Jie * Error recovery for a PD_DATA_SOURCE_CAP reply timeout.
2288*a2c81616SWang Jie *
2289*a2c81616SWang Jie * PD 2.0 sinks are supposed to accept src-capabilities with a
2290*a2c81616SWang Jie * 3.0 header and simply ignore any src PDOs which the sink does
2291*a2c81616SWang Jie * not understand such as PPS but some 2.0 sinks instead ignore
2292*a2c81616SWang Jie * the entire PD_DATA_SOURCE_CAP message, causing contract
2293*a2c81616SWang Jie * negotiation to fail.
2294*a2c81616SWang Jie *
2295*a2c81616SWang Jie * After PD_N_HARD_RESET_COUNT hard-reset attempts, we try
2296*a2c81616SWang Jie * sending src-capabilities with a lower PD revision to
2297*a2c81616SWang Jie * make these broken sinks work.
2298*a2c81616SWang Jie */
2299*a2c81616SWang Jie if (port->hard_reset_count < PD_N_HARD_RESET_COUNT) {
2300*a2c81616SWang Jie tcpm_set_state(port, HARD_RESET_SEND, 0);
2301*a2c81616SWang Jie } else if (port->negotiated_rev > PD_REV20) {
2302*a2c81616SWang Jie port->negotiated_rev--;
2303*a2c81616SWang Jie port->hard_reset_count = 0;
2304*a2c81616SWang Jie tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
2305*a2c81616SWang Jie } else {
2306*a2c81616SWang Jie tcpm_set_state(port, hard_reset_state(port), 0);
2307*a2c81616SWang Jie }
2308*a2c81616SWang Jie break;
2309*a2c81616SWang Jie case SRC_NEGOTIATE_CAPABILITIES:
2310*a2c81616SWang Jie ret = tcpm_pd_check_request(port);
2311*a2c81616SWang Jie if (ret < 0) {
2312*a2c81616SWang Jie tcpm_pd_send_control(port, PD_CTRL_REJECT);
2313*a2c81616SWang Jie if (!port->explicit_contract) {
2314*a2c81616SWang Jie tcpm_set_state(port,
2315*a2c81616SWang Jie SRC_WAIT_NEW_CAPABILITIES, 0);
2316*a2c81616SWang Jie } else {
2317*a2c81616SWang Jie tcpm_set_state(port, SRC_READY, 0);
2318*a2c81616SWang Jie }
2319*a2c81616SWang Jie } else {
2320*a2c81616SWang Jie tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
2321*a2c81616SWang Jie tcpm_set_state(port, SRC_TRANSITION_SUPPLY,
2322*a2c81616SWang Jie PD_T_SRC_TRANSITION);
2323*a2c81616SWang Jie }
2324*a2c81616SWang Jie break;
2325*a2c81616SWang Jie case SRC_TRANSITION_SUPPLY:
2326*a2c81616SWang Jie /* XXX: regulator_set_voltage(vbus, ...) */
2327*a2c81616SWang Jie tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
2328*a2c81616SWang Jie port->explicit_contract = true;
2329*a2c81616SWang Jie tcpm_set_state_cond(port, SRC_READY, 0);
2330*a2c81616SWang Jie break;
2331*a2c81616SWang Jie case SRC_READY:
2332*a2c81616SWang Jie #if 1
2333*a2c81616SWang Jie port->hard_reset_count = 0;
2334*a2c81616SWang Jie #endif
2335*a2c81616SWang Jie port->try_src_count = 0;
2336*a2c81616SWang Jie
2337*a2c81616SWang Jie tcpm_typec_connect(port);
2338*a2c81616SWang Jie break;
2339*a2c81616SWang Jie case SRC_WAIT_NEW_CAPABILITIES:
2340*a2c81616SWang Jie /* Nothing to do... */
2341*a2c81616SWang Jie break;
2342*a2c81616SWang Jie
2343*a2c81616SWang Jie /* SNK states */
2344*a2c81616SWang Jie case SNK_UNATTACHED:
2345*a2c81616SWang Jie tcpm_snk_detach(port);
2346*a2c81616SWang Jie if (tcpm_start_toggling(port, TYPEC_CC_RD)) {
2347*a2c81616SWang Jie tcpm_set_state(port, TOGGLING, 0);
2348*a2c81616SWang Jie break;
2349*a2c81616SWang Jie }
2350*a2c81616SWang Jie tcpm_set_cc(port, TYPEC_CC_RD);
2351*a2c81616SWang Jie if (port->port_type == TYPEC_PORT_DRP)
2352*a2c81616SWang Jie tcpm_set_state(port, SRC_UNATTACHED, PD_T_DRP_SRC);
2353*a2c81616SWang Jie break;
2354*a2c81616SWang Jie case SNK_ATTACH_WAIT:
2355*a2c81616SWang Jie if ((port->cc1 == TYPEC_CC_OPEN &&
2356*a2c81616SWang Jie port->cc2 != TYPEC_CC_OPEN) ||
2357*a2c81616SWang Jie (port->cc1 != TYPEC_CC_OPEN &&
2358*a2c81616SWang Jie port->cc2 == TYPEC_CC_OPEN))
2359*a2c81616SWang Jie tcpm_set_state(port, SNK_DEBOUNCED,
2360*a2c81616SWang Jie PD_T_CC_DEBOUNCE);
2361*a2c81616SWang Jie else if (tcpm_port_is_disconnected(port))
2362*a2c81616SWang Jie tcpm_set_state(port, SNK_UNATTACHED,
2363*a2c81616SWang Jie PD_T_CC_DEBOUNCE);
2364*a2c81616SWang Jie break;
2365*a2c81616SWang Jie case SNK_DEBOUNCED:
2366*a2c81616SWang Jie if (tcpm_port_is_disconnected(port)) {
2367*a2c81616SWang Jie tcpm_set_state(port, SNK_UNATTACHED,
2368*a2c81616SWang Jie PD_T_PD_DEBOUNCE);
2369*a2c81616SWang Jie } else if (port->vbus_present)
2370*a2c81616SWang Jie tcpm_set_state(port, SNK_ATTACHED, 0);
2371*a2c81616SWang Jie else
2372*a2c81616SWang Jie /* Wait for VBUS, but not forever */
2373*a2c81616SWang Jie tcpm_set_state(port, PORT_RESET, PD_T_PS_SOURCE_ON);
2374*a2c81616SWang Jie break;
2375*a2c81616SWang Jie
2376*a2c81616SWang Jie case SNK_ATTACHED:
2377*a2c81616SWang Jie ret = tcpm_snk_attach(port);
2378*a2c81616SWang Jie if (ret < 0)
2379*a2c81616SWang Jie tcpm_set_state(port, SNK_UNATTACHED, 0);
2380*a2c81616SWang Jie else
2381*a2c81616SWang Jie tcpm_set_state(port, SNK_STARTUP, 0);
2382*a2c81616SWang Jie break;
2383*a2c81616SWang Jie case SNK_STARTUP:
2384*a2c81616SWang Jie port->negotiated_rev = PD_MAX_REV;
2385*a2c81616SWang Jie port->message_id = 0;
2386*a2c81616SWang Jie port->rx_msgid = -1;
2387*a2c81616SWang Jie port->explicit_contract = false;
2388*a2c81616SWang Jie tcpm_set_state(port, SNK_DISCOVERY, 0);
2389*a2c81616SWang Jie break;
2390*a2c81616SWang Jie case SNK_DISCOVERY:
2391*a2c81616SWang Jie if (port->vbus_present) {
2392*a2c81616SWang Jie tcpm_set_current_limit(port,
2393*a2c81616SWang Jie tcpm_get_current_limit(port),
2394*a2c81616SWang Jie 5000);
2395*a2c81616SWang Jie tcpm_set_charge(port, true);
2396*a2c81616SWang Jie tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0);
2397*a2c81616SWang Jie break;
2398*a2c81616SWang Jie }
2399*a2c81616SWang Jie /*
2400*a2c81616SWang Jie * For DRP, timeouts differ. Also, handling is supposed to be
2401*a2c81616SWang Jie * different and much more complex (dead battery detection;
2402*a2c81616SWang Jie * see USB power delivery specification, section 8.3.3.6.1.5.1).
2403*a2c81616SWang Jie */
2404*a2c81616SWang Jie tcpm_set_state(port, hard_reset_state(port),
2405*a2c81616SWang Jie port->port_type == TYPEC_PORT_DRP ?
2406*a2c81616SWang Jie PD_T_DB_DETECT : PD_T_NO_RESPONSE);
2407*a2c81616SWang Jie break;
2408*a2c81616SWang Jie case SNK_DISCOVERY_DEBOUNCE:
2409*a2c81616SWang Jie tcpm_set_state(port, SNK_DISCOVERY_DEBOUNCE_DONE,
2410*a2c81616SWang Jie PD_T_CC_DEBOUNCE);
2411*a2c81616SWang Jie break;
2412*a2c81616SWang Jie case SNK_DISCOVERY_DEBOUNCE_DONE:
2413*a2c81616SWang Jie #if 0
2414*a2c81616SWang Jie if (!tcpm_port_is_disconnected(port) &&
2415*a2c81616SWang Jie tcpm_port_is_sink(port) &&
2416*a2c81616SWang Jie ktime_after(port->delayed_runtime, ktime_get())) {
2417*a2c81616SWang Jie tcpm_set_state(port, SNK_DISCOVERY,
2418*a2c81616SWang Jie ktime_to_ms(ktime_sub(port->delayed_runtime, ktime_get())));
2419*a2c81616SWang Jie break;
2420*a2c81616SWang Jie }
2421*a2c81616SWang Jie #endif
2422*a2c81616SWang Jie tcpm_set_state(port, unattached_state(port), 0);
2423*a2c81616SWang Jie break;
2424*a2c81616SWang Jie case SNK_WAIT_CAPABILITIES:
2425*a2c81616SWang Jie ret = port->tcpc->set_pd_rx(port->tcpc, true);
2426*a2c81616SWang Jie if (ret < 0) {
2427*a2c81616SWang Jie tcpm_set_state(port, SNK_READY, 0);
2428*a2c81616SWang Jie break;
2429*a2c81616SWang Jie }
2430*a2c81616SWang Jie /*
2431*a2c81616SWang Jie * If VBUS has never been low, and we time out waiting
2432*a2c81616SWang Jie * for source cap, try a soft reset first, in case we
2433*a2c81616SWang Jie * were already in a stable contract before this boot.
2434*a2c81616SWang Jie * Do this only once.
2435*a2c81616SWang Jie */
2436*a2c81616SWang Jie if (port->vbus_never_low) {
2437*a2c81616SWang Jie port->vbus_never_low = false;
2438*a2c81616SWang Jie tcpm_set_state(port, SOFT_RESET_SEND,
2439*a2c81616SWang Jie PD_T_SINK_WAIT_CAP);
2440*a2c81616SWang Jie } else {
2441*a2c81616SWang Jie tcpm_set_state(port, hard_reset_state(port),
2442*a2c81616SWang Jie PD_T_SINK_WAIT_CAP);
2443*a2c81616SWang Jie }
2444*a2c81616SWang Jie break;
2445*a2c81616SWang Jie case SNK_NEGOTIATE_CAPABILITIES:
2446*a2c81616SWang Jie port->pd_capable = true;
2447*a2c81616SWang Jie port->hard_reset_count = 0;
2448*a2c81616SWang Jie ret = tcpm_pd_send_request(port);
2449*a2c81616SWang Jie if (ret < 0) {
2450*a2c81616SWang Jie /* Let the Source send capabilities again. */
2451*a2c81616SWang Jie tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0);
2452*a2c81616SWang Jie } else {
2453*a2c81616SWang Jie tcpm_set_state_cond(port, hard_reset_state(port),
2454*a2c81616SWang Jie PD_T_SENDER_RESPONSE);
2455*a2c81616SWang Jie }
2456*a2c81616SWang Jie break;
2457*a2c81616SWang Jie case SNK_NEGOTIATE_PPS_CAPABILITIES:
2458*a2c81616SWang Jie ret = tcpm_pd_send_pps_request(port);
2459*a2c81616SWang Jie if (ret < 0) {
2460*a2c81616SWang Jie port->pps_status = ret;
2461*a2c81616SWang Jie /*
2462*a2c81616SWang Jie * If this was called due to updates to sink
2463*a2c81616SWang Jie * capabilities, and pps is no longer valid, we should
2464*a2c81616SWang Jie * safely fall back to a standard PDO.
2465*a2c81616SWang Jie */
2466*a2c81616SWang Jie if (port->update_sink_caps)
2467*a2c81616SWang Jie tcpm_set_state(port, SNK_NEGOTIATE_CAPABILITIES, 0);
2468*a2c81616SWang Jie else
2469*a2c81616SWang Jie tcpm_set_state(port, SNK_READY, 0);
2470*a2c81616SWang Jie } else {
2471*a2c81616SWang Jie tcpm_set_state_cond(port, hard_reset_state(port),
2472*a2c81616SWang Jie PD_T_SENDER_RESPONSE);
2473*a2c81616SWang Jie }
2474*a2c81616SWang Jie break;
2475*a2c81616SWang Jie case SNK_TRANSITION_SINK:
2476*a2c81616SWang Jie case SNK_TRANSITION_SINK_VBUS:
2477*a2c81616SWang Jie tcpm_set_state(port, hard_reset_state(port),
2478*a2c81616SWang Jie PD_T_PS_TRANSITION);
2479*a2c81616SWang Jie break;
2480*a2c81616SWang Jie case SNK_READY:
2481*a2c81616SWang Jie port->try_snk_count = 0;
2482*a2c81616SWang Jie port->update_sink_caps = false;
2483*a2c81616SWang Jie tcpm_typec_connect(port);
2484*a2c81616SWang Jie /*
2485*a2c81616SWang Jie * Here poll_event_cnt is cleared, waiting for self-powered Type-C devices
2486*a2c81616SWang Jie * to send DR_swap Messge until 1s (TCPM_POLL_EVENT_TIME_OUT * 500us)timeout
2487*a2c81616SWang Jie */
2488*a2c81616SWang Jie if (port->wait_dr_swap_Message)
2489*a2c81616SWang Jie port->poll_event_cnt = 0;
2490*a2c81616SWang Jie
2491*a2c81616SWang Jie break;
2492*a2c81616SWang Jie
2493*a2c81616SWang Jie /* Accessory states */
2494*a2c81616SWang Jie case ACC_UNATTACHED:
2495*a2c81616SWang Jie tcpm_acc_detach(port);
2496*a2c81616SWang Jie tcpm_set_state(port, SRC_UNATTACHED, 0);
2497*a2c81616SWang Jie break;
2498*a2c81616SWang Jie case DEBUG_ACC_ATTACHED:
2499*a2c81616SWang Jie case AUDIO_ACC_ATTACHED:
2500*a2c81616SWang Jie ret = tcpm_acc_attach(port);
2501*a2c81616SWang Jie if (ret < 0)
2502*a2c81616SWang Jie tcpm_set_state(port, ACC_UNATTACHED, 0);
2503*a2c81616SWang Jie break;
2504*a2c81616SWang Jie case AUDIO_ACC_DEBOUNCE:
2505*a2c81616SWang Jie tcpm_set_state(port, ACC_UNATTACHED, PD_T_CC_DEBOUNCE);
2506*a2c81616SWang Jie break;
2507*a2c81616SWang Jie
2508*a2c81616SWang Jie /* Hard_Reset states */
2509*a2c81616SWang Jie case HARD_RESET_SEND:
2510*a2c81616SWang Jie tcpm_pd_transmit(port, TCPC_TX_HARD_RESET, NULL);
2511*a2c81616SWang Jie tcpm_set_state(port, HARD_RESET_START, 0);
2512*a2c81616SWang Jie port->wait_dr_swap_Message = false;
2513*a2c81616SWang Jie break;
2514*a2c81616SWang Jie case HARD_RESET_START:
2515*a2c81616SWang Jie port->hard_reset_count++;
2516*a2c81616SWang Jie port->tcpc->set_pd_rx(port->tcpc, false);
2517*a2c81616SWang Jie port->nr_sink_caps = 0;
2518*a2c81616SWang Jie port->send_discover = true;
2519*a2c81616SWang Jie if (port->pwr_role == TYPEC_SOURCE)
2520*a2c81616SWang Jie tcpm_set_state(port, SRC_HARD_RESET_VBUS_OFF,
2521*a2c81616SWang Jie PD_T_PS_HARD_RESET);
2522*a2c81616SWang Jie else
2523*a2c81616SWang Jie tcpm_set_state(port, SNK_HARD_RESET_SINK_OFF, 0);
2524*a2c81616SWang Jie break;
2525*a2c81616SWang Jie case SRC_HARD_RESET_VBUS_OFF:
2526*a2c81616SWang Jie tcpm_set_vconn(port, true);
2527*a2c81616SWang Jie tcpm_set_vbus(port, false);
2528*a2c81616SWang Jie tcpm_set_roles(port, port->self_powered, TYPEC_SOURCE,
2529*a2c81616SWang Jie TYPEC_HOST);
2530*a2c81616SWang Jie tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, PD_T_SRC_RECOVER);
2531*a2c81616SWang Jie break;
2532*a2c81616SWang Jie case SRC_HARD_RESET_VBUS_ON:
2533*a2c81616SWang Jie tcpm_set_vconn(port, true);
2534*a2c81616SWang Jie tcpm_set_vbus(port, true);
2535*a2c81616SWang Jie port->tcpc->set_pd_rx(port->tcpc, true);
2536*a2c81616SWang Jie tcpm_set_attached_state(port, true);
2537*a2c81616SWang Jie tcpm_set_state(port, SRC_UNATTACHED, PD_T_PS_SOURCE_ON);
2538*a2c81616SWang Jie break;
2539*a2c81616SWang Jie case SNK_HARD_RESET_SINK_OFF:
2540*a2c81616SWang Jie memset(&port->pps_data, 0, sizeof(port->pps_data));
2541*a2c81616SWang Jie tcpm_set_vconn(port, false);
2542*a2c81616SWang Jie if (port->pd_capable)
2543*a2c81616SWang Jie tcpm_set_charge(port, false);
2544*a2c81616SWang Jie tcpm_set_roles(port, port->self_powered, TYPEC_SINK,
2545*a2c81616SWang Jie TYPEC_DEVICE);
2546*a2c81616SWang Jie /*
2547*a2c81616SWang Jie * VBUS may or may not toggle, depending on the adapter.
2548*a2c81616SWang Jie * If it doesn't toggle, transition to SNK_HARD_RESET_SINK_ON
2549*a2c81616SWang Jie * directly after timeout.
2550*a2c81616SWang Jie */
2551*a2c81616SWang Jie tcpm_set_state(port, SNK_HARD_RESET_SINK_ON, PD_T_SAFE_0V);
2552*a2c81616SWang Jie break;
2553*a2c81616SWang Jie case SNK_HARD_RESET_WAIT_VBUS:
2554*a2c81616SWang Jie /* Assume we're disconnected if VBUS doesn't come back. */
2555*a2c81616SWang Jie tcpm_set_state(port, SNK_UNATTACHED,
2556*a2c81616SWang Jie PD_T_SRC_RECOVER_MAX + PD_T_SRC_TURN_ON);
2557*a2c81616SWang Jie break;
2558*a2c81616SWang Jie case SNK_HARD_RESET_SINK_ON:
2559*a2c81616SWang Jie /* Note: There is no guarantee that VBUS is on in this state */
2560*a2c81616SWang Jie /*
2561*a2c81616SWang Jie * XXX:
2562*a2c81616SWang Jie * The specification suggests that dual mode ports in sink
2563*a2c81616SWang Jie * mode should transition to state PE_SRC_Transition_to_default.
2564*a2c81616SWang Jie * See USB power delivery specification chapter 8.3.3.6.1.3.
2565*a2c81616SWang Jie * This would mean to to
2566*a2c81616SWang Jie * - turn off VCONN, reset power supply
2567*a2c81616SWang Jie * - request hardware reset
2568*a2c81616SWang Jie * - turn on VCONN
2569*a2c81616SWang Jie * - Transition to state PE_Src_Startup
2570*a2c81616SWang Jie * SNK only ports shall transition to state Snk_Startup
2571*a2c81616SWang Jie * (see chapter 8.3.3.3.8).
2572*a2c81616SWang Jie * Similar, dual-mode ports in source mode should transition
2573*a2c81616SWang Jie * to PE_SNK_Transition_to_default.
2574*a2c81616SWang Jie */
2575*a2c81616SWang Jie if (port->pd_capable) {
2576*a2c81616SWang Jie tcpm_set_current_limit(port,
2577*a2c81616SWang Jie tcpm_get_current_limit(port),
2578*a2c81616SWang Jie 5000);
2579*a2c81616SWang Jie tcpm_set_charge(port, true);
2580*a2c81616SWang Jie }
2581*a2c81616SWang Jie tcpm_set_attached_state(port, true);
2582*a2c81616SWang Jie tcpm_set_state(port, SNK_STARTUP, 0);
2583*a2c81616SWang Jie break;
2584*a2c81616SWang Jie
2585*a2c81616SWang Jie /* Soft_Reset states */
2586*a2c81616SWang Jie case SOFT_RESET:
2587*a2c81616SWang Jie port->message_id = 0;
2588*a2c81616SWang Jie port->rx_msgid = -1;
2589*a2c81616SWang Jie tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
2590*a2c81616SWang Jie if (port->pwr_role == TYPEC_SOURCE) {
2591*a2c81616SWang Jie tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
2592*a2c81616SWang Jie } else {
2593*a2c81616SWang Jie tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0);
2594*a2c81616SWang Jie }
2595*a2c81616SWang Jie break;
2596*a2c81616SWang Jie case SOFT_RESET_SEND:
2597*a2c81616SWang Jie port->message_id = 0;
2598*a2c81616SWang Jie port->rx_msgid = -1;
2599*a2c81616SWang Jie if (tcpm_pd_send_control(port, PD_CTRL_SOFT_RESET))
2600*a2c81616SWang Jie tcpm_set_state_cond(port, hard_reset_state(port), 0);
2601*a2c81616SWang Jie else
2602*a2c81616SWang Jie tcpm_set_state_cond(port, hard_reset_state(port),
2603*a2c81616SWang Jie PD_T_SENDER_RESPONSE);
2604*a2c81616SWang Jie break;
2605*a2c81616SWang Jie
2606*a2c81616SWang Jie /* DR_Swap states */
2607*a2c81616SWang Jie case DR_SWAP_SEND:
2608*a2c81616SWang Jie tcpm_pd_send_control(port, PD_CTRL_DR_SWAP);
2609*a2c81616SWang Jie tcpm_set_state_cond(port, DR_SWAP_SEND_TIMEOUT,
2610*a2c81616SWang Jie PD_T_SENDER_RESPONSE);
2611*a2c81616SWang Jie break;
2612*a2c81616SWang Jie case DR_SWAP_ACCEPT:
2613*a2c81616SWang Jie tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
2614*a2c81616SWang Jie #if 0
2615*a2c81616SWang Jie /* Set VDM state machine running flag ASAP */
2616*a2c81616SWang Jie if (port->data_role == TYPEC_DEVICE && port->send_discover)
2617*a2c81616SWang Jie port->vdm_sm_running = true;
2618*a2c81616SWang Jie #endif
2619*a2c81616SWang Jie tcpm_set_state_cond(port, DR_SWAP_CHANGE_DR, 0);
2620*a2c81616SWang Jie break;
2621*a2c81616SWang Jie case DR_SWAP_SEND_TIMEOUT:
2622*a2c81616SWang Jie //tcpm_swap_complete(port, -ETIMEDOUT);
2623*a2c81616SWang Jie tcpm_set_state(port, ready_state(port), 0);
2624*a2c81616SWang Jie break;
2625*a2c81616SWang Jie case DR_SWAP_CHANGE_DR:
2626*a2c81616SWang Jie if (port->data_role == TYPEC_HOST) {
2627*a2c81616SWang Jie //tcpm_unregister_altmodes(port);
2628*a2c81616SWang Jie tcpm_set_roles(port, true, port->pwr_role,
2629*a2c81616SWang Jie TYPEC_DEVICE);
2630*a2c81616SWang Jie } else {
2631*a2c81616SWang Jie tcpm_set_roles(port, true, port->pwr_role,
2632*a2c81616SWang Jie TYPEC_HOST);
2633*a2c81616SWang Jie //port->send_discover = true;
2634*a2c81616SWang Jie }
2635*a2c81616SWang Jie /* DR_swap process complete, wait_dr_swap_Message is cleared */
2636*a2c81616SWang Jie port->wait_dr_swap_Message = false;
2637*a2c81616SWang Jie tcpm_set_state(port, ready_state(port), 0);
2638*a2c81616SWang Jie break;
2639*a2c81616SWang Jie
2640*a2c81616SWang Jie #if 0
2641*a2c81616SWang Jie
2642*a2c81616SWang Jie /* PR_Swap states */
2643*a2c81616SWang Jie case PR_SWAP_ACCEPT:
2644*a2c81616SWang Jie tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
2645*a2c81616SWang Jie tcpm_set_state(port, PR_SWAP_START, 0);
2646*a2c81616SWang Jie break;
2647*a2c81616SWang Jie case PR_SWAP_SEND:
2648*a2c81616SWang Jie tcpm_pd_send_control(port, PD_CTRL_PR_SWAP);
2649*a2c81616SWang Jie tcpm_set_state_cond(port, PR_SWAP_SEND_TIMEOUT,
2650*a2c81616SWang Jie PD_T_SENDER_RESPONSE);
2651*a2c81616SWang Jie break;
2652*a2c81616SWang Jie case PR_SWAP_SEND_TIMEOUT:
2653*a2c81616SWang Jie tcpm_set_state(port, ready_state(port), 0);
2654*a2c81616SWang Jie break;
2655*a2c81616SWang Jie case PR_SWAP_START:
2656*a2c81616SWang Jie tcpm_apply_rc(port);
2657*a2c81616SWang Jie if (port->pwr_role == TYPEC_SOURCE)
2658*a2c81616SWang Jie tcpm_set_state(port, PR_SWAP_SRC_SNK_TRANSITION_OFF,
2659*a2c81616SWang Jie PD_T_SRC_TRANSITION);
2660*a2c81616SWang Jie else
2661*a2c81616SWang Jie tcpm_set_state(port, PR_SWAP_SNK_SRC_SINK_OFF, 0);
2662*a2c81616SWang Jie break;
2663*a2c81616SWang Jie case PR_SWAP_SRC_SNK_TRANSITION_OFF:
2664*a2c81616SWang Jie /*
2665*a2c81616SWang Jie * Prevent vbus discharge circuit from turning on during PR_SWAP
2666*a2c81616SWang Jie * as this is not a disconnect.
2667*a2c81616SWang Jie */
2668*a2c81616SWang Jie tcpm_set_vbus(port, false);
2669*a2c81616SWang Jie port->explicit_contract = false;
2670*a2c81616SWang Jie /* allow time for Vbus discharge, must be < tSrcSwapStdby */
2671*a2c81616SWang Jie tcpm_set_state(port, PR_SWAP_SRC_SNK_SOURCE_OFF,
2672*a2c81616SWang Jie PD_T_SRCSWAPSTDBY);
2673*a2c81616SWang Jie break;
2674*a2c81616SWang Jie case PR_SWAP_SRC_SNK_SOURCE_OFF:
2675*a2c81616SWang Jie timer_val_msecs = PD_T_CC_DEBOUNCE;
2676*a2c81616SWang Jie trace_android_vh_typec_tcpm_get_timer(tcpm_states[PR_SWAP_SRC_SNK_SOURCE_OFF],
2677*a2c81616SWang Jie CC_DEBOUNCE, &timer_val_msecs);
2678*a2c81616SWang Jie tcpm_set_cc(port, TYPEC_CC_RD);
2679*a2c81616SWang Jie /* allow CC debounce */
2680*a2c81616SWang Jie tcpm_set_state(port, PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED,
2681*a2c81616SWang Jie timer_val_msecs);
2682*a2c81616SWang Jie break;
2683*a2c81616SWang Jie case PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED:
2684*a2c81616SWang Jie /*
2685*a2c81616SWang Jie * USB-PD standard, 6.2.1.4, Port Power Role:
2686*a2c81616SWang Jie * "During the Power Role Swap Sequence, for the initial Source
2687*a2c81616SWang Jie * Port, the Port Power Role field shall be set to Sink in the
2688*a2c81616SWang Jie * PS_RDY Message indicating that the initial Source’s power
2689*a2c81616SWang Jie * supply is turned off"
2690*a2c81616SWang Jie */
2691*a2c81616SWang Jie tcpm_set_pwr_role(port, TYPEC_SINK);
2692*a2c81616SWang Jie if (tcpm_pd_send_control(port, PD_CTRL_PS_RDY)) {
2693*a2c81616SWang Jie tcpm_set_state(port, ERROR_RECOVERY, 0);
2694*a2c81616SWang Jie break;
2695*a2c81616SWang Jie }
2696*a2c81616SWang Jie tcpm_set_state(port, ERROR_RECOVERY, PD_T_PS_SOURCE_ON_PRS);
2697*a2c81616SWang Jie break;
2698*a2c81616SWang Jie case PR_SWAP_SRC_SNK_SINK_ON:
2699*a2c81616SWang Jie tcpm_enable_auto_vbus_discharge(port, true);
2700*a2c81616SWang Jie /* Set the vbus disconnect threshold for implicit contract */
2701*a2c81616SWang Jie tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_USB, false, VSAFE5V);
2702*a2c81616SWang Jie tcpm_set_state(port, SNK_STARTUP, 0);
2703*a2c81616SWang Jie break;
2704*a2c81616SWang Jie case PR_SWAP_SNK_SRC_SINK_OFF:
2705*a2c81616SWang Jie timer_val_msecs = PD_T_PS_SOURCE_OFF;
2706*a2c81616SWang Jie trace_android_vh_typec_tcpm_get_timer(tcpm_states[PR_SWAP_SNK_SRC_SINK_OFF],
2707*a2c81616SWang Jie SOURCE_OFF, &timer_val_msecs);
2708*a2c81616SWang Jie /*
2709*a2c81616SWang Jie * Prevent vbus discharge circuit from turning on during PR_SWAP
2710*a2c81616SWang Jie * as this is not a disconnect.
2711*a2c81616SWang Jie */
2712*a2c81616SWang Jie tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_USB,
2713*a2c81616SWang Jie port->pps_data.active, 0);
2714*a2c81616SWang Jie tcpm_set_charge(port, false);
2715*a2c81616SWang Jie tcpm_set_state(port, hard_reset_state(port), timer_val_msecs);
2716*a2c81616SWang Jie break;
2717*a2c81616SWang Jie case PR_SWAP_SNK_SRC_SOURCE_ON:
2718*a2c81616SWang Jie tcpm_enable_auto_vbus_discharge(port, true);
2719*a2c81616SWang Jie tcpm_set_cc(port, tcpm_rp_cc(port));
2720*a2c81616SWang Jie tcpm_set_vbus(port, true);
2721*a2c81616SWang Jie /*
2722*a2c81616SWang Jie * allow time VBUS ramp-up, must be < tNewSrc
2723*a2c81616SWang Jie * Also, this window overlaps with CC debounce as well.
2724*a2c81616SWang Jie * So, Wait for the max of two which is PD_T_NEWSRC
2725*a2c81616SWang Jie */
2726*a2c81616SWang Jie tcpm_set_state(port, PR_SWAP_SNK_SRC_SOURCE_ON_VBUS_RAMPED_UP,
2727*a2c81616SWang Jie PD_T_NEWSRC);
2728*a2c81616SWang Jie break;
2729*a2c81616SWang Jie case PR_SWAP_SNK_SRC_SOURCE_ON_VBUS_RAMPED_UP:
2730*a2c81616SWang Jie /*
2731*a2c81616SWang Jie * USB PD standard, 6.2.1.4:
2732*a2c81616SWang Jie * "Subsequent Messages initiated by the Policy Engine,
2733*a2c81616SWang Jie * such as the PS_RDY Message sent to indicate that Vbus
2734*a2c81616SWang Jie * is ready, will have the Port Power Role field set to
2735*a2c81616SWang Jie * Source."
2736*a2c81616SWang Jie */
2737*a2c81616SWang Jie tcpm_set_pwr_role(port, TYPEC_SOURCE);
2738*a2c81616SWang Jie tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
2739*a2c81616SWang Jie tcpm_set_state(port, SRC_STARTUP, PD_T_SWAP_SRC_START);
2740*a2c81616SWang Jie break;
2741*a2c81616SWang Jie #endif
2742*a2c81616SWang Jie case GET_STATUS_SEND:
2743*a2c81616SWang Jie tcpm_pd_send_control(port, PD_CTRL_GET_STATUS);
2744*a2c81616SWang Jie tcpm_set_state(port, GET_STATUS_SEND_TIMEOUT,
2745*a2c81616SWang Jie PD_T_SENDER_RESPONSE);
2746*a2c81616SWang Jie break;
2747*a2c81616SWang Jie case GET_STATUS_SEND_TIMEOUT:
2748*a2c81616SWang Jie tcpm_set_state(port, ready_state(port), 0);
2749*a2c81616SWang Jie break;
2750*a2c81616SWang Jie case GET_PPS_STATUS_SEND:
2751*a2c81616SWang Jie tcpm_pd_send_control(port, PD_CTRL_GET_PPS_STATUS);
2752*a2c81616SWang Jie tcpm_set_state(port, GET_PPS_STATUS_SEND_TIMEOUT,
2753*a2c81616SWang Jie PD_T_SENDER_RESPONSE);
2754*a2c81616SWang Jie break;
2755*a2c81616SWang Jie case GET_PPS_STATUS_SEND_TIMEOUT:
2756*a2c81616SWang Jie tcpm_set_state(port, ready_state(port), 0);
2757*a2c81616SWang Jie break;
2758*a2c81616SWang Jie case GET_SINK_CAP:
2759*a2c81616SWang Jie tcpm_pd_send_control(port, PD_CTRL_GET_SINK_CAP);
2760*a2c81616SWang Jie tcpm_set_state(port, GET_SINK_CAP_TIMEOUT, PD_T_SENDER_RESPONSE);
2761*a2c81616SWang Jie break;
2762*a2c81616SWang Jie case GET_SINK_CAP_TIMEOUT:
2763*a2c81616SWang Jie tcpm_set_state(port, ready_state(port), 0);
2764*a2c81616SWang Jie break;
2765*a2c81616SWang Jie case ERROR_RECOVERY:
2766*a2c81616SWang Jie tcpm_set_state(port, PORT_RESET, 0);
2767*a2c81616SWang Jie break;
2768*a2c81616SWang Jie case PORT_RESET:
2769*a2c81616SWang Jie tcpm_reset_port(port);
2770*a2c81616SWang Jie tcpm_set_cc(port, TYPEC_CC_OPEN);
2771*a2c81616SWang Jie tcpm_set_state(port, PORT_RESET_WAIT_OFF,
2772*a2c81616SWang Jie PD_T_ERROR_RECOVERY);
2773*a2c81616SWang Jie break;
2774*a2c81616SWang Jie case PORT_RESET_WAIT_OFF:
2775*a2c81616SWang Jie tcpm_set_state(port,
2776*a2c81616SWang Jie tcpm_default_state(port),
2777*a2c81616SWang Jie port->vbus_present ? PD_T_PS_SOURCE_OFF : 0);
2778*a2c81616SWang Jie break;
2779*a2c81616SWang Jie default:
2780*a2c81616SWang Jie printf("Unexpected port state %d\n", port->state);
2781*a2c81616SWang Jie break;
2782*a2c81616SWang Jie }
2783*a2c81616SWang Jie }
2784*a2c81616SWang Jie
tcpm_state_machine(struct tcpm_port * port)2785*a2c81616SWang Jie static void tcpm_state_machine(struct tcpm_port *port)
2786*a2c81616SWang Jie {
2787*a2c81616SWang Jie enum tcpm_state prev_state;
2788*a2c81616SWang Jie
2789*a2c81616SWang Jie mutex_lock(&port->lock);
2790*a2c81616SWang Jie port->state_machine_running = true;
2791*a2c81616SWang Jie
2792*a2c81616SWang Jie if (port->queued_message && tcpm_send_queued_message(port))
2793*a2c81616SWang Jie goto done;
2794*a2c81616SWang Jie
2795*a2c81616SWang Jie /* If we were queued due to a delayed state change, update it now */
2796*a2c81616SWang Jie if (port->delayed_state) {
2797*a2c81616SWang Jie debug("state change %s -> %s [delayed %ld ms]\n",
2798*a2c81616SWang Jie tcpm_states[port->state],
2799*a2c81616SWang Jie tcpm_states[port->delayed_state], port->delay_ms);
2800*a2c81616SWang Jie port->prev_state = port->state;
2801*a2c81616SWang Jie port->state = port->delayed_state;
2802*a2c81616SWang Jie port->delayed_state = INVALID_STATE;
2803*a2c81616SWang Jie }
2804*a2c81616SWang Jie
2805*a2c81616SWang Jie /*
2806*a2c81616SWang Jie * Continue running as long as we have (non-delayed) state changes
2807*a2c81616SWang Jie * to make.
2808*a2c81616SWang Jie */
2809*a2c81616SWang Jie do {
2810*a2c81616SWang Jie prev_state = port->state;
2811*a2c81616SWang Jie run_state_machine(port);
2812*a2c81616SWang Jie if (port->queued_message)
2813*a2c81616SWang Jie tcpm_send_queued_message(port);
2814*a2c81616SWang Jie } while (port->state != prev_state && !port->delayed_state);
2815*a2c81616SWang Jie
2816*a2c81616SWang Jie done:
2817*a2c81616SWang Jie port->state_machine_running = false;
2818*a2c81616SWang Jie mutex_unlock(&port->lock);
2819*a2c81616SWang Jie }
2820*a2c81616SWang Jie
_tcpm_cc_change(struct tcpm_port * port,enum typec_cc_status cc1,enum typec_cc_status cc2)2821*a2c81616SWang Jie static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
2822*a2c81616SWang Jie enum typec_cc_status cc2)
2823*a2c81616SWang Jie {
2824*a2c81616SWang Jie enum typec_cc_status old_cc1, old_cc2;
2825*a2c81616SWang Jie enum tcpm_state new_state;
2826*a2c81616SWang Jie
2827*a2c81616SWang Jie old_cc1 = port->cc1;
2828*a2c81616SWang Jie old_cc2 = port->cc2;
2829*a2c81616SWang Jie port->cc1 = cc1;
2830*a2c81616SWang Jie port->cc2 = cc2;
2831*a2c81616SWang Jie
2832*a2c81616SWang Jie debug("CC1: %u -> %u, CC2: %u -> %u [state %s, polarity %d, %s]\n",
2833*a2c81616SWang Jie old_cc1, cc1, old_cc2, cc2, tcpm_states[port->state],
2834*a2c81616SWang Jie port->polarity,
2835*a2c81616SWang Jie tcpm_port_is_disconnected(port) ? "disconnected" : "connected");
2836*a2c81616SWang Jie
2837*a2c81616SWang Jie switch (port->state) {
2838*a2c81616SWang Jie case TOGGLING:
2839*a2c81616SWang Jie if (tcpm_port_is_debug(port) || tcpm_port_is_audio(port) ||
2840*a2c81616SWang Jie tcpm_port_is_source(port))
2841*a2c81616SWang Jie tcpm_set_state(port, SRC_ATTACH_WAIT, 0);
2842*a2c81616SWang Jie else if (tcpm_port_is_sink(port))
2843*a2c81616SWang Jie tcpm_set_state(port, SNK_ATTACH_WAIT, 0);
2844*a2c81616SWang Jie break;
2845*a2c81616SWang Jie case SRC_UNATTACHED:
2846*a2c81616SWang Jie case ACC_UNATTACHED:
2847*a2c81616SWang Jie if (tcpm_port_is_debug(port) || tcpm_port_is_audio(port) ||
2848*a2c81616SWang Jie tcpm_port_is_source(port))
2849*a2c81616SWang Jie tcpm_set_state(port, SRC_ATTACH_WAIT, 0);
2850*a2c81616SWang Jie break;
2851*a2c81616SWang Jie case SRC_ATTACH_WAIT:
2852*a2c81616SWang Jie if (tcpm_port_is_disconnected(port) ||
2853*a2c81616SWang Jie tcpm_port_is_audio_detached(port))
2854*a2c81616SWang Jie tcpm_set_state(port, SRC_UNATTACHED, 0);
2855*a2c81616SWang Jie else if (cc1 != old_cc1 || cc2 != old_cc2)
2856*a2c81616SWang Jie tcpm_set_state(port, SRC_ATTACH_WAIT, 0);
2857*a2c81616SWang Jie break;
2858*a2c81616SWang Jie case SRC_ATTACHED:
2859*a2c81616SWang Jie case SRC_SEND_CAPABILITIES:
2860*a2c81616SWang Jie case SRC_READY:
2861*a2c81616SWang Jie if (tcpm_port_is_disconnected(port) ||
2862*a2c81616SWang Jie !tcpm_port_is_source(port))
2863*a2c81616SWang Jie tcpm_set_state(port, SRC_UNATTACHED, 0);
2864*a2c81616SWang Jie break;
2865*a2c81616SWang Jie case SNK_UNATTACHED:
2866*a2c81616SWang Jie if (tcpm_port_is_sink(port))
2867*a2c81616SWang Jie tcpm_set_state(port, SNK_ATTACH_WAIT, 0);
2868*a2c81616SWang Jie break;
2869*a2c81616SWang Jie case SNK_ATTACH_WAIT:
2870*a2c81616SWang Jie if ((port->cc1 == TYPEC_CC_OPEN &&
2871*a2c81616SWang Jie port->cc2 != TYPEC_CC_OPEN) ||
2872*a2c81616SWang Jie (port->cc1 != TYPEC_CC_OPEN &&
2873*a2c81616SWang Jie port->cc2 == TYPEC_CC_OPEN))
2874*a2c81616SWang Jie new_state = SNK_DEBOUNCED;
2875*a2c81616SWang Jie else if (tcpm_port_is_disconnected(port))
2876*a2c81616SWang Jie new_state = SNK_UNATTACHED;
2877*a2c81616SWang Jie else
2878*a2c81616SWang Jie break;
2879*a2c81616SWang Jie if (new_state != port->delayed_state)
2880*a2c81616SWang Jie tcpm_set_state(port, SNK_ATTACH_WAIT, 0);
2881*a2c81616SWang Jie break;
2882*a2c81616SWang Jie case SNK_DEBOUNCED:
2883*a2c81616SWang Jie if (tcpm_port_is_disconnected(port))
2884*a2c81616SWang Jie new_state = SNK_UNATTACHED;
2885*a2c81616SWang Jie else if (port->vbus_present)
2886*a2c81616SWang Jie new_state = tcpm_try_src(port) ? SRC_TRY : SNK_ATTACHED;
2887*a2c81616SWang Jie else
2888*a2c81616SWang Jie new_state = SNK_UNATTACHED;
2889*a2c81616SWang Jie if (new_state != port->delayed_state)
2890*a2c81616SWang Jie tcpm_set_state(port, SNK_DEBOUNCED, 0);
2891*a2c81616SWang Jie break;
2892*a2c81616SWang Jie case SNK_READY:
2893*a2c81616SWang Jie if (tcpm_port_is_disconnected(port))
2894*a2c81616SWang Jie tcpm_set_state(port, unattached_state(port), 0);
2895*a2c81616SWang Jie else if (!port->pd_capable &&
2896*a2c81616SWang Jie (cc1 != old_cc1 || cc2 != old_cc2))
2897*a2c81616SWang Jie tcpm_set_current_limit(port,
2898*a2c81616SWang Jie tcpm_get_current_limit(port),
2899*a2c81616SWang Jie 5000);
2900*a2c81616SWang Jie break;
2901*a2c81616SWang Jie
2902*a2c81616SWang Jie case AUDIO_ACC_ATTACHED:
2903*a2c81616SWang Jie if (cc1 == TYPEC_CC_OPEN || cc2 == TYPEC_CC_OPEN)
2904*a2c81616SWang Jie tcpm_set_state(port, AUDIO_ACC_DEBOUNCE, 0);
2905*a2c81616SWang Jie break;
2906*a2c81616SWang Jie case AUDIO_ACC_DEBOUNCE:
2907*a2c81616SWang Jie if (tcpm_port_is_audio(port))
2908*a2c81616SWang Jie tcpm_set_state(port, AUDIO_ACC_ATTACHED, 0);
2909*a2c81616SWang Jie break;
2910*a2c81616SWang Jie
2911*a2c81616SWang Jie case DEBUG_ACC_ATTACHED:
2912*a2c81616SWang Jie if (cc1 == TYPEC_CC_OPEN || cc2 == TYPEC_CC_OPEN)
2913*a2c81616SWang Jie tcpm_set_state(port, ACC_UNATTACHED, 0);
2914*a2c81616SWang Jie break;
2915*a2c81616SWang Jie
2916*a2c81616SWang Jie case SNK_TRY:
2917*a2c81616SWang Jie /* Do nothing, waiting for timeout */
2918*a2c81616SWang Jie break;
2919*a2c81616SWang Jie
2920*a2c81616SWang Jie case SNK_DISCOVERY:
2921*a2c81616SWang Jie /* CC line is unstable, wait for debounce */
2922*a2c81616SWang Jie if (tcpm_port_is_disconnected(port))
2923*a2c81616SWang Jie tcpm_set_state(port, SNK_DISCOVERY_DEBOUNCE, 0);
2924*a2c81616SWang Jie break;
2925*a2c81616SWang Jie case SNK_DISCOVERY_DEBOUNCE:
2926*a2c81616SWang Jie break;
2927*a2c81616SWang Jie
2928*a2c81616SWang Jie case SRC_TRYWAIT:
2929*a2c81616SWang Jie /* Hand over to state machine if needed */
2930*a2c81616SWang Jie if (!port->vbus_present && tcpm_port_is_source(port))
2931*a2c81616SWang Jie tcpm_set_state(port, SRC_TRYWAIT_DEBOUNCE, 0);
2932*a2c81616SWang Jie break;
2933*a2c81616SWang Jie case SRC_TRYWAIT_DEBOUNCE:
2934*a2c81616SWang Jie if (port->vbus_present || !tcpm_port_is_source(port))
2935*a2c81616SWang Jie tcpm_set_state(port, SRC_TRYWAIT, 0);
2936*a2c81616SWang Jie break;
2937*a2c81616SWang Jie case SNK_TRY_WAIT_DEBOUNCE:
2938*a2c81616SWang Jie if (!tcpm_port_is_sink(port)) {
2939*a2c81616SWang Jie port->max_wait = 0;
2940*a2c81616SWang Jie tcpm_set_state(port, SRC_TRYWAIT, 0);
2941*a2c81616SWang Jie }
2942*a2c81616SWang Jie break;
2943*a2c81616SWang Jie case SRC_TRY_WAIT:
2944*a2c81616SWang Jie if (tcpm_port_is_source(port))
2945*a2c81616SWang Jie tcpm_set_state(port, SRC_TRY_DEBOUNCE, 0);
2946*a2c81616SWang Jie break;
2947*a2c81616SWang Jie case SRC_TRY_DEBOUNCE:
2948*a2c81616SWang Jie tcpm_set_state(port, SRC_TRY_WAIT, 0);
2949*a2c81616SWang Jie break;
2950*a2c81616SWang Jie case SNK_TRYWAIT_DEBOUNCE:
2951*a2c81616SWang Jie if (tcpm_port_is_sink(port))
2952*a2c81616SWang Jie tcpm_set_state(port, SNK_TRYWAIT_VBUS, 0);
2953*a2c81616SWang Jie break;
2954*a2c81616SWang Jie case SNK_TRYWAIT_VBUS:
2955*a2c81616SWang Jie if (!tcpm_port_is_sink(port))
2956*a2c81616SWang Jie tcpm_set_state(port, SNK_TRYWAIT_DEBOUNCE, 0);
2957*a2c81616SWang Jie break;
2958*a2c81616SWang Jie case SNK_TRYWAIT:
2959*a2c81616SWang Jie /* Do nothing, waiting for tCCDebounce */
2960*a2c81616SWang Jie break;
2961*a2c81616SWang Jie case PR_SWAP_SNK_SRC_SINK_OFF:
2962*a2c81616SWang Jie case PR_SWAP_SRC_SNK_TRANSITION_OFF:
2963*a2c81616SWang Jie case PR_SWAP_SRC_SNK_SOURCE_OFF:
2964*a2c81616SWang Jie case PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED:
2965*a2c81616SWang Jie case PR_SWAP_SNK_SRC_SOURCE_ON:
2966*a2c81616SWang Jie /*
2967*a2c81616SWang Jie * CC state change is expected in PR_SWAP
2968*a2c81616SWang Jie * Ignore it.
2969*a2c81616SWang Jie */
2970*a2c81616SWang Jie break;
2971*a2c81616SWang Jie
2972*a2c81616SWang Jie case PORT_RESET:
2973*a2c81616SWang Jie case PORT_RESET_WAIT_OFF:
2974*a2c81616SWang Jie /*
2975*a2c81616SWang Jie * State set back to default mode once the timer completes.
2976*a2c81616SWang Jie * Ignore CC changes here.
2977*a2c81616SWang Jie */
2978*a2c81616SWang Jie break;
2979*a2c81616SWang Jie default:
2980*a2c81616SWang Jie /*
2981*a2c81616SWang Jie * While acting as sink and auto vbus discharge is enabled, Allow disconnect
2982*a2c81616SWang Jie * to be driven by vbus disconnect.
2983*a2c81616SWang Jie */
2984*a2c81616SWang Jie if (tcpm_port_is_disconnected(port))
2985*a2c81616SWang Jie tcpm_set_state(port, unattached_state(port), 0);
2986*a2c81616SWang Jie break;
2987*a2c81616SWang Jie }
2988*a2c81616SWang Jie }
2989*a2c81616SWang Jie
_tcpm_pd_vbus_on(struct tcpm_port * port)2990*a2c81616SWang Jie static void _tcpm_pd_vbus_on(struct tcpm_port *port)
2991*a2c81616SWang Jie {
2992*a2c81616SWang Jie debug("%s: VBUS on\n", __func__);
2993*a2c81616SWang Jie port->vbus_present = true;
2994*a2c81616SWang Jie /*
2995*a2c81616SWang Jie * When vbus_present is true i.e. Voltage at VBUS is greater than VSAFE5V implicitly
2996*a2c81616SWang Jie * states that vbus is not at VSAFE0V, hence clear the vbus_vsafe0v flag here.
2997*a2c81616SWang Jie */
2998*a2c81616SWang Jie port->vbus_vsafe0v = false;
2999*a2c81616SWang Jie
3000*a2c81616SWang Jie switch (port->state) {
3001*a2c81616SWang Jie case SNK_TRANSITION_SINK_VBUS:
3002*a2c81616SWang Jie port->explicit_contract = true;
3003*a2c81616SWang Jie tcpm_set_state(port, SNK_READY, 0);
3004*a2c81616SWang Jie break;
3005*a2c81616SWang Jie case SNK_DISCOVERY:
3006*a2c81616SWang Jie tcpm_set_state(port, SNK_DISCOVERY, 0);
3007*a2c81616SWang Jie break;
3008*a2c81616SWang Jie case SNK_DEBOUNCED:
3009*a2c81616SWang Jie tcpm_set_state(port, SNK_ATTACHED, 0);
3010*a2c81616SWang Jie break;
3011*a2c81616SWang Jie case SNK_HARD_RESET_WAIT_VBUS:
3012*a2c81616SWang Jie tcpm_set_state(port, SNK_HARD_RESET_SINK_ON, 0);
3013*a2c81616SWang Jie break;
3014*a2c81616SWang Jie case SRC_ATTACHED:
3015*a2c81616SWang Jie tcpm_set_state(port, SRC_STARTUP, 0);
3016*a2c81616SWang Jie break;
3017*a2c81616SWang Jie case SRC_HARD_RESET_VBUS_ON:
3018*a2c81616SWang Jie tcpm_set_state(port, SRC_STARTUP, 0);
3019*a2c81616SWang Jie break;
3020*a2c81616SWang Jie
3021*a2c81616SWang Jie case SNK_TRY:
3022*a2c81616SWang Jie /* Do nothing, waiting for timeout */
3023*a2c81616SWang Jie break;
3024*a2c81616SWang Jie case SRC_TRYWAIT:
3025*a2c81616SWang Jie /* Do nothing, Waiting for Rd to be detected */
3026*a2c81616SWang Jie break;
3027*a2c81616SWang Jie case SRC_TRYWAIT_DEBOUNCE:
3028*a2c81616SWang Jie tcpm_set_state(port, SRC_TRYWAIT, 0);
3029*a2c81616SWang Jie break;
3030*a2c81616SWang Jie case SNK_TRY_WAIT_DEBOUNCE:
3031*a2c81616SWang Jie /* Do nothing, waiting for PD_DEBOUNCE to do be done */
3032*a2c81616SWang Jie break;
3033*a2c81616SWang Jie case SNK_TRYWAIT:
3034*a2c81616SWang Jie /* Do nothing, waiting for tCCDebounce */
3035*a2c81616SWang Jie break;
3036*a2c81616SWang Jie case SNK_TRYWAIT_VBUS:
3037*a2c81616SWang Jie if (tcpm_port_is_sink(port))
3038*a2c81616SWang Jie tcpm_set_state(port, SNK_ATTACHED, 0);
3039*a2c81616SWang Jie break;
3040*a2c81616SWang Jie case SNK_TRYWAIT_DEBOUNCE:
3041*a2c81616SWang Jie /* Do nothing, waiting for Rp */
3042*a2c81616SWang Jie break;
3043*a2c81616SWang Jie case SRC_TRY_WAIT:
3044*a2c81616SWang Jie case SRC_TRY_DEBOUNCE:
3045*a2c81616SWang Jie /* Do nothing, waiting for sink detection */
3046*a2c81616SWang Jie break;
3047*a2c81616SWang Jie
3048*a2c81616SWang Jie case PORT_RESET:
3049*a2c81616SWang Jie case PORT_RESET_WAIT_OFF:
3050*a2c81616SWang Jie /*
3051*a2c81616SWang Jie * State set back to default mode once the timer completes.
3052*a2c81616SWang Jie * Ignore vbus changes here.
3053*a2c81616SWang Jie */
3054*a2c81616SWang Jie break;
3055*a2c81616SWang Jie
3056*a2c81616SWang Jie default:
3057*a2c81616SWang Jie break;
3058*a2c81616SWang Jie }
3059*a2c81616SWang Jie }
3060*a2c81616SWang Jie
_tcpm_pd_vbus_off(struct tcpm_port * port)3061*a2c81616SWang Jie static void _tcpm_pd_vbus_off(struct tcpm_port *port)
3062*a2c81616SWang Jie {
3063*a2c81616SWang Jie debug("%s: VBUS off\n", __func__);
3064*a2c81616SWang Jie port->vbus_present = false;
3065*a2c81616SWang Jie port->vbus_never_low = false;
3066*a2c81616SWang Jie switch (port->state) {
3067*a2c81616SWang Jie case SNK_HARD_RESET_SINK_OFF:
3068*a2c81616SWang Jie tcpm_set_state(port, SNK_HARD_RESET_WAIT_VBUS, 0);
3069*a2c81616SWang Jie break;
3070*a2c81616SWang Jie case HARD_RESET_SEND:
3071*a2c81616SWang Jie break;
3072*a2c81616SWang Jie case SNK_TRY:
3073*a2c81616SWang Jie /* Do nothing, waiting for timeout */
3074*a2c81616SWang Jie break;
3075*a2c81616SWang Jie case SRC_TRYWAIT:
3076*a2c81616SWang Jie /* Hand over to state machine if needed */
3077*a2c81616SWang Jie if (tcpm_port_is_source(port))
3078*a2c81616SWang Jie tcpm_set_state(port, SRC_TRYWAIT_DEBOUNCE, 0);
3079*a2c81616SWang Jie break;
3080*a2c81616SWang Jie case SNK_TRY_WAIT_DEBOUNCE:
3081*a2c81616SWang Jie /* Do nothing, waiting for PD_DEBOUNCE to do be done */
3082*a2c81616SWang Jie break;
3083*a2c81616SWang Jie case SNK_TRYWAIT:
3084*a2c81616SWang Jie case SNK_TRYWAIT_VBUS:
3085*a2c81616SWang Jie case SNK_TRYWAIT_DEBOUNCE:
3086*a2c81616SWang Jie break;
3087*a2c81616SWang Jie case SNK_ATTACH_WAIT:
3088*a2c81616SWang Jie port->debouncing = false;
3089*a2c81616SWang Jie tcpm_set_state(port, SNK_UNATTACHED, 0);
3090*a2c81616SWang Jie break;
3091*a2c81616SWang Jie
3092*a2c81616SWang Jie case SNK_NEGOTIATE_CAPABILITIES:
3093*a2c81616SWang Jie break;
3094*a2c81616SWang Jie
3095*a2c81616SWang Jie case PR_SWAP_SRC_SNK_TRANSITION_OFF:
3096*a2c81616SWang Jie tcpm_set_state(port, PR_SWAP_SRC_SNK_SOURCE_OFF, 0);
3097*a2c81616SWang Jie break;
3098*a2c81616SWang Jie
3099*a2c81616SWang Jie case PR_SWAP_SNK_SRC_SINK_OFF:
3100*a2c81616SWang Jie /* Do nothing, expected */
3101*a2c81616SWang Jie break;
3102*a2c81616SWang Jie
3103*a2c81616SWang Jie case PR_SWAP_SNK_SRC_SOURCE_ON:
3104*a2c81616SWang Jie /*
3105*a2c81616SWang Jie * Do nothing when vbus off notification is received.
3106*a2c81616SWang Jie * TCPM can wait for PD_T_NEWSRC in PR_SWAP_SNK_SRC_SOURCE_ON
3107*a2c81616SWang Jie * for the vbus source to ramp up.
3108*a2c81616SWang Jie */
3109*a2c81616SWang Jie break;
3110*a2c81616SWang Jie
3111*a2c81616SWang Jie case PORT_RESET_WAIT_OFF:
3112*a2c81616SWang Jie tcpm_set_state(port, tcpm_default_state(port), 0);
3113*a2c81616SWang Jie break;
3114*a2c81616SWang Jie
3115*a2c81616SWang Jie case SRC_TRY_WAIT:
3116*a2c81616SWang Jie case SRC_TRY_DEBOUNCE:
3117*a2c81616SWang Jie /* Do nothing, waiting for sink detection */
3118*a2c81616SWang Jie break;
3119*a2c81616SWang Jie
3120*a2c81616SWang Jie case PORT_RESET:
3121*a2c81616SWang Jie /*
3122*a2c81616SWang Jie * State set back to default mode once the timer completes.
3123*a2c81616SWang Jie * Ignore vbus changes here.
3124*a2c81616SWang Jie */
3125*a2c81616SWang Jie break;
3126*a2c81616SWang Jie
3127*a2c81616SWang Jie default:
3128*a2c81616SWang Jie if (port->pwr_role == TYPEC_SINK && port->attached)
3129*a2c81616SWang Jie tcpm_set_state(port, SNK_UNATTACHED, 0);
3130*a2c81616SWang Jie break;
3131*a2c81616SWang Jie }
3132*a2c81616SWang Jie }
3133*a2c81616SWang Jie
_tcpm_pd_hard_reset(struct tcpm_port * port)3134*a2c81616SWang Jie static void _tcpm_pd_hard_reset(struct tcpm_port *port)
3135*a2c81616SWang Jie {
3136*a2c81616SWang Jie debug("Received hard reset\n");
3137*a2c81616SWang Jie port->poll_event_cnt = 0;
3138*a2c81616SWang Jie
3139*a2c81616SWang Jie /* If a hard reset message is received during the port reset process,
3140*a2c81616SWang Jie * we should ignore it, that is, do not set port->state to HARD_RESET_START.
3141*a2c81616SWang Jie */
3142*a2c81616SWang Jie if (port->state == PORT_RESET || port->state == PORT_RESET_WAIT_OFF)
3143*a2c81616SWang Jie return ;
3144*a2c81616SWang Jie
3145*a2c81616SWang Jie /*
3146*a2c81616SWang Jie * If we keep receiving hard reset requests, executing the hard reset
3147*a2c81616SWang Jie * must have failed. Revert to error recovery if that happens.
3148*a2c81616SWang Jie */
3149*a2c81616SWang Jie tcpm_set_state(port,
3150*a2c81616SWang Jie port->hard_reset_count < PD_N_HARD_RESET_COUNT ?
3151*a2c81616SWang Jie HARD_RESET_START : ERROR_RECOVERY,
3152*a2c81616SWang Jie 0);
3153*a2c81616SWang Jie }
3154*a2c81616SWang Jie
3155*a2c81616SWang Jie #if 0
3156*a2c81616SWang Jie static void tcpm_pd_event_handler(struct tcpm_port *port)
3157*a2c81616SWang Jie {
3158*a2c81616SWang Jie u32 events;
3159*a2c81616SWang Jie
3160*a2c81616SWang Jie while (port->pd_events) {
3161*a2c81616SWang Jie events = port->pd_events;
3162*a2c81616SWang Jie port->pd_events = 0;
3163*a2c81616SWang Jie if (events & TCPM_RESET_EVENT)
3164*a2c81616SWang Jie _tcpm_pd_hard_reset(port);
3165*a2c81616SWang Jie if (events & TCPM_VBUS_EVENT) {
3166*a2c81616SWang Jie bool vbus;
3167*a2c81616SWang Jie
3168*a2c81616SWang Jie vbus = port->tcpc->get_vbus(port->tcpc);
3169*a2c81616SWang Jie if (vbus) {
3170*a2c81616SWang Jie _tcpm_pd_vbus_on(port);
3171*a2c81616SWang Jie } else {
3172*a2c81616SWang Jie _tcpm_pd_vbus_off(port);
3173*a2c81616SWang Jie /*
3174*a2c81616SWang Jie * When TCPC does not support detecting vsafe0v voltage level,
3175*a2c81616SWang Jie * treat vbus absent as vsafe0v. Else invoke is_vbus_vsafe0v
3176*a2c81616SWang Jie * to see if vbus has discharge to VSAFE0V.
3177*a2c81616SWang Jie */
3178*a2c81616SWang Jie if (!port->tcpc->is_vbus_vsafe0v ||
3179*a2c81616SWang Jie port->tcpc->is_vbus_vsafe0v(port->tcpc))
3180*a2c81616SWang Jie _tcpm_pd_vbus_vsafe0v(port);
3181*a2c81616SWang Jie }
3182*a2c81616SWang Jie }
3183*a2c81616SWang Jie if (events & TCPM_CC_EVENT) {
3184*a2c81616SWang Jie enum typec_cc_status cc1, cc2;
3185*a2c81616SWang Jie
3186*a2c81616SWang Jie if (port->tcpc->get_cc(port->tcpc, &cc1, &cc2) == 0)
3187*a2c81616SWang Jie _tcpm_cc_change(port, cc1, cc2);
3188*a2c81616SWang Jie }
3189*a2c81616SWang Jie if (events & TCPM_FRS_EVENT) {
3190*a2c81616SWang Jie if (port->state == SNK_READY) {
3191*a2c81616SWang Jie int ret;
3192*a2c81616SWang Jie
3193*a2c81616SWang Jie port->upcoming_state = FR_SWAP_SEND;
3194*a2c81616SWang Jie ret = tcpm_ams_start(port, FAST_ROLE_SWAP);
3195*a2c81616SWang Jie if (ret == -EAGAIN)
3196*a2c81616SWang Jie port->upcoming_state = INVALID_STATE;
3197*a2c81616SWang Jie } else {
3198*a2c81616SWang Jie tcpm_log(port, "Discarding FRS_SIGNAL! Not in sink ready");
3199*a2c81616SWang Jie }
3200*a2c81616SWang Jie }
3201*a2c81616SWang Jie if (events & TCPM_SOURCING_VBUS) {
3202*a2c81616SWang Jie tcpm_log(port, "sourcing vbus");
3203*a2c81616SWang Jie /*
3204*a2c81616SWang Jie * In fast role swap case TCPC autonomously sources vbus. Set vbus_source
3205*a2c81616SWang Jie * true as TCPM wouldn't have called tcpm_set_vbus.
3206*a2c81616SWang Jie *
3207*a2c81616SWang Jie * When vbus is sourced on the command on TCPM i.e. TCPM called
3208*a2c81616SWang Jie * tcpm_set_vbus to source vbus, vbus_source would already be true.
3209*a2c81616SWang Jie */
3210*a2c81616SWang Jie port->vbus_source = true;
3211*a2c81616SWang Jie _tcpm_pd_vbus_on(port);
3212*a2c81616SWang Jie }
3213*a2c81616SWang Jie }
3214*a2c81616SWang Jie }
3215*a2c81616SWang Jie #endif
3216*a2c81616SWang Jie
tcpm_cc_change(struct tcpm_port * port)3217*a2c81616SWang Jie void tcpm_cc_change(struct tcpm_port *port)
3218*a2c81616SWang Jie {
3219*a2c81616SWang Jie enum typec_cc_status cc1, cc2;
3220*a2c81616SWang Jie
3221*a2c81616SWang Jie port->poll_event_cnt = 0;
3222*a2c81616SWang Jie if (port->tcpc->get_cc(port->tcpc, &cc1, &cc2) == 0)
3223*a2c81616SWang Jie _tcpm_cc_change(port, cc1, cc2);
3224*a2c81616SWang Jie }
3225*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpm_cc_change);
3226*a2c81616SWang Jie
tcpm_vbus_change(struct tcpm_port * port)3227*a2c81616SWang Jie void tcpm_vbus_change(struct tcpm_port *port)
3228*a2c81616SWang Jie {
3229*a2c81616SWang Jie bool vbus;
3230*a2c81616SWang Jie
3231*a2c81616SWang Jie port->poll_event_cnt = 0;
3232*a2c81616SWang Jie vbus = port->tcpc->get_vbus(port->tcpc);
3233*a2c81616SWang Jie if (vbus)
3234*a2c81616SWang Jie _tcpm_pd_vbus_on(port);
3235*a2c81616SWang Jie else
3236*a2c81616SWang Jie _tcpm_pd_vbus_off(port);
3237*a2c81616SWang Jie }
3238*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpm_vbus_change);
3239*a2c81616SWang Jie
tcpm_pd_hard_reset(struct tcpm_port * port)3240*a2c81616SWang Jie void tcpm_pd_hard_reset(struct tcpm_port *port)
3241*a2c81616SWang Jie {
3242*a2c81616SWang Jie port->poll_event_cnt = 0;
3243*a2c81616SWang Jie _tcpm_pd_hard_reset(port);
3244*a2c81616SWang Jie }
3245*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpm_pd_hard_reset);
3246*a2c81616SWang Jie
tcpm_init(struct tcpm_port * port)3247*a2c81616SWang Jie static void tcpm_init(struct tcpm_port *port)
3248*a2c81616SWang Jie {
3249*a2c81616SWang Jie enum typec_cc_status cc1, cc2;
3250*a2c81616SWang Jie
3251*a2c81616SWang Jie port->tcpc->init(port->tcpc);
3252*a2c81616SWang Jie
3253*a2c81616SWang Jie tcpm_reset_port(port);
3254*a2c81616SWang Jie
3255*a2c81616SWang Jie /*
3256*a2c81616SWang Jie * XXX
3257*a2c81616SWang Jie * Should possibly wait for VBUS to settle if it was enabled locally
3258*a2c81616SWang Jie * since tcpm_reset_port() will disable VBUS.
3259*a2c81616SWang Jie */
3260*a2c81616SWang Jie port->vbus_present = port->tcpc->get_vbus(port->tcpc);
3261*a2c81616SWang Jie if (port->vbus_present)
3262*a2c81616SWang Jie port->vbus_never_low = true;
3263*a2c81616SWang Jie
3264*a2c81616SWang Jie /*
3265*a2c81616SWang Jie * 1. When vbus_present is true, voltage on VBUS is already at VSAFE5V.
3266*a2c81616SWang Jie * So implicitly vbus_vsafe0v = false.
3267*a2c81616SWang Jie *
3268*a2c81616SWang Jie * 2. When vbus_present is false and TCPC does NOT support querying
3269*a2c81616SWang Jie * vsafe0v status, then, it's best to assume vbus is at VSAFE0V i.e.
3270*a2c81616SWang Jie * vbus_vsafe0v is true.
3271*a2c81616SWang Jie *
3272*a2c81616SWang Jie * 3. When vbus_present is false and TCPC does support querying vsafe0v,
3273*a2c81616SWang Jie * then, query tcpc for vsafe0v status.
3274*a2c81616SWang Jie */
3275*a2c81616SWang Jie if (port->vbus_present)
3276*a2c81616SWang Jie port->vbus_vsafe0v = false;
3277*a2c81616SWang Jie else if (!port->tcpc->is_vbus_vsafe0v)
3278*a2c81616SWang Jie port->vbus_vsafe0v = true;
3279*a2c81616SWang Jie else
3280*a2c81616SWang Jie port->vbus_vsafe0v = port->tcpc->is_vbus_vsafe0v(port->tcpc);
3281*a2c81616SWang Jie
3282*a2c81616SWang Jie tcpm_set_state(port, tcpm_default_state(port), 0);
3283*a2c81616SWang Jie
3284*a2c81616SWang Jie if (port->tcpc->get_cc(port->tcpc, &cc1, &cc2) == 0)
3285*a2c81616SWang Jie _tcpm_cc_change(port, cc1, cc2);
3286*a2c81616SWang Jie }
3287*a2c81616SWang Jie
tcpm_tcpc_reset(struct tcpm_port * port)3288*a2c81616SWang Jie void tcpm_tcpc_reset(struct tcpm_port *port)
3289*a2c81616SWang Jie {
3290*a2c81616SWang Jie mutex_lock(&port->lock);
3291*a2c81616SWang Jie /* XXX: Maintain PD connection if possible? */
3292*a2c81616SWang Jie tcpm_init(port);
3293*a2c81616SWang Jie mutex_unlock(&port->lock);
3294*a2c81616SWang Jie }
3295*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpm_tcpc_reset);
3296*a2c81616SWang Jie
tcpm_fw_get_caps(struct tcpm_port * port)3297*a2c81616SWang Jie static int tcpm_fw_get_caps(struct tcpm_port *port)
3298*a2c81616SWang Jie {
3299*a2c81616SWang Jie const char *cap_str;
3300*a2c81616SWang Jie ofnode node = port->tcpc->connector_node;
3301*a2c81616SWang Jie int ret;
3302*a2c81616SWang Jie u32 mw, frs_current;
3303*a2c81616SWang Jie
3304*a2c81616SWang Jie #if 0
3305*a2c81616SWang Jie /* USB data support is optional */
3306*a2c81616SWang Jie cap_str = ofnode_read_string(node, "data-role");
3307*a2c81616SWang Jie if (cap_str) {
3308*a2c81616SWang Jie ret = typec_find_port_data_role(cap_str);
3309*a2c81616SWang Jie if (ret < 0)
3310*a2c81616SWang Jie return ret;
3311*a2c81616SWang Jie port->typec_caps.data = ret;
3312*a2c81616SWang Jie }
3313*a2c81616SWang Jie #endif
3314*a2c81616SWang Jie
3315*a2c81616SWang Jie cap_str = ofnode_read_string(node, "power-role");
3316*a2c81616SWang Jie if (!cap_str) {
3317*a2c81616SWang Jie return -EINVAL;
3318*a2c81616SWang Jie } else {
3319*a2c81616SWang Jie if (!strcmp("dual", cap_str))
3320*a2c81616SWang Jie port->typec_caps.type = TYPEC_PORT_DRP;
3321*a2c81616SWang Jie else if (!strcmp("source", cap_str))
3322*a2c81616SWang Jie port->typec_caps.type = TYPEC_PORT_SRC;
3323*a2c81616SWang Jie else if (!strcmp("sink", cap_str))
3324*a2c81616SWang Jie port->typec_caps.type = TYPEC_PORT_SNK;
3325*a2c81616SWang Jie else
3326*a2c81616SWang Jie return EINVAL;
3327*a2c81616SWang Jie }
3328*a2c81616SWang Jie
3329*a2c81616SWang Jie port->port_type = port->typec_caps.type;
3330*a2c81616SWang Jie
3331*a2c81616SWang Jie port->slow_charger_loop = ofnode_read_bool(node, "slow-charger-loop");
3332*a2c81616SWang Jie if (port->port_type == TYPEC_PORT_SNK)
3333*a2c81616SWang Jie goto sink;
3334*a2c81616SWang Jie
3335*a2c81616SWang Jie /* Get source pdos */
3336*a2c81616SWang Jie ret = ofnode_read_size(node, "source-pdos") / sizeof(u32);
3337*a2c81616SWang Jie if (ret <= 0)
3338*a2c81616SWang Jie return -EINVAL;
3339*a2c81616SWang Jie
3340*a2c81616SWang Jie port->nr_src_pdo = min(ret, PDO_MAX_OBJECTS);
3341*a2c81616SWang Jie ret = ofnode_read_u32_array(node, "source-pdos",
3342*a2c81616SWang Jie port->src_pdo, port->nr_src_pdo);
3343*a2c81616SWang Jie if (ret || tcpm_validate_caps(port, port->src_pdo,
3344*a2c81616SWang Jie port->nr_src_pdo))
3345*a2c81616SWang Jie return -EINVAL;
3346*a2c81616SWang Jie
3347*a2c81616SWang Jie if (port->port_type == TYPEC_PORT_SRC)
3348*a2c81616SWang Jie return 0;
3349*a2c81616SWang Jie
3350*a2c81616SWang Jie /* Get the preferred power role for DRP */
3351*a2c81616SWang Jie cap_str = ofnode_read_string(node, "try-power-role");
3352*a2c81616SWang Jie if (!cap_str) {
3353*a2c81616SWang Jie return -EINVAL;
3354*a2c81616SWang Jie } else {
3355*a2c81616SWang Jie if (!strcmp("sink", cap_str))
3356*a2c81616SWang Jie port->typec_caps.prefer_role = TYPEC_SINK;
3357*a2c81616SWang Jie else if (!strcmp("source", cap_str))
3358*a2c81616SWang Jie port->typec_caps.prefer_role = TYPEC_SOURCE;
3359*a2c81616SWang Jie else
3360*a2c81616SWang Jie return -EINVAL;
3361*a2c81616SWang Jie }
3362*a2c81616SWang Jie if (port->typec_caps.prefer_role < 0)
3363*a2c81616SWang Jie return -EINVAL;
3364*a2c81616SWang Jie sink:
3365*a2c81616SWang Jie /* Get sink pdos */
3366*a2c81616SWang Jie ret = ofnode_read_size(node, "sink-pdos") / sizeof(u32);
3367*a2c81616SWang Jie if (ret <= 0)
3368*a2c81616SWang Jie return -EINVAL;
3369*a2c81616SWang Jie
3370*a2c81616SWang Jie port->nr_snk_pdo = min(ret, PDO_MAX_OBJECTS);
3371*a2c81616SWang Jie ret = ofnode_read_u32_array(node, "sink-pdos",
3372*a2c81616SWang Jie port->snk_pdo, port->nr_snk_pdo);
3373*a2c81616SWang Jie if (ret || tcpm_validate_caps(port, port->snk_pdo,
3374*a2c81616SWang Jie port->nr_snk_pdo))
3375*a2c81616SWang Jie return -EINVAL;
3376*a2c81616SWang Jie
3377*a2c81616SWang Jie if (ofnode_read_u32_array(node, "op-sink-microwatt", &mw, 1))
3378*a2c81616SWang Jie return -EINVAL;
3379*a2c81616SWang Jie port->operating_snk_mw = mw / 1000;
3380*a2c81616SWang Jie
3381*a2c81616SWang Jie port->self_powered = ofnode_read_bool(node, "self-powered");
3382*a2c81616SWang Jie
3383*a2c81616SWang Jie /* FRS can only be supported by DRP ports */
3384*a2c81616SWang Jie if (port->port_type == TYPEC_PORT_DRP) {
3385*a2c81616SWang Jie ret = ofnode_read_u32_array(node, "new-source-frs-typec-current",
3386*a2c81616SWang Jie &frs_current, 1);
3387*a2c81616SWang Jie if (ret >= 0 && frs_current <= FRS_5V_3A)
3388*a2c81616SWang Jie port->new_source_frs_current = frs_current;
3389*a2c81616SWang Jie }
3390*a2c81616SWang Jie
3391*a2c81616SWang Jie /* sink-vdos is optional */
3392*a2c81616SWang Jie ret = ofnode_read_size(node, "sink-vdos") / sizeof(u32);
3393*a2c81616SWang Jie if (ret < 0)
3394*a2c81616SWang Jie ret = 0;
3395*a2c81616SWang Jie
3396*a2c81616SWang Jie port->nr_snk_vdo = min(ret, VDO_MAX_OBJECTS);
3397*a2c81616SWang Jie if (port->nr_snk_vdo) {
3398*a2c81616SWang Jie ret = ofnode_read_u32_array(node, "sink-vdos",
3399*a2c81616SWang Jie port->snk_vdo, port->nr_snk_vdo);
3400*a2c81616SWang Jie if (ret)
3401*a2c81616SWang Jie return ret;
3402*a2c81616SWang Jie }
3403*a2c81616SWang Jie
3404*a2c81616SWang Jie /* If sink-vdos is found, sink-vdos-v1 is expected for backward compatibility. */
3405*a2c81616SWang Jie if (port->nr_snk_vdo) {
3406*a2c81616SWang Jie ret = ofnode_read_size(node, "sink-vdos-v1") / sizeof(u32);
3407*a2c81616SWang Jie if (ret < 0)
3408*a2c81616SWang Jie return ret;
3409*a2c81616SWang Jie else if (ret == 0)
3410*a2c81616SWang Jie return -ENODATA;
3411*a2c81616SWang Jie
3412*a2c81616SWang Jie port->nr_snk_vdo_v1 = min(ret, VDO_MAX_OBJECTS);
3413*a2c81616SWang Jie ret = ofnode_read_u32_array(node, "sink-vdos-v1",
3414*a2c81616SWang Jie port->snk_vdo_v1,
3415*a2c81616SWang Jie port->nr_snk_vdo_v1);
3416*a2c81616SWang Jie if (ret)
3417*a2c81616SWang Jie return ret;
3418*a2c81616SWang Jie }
3419*a2c81616SWang Jie
3420*a2c81616SWang Jie return 0;
3421*a2c81616SWang Jie }
3422*a2c81616SWang Jie
tcpm_port_init(struct udevice * dev,struct tcpc_dev * tcpc)3423*a2c81616SWang Jie struct tcpm_port *tcpm_port_init(struct udevice *dev, struct tcpc_dev *tcpc)
3424*a2c81616SWang Jie {
3425*a2c81616SWang Jie struct tcpm_port *port;
3426*a2c81616SWang Jie int err;
3427*a2c81616SWang Jie
3428*a2c81616SWang Jie if (!dev || !tcpc ||
3429*a2c81616SWang Jie !tcpc->get_vbus || !tcpc->set_cc || !tcpc->get_cc ||
3430*a2c81616SWang Jie !tcpc->set_polarity || !tcpc->set_vconn || !tcpc->set_vbus ||
3431*a2c81616SWang Jie !tcpc->set_pd_rx || !tcpc->set_roles || !tcpc->pd_transmit)
3432*a2c81616SWang Jie return ERR_PTR(-EINVAL);
3433*a2c81616SWang Jie
3434*a2c81616SWang Jie port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
3435*a2c81616SWang Jie if (!port)
3436*a2c81616SWang Jie return ERR_PTR(-ENOMEM);
3437*a2c81616SWang Jie
3438*a2c81616SWang Jie port->dev = dev;
3439*a2c81616SWang Jie port->tcpc = tcpc;
3440*a2c81616SWang Jie
3441*a2c81616SWang Jie err = tcpm_fw_get_caps(port);
3442*a2c81616SWang Jie if (err < 0) {
3443*a2c81616SWang Jie printf("%s: please check the dts config of %s node(%d)\n",
3444*a2c81616SWang Jie __func__, dev_read_name(dev), err);
3445*a2c81616SWang Jie return ERR_PTR(err);
3446*a2c81616SWang Jie }
3447*a2c81616SWang Jie
3448*a2c81616SWang Jie port->try_role = port->typec_caps.prefer_role;
3449*a2c81616SWang Jie
3450*a2c81616SWang Jie port->typec_caps.revision = 0x0120; /* Type-C spec release 1.2 */
3451*a2c81616SWang Jie port->typec_caps.pd_revision = 0x0300; /* USB-PD spec release 3.0 */
3452*a2c81616SWang Jie port->typec_caps.svdm_version = SVDM_VER_2_0;
3453*a2c81616SWang Jie port->typec_caps.driver_data = port;
3454*a2c81616SWang Jie port->typec_caps.orientation_aware = 1;
3455*a2c81616SWang Jie
3456*a2c81616SWang Jie port->port_type = port->typec_caps.type;
3457*a2c81616SWang Jie
3458*a2c81616SWang Jie tcpm_init(port);
3459*a2c81616SWang Jie
3460*a2c81616SWang Jie printf("%s: init finished\n", dev_read_name(dev));
3461*a2c81616SWang Jie
3462*a2c81616SWang Jie return port;
3463*a2c81616SWang Jie }
3464*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpm_port_init);
3465*a2c81616SWang Jie
tcpm_poll_event(struct tcpm_port * port)3466*a2c81616SWang Jie void tcpm_poll_event(struct tcpm_port *port)
3467*a2c81616SWang Jie {
3468*a2c81616SWang Jie if (!port->tcpc->get_vbus(port->tcpc))
3469*a2c81616SWang Jie return ;
3470*a2c81616SWang Jie
3471*a2c81616SWang Jie while (port->poll_event_cnt < TCPM_POLL_EVENT_TIME_OUT) {
3472*a2c81616SWang Jie if (!port->wait_dr_swap_Message &&
3473*a2c81616SWang Jie ((port->state == SNK_READY) ||
3474*a2c81616SWang Jie (port->state == SRC_READY) ||
3475*a2c81616SWang Jie (port->state == DEBUG_ACC_ATTACHED) ||
3476*a2c81616SWang Jie (port->state == AUDIO_ACC_ATTACHED)))
3477*a2c81616SWang Jie break;
3478*a2c81616SWang Jie
3479*a2c81616SWang Jie port->tcpc->poll_event(port->tcpc);
3480*a2c81616SWang Jie port->poll_event_cnt++;
3481*a2c81616SWang Jie udelay(500);
3482*a2c81616SWang Jie }
3483*a2c81616SWang Jie
3484*a2c81616SWang Jie /*
3485*a2c81616SWang Jie * At this time, call the callback function of the respective pd chip
3486*a2c81616SWang Jie * to enter the low-power mode. In order to reduce the time spent on
3487*a2c81616SWang Jie * the PD chip driver as much as possible, the tcpm framework does not
3488*a2c81616SWang Jie * fully process the communication initiated by the device,so it should
3489*a2c81616SWang Jie * be noted that we can disable the internal oscillator, etc., but do
3490*a2c81616SWang Jie * not turn off the power of the transceiver module, otherwise the
3491*a2c81616SWang Jie * self-powered Type-C device will initiate a Message(eg: self-powered
3492*a2c81616SWang Jie * Type-C hub initiates a SINK capability request(PD_CTRL_GET_SINK_CAP))
3493*a2c81616SWang Jie * and the pd chip cannot reply to GoodCRC, causing the self-powered Type-C
3494*a2c81616SWang Jie * device to switch vbus to vSafe5v, or even turn off vbus.
3495*a2c81616SWang Jie */
3496*a2c81616SWang Jie if (port->tcpc->enter_low_power_mode) {
3497*a2c81616SWang Jie if (port->tcpc->enter_low_power_mode(port->tcpc,
3498*a2c81616SWang Jie port->attached,
3499*a2c81616SWang Jie port->pd_capable))
3500*a2c81616SWang Jie printf("failed to enter low power\n");
3501*a2c81616SWang Jie else
3502*a2c81616SWang Jie printf("PD chip enter low power mode\n");
3503*a2c81616SWang Jie }
3504*a2c81616SWang Jie }
3505*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpm_poll_event);
3506*a2c81616SWang Jie
tcpm_get_voltage(struct tcpm_port * port)3507*a2c81616SWang Jie int tcpm_get_voltage(struct tcpm_port *port)
3508*a2c81616SWang Jie {
3509*a2c81616SWang Jie return port->supply_voltage * 1000;
3510*a2c81616SWang Jie }
3511*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpm_get_voltage);
3512*a2c81616SWang Jie
tcpm_get_current(struct tcpm_port * port)3513*a2c81616SWang Jie int tcpm_get_current(struct tcpm_port *port)
3514*a2c81616SWang Jie {
3515*a2c81616SWang Jie return port->current_limit * 1000;
3516*a2c81616SWang Jie }
3517*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpm_get_voltage);
3518*a2c81616SWang Jie
tcpm_get_online(struct tcpm_port * port)3519*a2c81616SWang Jie int tcpm_get_online(struct tcpm_port *port)
3520*a2c81616SWang Jie {
3521*a2c81616SWang Jie if (port->state == SNK_READY)
3522*a2c81616SWang Jie return 1;
3523*a2c81616SWang Jie else
3524*a2c81616SWang Jie return 0;
3525*a2c81616SWang Jie }
3526*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpm_get_online);
3527*a2c81616SWang Jie
tcpm_uninit_port(struct tcpm_port * port)3528*a2c81616SWang Jie void tcpm_uninit_port(struct tcpm_port *port)
3529*a2c81616SWang Jie {
3530*a2c81616SWang Jie tcpm_reset_port(port);
3531*a2c81616SWang Jie }
3532*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpm_unregister_port);
3533