2 * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
3 * Author: Zain Wang <zain.wang@rock-chips.com>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * Some ideas are from chrome ec and fairchild GPL fusb302 driver.
15 #include <linux/i2c.h>
16 #include <linux/hrtimer.h>
18 #define FUSB_VCONN_SUPPORT
19 /* TODO: more modes would be added here later on */
22 const char *FUSB_DT_INTERRUPT_INTN = "fsc_interrupt_int_n";
23 #define FUSB_DT_GPIO_INTN "fairchild,int_n"
24 #define FUSB_DT_GPIO_VBUS_5V "fairchild,vbus5v"
25 #define FUSB_DT_GPIO_VBUS_OTHER "fairchild,vbusOther"
27 #define FUSB30X_I2C_DRIVER_NAME "fusb302"
28 #define FUSB30X_I2C_DEVICETREE_NAME "fairchild,fusb302"
30 /* FUSB300 Register Addresses */
31 #define FUSB_REG_DEVICEID 0x01
32 #define FUSB_REG_SWITCHES0 0x02
33 #define FUSB_REG_SWITCHES1 0x03
34 #define FUSB_REG_MEASURE 0x04
35 #define FUSB_REG_SLICE 0x05
36 #define FUSB_REG_CONTROL0 0x06
37 #define FUSB_REG_CONTROL1 0x07
38 #define FUSB_REG_CONTROL2 0x08
39 #define FUSB_REG_CONTROL3 0x09
40 #define FUSB_REG_MASK 0x0A
41 #define FUSB_REG_POWER 0x0B
42 #define FUSB_REG_RESET 0x0C
43 #define FUSB_REG_OCPREG 0x0D
44 #define FUSB_REG_MASKA 0x0E
45 #define FUSB_REG_MASKB 0x0F
46 #define FUSB_REG_CONTROL4 0x10
47 #define FUSB_REG_STATUS0A 0x3C
48 #define FUSB_REG_STATUS1A 0x3D
49 #define FUSB_REG_INTERRUPTA 0x3E
50 #define FUSB_REG_INTERRUPTB 0x3F
51 #define FUSB_REG_STATUS0 0x40
52 #define FUSB_REG_STATUS1 0x41
53 #define FUSB_REG_INTERRUPT 0x42
54 #define FUSB_REG_FIFO 0x43
56 enum connection_state {
68 policy_src_negotiate_cap,
69 policy_src_cap_response,
70 policy_src_transition_supply,
71 policy_src_transition_default,
74 policy_src_get_sink_caps,
76 policy_src_send_softrst,
77 policy_src_send_hardrst,
82 policy_snk_evaluate_caps,
83 policy_snk_select_cap,
84 policy_snk_transition_sink,
87 policy_snk_send_softrst,
88 policy_snk_send_hardrst,
90 policy_snk_transition_default,
93 #define SBF(s, v) ((s) << (v))
94 #define SWITCHES0_PDWN1 SBF(1, 0)
95 #define SWITCHES0_PDWN2 SBF(1, 1)
96 #define SWITCHES0_MEAS_CC1 SBF(1, 2)
97 #define SWITCHES0_MEAS_CC2 SBF(1, 3)
98 #define SWITCHES0_VCONN_CC1 SBF(1, 4)
99 #define SWITCHES0_VCONN_CC2 SBF(1, 5)
100 #define SWITCHES0_PU_EN1 SBF(1, 6)
101 #define SWITCHES0_PU_EN2 SBF(1, 7)
103 #define SWITCHES1_TXCC1 SBF(1, 0)
104 #define SWITCHES1_TXCC2 SBF(1, 1)
105 #define SWITCHES1_AUTO_CRC SBF(1, 2)
106 #define SWITCHES1_DATAROLE SBF(1, 4)
107 #define SWITCHES1_SPECREV SBF(3, 5)
108 #define SWITCHES1_POWERROLE SBF(1, 7)
110 #define MEASURE_MDAC SBF(0x3f, 0)
111 #define MEASURE_VBUS SBF(1, 6)
113 #define SLICE_SDAC SBF(0x3f, 0)
114 #define SLICE_SDAC_HYS SBF(3, 6)
116 #define CONTROL0_TX_START SBF(1, 0)
117 #define CONTROL0_AUTO_PRE SBF(1, 1)
118 #define CONTROL0_HOST_CUR SBF(3, 2)
119 #define CONTROL0_INT_MASK SBF(1, 5)
120 #define CONTROL0_TX_FLUSH SBF(1, 6)
122 #define CONTROL1_ENSOP1 SBF(1, 0)
123 #define CONTROL1_ENSOP2 SBF(1, 1)
124 #define CONTROL1_RX_FLUSH SBF(1, 2)
125 #define CONTROL1_BIST_MODE2 SBF(1, 4)
126 #define CONTROL1_ENSOP1DB SBF(1, 5)
127 #define CONTROL1_ENSOP2DB SBF(1, 6)
129 #define CONTROL2_TOGGLE SBF(1, 0)
130 #define CONTROL2_MODE SBF(3, 1)
131 #define CONTROL2_WAKE_EN SBF(1, 3)
132 #define CONTROL2_TOG_RD_ONLY SBF(1, 5)
133 #define CONTROL2_TOG_SAVE_PWR1 SBF(1, 6)
134 #define CONTROL2_TOG_SAVE_PWR2 SBF(1, 7)
136 #define CONTROL3_AUTO_RETRY SBF(1, 0)
137 #define CONTROL3_N_RETRIES SBF(3, 1)
138 #define CONTROL3_AUTO_SOFTRESET SBF(1, 3)
139 #define CONTROL3_AUTO_HARDRESET SBF(1, 4)
140 #define CONTROL3_SEND_HARDRESET SBF(1, 6)
142 #define MASK_M_BC_LVL SBF(1, 0)
143 #define MASK_M_COLLISION SBF(1, 1)
144 #define MASK_M_WAKE SBF(1, 2)
145 #define MASK_M_ALERT SBF(1, 3)
146 #define MASK_M_CRC_CHK SBF(1, 4)
147 #define MASK_M_COMP_CHNG SBF(1, 5)
148 #define MASK_M_ACTIVITY SBF(1, 6)
149 #define MASK_M_VBUSOK SBF(1, 7)
151 #define POWER_PWR SBF(0xf, 0)
153 #define RESET_SW_RESET SBF(1, 0)
154 #define RESET_PD_RESET SBF(1, 1)
156 #define MASKA_M_HARDRST SBF(1, 0)
157 #define MASKA_M_SOFTRST SBF(1, 1)
158 #define MASKA_M_TXSENT SBF(1, 2)
159 #define MASKA_M_HARDSENT SBF(1, 3)
160 #define MASKA_M_RETRYFAIL SBF(1, 4)
161 #define MASKA_M_SOFTFAIL SBF(1, 5)
162 #define MASKA_M_TOGDONE SBF(1, 6)
163 #define MASKA_M_OCP_TEMP SBF(1, 7)
165 #define MASKB_M_GCRCSEND SBF(1, 0)
167 #define CONTROL4_TOG_USRC_EXIT SBF(1, 0)
169 #define MDAC_1P6V 0x26
171 #define STATUS0A_HARDRST SBF(1, 0)
172 #define STATUS0A_SOFTRST SBF(1, 1)
173 #define STATUS0A_POWER23 SBF(3, 2)
174 #define STATUS0A_RETRYFAIL SBF(1, 4)
175 #define STATUS0A_SOFTFAIL SBF(1, 5)
176 #define STATUS0A_TOGDONE SBF(1, 6)
177 #define STATUS0A_M_OCP_TEMP SBF(1, 7)
179 #define STATUS1A_RXSOP SBF(1, 0)
180 #define STATUS1A_RXSOP1DB SBF(1, 1)
181 #define STATUS1A_RXSOP2DB SBF(1, 2)
182 #define STATUS1A_TOGSS SBF(7, 3)
184 #define INTERRUPTA_HARDRST SBF(1, 0)
185 #define INTERRUPTA_SOFTRST SBF(1, 1)
186 #define INTERRUPTA_TXSENT SBF(1, 2)
187 #define INTERRUPTA_HARDSENT SBF(1, 3)
188 #define INTERRUPTA_RETRYFAIL SBF(1, 4)
189 #define INTERRUPTA_SOFTFAIL SBF(1, 5)
190 #define INTERRUPTA_TOGDONE SBF(1, 6)
191 #define INTERRUPTA_OCP_TEMP SBF(1, 7)
193 #define INTERRUPTB_GCRCSENT SBF(1, 0)
195 #define STATUS0_BC_LVL SBF(3, 0)
196 #define STATUS0_WAKE SBF(1, 2)
197 #define STATUS0_ALERT SBF(1, 3)
198 #define STATUS0_CRC_CHK SBF(1, 4)
199 #define STATUS0_COMP SBF(1, 5)
200 #define STATUS0_ACTIVITY SBF(1, 6)
201 #define STATUS0_VBUSOK SBF(1, 7)
203 #define STATUS1_OCP SBF(1, 0)
204 #define STATUS1_OVRTEMP SBF(1, 1)
205 #define STATUS1_TX_FULL SBF(1, 2)
206 #define STATUS1_TX_EMPTY SBF(1, 3)
207 #define STATUS1_RX_FULL SBF(1, 4)
208 #define STATUS1_RX_EMPTY SBF(1, 5)
209 #define STATUS1_RXSOP1 SBF(1, 6)
210 #define STATUS1_RXSOP2 SBF(1, 7)
212 #define INTERRUPT_BC_LVL SBF(1, 0)
213 #define INTERRUPT_COLLISION SBF(1, 1)
214 #define INTERRUPT_WAKE SBF(1, 2)
215 #define INTERRUPT_ALERT SBF(1, 3)
216 #define INTERRUPT_CRC_CHK SBF(1, 4)
217 #define INTERRUPT_COMP_CHNG SBF(1, 5)
218 #define INTERRUPT_ACTIVITY SBF(1, 6)
219 #define INTERRUPT_VBUSOK SBF(1, 7)
221 #define FUSB_TKN_TXON 0xa1
222 #define FUSB_TKN_SYNC1 0x12
223 #define FUSB_TKN_SYNC2 0x13
224 #define FUSB_TKN_SYNC3 0x1b
225 #define FUSB_TKN_RST1 0x15
226 #define FUSB_TKN_RST2 0x16
227 #define FUSB_TKN_PACKSYM 0x80
228 #define FUSB_TKN_JAMCRC 0xff
229 #define FUSB_TKN_EOP 0x14
230 #define FUSB_TKN_TXOFF 0xfe
232 /* USB PD Control Message Types */
233 #define CONTROLMESSAGE 0
234 #define CMT_GOODCRC 1
235 #define CMT_GOTOMIN 2
240 #define CMT_GETSOURCECAP 7
241 #define CMT_GETSINKCAP 8
242 #define CMT_DR_SWAP 9
243 #define CMT_PR_SWAP 10
244 #define CMT_VCONN_SWAP 11
246 #define CMT_SOFTRESET 13
248 /* USB PD Data Message Types */
249 #define DATAMESSAGE 1
250 #define DMT_SOURCECAPABILITIES 1
251 #define DMT_REQUEST 2
253 #define DMT_SINKCAPABILITIES 4
254 #define DMT_VENDERDEFINED 15
256 /* VDM Command Types */
257 #define VDM_DISCOVERY_ID 0X01
258 #define VDM_DISCOVERY_SVIDS 0X02
259 #define VDM_DISCOVERY_MODES 0X03
260 #define VDM_ENTER_MODE 0X04
261 #define VDM_EXIT_MODE 0X05
262 #define VDM_ATTENTION 0X06
263 #define VDM_DP_STATUS_UPDATE 0X10
264 #define VDM_DP_CONFIG 0X11
266 #define VDM_TYPE_INIT 0
267 #define VDM_TYPE_ACK 1
268 #define VDM_TYPE_NACK 2
269 #define VDM_TYPE_BUSY 3
271 #define N_DEBOUNCE_CNT (10 - 1)
272 #define N_CAPS_COUNT 50
273 #define N_HARDRESET_COUNT 0
275 #define T_NO_RESPONSE 5000
276 #define T_SRC_RECOVER 830
277 #define T_TYPEC_SEND_SOURCECAP 3
278 #define T_SENDER_RESPONSE 30
279 #define T_SRC_TRANSITION 30
280 #define T_TYPEC_SINK_WAIT_CAP 500
281 #define T_PS_TRANSITION 500
282 #define T_BMC_TIMEOUT 5
283 #define T_PS_HARD_RESET_MAX 35
284 #define T_SAFE_0V 650
285 #define T_SRC_TURN_ON 275
286 #define T_SRC_RECOVER_MAX 1000
288 #define T_NO_TRIGGER 500
289 #define T_DISABLED 0xffff
291 #define PD_HEADER_CNT(header) (((header) >> 12) & 7)
292 #define PD_HEADER_TYPE(header) ((header) & 0xF)
293 #define PD_HEADER_ID(header) (((header) >> 9) & 7)
295 #define VDM_HEADER_TYPE(header) (((header) >> 6) & 3)
296 #define VDMHEAD_CMD_TYPE_MASK (3 << 6)
297 #define VDMHEAD_CMD_MASK (0x1f << 0)
298 #define VDMHEAD_STRUCT_TYPE_MASK BIT(15)
300 #define GET_VDMHEAD_CMD_TYPE(head) ((head & VDMHEAD_CMD_TYPE_MASK) >> 6)
301 #define GET_VDMHEAD_CMD(head) (head & VDMHEAD_CMD_MASK)
302 #define GET_VDMHEAD_STRUCT_TYPE(head) ((head & VDMHEAD_STRUCT_TYPE_MASK) >> 15)
304 #define VDM_IDHEAD_USBVID_MASK (0xffff << 0)
305 #define VDM_IDHEAD_MODALSUPPORT_MASK BIT(26)
306 #define VDM_IDHEAD_PRODUCTTYPE (7 << 27)
307 #define VDM_IDHEAD_USBDEVICE BIT(30)
308 #define VDM_IDHEAD_USBHOST BIT(30)
310 #define CAP_POWER_TYPE(PDO) ((PDO >> 30) & 3)
311 #define CAP_FPDO_VOLTAGE(PDO) ((PDO >> 10) & 0x3ff)
312 #define CAP_VPDO_VOLTAGE(PDO) ((PDO >> 20) & 0x3ff)
313 #define CAP_FPDO_CURRENT(PDO) ((PDO >> 0) & 0x3ff)
314 #define CAP_VPDO_CURRENT(PDO) ((PDO >> 0) & 0x3ff)
316 enum CC_ORIENTATION {
323 enum CC_ORIENTATION orientation;
328 bool is_cc_connected;
329 bool is_pd_connected;
332 int pin_assignment_support;
333 int pin_assignment_def;
346 u32 specification_revision;
347 u32 externally_powered;
348 u32 usb_suspend_support;
349 u32 usb_communications_cap;
355 struct fusb30x_chip {
356 struct i2c_client *client;
358 struct regmap *regmap;
359 struct work_struct work;
360 struct workqueue_struct *fusb30x_wq;
361 struct hrtimer timer_state_machine;
362 struct hrtimer timer_mux_machine;
363 struct PD_CAP_INFO pd_cap_info;
364 struct notify_info notify;
365 struct notify_info notify_cmp;
366 struct extcon_dev *extcon;
367 enum connection_state conn_state;
368 struct gpio_desc *gpio_vbus_5v;
369 struct gpio_desc *gpio_vbus_other;
370 struct gpio_desc *gpio_int;
380 * ---------------------------------
381 * | role 0x03 << 2, | cc_use 0x03 |
382 * | src 1 << 2, | cc1 1 |
383 * | snk 2 << 2, | cc2 2 |
384 * ---------------------------------
400 enum tx_state tx_state;
402 u32 source_power_supply[7];
404 u32 source_max_current[7];
408 * if PartnerCap[0] == 0xffffffff
409 * show Partner Device do not support supply
425 #endif /* FUSB302_H */