1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | |
3 | /* |
4 | * Driver for Analogix ANX7411 USB Type-C and PD controller |
5 | * |
6 | * Copyright(c) 2022, Analogix Semiconductor. All rights reserved. |
7 | * |
8 | */ |
9 | #include <linux/gpio/consumer.h> |
10 | #include <linux/i2c.h> |
11 | #include <linux/interrupt.h> |
12 | #include <linux/iopoll.h> |
13 | #include <linux/kernel.h> |
14 | #include <linux/module.h> |
15 | #include <linux/mutex.h> |
16 | #include <linux/of_graph.h> |
17 | #include <linux/of_platform.h> |
18 | #include <linux/pm_runtime.h> |
19 | #include <linux/regulator/consumer.h> |
20 | #include <linux/slab.h> |
21 | #include <linux/types.h> |
22 | #include <linux/usb/pd.h> |
23 | #include <linux/usb/role.h> |
24 | #include <linux/usb/tcpci.h> |
25 | #include <linux/usb/typec.h> |
26 | #include <linux/usb/typec_dp.h> |
27 | #include <linux/usb/typec_mux.h> |
28 | #include <linux/workqueue.h> |
29 | #include <linux/power_supply.h> |
30 | |
31 | #define TCPC_ADDRESS1 0x58 |
32 | #define TCPC_ADDRESS2 0x56 |
33 | #define TCPC_ADDRESS3 0x54 |
34 | #define TCPC_ADDRESS4 0x52 |
35 | #define SPI_ADDRESS1 0x7e |
36 | #define SPI_ADDRESS2 0x6e |
37 | #define SPI_ADDRESS3 0x64 |
38 | #define SPI_ADDRESS4 0x62 |
39 | |
40 | struct anx7411_i2c_select { |
41 | u8 tcpc_address; |
42 | u8 spi_address; |
43 | }; |
44 | |
45 | #define VID_ANALOGIX 0x1F29 |
46 | #define PID_ANALOGIX 0x7411 |
47 | |
48 | /* TCPC register define */ |
49 | |
50 | #define ANALOG_CTRL_10 0xAA |
51 | |
52 | #define STATUS_LEN 2 |
53 | #define ALERT_0 0xCB |
54 | #define RECEIVED_MSG BIT(7) |
55 | #define SOFTWARE_INT BIT(6) |
56 | #define MSG_LEN 32 |
57 | #define 2 |
58 | #define 0x00 |
59 | #define MSG_TYPE 0x01 |
60 | #define MSG_RAWDATA 0x02 |
61 | #define MSG_LEN_MASK 0x1F |
62 | |
63 | #define ALERT_1 0xCC |
64 | #define INTP_POW_ON BIT(7) |
65 | #define INTP_POW_OFF BIT(6) |
66 | |
67 | #define VBUS_THRESHOLD_H 0xDD |
68 | #define VBUS_THRESHOLD_L 0xDE |
69 | |
70 | #define FW_CTRL_0 0xF0 |
71 | #define UNSTRUCT_VDM_EN BIT(0) |
72 | #define DELAY_200MS BIT(1) |
73 | #define VSAFE0 0 |
74 | #define VSAFE1 BIT(2) |
75 | #define VSAFE2 BIT(3) |
76 | #define VSAFE3 (BIT(2) | BIT(3)) |
77 | #define FRS_EN BIT(7) |
78 | |
79 | #define FW_PARAM 0xF1 |
80 | #define DONGLE_IOP BIT(0) |
81 | |
82 | #define FW_CTRL_2 0xF7 |
83 | #define SINK_CTRL_DIS_FLAG BIT(5) |
84 | |
85 | /* SPI register define */ |
86 | #define OCM_CTRL_0 0x6E |
87 | #define OCM_RESET BIT(6) |
88 | |
89 | #define MAX_VOLTAGE 0xAC |
90 | #define MAX_POWER 0xAD |
91 | #define MIN_POWER 0xAE |
92 | |
93 | #define REQUEST_VOLTAGE 0xAF |
94 | #define VOLTAGE_UNIT 100 /* mV per unit */ |
95 | |
96 | #define REQUEST_CURRENT 0xB1 |
97 | #define CURRENT_UNIT 50 /* mA per unit */ |
98 | |
99 | #define CMD_SEND_BUF 0xC0 |
100 | #define CMD_RECV_BUF 0xE0 |
101 | |
102 | #define REQ_VOL_20V_IN_100MV 0xC8 |
103 | #define REQ_CUR_2_25A_IN_50MA 0x2D |
104 | #define REQ_CUR_3_25A_IN_50MA 0x41 |
105 | |
106 | #define DEF_5V 5000 |
107 | #define DEF_1_5A 1500 |
108 | |
109 | #define LOBYTE(w) ((u8)((w) & 0xFF)) |
110 | #define HIBYTE(w) ((u8)(((u16)(w) >> 8) & 0xFF)) |
111 | |
112 | enum anx7411_typec_message_type { |
113 | TYPE_SRC_CAP = 0x00, |
114 | TYPE_SNK_CAP = 0x01, |
115 | TYPE_SNK_IDENTITY = 0x02, |
116 | TYPE_SVID = 0x03, |
117 | TYPE_SET_SNK_DP_CAP = 0x08, |
118 | TYPE_PSWAP_REQ = 0x10, |
119 | TYPE_DSWAP_REQ = 0x11, |
120 | TYPE_VDM = 0x14, |
121 | TYPE_OBJ_REQ = 0x16, |
122 | TYPE_DP_ALT_ENTER = 0x19, |
123 | TYPE_DP_DISCOVER_MODES_INFO = 0x27, |
124 | TYPE_GET_DP_CONFIG = 0x29, |
125 | TYPE_DP_CONFIGURE = 0x2A, |
126 | TYPE_GET_DP_DISCOVER_MODES_INFO = 0x2E, |
127 | TYPE_GET_DP_ALT_ENTER = 0x2F, |
128 | }; |
129 | |
130 | #define FW_CTRL_1 0xB2 |
131 | #define AUTO_PD_EN BIT(1) |
132 | #define TRYSRC_EN BIT(2) |
133 | #define TRYSNK_EN BIT(3) |
134 | #define FORCE_SEND_RDO BIT(6) |
135 | |
136 | #define FW_VER 0xB4 |
137 | #define FW_SUBVER 0xB5 |
138 | |
139 | #define INT_MASK 0xB6 |
140 | #define INT_STS 0xB7 |
141 | #define OCM_BOOT_UP BIT(0) |
142 | #define OC_OV_EVENT BIT(1) |
143 | #define VCONN_CHANGE BIT(2) |
144 | #define VBUS_CHANGE BIT(3) |
145 | #define CC_STATUS_CHANGE BIT(4) |
146 | #define DATA_ROLE_CHANGE BIT(5) |
147 | #define PR_CONSUMER_GOT_POWER BIT(6) |
148 | #define HPD_STATUS_CHANGE BIT(7) |
149 | |
150 | #define SYSTEM_STSTUS 0xB8 |
151 | /* 0: SINK off; 1: SINK on */ |
152 | #define SINK_STATUS BIT(1) |
153 | /* 0: VCONN off; 1: VCONN on*/ |
154 | #define VCONN_STATUS BIT(2) |
155 | /* 0: vbus off; 1: vbus on*/ |
156 | #define VBUS_STATUS BIT(3) |
157 | /* 1: host; 0:device*/ |
158 | #define DATA_ROLE BIT(5) |
159 | /* 0: Chunking; 1: Unchunked*/ |
160 | #define SUPPORT_UNCHUNKING BIT(6) |
161 | /* 0: HPD low; 1: HPD high*/ |
162 | #define HPD_STATUS BIT(7) |
163 | |
164 | #define DATA_DFP 1 |
165 | #define DATA_UFP 2 |
166 | #define POWER_SOURCE 1 |
167 | #define POWER_SINK 2 |
168 | |
169 | #define CC_STATUS 0xB9 |
170 | #define CC1_RD BIT(0) |
171 | #define CC2_RD BIT(4) |
172 | #define CC1_RA BIT(1) |
173 | #define CC2_RA BIT(5) |
174 | #define CC1_RD BIT(0) |
175 | #define CC1_RP(cc) (((cc) >> 2) & 0x03) |
176 | #define CC2_RP(cc) (((cc) >> 6) & 0x03) |
177 | |
178 | #define PD_REV_INIT 0xBA |
179 | |
180 | #define PD_EXT_MSG_CTRL 0xBB |
181 | #define SRC_CAP_EXT_REPLY BIT(0) |
182 | #define MANUFACTURER_INFO_REPLY BIT(1) |
183 | #define BATTERY_STS_REPLY BIT(2) |
184 | #define BATTERY_CAP_REPLY BIT(3) |
185 | #define ALERT_REPLY BIT(4) |
186 | #define STATUS_REPLY BIT(5) |
187 | #define PPS_STATUS_REPLY BIT(6) |
188 | #define SNK_CAP_EXT_REPLY BIT(7) |
189 | |
190 | #define NO_CONNECT 0x00 |
191 | #define USB3_1_CONNECTED 0x01 |
192 | #define DP_ALT_4LANES 0x02 |
193 | #define USB3_1_DP_2LANES 0x03 |
194 | #define CC1_CONNECTED 0x01 |
195 | #define CC2_CONNECTED 0x02 |
196 | #define SELECT_PIN_ASSIGMENT_C 0x04 |
197 | #define SELECT_PIN_ASSIGMENT_D 0x08 |
198 | #define SELECT_PIN_ASSIGMENT_E 0x10 |
199 | #define SELECT_PIN_ASSIGMENT_U 0x00 |
200 | #define REDRIVER_ADDRESS 0x20 |
201 | #define REDRIVER_OFFSET 0x00 |
202 | |
203 | #define DP_SVID 0xFF01 |
204 | #define VDM_ACK 0x40 |
205 | #define VDM_CMD_RES 0x00 |
206 | #define VDM_CMD_DIS_ID 0x01 |
207 | #define VDM_CMD_DIS_SVID 0x02 |
208 | #define VDM_CMD_DIS_MOD 0x03 |
209 | #define VDM_CMD_ENTER_MODE 0x04 |
210 | #define VDM_CMD_EXIT_MODE 0x05 |
211 | #define VDM_CMD_ATTENTION 0x06 |
212 | #define VDM_CMD_GET_STS 0x10 |
213 | #define VDM_CMD_AND_ACK_MASK 0x5F |
214 | |
215 | #define MAX_ALTMODE 2 |
216 | |
217 | #define HAS_SOURCE_CAP BIT(0) |
218 | #define HAS_SINK_CAP BIT(1) |
219 | #define HAS_SINK_WATT BIT(2) |
220 | |
221 | enum anx7411_psy_state { |
222 | /* copy from drivers/usb/typec/tcpm */ |
223 | ANX7411_PSY_OFFLINE = 0, |
224 | ANX7411_PSY_FIXED_ONLINE, |
225 | |
226 | /* private */ |
227 | /* PD keep in, but disconnct power to bq25700, |
228 | * this state can be active when higher capacity adapter plug in, |
229 | * and change to ONLINE state when higher capacity adapter plug out |
230 | */ |
231 | ANX7411_PSY_HANG = 0xff, |
232 | }; |
233 | |
234 | struct typec_params { |
235 | int request_current; /* ma */ |
236 | int request_voltage; /* mv */ |
237 | int cc_connect; |
238 | int cc_orientation_valid; |
239 | int cc_status; |
240 | int data_role; |
241 | int power_role; |
242 | int vconn_role; |
243 | int dp_altmode_enter; |
244 | int cust_altmode_enter; |
245 | struct usb_role_switch *role_sw; |
246 | struct typec_port *port; |
247 | struct typec_partner *partner; |
248 | struct typec_mux_dev *typec_mux; |
249 | struct typec_switch_dev *typec_switch; |
250 | struct typec_altmode *amode[MAX_ALTMODE]; |
251 | struct typec_altmode *port_amode[MAX_ALTMODE]; |
252 | struct typec_displayport_data data; |
253 | int pin_assignment; |
254 | struct typec_capability caps; |
255 | u32 src_pdo[PDO_MAX_OBJECTS]; |
256 | u32 sink_pdo[PDO_MAX_OBJECTS]; |
257 | u8 caps_flags; |
258 | u8 src_pdo_nr; |
259 | u8 sink_pdo_nr; |
260 | u8 sink_watt; |
261 | u8 sink_voltage; |
262 | }; |
263 | |
264 | #define MAX_BUF_LEN 30 |
265 | struct fw_msg { |
266 | u8 msg_len; |
267 | u8 msg_type; |
268 | u8 buf[MAX_BUF_LEN]; |
269 | } __packed; |
270 | |
271 | struct anx7411_data { |
272 | int fw_version; |
273 | int fw_subversion; |
274 | struct i2c_client *tcpc_client; |
275 | struct i2c_client *spi_client; |
276 | struct fw_msg send_msg; |
277 | struct fw_msg recv_msg; |
278 | struct gpio_desc *intp_gpiod; |
279 | struct fwnode_handle *connector_fwnode; |
280 | struct typec_params typec; |
281 | int intp_irq; |
282 | struct work_struct work; |
283 | struct workqueue_struct *workqueue; |
284 | /* Lock for interrupt work queue */ |
285 | struct mutex lock; |
286 | |
287 | enum anx7411_psy_state psy_online; |
288 | enum power_supply_usb_type usb_type; |
289 | struct power_supply *psy; |
290 | struct power_supply_desc psy_desc; |
291 | struct device *dev; |
292 | }; |
293 | |
294 | static u8 snk_identity[] = { |
295 | LOBYTE(VID_ANALOGIX), HIBYTE(VID_ANALOGIX), 0x00, 0x82, /* snk_id_hdr */ |
296 | 0x00, 0x00, 0x00, 0x00, /* snk_cert */ |
297 | 0x00, 0x00, LOBYTE(PID_ANALOGIX), HIBYTE(PID_ANALOGIX), /* 5snk_ama */ |
298 | }; |
299 | |
300 | static u8 dp_caps[4] = {0xC6, 0x00, 0x00, 0x00}; |
301 | |
302 | static int anx7411_reg_read(struct i2c_client *client, |
303 | u8 reg_addr) |
304 | { |
305 | return i2c_smbus_read_byte_data(client, command: reg_addr); |
306 | } |
307 | |
308 | static int anx7411_reg_block_read(struct i2c_client *client, |
309 | u8 reg_addr, u8 len, u8 *buf) |
310 | { |
311 | return i2c_smbus_read_i2c_block_data(client, command: reg_addr, length: len, values: buf); |
312 | } |
313 | |
314 | static int anx7411_reg_write(struct i2c_client *client, |
315 | u8 reg_addr, u8 reg_val) |
316 | { |
317 | return i2c_smbus_write_byte_data(client, command: reg_addr, value: reg_val); |
318 | } |
319 | |
320 | static int anx7411_reg_block_write(struct i2c_client *client, |
321 | u8 reg_addr, u8 len, u8 *buf) |
322 | { |
323 | return i2c_smbus_write_i2c_block_data(client, command: reg_addr, length: len, values: buf); |
324 | } |
325 | |
326 | static struct anx7411_i2c_select anx7411_i2c_addr[] = { |
327 | {TCPC_ADDRESS1, SPI_ADDRESS1}, |
328 | {TCPC_ADDRESS2, SPI_ADDRESS2}, |
329 | {TCPC_ADDRESS3, SPI_ADDRESS3}, |
330 | {TCPC_ADDRESS4, SPI_ADDRESS4}, |
331 | }; |
332 | |
333 | static int anx7411_detect_power_mode(struct anx7411_data *ctx) |
334 | { |
335 | int ret; |
336 | int mode; |
337 | |
338 | ret = anx7411_reg_read(client: ctx->spi_client, REQUEST_CURRENT); |
339 | if (ret < 0) |
340 | return ret; |
341 | |
342 | ctx->typec.request_current = ret * CURRENT_UNIT; /* 50ma per unit */ |
343 | |
344 | ret = anx7411_reg_read(client: ctx->spi_client, REQUEST_VOLTAGE); |
345 | if (ret < 0) |
346 | return ret; |
347 | |
348 | ctx->typec.request_voltage = ret * VOLTAGE_UNIT; /* 100mv per unit */ |
349 | |
350 | if (ctx->psy_online == ANX7411_PSY_OFFLINE) { |
351 | ctx->psy_online = ANX7411_PSY_FIXED_ONLINE; |
352 | ctx->usb_type = POWER_SUPPLY_USB_TYPE_PD; |
353 | power_supply_changed(psy: ctx->psy); |
354 | } |
355 | |
356 | if (!ctx->typec.cc_orientation_valid) |
357 | return 0; |
358 | |
359 | if (ctx->typec.cc_connect == CC1_CONNECTED) |
360 | mode = CC1_RP(ctx->typec.cc_status); |
361 | else |
362 | mode = CC2_RP(ctx->typec.cc_status); |
363 | if (mode) { |
364 | typec_set_pwr_opmode(port: ctx->typec.port, mode: mode - 1); |
365 | return 0; |
366 | } |
367 | |
368 | typec_set_pwr_opmode(port: ctx->typec.port, mode: TYPEC_PWR_MODE_PD); |
369 | |
370 | return 0; |
371 | } |
372 | |
373 | static int anx7411_register_partner(struct anx7411_data *ctx, |
374 | int pd, int accessory) |
375 | { |
376 | struct typec_partner_desc desc; |
377 | struct typec_partner *partner; |
378 | |
379 | if (ctx->typec.partner) |
380 | return 0; |
381 | |
382 | desc.usb_pd = pd; |
383 | desc.accessory = accessory; |
384 | desc.identity = NULL; |
385 | partner = typec_register_partner(port: ctx->typec.port, desc: &desc); |
386 | if (IS_ERR(ptr: partner)) |
387 | return PTR_ERR(ptr: partner); |
388 | |
389 | ctx->typec.partner = partner; |
390 | |
391 | return 0; |
392 | } |
393 | |
394 | static int anx7411_detect_cc_orientation(struct anx7411_data *ctx) |
395 | { |
396 | struct device *dev = &ctx->spi_client->dev; |
397 | int ret; |
398 | int cc1_rd, cc2_rd; |
399 | int cc1_ra, cc2_ra; |
400 | int cc1_rp, cc2_rp; |
401 | |
402 | ret = anx7411_reg_read(client: ctx->spi_client, CC_STATUS); |
403 | if (ret < 0) |
404 | return ret; |
405 | |
406 | ctx->typec.cc_status = ret; |
407 | |
408 | cc1_rd = ret & CC1_RD ? 1 : 0; |
409 | cc2_rd = ret & CC2_RD ? 1 : 0; |
410 | cc1_ra = ret & CC1_RA ? 1 : 0; |
411 | cc2_ra = ret & CC2_RA ? 1 : 0; |
412 | cc1_rp = CC1_RP(ret); |
413 | cc2_rp = CC2_RP(ret); |
414 | |
415 | /* Debug cable, nothing to do */ |
416 | if (cc1_rd && cc2_rd) { |
417 | ctx->typec.cc_orientation_valid = 0; |
418 | return anx7411_register_partner(ctx, pd: 0, accessory: TYPEC_ACCESSORY_DEBUG); |
419 | } |
420 | |
421 | if (cc1_ra && cc2_ra) { |
422 | ctx->typec.cc_orientation_valid = 0; |
423 | return anx7411_register_partner(ctx, pd: 0, accessory: TYPEC_ACCESSORY_AUDIO); |
424 | } |
425 | |
426 | ctx->typec.cc_orientation_valid = 1; |
427 | |
428 | ret = anx7411_register_partner(ctx, pd: 1, accessory: TYPEC_ACCESSORY_NONE); |
429 | if (ret) { |
430 | dev_err(dev, "register partner\n" ); |
431 | return ret; |
432 | } |
433 | |
434 | if (cc1_rd || cc1_rp) { |
435 | typec_set_orientation(port: ctx->typec.port, orientation: TYPEC_ORIENTATION_NORMAL); |
436 | ctx->typec.cc_connect = CC1_CONNECTED; |
437 | } |
438 | |
439 | if (cc2_rd || cc2_rp) { |
440 | typec_set_orientation(port: ctx->typec.port, orientation: TYPEC_ORIENTATION_REVERSE); |
441 | ctx->typec.cc_connect = CC2_CONNECTED; |
442 | } |
443 | |
444 | return 0; |
445 | } |
446 | |
447 | static int anx7411_set_mux(struct anx7411_data *ctx, int pin_assignment) |
448 | { |
449 | int mode = TYPEC_STATE_SAFE; |
450 | |
451 | switch (pin_assignment) { |
452 | case SELECT_PIN_ASSIGMENT_U: |
453 | /* default 4 line USB 3.1 */ |
454 | mode = TYPEC_STATE_MODAL; |
455 | break; |
456 | case SELECT_PIN_ASSIGMENT_C: |
457 | case SELECT_PIN_ASSIGMENT_E: |
458 | /* 4 line DP */ |
459 | mode = TYPEC_STATE_SAFE; |
460 | break; |
461 | case SELECT_PIN_ASSIGMENT_D: |
462 | /* 2 line DP, 2 line USB */ |
463 | mode = TYPEC_MODE_USB3; |
464 | break; |
465 | default: |
466 | mode = TYPEC_STATE_SAFE; |
467 | break; |
468 | } |
469 | |
470 | ctx->typec.pin_assignment = pin_assignment; |
471 | |
472 | return typec_set_mode(port: ctx->typec.port, mode); |
473 | } |
474 | |
475 | static int anx7411_set_usb_role(struct anx7411_data *ctx, enum usb_role role) |
476 | { |
477 | if (!ctx->typec.role_sw) |
478 | return 0; |
479 | |
480 | return usb_role_switch_set_role(sw: ctx->typec.role_sw, role); |
481 | } |
482 | |
483 | static int anx7411_data_role_detect(struct anx7411_data *ctx) |
484 | { |
485 | int ret; |
486 | |
487 | ret = anx7411_reg_read(client: ctx->spi_client, SYSTEM_STSTUS); |
488 | if (ret < 0) |
489 | return ret; |
490 | |
491 | ctx->typec.data_role = (ret & DATA_ROLE) ? TYPEC_HOST : TYPEC_DEVICE; |
492 | ctx->typec.vconn_role = (ret & VCONN_STATUS) ? TYPEC_SOURCE : TYPEC_SINK; |
493 | |
494 | typec_set_data_role(port: ctx->typec.port, role: ctx->typec.data_role); |
495 | |
496 | typec_set_vconn_role(port: ctx->typec.port, role: ctx->typec.vconn_role); |
497 | |
498 | if (ctx->typec.data_role == TYPEC_HOST) |
499 | return anx7411_set_usb_role(ctx, role: USB_ROLE_HOST); |
500 | |
501 | return anx7411_set_usb_role(ctx, role: USB_ROLE_DEVICE); |
502 | } |
503 | |
504 | static int anx7411_power_role_detect(struct anx7411_data *ctx) |
505 | { |
506 | int ret; |
507 | |
508 | ret = anx7411_reg_read(client: ctx->spi_client, SYSTEM_STSTUS); |
509 | if (ret < 0) |
510 | return ret; |
511 | |
512 | ctx->typec.power_role = (ret & SINK_STATUS) ? TYPEC_SINK : TYPEC_SOURCE; |
513 | |
514 | if (ctx->typec.power_role == TYPEC_SOURCE) { |
515 | ctx->typec.request_current = DEF_1_5A; |
516 | ctx->typec.request_voltage = DEF_5V; |
517 | } |
518 | |
519 | typec_set_pwr_role(port: ctx->typec.port, role: ctx->typec.power_role); |
520 | |
521 | return 0; |
522 | } |
523 | |
524 | static int anx7411_cc_status_detect(struct anx7411_data *ctx) |
525 | { |
526 | anx7411_detect_cc_orientation(ctx); |
527 | anx7411_detect_power_mode(ctx); |
528 | |
529 | return 0; |
530 | } |
531 | |
532 | static void anx7411_partner_unregister_altmode(struct anx7411_data *ctx) |
533 | { |
534 | int i; |
535 | |
536 | ctx->typec.dp_altmode_enter = 0; |
537 | ctx->typec.cust_altmode_enter = 0; |
538 | |
539 | for (i = 0; i < MAX_ALTMODE; i++) |
540 | if (ctx->typec.amode[i]) { |
541 | typec_unregister_altmode(altmode: ctx->typec.amode[i]); |
542 | ctx->typec.amode[i] = NULL; |
543 | } |
544 | |
545 | ctx->typec.pin_assignment = 0; |
546 | } |
547 | |
548 | static int anx7411_typec_register_altmode(struct anx7411_data *ctx, |
549 | int svid, int vdo) |
550 | { |
551 | struct device *dev = &ctx->spi_client->dev; |
552 | struct typec_altmode_desc desc; |
553 | int err; |
554 | int i; |
555 | |
556 | desc.svid = svid; |
557 | desc.vdo = vdo; |
558 | |
559 | for (i = 0; i < MAX_ALTMODE; i++) |
560 | if (!ctx->typec.amode[i]) |
561 | break; |
562 | |
563 | desc.mode = i + 1; /* start with 1 */ |
564 | |
565 | if (i >= MAX_ALTMODE) { |
566 | dev_err(dev, "no altmode space for registering\n" ); |
567 | return -ENOMEM; |
568 | } |
569 | |
570 | ctx->typec.amode[i] = typec_partner_register_altmode(partner: ctx->typec.partner, |
571 | desc: &desc); |
572 | if (IS_ERR(ptr: ctx->typec.amode[i])) { |
573 | dev_err(dev, "failed to register altmode\n" ); |
574 | err = PTR_ERR(ptr: ctx->typec.amode[i]); |
575 | ctx->typec.amode[i] = NULL; |
576 | return err; |
577 | } |
578 | |
579 | return 0; |
580 | } |
581 | |
582 | static void anx7411_unregister_partner(struct anx7411_data *ctx) |
583 | { |
584 | if (ctx->typec.partner) { |
585 | typec_unregister_partner(partner: ctx->typec.partner); |
586 | ctx->typec.partner = NULL; |
587 | } |
588 | } |
589 | |
590 | static int anx7411_update_altmode(struct anx7411_data *ctx, int svid) |
591 | { |
592 | int i; |
593 | |
594 | if (svid == DP_SVID) |
595 | ctx->typec.dp_altmode_enter = 1; |
596 | else |
597 | ctx->typec.cust_altmode_enter = 1; |
598 | |
599 | for (i = 0; i < MAX_ALTMODE; i++) { |
600 | if (!ctx->typec.amode[i]) |
601 | continue; |
602 | |
603 | if (ctx->typec.amode[i]->svid == svid) { |
604 | typec_altmode_update_active(alt: ctx->typec.amode[i], active: true); |
605 | typec_altmode_notify(altmode: ctx->typec.amode[i], |
606 | conf: ctx->typec.pin_assignment, |
607 | data: &ctx->typec.data); |
608 | break; |
609 | } |
610 | } |
611 | |
612 | return 0; |
613 | } |
614 | |
615 | static int anx7411_register_altmode(struct anx7411_data *ctx, |
616 | bool dp_altmode, u8 *buf) |
617 | { |
618 | int ret; |
619 | int svid; |
620 | int mid; |
621 | |
622 | if (!ctx->typec.partner) |
623 | return 0; |
624 | |
625 | svid = DP_SVID; |
626 | if (dp_altmode) { |
627 | mid = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); |
628 | |
629 | return anx7411_typec_register_altmode(ctx, svid, vdo: mid); |
630 | } |
631 | |
632 | svid = (buf[3] << 8) | buf[2]; |
633 | if ((buf[0] & VDM_CMD_AND_ACK_MASK) != (VDM_ACK | VDM_CMD_ENTER_MODE)) |
634 | return anx7411_update_altmode(ctx, svid); |
635 | |
636 | if ((buf[0] & VDM_CMD_AND_ACK_MASK) != (VDM_ACK | VDM_CMD_DIS_MOD)) |
637 | return 0; |
638 | |
639 | mid = buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24); |
640 | |
641 | ret = anx7411_typec_register_altmode(ctx, svid, vdo: mid); |
642 | if (ctx->typec.cust_altmode_enter) |
643 | ret |= anx7411_update_altmode(ctx, svid); |
644 | |
645 | return ret; |
646 | } |
647 | |
648 | static int anx7411_parse_cmd(struct anx7411_data *ctx, u8 type, u8 *buf, u8 len) |
649 | { |
650 | struct device *dev = &ctx->spi_client->dev; |
651 | u8 cur_50ma, vol_100mv; |
652 | |
653 | switch (type) { |
654 | case TYPE_SRC_CAP: |
655 | cur_50ma = anx7411_reg_read(client: ctx->spi_client, REQUEST_CURRENT); |
656 | vol_100mv = anx7411_reg_read(client: ctx->spi_client, REQUEST_VOLTAGE); |
657 | |
658 | ctx->typec.request_voltage = vol_100mv * VOLTAGE_UNIT; |
659 | ctx->typec.request_current = cur_50ma * CURRENT_UNIT; |
660 | |
661 | ctx->psy_online = ANX7411_PSY_FIXED_ONLINE; |
662 | ctx->usb_type = POWER_SUPPLY_USB_TYPE_PD; |
663 | power_supply_changed(psy: ctx->psy); |
664 | break; |
665 | case TYPE_SNK_CAP: |
666 | break; |
667 | case TYPE_SVID: |
668 | break; |
669 | case TYPE_SNK_IDENTITY: |
670 | break; |
671 | case TYPE_GET_DP_ALT_ENTER: |
672 | /* DP alt mode enter success */ |
673 | if (buf[0]) |
674 | anx7411_update_altmode(ctx, DP_SVID); |
675 | break; |
676 | case TYPE_DP_ALT_ENTER: |
677 | /* Update DP altmode */ |
678 | anx7411_update_altmode(ctx, DP_SVID); |
679 | break; |
680 | case TYPE_OBJ_REQ: |
681 | anx7411_detect_power_mode(ctx); |
682 | break; |
683 | case TYPE_DP_CONFIGURE: |
684 | anx7411_set_mux(ctx, pin_assignment: buf[1]); |
685 | break; |
686 | case TYPE_DP_DISCOVER_MODES_INFO: |
687 | /* Make sure discover modes valid */ |
688 | if (buf[0] | buf[1]) |
689 | /* Register DP Altmode */ |
690 | anx7411_register_altmode(ctx, dp_altmode: 1, buf); |
691 | break; |
692 | case TYPE_VDM: |
693 | /* Register other altmode */ |
694 | anx7411_register_altmode(ctx, dp_altmode: 0, buf); |
695 | break; |
696 | default: |
697 | dev_err(dev, "ignore message(0x%.02x).\n" , type); |
698 | break; |
699 | } |
700 | |
701 | return 0; |
702 | } |
703 | |
704 | static u8 checksum(struct device *dev, u8 *buf, u8 len) |
705 | { |
706 | u8 ret = 0; |
707 | u8 i; |
708 | |
709 | for (i = 0; i < len; i++) |
710 | ret += buf[i]; |
711 | |
712 | return ret; |
713 | } |
714 | |
715 | static int anx7411_read_msg_ctrl_status(struct i2c_client *client) |
716 | { |
717 | return anx7411_reg_read(client, CMD_SEND_BUF); |
718 | } |
719 | |
720 | static int anx7411_wait_msg_empty(struct i2c_client *client) |
721 | { |
722 | int val; |
723 | |
724 | return readx_poll_timeout(anx7411_read_msg_ctrl_status, |
725 | client, val, (val < 0) || (val == 0), |
726 | 2000, 2000 * 150); |
727 | } |
728 | |
729 | static int anx7411_send_msg(struct anx7411_data *ctx, u8 type, u8 *buf, u8 size) |
730 | { |
731 | struct device *dev = &ctx->spi_client->dev; |
732 | struct fw_msg *msg = &ctx->send_msg; |
733 | u8 crc; |
734 | int ret; |
735 | |
736 | size = min_t(u8, size, (u8)MAX_BUF_LEN); |
737 | memcpy(msg->buf, buf, size); |
738 | msg->msg_type = type; |
739 | /* msg len equals buffer length + msg_type */ |
740 | msg->msg_len = size + 1; |
741 | |
742 | /* Do CRC check for all buffer data and msg_len and msg_type */ |
743 | crc = checksum(dev, buf: (u8 *)msg, len: size + HEADER_LEN); |
744 | msg->buf[size] = 0 - crc; |
745 | |
746 | ret = anx7411_wait_msg_empty(client: ctx->spi_client); |
747 | if (ret) |
748 | return ret; |
749 | |
750 | ret = anx7411_reg_block_write(client: ctx->spi_client, |
751 | CMD_SEND_BUF + 1, len: size + HEADER_LEN, |
752 | buf: &msg->msg_type); |
753 | ret |= anx7411_reg_write(client: ctx->spi_client, CMD_SEND_BUF, |
754 | reg_val: msg->msg_len); |
755 | return ret; |
756 | } |
757 | |
758 | static int anx7411_process_cmd(struct anx7411_data *ctx) |
759 | { |
760 | struct device *dev = &ctx->spi_client->dev; |
761 | struct fw_msg *msg = &ctx->recv_msg; |
762 | u8 len; |
763 | u8 crc; |
764 | int ret; |
765 | |
766 | /* Read message from firmware */ |
767 | ret = anx7411_reg_block_read(client: ctx->spi_client, CMD_RECV_BUF, |
768 | MSG_LEN, buf: (u8 *)msg); |
769 | if (ret < 0) |
770 | return 0; |
771 | |
772 | if (!msg->msg_len) |
773 | return 0; |
774 | |
775 | ret = anx7411_reg_write(client: ctx->spi_client, CMD_RECV_BUF, reg_val: 0); |
776 | if (ret) |
777 | return ret; |
778 | |
779 | len = msg->msg_len & MSG_LEN_MASK; |
780 | crc = checksum(dev, buf: (u8 *)msg, len: len + HEADER_LEN); |
781 | if (crc) { |
782 | dev_err(dev, "message error crc(0x%.02x)\n" , crc); |
783 | return -ERANGE; |
784 | } |
785 | |
786 | return anx7411_parse_cmd(ctx, type: msg->msg_type, buf: msg->buf, len: len - 1); |
787 | } |
788 | |
789 | static void anx7411_translate_payload(struct device *dev, __le32 *payload, |
790 | u32 *pdo, int nr, const char *type) |
791 | { |
792 | int i; |
793 | |
794 | if (nr > PDO_MAX_OBJECTS) { |
795 | dev_err(dev, "nr(%d) exceed PDO_MAX_OBJECTS(%d)\n" , |
796 | nr, PDO_MAX_OBJECTS); |
797 | |
798 | return; |
799 | } |
800 | |
801 | for (i = 0; i < nr; i++) |
802 | payload[i] = cpu_to_le32(pdo[i]); |
803 | } |
804 | |
805 | static int anx7411_config(struct anx7411_data *ctx) |
806 | { |
807 | struct device *dev = &ctx->spi_client->dev; |
808 | struct typec_params *typecp = &ctx->typec; |
809 | __le32 payload[PDO_MAX_OBJECTS]; |
810 | int ret; |
811 | |
812 | /* Config PD FW work under PD 2.0 */ |
813 | ret = anx7411_reg_write(client: ctx->spi_client, PD_REV_INIT, PD_REV20); |
814 | ret |= anx7411_reg_write(client: ctx->tcpc_client, FW_CTRL_0, |
815 | UNSTRUCT_VDM_EN | DELAY_200MS | |
816 | VSAFE1 | FRS_EN); |
817 | ret |= anx7411_reg_write(client: ctx->spi_client, FW_CTRL_1, |
818 | AUTO_PD_EN | FORCE_SEND_RDO); |
819 | |
820 | /* Set VBUS current threshold */ |
821 | ret |= anx7411_reg_write(client: ctx->tcpc_client, VBUS_THRESHOLD_H, reg_val: 0xff); |
822 | ret |= anx7411_reg_write(client: ctx->tcpc_client, VBUS_THRESHOLD_L, reg_val: 0x03); |
823 | |
824 | /* Fix dongle compatible issue */ |
825 | ret |= anx7411_reg_write(client: ctx->tcpc_client, FW_PARAM, |
826 | reg_val: anx7411_reg_read(client: ctx->tcpc_client, FW_PARAM) | |
827 | DONGLE_IOP); |
828 | ret |= anx7411_reg_write(client: ctx->spi_client, INT_MASK, reg_val: 0); |
829 | |
830 | ret |= anx7411_reg_write(client: ctx->spi_client, PD_EXT_MSG_CTRL, reg_val: 0xFF); |
831 | if (ret) |
832 | return ret; |
833 | |
834 | if (typecp->caps_flags & HAS_SOURCE_CAP) { |
835 | anx7411_translate_payload(dev, payload, pdo: typecp->src_pdo, |
836 | nr: typecp->src_pdo_nr, type: "source" ); |
837 | anx7411_send_msg(ctx, type: TYPE_SRC_CAP, buf: (u8 *)&payload, |
838 | size: typecp->src_pdo_nr * 4); |
839 | anx7411_send_msg(ctx, type: TYPE_SNK_IDENTITY, buf: snk_identity, |
840 | size: sizeof(snk_identity)); |
841 | anx7411_send_msg(ctx, type: TYPE_SET_SNK_DP_CAP, buf: dp_caps, |
842 | size: sizeof(dp_caps)); |
843 | } |
844 | |
845 | if (typecp->caps_flags & HAS_SINK_CAP) { |
846 | anx7411_translate_payload(dev, payload, pdo: typecp->sink_pdo, |
847 | nr: typecp->sink_pdo_nr, type: "sink" ); |
848 | anx7411_send_msg(ctx, type: TYPE_SNK_CAP, buf: (u8 *)&payload, |
849 | size: typecp->sink_pdo_nr * 4); |
850 | } |
851 | |
852 | if (typecp->caps_flags & HAS_SINK_WATT) { |
853 | if (typecp->sink_watt) { |
854 | ret |= anx7411_reg_write(client: ctx->spi_client, MAX_POWER, |
855 | reg_val: typecp->sink_watt); |
856 | /* Set min power to 1W */ |
857 | ret |= anx7411_reg_write(client: ctx->spi_client, MIN_POWER, reg_val: 2); |
858 | } |
859 | |
860 | if (typecp->sink_voltage) |
861 | ret |= anx7411_reg_write(client: ctx->spi_client, MAX_VOLTAGE, |
862 | reg_val: typecp->sink_voltage); |
863 | if (ret) |
864 | return ret; |
865 | } |
866 | |
867 | if (!typecp->caps_flags) |
868 | usleep_range(min: 5000, max: 6000); |
869 | |
870 | ctx->fw_version = anx7411_reg_read(client: ctx->spi_client, FW_VER); |
871 | ctx->fw_subversion = anx7411_reg_read(client: ctx->spi_client, FW_SUBVER); |
872 | |
873 | return 0; |
874 | } |
875 | |
876 | static void anx7411_chip_standby(struct anx7411_data *ctx) |
877 | { |
878 | int ret; |
879 | u8 cc1, cc2; |
880 | struct device *dev = &ctx->spi_client->dev; |
881 | |
882 | ret = anx7411_reg_write(client: ctx->spi_client, OCM_CTRL_0, |
883 | reg_val: anx7411_reg_read(client: ctx->spi_client, OCM_CTRL_0) | |
884 | OCM_RESET); |
885 | ret |= anx7411_reg_write(client: ctx->tcpc_client, ANALOG_CTRL_10, reg_val: 0x80); |
886 | /* Set TCPC to RD and DRP enable */ |
887 | cc1 = TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT; |
888 | cc2 = TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT; |
889 | ret |= anx7411_reg_write(client: ctx->tcpc_client, TCPC_ROLE_CTRL, |
890 | TCPC_ROLE_CTRL_DRP | cc1 | cc2); |
891 | |
892 | /* Send DRP toggle command */ |
893 | ret |= anx7411_reg_write(client: ctx->tcpc_client, TCPC_COMMAND, |
894 | TCPC_CMD_LOOK4CONNECTION); |
895 | |
896 | /* Send TCPC enter standby command */ |
897 | ret |= anx7411_reg_write(client: ctx->tcpc_client, |
898 | TCPC_COMMAND, TCPC_CMD_I2C_IDLE); |
899 | if (ret) |
900 | dev_err(dev, "Chip standby failed\n" ); |
901 | } |
902 | |
903 | static void anx7411_work_func(struct work_struct *work) |
904 | { |
905 | int ret; |
906 | u8 buf[STATUS_LEN]; |
907 | u8 int_change; /* Interrupt change */ |
908 | u8 int_status; /* Firmware status update */ |
909 | u8 alert0, alert1; /* Interrupt alert source */ |
910 | struct anx7411_data *ctx = container_of(work, struct anx7411_data, work); |
911 | struct device *dev = &ctx->spi_client->dev; |
912 | |
913 | mutex_lock(&ctx->lock); |
914 | |
915 | /* Read interrupt change status */ |
916 | ret = anx7411_reg_block_read(client: ctx->spi_client, INT_STS, STATUS_LEN, buf); |
917 | if (ret < 0) { |
918 | /* Power standby mode, just return */ |
919 | goto unlock; |
920 | } |
921 | int_change = buf[0]; |
922 | int_status = buf[1]; |
923 | |
924 | /* Read alert register */ |
925 | ret = anx7411_reg_block_read(client: ctx->tcpc_client, ALERT_0, STATUS_LEN, buf); |
926 | if (ret < 0) |
927 | goto unlock; |
928 | |
929 | alert0 = buf[0]; |
930 | alert1 = buf[1]; |
931 | |
932 | /* Clear interrupt and alert status */ |
933 | ret = anx7411_reg_write(client: ctx->spi_client, INT_STS, reg_val: 0); |
934 | ret |= anx7411_reg_write(client: ctx->tcpc_client, ALERT_0, reg_val: alert0); |
935 | ret |= anx7411_reg_write(client: ctx->tcpc_client, ALERT_1, reg_val: alert1); |
936 | if (ret) |
937 | goto unlock; |
938 | |
939 | if (alert1 & INTP_POW_OFF) { |
940 | anx7411_partner_unregister_altmode(ctx); |
941 | if (anx7411_set_usb_role(ctx, role: USB_ROLE_NONE)) |
942 | dev_err(dev, "Set usb role\n" ); |
943 | anx7411_unregister_partner(ctx); |
944 | ctx->psy_online = ANX7411_PSY_OFFLINE; |
945 | ctx->usb_type = POWER_SUPPLY_USB_TYPE_C; |
946 | ctx->typec.request_voltage = 0; |
947 | ctx->typec.request_current = 0; |
948 | power_supply_changed(psy: ctx->psy); |
949 | anx7411_chip_standby(ctx); |
950 | goto unlock; |
951 | } |
952 | |
953 | if ((alert0 & SOFTWARE_INT) && (int_change & OCM_BOOT_UP)) { |
954 | if (anx7411_config(ctx)) |
955 | dev_err(dev, "Config failed\n" ); |
956 | if (anx7411_data_role_detect(ctx)) |
957 | dev_err(dev, "set PD data role\n" ); |
958 | if (anx7411_power_role_detect(ctx)) |
959 | dev_err(dev, "set PD power role\n" ); |
960 | anx7411_set_mux(ctx, SELECT_PIN_ASSIGMENT_C); |
961 | } |
962 | |
963 | if (alert0 & RECEIVED_MSG) |
964 | anx7411_process_cmd(ctx); |
965 | |
966 | ret = (int_status & DATA_ROLE) ? TYPEC_HOST : TYPEC_DEVICE; |
967 | if (ctx->typec.data_role != ret) |
968 | if (anx7411_data_role_detect(ctx)) |
969 | dev_err(dev, "set PD data role\n" ); |
970 | |
971 | ret = (int_status & SINK_STATUS) ? TYPEC_SINK : TYPEC_SOURCE; |
972 | if (ctx->typec.power_role != ret) |
973 | if (anx7411_power_role_detect(ctx)) |
974 | dev_err(dev, "set PD power role\n" ); |
975 | |
976 | if ((alert0 & SOFTWARE_INT) && (int_change & CC_STATUS_CHANGE)) |
977 | anx7411_cc_status_detect(ctx); |
978 | |
979 | unlock: |
980 | mutex_unlock(lock: &ctx->lock); |
981 | } |
982 | |
983 | static irqreturn_t anx7411_intr_isr(int irq, void *data) |
984 | { |
985 | struct anx7411_data *ctx = (struct anx7411_data *)data; |
986 | |
987 | queue_work(wq: ctx->workqueue, work: &ctx->work); |
988 | |
989 | return IRQ_HANDLED; |
990 | } |
991 | |
992 | static int anx7411_register_i2c_dummy_clients(struct anx7411_data *ctx, |
993 | struct i2c_client *client) |
994 | { |
995 | int i; |
996 | u8 spi_addr; |
997 | |
998 | for (i = 0; i < ARRAY_SIZE(anx7411_i2c_addr); i++) { |
999 | if (client->addr == (anx7411_i2c_addr[i].tcpc_address >> 1)) { |
1000 | spi_addr = anx7411_i2c_addr[i].spi_address >> 1; |
1001 | ctx->spi_client = i2c_new_dummy_device(adapter: client->adapter, |
1002 | address: spi_addr); |
1003 | if (!IS_ERR(ptr: ctx->spi_client)) |
1004 | return 0; |
1005 | } |
1006 | } |
1007 | |
1008 | dev_err(&client->dev, "unable to get SPI slave\n" ); |
1009 | return -ENOMEM; |
1010 | } |
1011 | |
1012 | static void anx7411_port_unregister_altmodes(struct typec_altmode **adev) |
1013 | { |
1014 | int i; |
1015 | |
1016 | for (i = 0; i < MAX_ALTMODE; i++) |
1017 | if (adev[i]) { |
1018 | typec_unregister_altmode(altmode: adev[i]); |
1019 | adev[i] = NULL; |
1020 | } |
1021 | } |
1022 | |
1023 | static int anx7411_usb_mux_set(struct typec_mux_dev *mux, |
1024 | struct typec_mux_state *state) |
1025 | { |
1026 | struct anx7411_data *ctx = typec_mux_get_drvdata(mux); |
1027 | struct device *dev = &ctx->spi_client->dev; |
1028 | int has_dp; |
1029 | |
1030 | has_dp = (state->alt && state->alt->svid == USB_TYPEC_DP_SID && |
1031 | state->alt->mode == USB_TYPEC_DP_MODE); |
1032 | if (!has_dp) |
1033 | dev_err(dev, "dp altmode not register\n" ); |
1034 | |
1035 | return 0; |
1036 | } |
1037 | |
1038 | static int anx7411_usb_set_orientation(struct typec_switch_dev *sw, |
1039 | enum typec_orientation orientation) |
1040 | { |
1041 | /* No need set */ |
1042 | |
1043 | return 0; |
1044 | } |
1045 | |
1046 | static int anx7411_register_switch(struct anx7411_data *ctx, |
1047 | struct device *dev, |
1048 | struct fwnode_handle *fwnode) |
1049 | { |
1050 | struct typec_switch_desc sw_desc = { }; |
1051 | |
1052 | sw_desc.fwnode = fwnode; |
1053 | sw_desc.drvdata = ctx; |
1054 | sw_desc.name = fwnode_get_name(fwnode); |
1055 | sw_desc.set = anx7411_usb_set_orientation; |
1056 | |
1057 | ctx->typec.typec_switch = typec_switch_register(parent: dev, desc: &sw_desc); |
1058 | if (IS_ERR(ptr: ctx->typec.typec_switch)) { |
1059 | dev_err(dev, "switch register failed\n" ); |
1060 | return PTR_ERR(ptr: ctx->typec.typec_switch); |
1061 | } |
1062 | |
1063 | return 0; |
1064 | } |
1065 | |
1066 | static int anx7411_register_mux(struct anx7411_data *ctx, |
1067 | struct device *dev, |
1068 | struct fwnode_handle *fwnode) |
1069 | { |
1070 | struct typec_mux_desc mux_desc = { }; |
1071 | |
1072 | mux_desc.fwnode = fwnode; |
1073 | mux_desc.drvdata = ctx; |
1074 | mux_desc.name = fwnode_get_name(fwnode); |
1075 | mux_desc.set = anx7411_usb_mux_set; |
1076 | |
1077 | ctx->typec.typec_mux = typec_mux_register(parent: dev, desc: &mux_desc); |
1078 | if (IS_ERR(ptr: ctx->typec.typec_mux)) { |
1079 | dev_err(dev, "mux register failed\n" ); |
1080 | return PTR_ERR(ptr: ctx->typec.typec_mux); |
1081 | } |
1082 | |
1083 | return 0; |
1084 | } |
1085 | |
1086 | static void anx7411_unregister_mux(struct anx7411_data *ctx) |
1087 | { |
1088 | if (ctx->typec.typec_mux) { |
1089 | typec_mux_unregister(mux: ctx->typec.typec_mux); |
1090 | ctx->typec.typec_mux = NULL; |
1091 | } |
1092 | } |
1093 | |
1094 | static void anx7411_unregister_switch(struct anx7411_data *ctx) |
1095 | { |
1096 | if (ctx->typec.typec_switch) { |
1097 | typec_switch_unregister(sw: ctx->typec.typec_switch); |
1098 | ctx->typec.typec_switch = NULL; |
1099 | } |
1100 | } |
1101 | |
1102 | static int anx7411_typec_switch_probe(struct anx7411_data *ctx, |
1103 | struct device *dev) |
1104 | { |
1105 | int ret; |
1106 | struct device_node *node; |
1107 | |
1108 | node = of_get_child_by_name(node: dev->of_node, name: "orientation_switch" ); |
1109 | if (!node) |
1110 | return 0; |
1111 | |
1112 | ret = anx7411_register_switch(ctx, dev, fwnode: &node->fwnode); |
1113 | if (ret) { |
1114 | dev_err(dev, "failed register switch" ); |
1115 | return ret; |
1116 | } |
1117 | |
1118 | node = of_get_child_by_name(node: dev->of_node, name: "mode_switch" ); |
1119 | if (!node) { |
1120 | dev_err(dev, "no typec mux exist" ); |
1121 | ret = -ENODEV; |
1122 | goto unregister_switch; |
1123 | } |
1124 | |
1125 | ret = anx7411_register_mux(ctx, dev, fwnode: &node->fwnode); |
1126 | if (ret) { |
1127 | dev_err(dev, "failed register mode switch" ); |
1128 | ret = -ENODEV; |
1129 | goto unregister_switch; |
1130 | } |
1131 | |
1132 | return 0; |
1133 | |
1134 | unregister_switch: |
1135 | anx7411_unregister_switch(ctx); |
1136 | |
1137 | return ret; |
1138 | } |
1139 | |
1140 | static int anx7411_typec_port_probe(struct anx7411_data *ctx, |
1141 | struct device *dev) |
1142 | { |
1143 | struct typec_capability *cap = &ctx->typec.caps; |
1144 | struct typec_params *typecp = &ctx->typec; |
1145 | struct fwnode_handle *fwnode; |
1146 | const char *buf; |
1147 | int ret, i; |
1148 | |
1149 | fwnode = device_get_named_child_node(dev, childname: "connector" ); |
1150 | if (!fwnode) |
1151 | return -EINVAL; |
1152 | |
1153 | ret = fwnode_property_read_string(fwnode, propname: "power-role" , val: &buf); |
1154 | if (ret) { |
1155 | dev_err(dev, "power-role not found: %d\n" , ret); |
1156 | return ret; |
1157 | } |
1158 | |
1159 | ret = typec_find_port_power_role(name: buf); |
1160 | if (ret < 0) |
1161 | return ret; |
1162 | cap->type = ret; |
1163 | |
1164 | ret = fwnode_property_read_string(fwnode, propname: "data-role" , val: &buf); |
1165 | if (ret) { |
1166 | dev_err(dev, "data-role not found: %d\n" , ret); |
1167 | return ret; |
1168 | } |
1169 | |
1170 | ret = typec_find_port_data_role(name: buf); |
1171 | if (ret < 0) |
1172 | return ret; |
1173 | cap->data = ret; |
1174 | |
1175 | ret = fwnode_property_read_string(fwnode, propname: "try-power-role" , val: &buf); |
1176 | if (ret) { |
1177 | dev_err(dev, "try-power-role not found: %d\n" , ret); |
1178 | return ret; |
1179 | } |
1180 | |
1181 | ret = typec_find_power_role(name: buf); |
1182 | if (ret < 0) |
1183 | return ret; |
1184 | cap->prefer_role = ret; |
1185 | |
1186 | /* Get source pdos */ |
1187 | ret = fwnode_property_count_u32(fwnode, propname: "source-pdos" ); |
1188 | if (ret > 0) { |
1189 | typecp->src_pdo_nr = min_t(u8, ret, PDO_MAX_OBJECTS); |
1190 | ret = fwnode_property_read_u32_array(fwnode, propname: "source-pdos" , |
1191 | val: typecp->src_pdo, |
1192 | nval: typecp->src_pdo_nr); |
1193 | if (ret < 0) { |
1194 | dev_err(dev, "source cap validate failed: %d\n" , ret); |
1195 | return -EINVAL; |
1196 | } |
1197 | |
1198 | typecp->caps_flags |= HAS_SOURCE_CAP; |
1199 | } |
1200 | |
1201 | ret = fwnode_property_count_u32(fwnode, propname: "sink-pdos" ); |
1202 | if (ret > 0) { |
1203 | typecp->sink_pdo_nr = min_t(u8, ret, PDO_MAX_OBJECTS); |
1204 | ret = fwnode_property_read_u32_array(fwnode, propname: "sink-pdos" , |
1205 | val: typecp->sink_pdo, |
1206 | nval: typecp->sink_pdo_nr); |
1207 | if (ret < 0) { |
1208 | dev_err(dev, "sink cap validate failed: %d\n" , ret); |
1209 | return -EINVAL; |
1210 | } |
1211 | |
1212 | for (i = 0; i < typecp->sink_pdo_nr; i++) { |
1213 | ret = 0; |
1214 | switch (pdo_type(pdo: typecp->sink_pdo[i])) { |
1215 | case PDO_TYPE_FIXED: |
1216 | ret = pdo_fixed_voltage(pdo: typecp->sink_pdo[i]); |
1217 | break; |
1218 | case PDO_TYPE_BATT: |
1219 | case PDO_TYPE_VAR: |
1220 | ret = pdo_max_voltage(pdo: typecp->sink_pdo[i]); |
1221 | break; |
1222 | case PDO_TYPE_APDO: |
1223 | default: |
1224 | ret = 0; |
1225 | break; |
1226 | } |
1227 | |
1228 | /* 100mv per unit */ |
1229 | typecp->sink_voltage = max(5000, ret) / 100; |
1230 | } |
1231 | |
1232 | typecp->caps_flags |= HAS_SINK_CAP; |
1233 | } |
1234 | |
1235 | if (!fwnode_property_read_u32(fwnode, propname: "op-sink-microwatt" , val: &ret)) { |
1236 | typecp->sink_watt = ret / 500000; /* 500mw per unit */ |
1237 | typecp->caps_flags |= HAS_SINK_WATT; |
1238 | } |
1239 | |
1240 | cap->fwnode = fwnode; |
1241 | |
1242 | ctx->typec.role_sw = usb_role_switch_get(dev); |
1243 | if (IS_ERR(ptr: ctx->typec.role_sw)) { |
1244 | dev_err(dev, "USB role switch not found.\n" ); |
1245 | ctx->typec.role_sw = NULL; |
1246 | } |
1247 | |
1248 | ctx->typec.port = typec_register_port(parent: dev, cap); |
1249 | if (IS_ERR(ptr: ctx->typec.port)) { |
1250 | ret = PTR_ERR(ptr: ctx->typec.port); |
1251 | ctx->typec.port = NULL; |
1252 | dev_err(dev, "Failed to register type c port %d\n" , ret); |
1253 | return ret; |
1254 | } |
1255 | |
1256 | typec_port_register_altmodes(port: ctx->typec.port, NULL, drvdata: ctx, |
1257 | altmodes: ctx->typec.port_amode, |
1258 | MAX_ALTMODE); |
1259 | return 0; |
1260 | } |
1261 | |
1262 | static int anx7411_typec_check_connection(struct anx7411_data *ctx) |
1263 | { |
1264 | int ret; |
1265 | |
1266 | ret = anx7411_reg_read(client: ctx->spi_client, FW_VER); |
1267 | if (ret < 0) |
1268 | return 0; /* No device attached in typec port */ |
1269 | |
1270 | /* Clear interrupt and alert status */ |
1271 | ret = anx7411_reg_write(client: ctx->spi_client, INT_STS, reg_val: 0); |
1272 | ret |= anx7411_reg_write(client: ctx->tcpc_client, ALERT_0, reg_val: 0xFF); |
1273 | ret |= anx7411_reg_write(client: ctx->tcpc_client, ALERT_1, reg_val: 0xFF); |
1274 | if (ret) |
1275 | return ret; |
1276 | |
1277 | ret = anx7411_cc_status_detect(ctx); |
1278 | ret |= anx7411_power_role_detect(ctx); |
1279 | ret |= anx7411_data_role_detect(ctx); |
1280 | ret |= anx7411_set_mux(ctx, SELECT_PIN_ASSIGMENT_C); |
1281 | if (ret) |
1282 | return ret; |
1283 | |
1284 | ret = anx7411_send_msg(ctx, type: TYPE_GET_DP_ALT_ENTER, NULL, size: 0); |
1285 | ret |= anx7411_send_msg(ctx, type: TYPE_GET_DP_DISCOVER_MODES_INFO, NULL, size: 0); |
1286 | |
1287 | return ret; |
1288 | } |
1289 | |
1290 | static int __maybe_unused anx7411_runtime_pm_suspend(struct device *dev) |
1291 | { |
1292 | struct anx7411_data *ctx = dev_get_drvdata(dev); |
1293 | |
1294 | mutex_lock(&ctx->lock); |
1295 | |
1296 | anx7411_partner_unregister_altmode(ctx); |
1297 | |
1298 | if (ctx->typec.partner) |
1299 | anx7411_unregister_partner(ctx); |
1300 | |
1301 | mutex_unlock(lock: &ctx->lock); |
1302 | |
1303 | return 0; |
1304 | } |
1305 | |
1306 | static int __maybe_unused anx7411_runtime_pm_resume(struct device *dev) |
1307 | { |
1308 | struct anx7411_data *ctx = dev_get_drvdata(dev); |
1309 | |
1310 | mutex_lock(&ctx->lock); |
1311 | /* Detect PD connection */ |
1312 | if (anx7411_typec_check_connection(ctx)) |
1313 | dev_err(dev, "check connection" ); |
1314 | |
1315 | mutex_unlock(lock: &ctx->lock); |
1316 | |
1317 | return 0; |
1318 | } |
1319 | |
1320 | static const struct dev_pm_ops anx7411_pm_ops = { |
1321 | SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, |
1322 | pm_runtime_force_resume) |
1323 | SET_RUNTIME_PM_OPS(anx7411_runtime_pm_suspend, |
1324 | anx7411_runtime_pm_resume, NULL) |
1325 | }; |
1326 | |
1327 | static void anx7411_get_gpio_irq(struct anx7411_data *ctx) |
1328 | { |
1329 | struct device *dev = &ctx->tcpc_client->dev; |
1330 | |
1331 | ctx->intp_gpiod = devm_gpiod_get_optional(dev, con_id: "interrupt" , flags: GPIOD_IN); |
1332 | if (IS_ERR_OR_NULL(ptr: ctx->intp_gpiod)) { |
1333 | dev_err(dev, "no interrupt gpio property\n" ); |
1334 | return; |
1335 | } |
1336 | |
1337 | ctx->intp_irq = gpiod_to_irq(desc: ctx->intp_gpiod); |
1338 | if (ctx->intp_irq < 0) |
1339 | dev_err(dev, "failed to get GPIO IRQ\n" ); |
1340 | } |
1341 | |
1342 | static enum power_supply_usb_type anx7411_psy_usb_types[] = { |
1343 | POWER_SUPPLY_USB_TYPE_C, |
1344 | POWER_SUPPLY_USB_TYPE_PD, |
1345 | POWER_SUPPLY_USB_TYPE_PD_PPS, |
1346 | }; |
1347 | |
1348 | static enum power_supply_property anx7411_psy_props[] = { |
1349 | POWER_SUPPLY_PROP_USB_TYPE, |
1350 | POWER_SUPPLY_PROP_ONLINE, |
1351 | POWER_SUPPLY_PROP_VOLTAGE_MIN, |
1352 | POWER_SUPPLY_PROP_VOLTAGE_MAX, |
1353 | POWER_SUPPLY_PROP_VOLTAGE_NOW, |
1354 | POWER_SUPPLY_PROP_CURRENT_MAX, |
1355 | POWER_SUPPLY_PROP_CURRENT_NOW, |
1356 | }; |
1357 | |
1358 | static int anx7411_psy_set_prop(struct power_supply *psy, |
1359 | enum power_supply_property psp, |
1360 | const union power_supply_propval *val) |
1361 | { |
1362 | struct anx7411_data *ctx = power_supply_get_drvdata(psy); |
1363 | int ret = 0; |
1364 | |
1365 | if (psp == POWER_SUPPLY_PROP_ONLINE) |
1366 | ctx->psy_online = val->intval; |
1367 | else |
1368 | ret = -EINVAL; |
1369 | |
1370 | power_supply_changed(psy: ctx->psy); |
1371 | return ret; |
1372 | } |
1373 | |
1374 | static int anx7411_psy_prop_writeable(struct power_supply *psy, |
1375 | enum power_supply_property psp) |
1376 | { |
1377 | return psp == POWER_SUPPLY_PROP_ONLINE; |
1378 | } |
1379 | |
1380 | static int anx7411_psy_get_prop(struct power_supply *psy, |
1381 | enum power_supply_property psp, |
1382 | union power_supply_propval *val) |
1383 | { |
1384 | struct anx7411_data *ctx = power_supply_get_drvdata(psy); |
1385 | int ret = 0; |
1386 | |
1387 | switch (psp) { |
1388 | case POWER_SUPPLY_PROP_USB_TYPE: |
1389 | val->intval = ctx->usb_type; |
1390 | break; |
1391 | case POWER_SUPPLY_PROP_ONLINE: |
1392 | val->intval = ctx->psy_online; |
1393 | break; |
1394 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: |
1395 | case POWER_SUPPLY_PROP_VOLTAGE_MIN: |
1396 | case POWER_SUPPLY_PROP_VOLTAGE_MAX: |
1397 | val->intval = (ctx->psy_online) ? |
1398 | ctx->typec.request_voltage * 1000 : 0; |
1399 | break; |
1400 | case POWER_SUPPLY_PROP_CURRENT_NOW: |
1401 | case POWER_SUPPLY_PROP_CURRENT_MAX: |
1402 | val->intval = (ctx->psy_online) ? |
1403 | ctx->typec.request_current * 1000 : 0; |
1404 | break; |
1405 | default: |
1406 | ret = -EINVAL; |
1407 | break; |
1408 | } |
1409 | return ret; |
1410 | } |
1411 | |
1412 | static int anx7411_psy_register(struct anx7411_data *ctx) |
1413 | { |
1414 | struct power_supply_desc *psy_desc = &ctx->psy_desc; |
1415 | struct power_supply_config psy_cfg = {}; |
1416 | char *psy_name; |
1417 | |
1418 | psy_name = devm_kasprintf(dev: ctx->dev, GFP_KERNEL, fmt: "anx7411-source-psy-%s" , |
1419 | dev_name(dev: ctx->dev)); |
1420 | if (!psy_name) |
1421 | return -ENOMEM; |
1422 | |
1423 | psy_desc->name = psy_name; |
1424 | psy_desc->type = POWER_SUPPLY_TYPE_USB; |
1425 | psy_desc->usb_types = anx7411_psy_usb_types; |
1426 | psy_desc->num_usb_types = ARRAY_SIZE(anx7411_psy_usb_types); |
1427 | psy_desc->properties = anx7411_psy_props; |
1428 | psy_desc->num_properties = ARRAY_SIZE(anx7411_psy_props); |
1429 | |
1430 | psy_desc->get_property = anx7411_psy_get_prop; |
1431 | psy_desc->set_property = anx7411_psy_set_prop; |
1432 | psy_desc->property_is_writeable = anx7411_psy_prop_writeable; |
1433 | |
1434 | ctx->usb_type = POWER_SUPPLY_USB_TYPE_C; |
1435 | ctx->psy = devm_power_supply_register(parent: ctx->dev, desc: psy_desc, cfg: &psy_cfg); |
1436 | |
1437 | if (IS_ERR(ptr: ctx->psy)) |
1438 | dev_warn(ctx->dev, "unable to register psy\n" ); |
1439 | |
1440 | return PTR_ERR_OR_ZERO(ptr: ctx->psy); |
1441 | } |
1442 | |
1443 | static int anx7411_i2c_probe(struct i2c_client *client) |
1444 | { |
1445 | struct anx7411_data *plat; |
1446 | struct device *dev = &client->dev; |
1447 | int ret; |
1448 | |
1449 | if (!i2c_check_functionality(adap: client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) |
1450 | return -ENODEV; |
1451 | |
1452 | plat = devm_kzalloc(dev, size: sizeof(*plat), GFP_KERNEL); |
1453 | if (!plat) |
1454 | return -ENOMEM; |
1455 | |
1456 | plat->tcpc_client = client; |
1457 | i2c_set_clientdata(client, data: plat); |
1458 | |
1459 | mutex_init(&plat->lock); |
1460 | |
1461 | ret = anx7411_register_i2c_dummy_clients(ctx: plat, client); |
1462 | if (ret) { |
1463 | dev_err(dev, "fail to reserve I2C bus\n" ); |
1464 | return ret; |
1465 | } |
1466 | |
1467 | ret = anx7411_typec_switch_probe(ctx: plat, dev); |
1468 | if (ret) { |
1469 | dev_err(dev, "fail to probe typec switch\n" ); |
1470 | goto free_i2c_dummy; |
1471 | } |
1472 | |
1473 | ret = anx7411_typec_port_probe(ctx: plat, dev); |
1474 | if (ret) { |
1475 | dev_err(dev, "fail to probe typec property.\n" ); |
1476 | ret = -ENODEV; |
1477 | goto free_typec_switch; |
1478 | } |
1479 | |
1480 | plat->intp_irq = client->irq; |
1481 | if (!client->irq) |
1482 | anx7411_get_gpio_irq(ctx: plat); |
1483 | |
1484 | if (!plat->intp_irq) { |
1485 | dev_err(dev, "fail to get interrupt IRQ\n" ); |
1486 | ret = -EINVAL; |
1487 | goto free_typec_port; |
1488 | } |
1489 | |
1490 | plat->dev = dev; |
1491 | plat->psy_online = ANX7411_PSY_OFFLINE; |
1492 | ret = anx7411_psy_register(ctx: plat); |
1493 | if (ret) { |
1494 | dev_err(dev, "register psy\n" ); |
1495 | goto free_typec_port; |
1496 | } |
1497 | |
1498 | INIT_WORK(&plat->work, anx7411_work_func); |
1499 | plat->workqueue = alloc_workqueue(fmt: "anx7411_work" , |
1500 | flags: WQ_FREEZABLE | |
1501 | WQ_MEM_RECLAIM, |
1502 | max_active: 1); |
1503 | if (!plat->workqueue) { |
1504 | dev_err(dev, "fail to create work queue\n" ); |
1505 | ret = -ENOMEM; |
1506 | goto free_typec_port; |
1507 | } |
1508 | |
1509 | ret = devm_request_threaded_irq(dev, irq: plat->intp_irq, |
1510 | NULL, thread_fn: anx7411_intr_isr, |
1511 | IRQF_TRIGGER_FALLING | |
1512 | IRQF_ONESHOT, |
1513 | devname: "anx7411-intp" , dev_id: plat); |
1514 | if (ret) { |
1515 | dev_err(dev, "fail to request irq\n" ); |
1516 | goto free_wq; |
1517 | } |
1518 | |
1519 | if (anx7411_typec_check_connection(ctx: plat)) |
1520 | dev_err(dev, "check status\n" ); |
1521 | |
1522 | pm_runtime_enable(dev); |
1523 | |
1524 | return 0; |
1525 | |
1526 | free_wq: |
1527 | destroy_workqueue(wq: plat->workqueue); |
1528 | |
1529 | free_typec_port: |
1530 | typec_unregister_port(port: plat->typec.port); |
1531 | anx7411_port_unregister_altmodes(adev: plat->typec.port_amode); |
1532 | |
1533 | free_typec_switch: |
1534 | anx7411_unregister_switch(ctx: plat); |
1535 | anx7411_unregister_mux(ctx: plat); |
1536 | |
1537 | free_i2c_dummy: |
1538 | i2c_unregister_device(client: plat->spi_client); |
1539 | |
1540 | return ret; |
1541 | } |
1542 | |
1543 | static void anx7411_i2c_remove(struct i2c_client *client) |
1544 | { |
1545 | struct anx7411_data *plat = i2c_get_clientdata(client); |
1546 | |
1547 | anx7411_partner_unregister_altmode(ctx: plat); |
1548 | anx7411_unregister_partner(ctx: plat); |
1549 | |
1550 | if (plat->workqueue) |
1551 | destroy_workqueue(wq: plat->workqueue); |
1552 | |
1553 | i2c_unregister_device(client: plat->spi_client); |
1554 | |
1555 | if (plat->typec.role_sw) |
1556 | usb_role_switch_put(sw: plat->typec.role_sw); |
1557 | |
1558 | anx7411_unregister_mux(ctx: plat); |
1559 | |
1560 | anx7411_unregister_switch(ctx: plat); |
1561 | |
1562 | if (plat->typec.port) |
1563 | typec_unregister_port(port: plat->typec.port); |
1564 | |
1565 | anx7411_port_unregister_altmodes(adev: plat->typec.port_amode); |
1566 | } |
1567 | |
1568 | static const struct i2c_device_id anx7411_id[] = { |
1569 | {"anx7411" , 0}, |
1570 | {} |
1571 | }; |
1572 | |
1573 | MODULE_DEVICE_TABLE(i2c, anx7411_id); |
1574 | |
1575 | static const struct of_device_id anx_match_table[] = { |
1576 | {.compatible = "analogix,anx7411" ,}, |
1577 | {}, |
1578 | }; |
1579 | |
1580 | static struct i2c_driver anx7411_driver = { |
1581 | .driver = { |
1582 | .name = "anx7411" , |
1583 | .of_match_table = anx_match_table, |
1584 | .pm = &anx7411_pm_ops, |
1585 | }, |
1586 | .probe = anx7411_i2c_probe, |
1587 | .remove = anx7411_i2c_remove, |
1588 | |
1589 | .id_table = anx7411_id, |
1590 | }; |
1591 | |
1592 | module_i2c_driver(anx7411_driver); |
1593 | |
1594 | MODULE_DESCRIPTION("Anx7411 USB Type-C PD driver" ); |
1595 | MODULE_AUTHOR("Xin Ji <xji@analogixsemi.com>" ); |
1596 | MODULE_LICENSE("GPL" ); |
1597 | MODULE_VERSION("0.1.5" ); |
1598 | |