1 /*
2 * Copyright 2024 Google LLC
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <zephyr/device.h>
7 #include <zephyr/logging/log.h>
8 #include <zephyr/drivers/gpio.h>
9 #include <zephyr/drivers/i2c.h>
10 #include <zephyr/drivers/usb_c/tcpci_priv.h>
11 #include <zephyr/usb_c/usbc.h>
12 #include <zephyr/usb_c/tcpci.h>
13 #include <zephyr/shell/shell.h>
14 #include "ps8xxx_priv.h"
15
16 #define DT_DRV_COMPAT parade_ps8xxx
17 LOG_MODULE_REGISTER(ps8xxx, CONFIG_USBC_LOG_LEVEL);
18
19 /** Data structure for device instances */
20 struct ps8xxx_data {
21 /** Device structure used to retrieve it in k_work functions */
22 const struct device *const dev;
23 /** Delayable work item for chip initialization */
24 struct k_work_delayable init_dwork;
25 /** Initialization retries counter */
26 int init_retries;
27 /** Boolean value if chip was successfully initialized */
28 bool initialized;
29
30 /** Callback for alert GPIO */
31 struct gpio_callback alert_cb;
32 /** Work item for alert handling out of interrupt context */
33 struct k_work alert_work;
34 /** Boolean value if there is a message pending */
35 bool msg_pending;
36
37 /** Alert handler set by USB-C stack */
38 tcpc_alert_handler_cb_t alert_handler;
39 /** Alert handler data set by USB-C stack */
40 void *alert_handler_data;
41
42 /** VCONN discharge callback set by USB-C stack */
43 tcpc_vconn_discharge_cb_t vconn_discharge_cb;
44 /** VCONN discharge callback data set by USB-C stack */
45 tcpc_vconn_control_cb_t vconn_cb;
46 /** Polarity of CC lines for PD and VCONN */
47 enum tc_cc_polarity cc_polarity;
48
49 /** Boolean value if there was a change on the CC lines since last check */
50 bool cc_changed;
51 /** State of CC1 line */
52 enum tc_cc_voltage_state cc1;
53 /** State of CC2 line */
54 enum tc_cc_voltage_state cc2;
55 };
56
57 /** Configuration structure for device instances */
58 struct ps8xxx_cfg {
59 /** I2C bus and address used for communication */
60 const struct i2c_dt_spec bus;
61 /** GPIO specification for alert pin */
62 const struct gpio_dt_spec alert_gpio;
63 /** Maximum number of packet retransmissions done by TCPC */
64 const uint8_t transmit_retries;
65 };
66
tcpci_init_alert_mask(const struct device * dev)67 static int tcpci_init_alert_mask(const struct device *dev)
68 {
69 const struct ps8xxx_cfg *cfg = dev->config;
70
71 uint16_t mask = TCPC_REG_ALERT_TX_COMPLETE | TCPC_REG_ALERT_RX_STATUS |
72 TCPC_REG_ALERT_RX_HARD_RST | TCPC_REG_ALERT_CC_STATUS |
73 TCPC_REG_ALERT_FAULT | TCPC_REG_ALERT_POWER_STATUS;
74
75 return tcpci_tcpm_mask_status_register(&cfg->bus, TCPC_ALERT_STATUS, mask);
76 }
77
ps8xxx_tcpc_init(const struct device * dev)78 static int ps8xxx_tcpc_init(const struct device *dev)
79 {
80 struct ps8xxx_data *data = dev->data;
81
82 if (!data->initialized) {
83 if (data->init_retries > CONFIG_USBC_TCPC_PS8XXX_INIT_RETRIES) {
84 LOG_ERR("TCPC was not initialized correctly");
85 return -EIO;
86 }
87
88 return -EAGAIN;
89 }
90
91 LOG_INF("PS8xxx TCPC initialized");
92 return 0;
93 }
94
ps8xxx_tcpc_get_cc(const struct device * dev,enum tc_cc_voltage_state * cc1,enum tc_cc_voltage_state * cc2)95 int ps8xxx_tcpc_get_cc(const struct device *dev, enum tc_cc_voltage_state *cc1,
96 enum tc_cc_voltage_state *cc2)
97 {
98 const struct ps8xxx_cfg *cfg = dev->config;
99 struct ps8xxx_data *data = dev->data;
100 int ret;
101
102 if (!data->initialized) {
103 return -EIO;
104 }
105
106 if (IS_ENABLED(CONFIG_USBC_CSM_SINK_ONLY) && !data->cc_changed) {
107 *cc1 = data->cc1;
108 *cc2 = data->cc2;
109
110 return 0;
111 }
112
113 data->cc_changed = false;
114
115 ret = tcpci_tcpm_get_cc(&cfg->bus, cc1, cc2);
116
117 if (IS_ENABLED(CONFIG_USBC_CSM_SINK_ONLY) || *cc1 != data->cc1 || *cc2 != data->cc2) {
118 LOG_DBG("CC changed values: %d->%d, %d->%d", data->cc1, *cc1, data->cc2, *cc2);
119 data->cc1 = *cc1;
120 data->cc2 = *cc2;
121 }
122
123 return ret;
124 }
125
ps8xxx_tcpc_select_rp_value(const struct device * dev,enum tc_rp_value rp)126 int ps8xxx_tcpc_select_rp_value(const struct device *dev, enum tc_rp_value rp)
127 {
128 const struct ps8xxx_cfg *cfg = dev->config;
129 struct ps8xxx_data *data = dev->data;
130
131 data->cc_changed = true;
132
133 return tcpci_tcpm_select_rp_value(&cfg->bus, rp);
134 }
135
ps8xxx_tcpc_get_rp_value(const struct device * dev,enum tc_rp_value * rp)136 int ps8xxx_tcpc_get_rp_value(const struct device *dev, enum tc_rp_value *rp)
137 {
138 const struct ps8xxx_cfg *cfg = dev->config;
139
140 return tcpci_tcpm_get_rp_value(&cfg->bus, rp);
141 }
142
ps8xxx_tcpc_set_cc(const struct device * dev,enum tc_cc_pull pull)143 int ps8xxx_tcpc_set_cc(const struct device *dev, enum tc_cc_pull pull)
144 {
145 const struct ps8xxx_cfg *cfg = dev->config;
146 struct ps8xxx_data *data = dev->data;
147
148 if (!data->initialized) {
149 return -EIO;
150 }
151
152 data->cc_changed = true;
153
154 return tcpci_tcpm_set_cc(&cfg->bus, pull);
155 }
156
ps8xxx_tcpc_set_vconn_discharge_cb(const struct device * dev,tcpc_vconn_discharge_cb_t cb)157 void ps8xxx_tcpc_set_vconn_discharge_cb(const struct device *dev, tcpc_vconn_discharge_cb_t cb)
158 {
159 struct ps8xxx_data *data = dev->data;
160
161 data->vconn_discharge_cb = cb;
162 }
163
ps8xxx_tcpc_set_vconn_cb(const struct device * dev,tcpc_vconn_control_cb_t vconn_cb)164 void ps8xxx_tcpc_set_vconn_cb(const struct device *dev, tcpc_vconn_control_cb_t vconn_cb)
165 {
166 struct ps8xxx_data *data = dev->data;
167
168 data->vconn_cb = vconn_cb;
169 }
170
ps8xxx_tcpc_vconn_discharge(const struct device * dev,bool enable)171 int ps8xxx_tcpc_vconn_discharge(const struct device *dev, bool enable)
172 {
173 const struct ps8xxx_cfg *cfg = dev->config;
174
175 return tcpci_update_reg8(&cfg->bus, TCPC_REG_POWER_CTRL,
176 TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT,
177 (enable) ? TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT : 0);
178 }
179
ps8xxx_tcpc_set_vconn(const struct device * dev,bool enable)180 int ps8xxx_tcpc_set_vconn(const struct device *dev, bool enable)
181 {
182 const struct ps8xxx_cfg *cfg = dev->config;
183 struct ps8xxx_data *data = dev->data;
184 int ret;
185
186 if (!data->initialized) {
187 return -EIO;
188 }
189
190 data->cc_changed = true;
191 ret = tcpci_tcpm_set_vconn(&cfg->bus, enable);
192
193 if (ret != 0) {
194 return ret;
195 }
196
197 if (data->vconn_cb != NULL) {
198 ret = data->vconn_cb(dev, data->cc_polarity, enable);
199 }
200
201 return ret;
202 }
203
ps8xxx_tcpc_set_roles(const struct device * dev,enum tc_power_role power_role,enum tc_data_role data_role)204 int ps8xxx_tcpc_set_roles(const struct device *dev, enum tc_power_role power_role,
205 enum tc_data_role data_role)
206 {
207 const struct ps8xxx_cfg *cfg = dev->config;
208
209 return tcpci_tcpm_set_roles(&cfg->bus, PD_REV30, power_role, data_role);
210 }
211
ps8xxx_tcpc_get_rx_pending_msg(const struct device * dev,struct pd_msg * msg)212 int ps8xxx_tcpc_get_rx_pending_msg(const struct device *dev, struct pd_msg *msg)
213 {
214 const struct ps8xxx_cfg *cfg = dev->config;
215 struct ps8xxx_data *data = dev->data;
216 struct i2c_msg buf[5];
217 uint8_t msg_len = 0;
218 uint8_t unused;
219 int buf_count;
220 int reg = TCPC_REG_RX_BUFFER;
221 int ret;
222
223 if (!data->msg_pending) {
224 return -ENODATA;
225 }
226
227 if (msg == NULL) {
228 return 0;
229 }
230
231 data->msg_pending = false;
232
233 buf[0].buf = (uint8_t *)®
234 buf[0].len = 1;
235 buf[0].flags = I2C_MSG_WRITE;
236
237 buf[1].buf = &msg_len;
238 buf[1].len = 1;
239 buf[1].flags = I2C_MSG_RESTART | I2C_MSG_READ | I2C_MSG_STOP;
240 ret = i2c_transfer(cfg->bus.bus, buf, 2, cfg->bus.addr);
241
242 if (msg_len <= 1) {
243 return 0;
244 }
245
246 buf[1].buf = &unused;
247 buf[1].len = 1;
248 buf[1].flags = I2C_MSG_RESTART | I2C_MSG_READ;
249
250 buf[2].buf = (uint8_t *)&msg->type;
251 buf[2].len = 1;
252 buf[2].flags = I2C_MSG_RESTART | I2C_MSG_READ;
253
254 msg->header.raw_value = 0;
255 buf[3].buf = (uint8_t *)&msg->header.raw_value;
256 buf[3].len = 2;
257 buf[3].flags = I2C_MSG_RESTART | I2C_MSG_READ;
258
259 if (msg_len > 3) {
260 buf[4].buf = msg->data;
261 buf[4].len = msg_len - 3;
262 buf[4].flags = I2C_MSG_RESTART | I2C_MSG_READ | I2C_MSG_STOP;
263 buf_count = 5;
264 } else if (msg_len == 3) {
265 buf[3].flags |= I2C_MSG_STOP;
266 buf_count = 4;
267 } else {
268 buf[2].flags |= I2C_MSG_STOP;
269 buf_count = 3;
270 }
271
272 ret = i2c_transfer(cfg->bus.bus, buf, buf_count, cfg->bus.addr);
273 if (ret != 0) {
274 LOG_ERR("I2C transfer error: %d", ret);
275 } else {
276 msg->len = (msg_len > 3) ? msg_len - 3 : 0;
277 ret = sizeof(msg->header.raw_value) + msg->len;
278 }
279
280 tcpci_write_reg16(&cfg->bus, TCPC_REG_ALERT, TCPC_REG_ALERT_RX_STATUS);
281 return ret;
282 }
283
ps8xxx_tcpc_set_rx_enable(const struct device * dev,bool enable)284 int ps8xxx_tcpc_set_rx_enable(const struct device *dev, bool enable)
285 {
286 const struct ps8xxx_cfg *cfg = dev->config;
287 int detect_sop_en = enable ? TCPC_REG_RX_DETECT_SOP_HRST_MASK : 0;
288
289 return tcpci_tcpm_set_rx_type(&cfg->bus, detect_sop_en);
290 }
291
ps8xxx_tcpc_set_cc_polarity(const struct device * dev,enum tc_cc_polarity polarity)292 int ps8xxx_tcpc_set_cc_polarity(const struct device *dev, enum tc_cc_polarity polarity)
293 {
294 const struct ps8xxx_cfg *cfg = dev->config;
295 struct ps8xxx_data *data = dev->data;
296 int ret;
297
298 if (!data->initialized) {
299 return -EIO;
300 }
301
302 ret = tcpci_tcpm_set_cc_polarity(&cfg->bus, polarity);
303
304 if (ret != 0) {
305 return ret;
306 }
307
308 data->cc_changed = true;
309 data->cc_polarity = polarity;
310 return 0;
311 }
312
ps8xxx_tcpc_transmit_data(const struct device * dev,struct pd_msg * msg)313 int ps8xxx_tcpc_transmit_data(const struct device *dev, struct pd_msg *msg)
314 {
315 const struct ps8xxx_cfg *cfg = dev->config;
316
317 return tcpci_tcpm_transmit_data(&cfg->bus, msg, cfg->transmit_retries);
318 }
319
ps8xxx_tcpc_dump_std_reg(const struct device * dev)320 int ps8xxx_tcpc_dump_std_reg(const struct device *dev)
321 {
322 const struct ps8xxx_cfg *cfg = dev->config;
323
324 LOG_INF("TCPC %s:%s registers:", cfg->bus.bus->name, dev->name);
325
326 return tcpci_tcpm_dump_std_reg(&cfg->bus);
327 }
328
ps8xxx_tcpc_alert_handler_cb(const struct device * dev,void * data,enum tcpc_alert alert)329 void ps8xxx_tcpc_alert_handler_cb(const struct device *dev, void *data, enum tcpc_alert alert)
330 {
331 }
332
ps8xxx_tcpc_get_status_register(const struct device * dev,enum tcpc_status_reg reg,uint32_t * status)333 int ps8xxx_tcpc_get_status_register(const struct device *dev, enum tcpc_status_reg reg,
334 uint32_t *status)
335 {
336 return -ENOSYS;
337 }
338
ps8xxx_tcpc_clear_status_register(const struct device * dev,enum tcpc_status_reg reg,uint32_t mask)339 int ps8xxx_tcpc_clear_status_register(const struct device *dev, enum tcpc_status_reg reg,
340 uint32_t mask)
341 {
342 return -ENOSYS;
343 }
344
ps8xxx_tcpc_mask_status_register(const struct device * dev,enum tcpc_status_reg reg,uint32_t mask)345 int ps8xxx_tcpc_mask_status_register(const struct device *dev, enum tcpc_status_reg reg,
346 uint32_t mask)
347 {
348 return -ENOSYS;
349 }
350
ps8xxx_tcpc_set_debug_accessory(const struct device * dev,bool enable)351 int ps8xxx_tcpc_set_debug_accessory(const struct device *dev, bool enable)
352 {
353 return -ENOSYS;
354 }
355
ps8xxx_tcpc_set_debug_detach(const struct device * dev)356 int ps8xxx_tcpc_set_debug_detach(const struct device *dev)
357 {
358 return -ENOSYS;
359 }
360
ps8xxx_tcpc_set_drp_toggle(const struct device * dev,bool enable)361 int ps8xxx_tcpc_set_drp_toggle(const struct device *dev, bool enable)
362 {
363 return -ENOSYS;
364 }
365
ps8xxx_tcpc_get_snk_ctrl(const struct device * dev)366 int ps8xxx_tcpc_get_snk_ctrl(const struct device *dev)
367 {
368 return -ENOSYS;
369 }
370
ps8xxx_tcpc_set_snk_ctrl(const struct device * dev,bool enable)371 int ps8xxx_tcpc_set_snk_ctrl(const struct device *dev, bool enable)
372 {
373 const struct ps8xxx_cfg *cfg = dev->config;
374 uint8_t cmd = (enable) ? TCPC_REG_COMMAND_SNK_CTRL_HIGH : TCPC_REG_COMMAND_SNK_CTRL_LOW;
375
376 return tcpci_write_reg8(&cfg->bus, TCPC_REG_COMMAND, cmd);
377 }
378
ps8xxx_tcpc_get_src_ctrl(const struct device * dev)379 int ps8xxx_tcpc_get_src_ctrl(const struct device *dev)
380 {
381 return -ENOSYS;
382 }
383
ps8xxx_tcpc_set_src_ctrl(const struct device * dev,bool enable)384 int ps8xxx_tcpc_set_src_ctrl(const struct device *dev, bool enable)
385 {
386 const struct ps8xxx_cfg *cfg = dev->config;
387 uint8_t cmd = (enable) ? TCPC_REG_COMMAND_SRC_CTRL_DEF : TCPC_REG_COMMAND_SRC_CTRL_LOW;
388
389 return tcpci_write_reg8(&cfg->bus, TCPC_REG_COMMAND, cmd);
390 }
391
ps8xxx_tcpc_get_chip_info(const struct device * dev,struct tcpc_chip_info * chip_info)392 int ps8xxx_tcpc_get_chip_info(const struct device *dev, struct tcpc_chip_info *chip_info)
393 {
394 const struct ps8xxx_cfg *cfg = dev->config;
395 int ret = 0;
396
397 if (chip_info == NULL) {
398 return -EIO;
399 }
400
401 ret = tcpci_tcpm_get_chip_info(&cfg->bus, chip_info);
402
403 /* Vendor specific register for PS8815 model only */
404 if (chip_info->product_id == PS8815_PRODUCT_ID) {
405 uint8_t fw_ver;
406
407 ret |= tcpci_read_reg8(&cfg->bus, PS8815_REG_FW_VER, &fw_ver);
408 chip_info->fw_version_number = fw_ver;
409 } else {
410 chip_info->fw_version_number = 0;
411 }
412
413 chip_info->min_req_fw_version_number = 0;
414
415 return ret;
416 }
417
ps8xxx_tcpc_set_low_power_mode(const struct device * dev,bool enable)418 int ps8xxx_tcpc_set_low_power_mode(const struct device *dev, bool enable)
419 {
420 const struct ps8xxx_cfg *cfg = dev->config;
421
422 return tcpci_write_reg8(&cfg->bus, TCPC_REG_COMMAND, TCPC_REG_COMMAND_I2CIDLE);
423 }
424
ps8xxx_tcpc_sop_prime_enable(const struct device * dev,bool enable)425 int ps8xxx_tcpc_sop_prime_enable(const struct device *dev, bool enable)
426 {
427 return -ENOSYS;
428 }
429
ps8xxx_tcpc_set_bist_test_mode(const struct device * dev,bool enable)430 int ps8xxx_tcpc_set_bist_test_mode(const struct device *dev, bool enable)
431 {
432 return -ENOSYS;
433 }
434
ps8xxx_tcpc_set_alert_handler_cb(const struct device * dev,tcpc_alert_handler_cb_t handler,void * handler_data)435 int ps8xxx_tcpc_set_alert_handler_cb(const struct device *dev, tcpc_alert_handler_cb_t handler,
436 void *handler_data)
437 {
438 struct ps8xxx_data *data = dev->data;
439
440 if (data->alert_handler == handler && data->alert_handler_data == handler_data) {
441 return 0;
442 }
443
444 data->alert_handler = handler;
445 data->alert_handler_data = handler_data;
446
447 return 0;
448 }
449
450 /* Functions not assigned to the driver API but used by device */
451
452 static DEVICE_API(tcpc, ps8xxx_driver_api) = {
453 .init = ps8xxx_tcpc_init,
454 .get_cc = ps8xxx_tcpc_get_cc,
455 .select_rp_value = ps8xxx_tcpc_select_rp_value,
456 .get_rp_value = ps8xxx_tcpc_get_rp_value,
457 .set_cc = ps8xxx_tcpc_set_cc,
458 .set_vconn_discharge_cb = ps8xxx_tcpc_set_vconn_discharge_cb,
459 .set_vconn_cb = ps8xxx_tcpc_set_vconn_cb,
460 .vconn_discharge = ps8xxx_tcpc_vconn_discharge,
461 .set_vconn = ps8xxx_tcpc_set_vconn,
462 .set_roles = ps8xxx_tcpc_set_roles,
463 .get_rx_pending_msg = ps8xxx_tcpc_get_rx_pending_msg,
464 .set_rx_enable = ps8xxx_tcpc_set_rx_enable,
465 .set_cc_polarity = ps8xxx_tcpc_set_cc_polarity,
466 .transmit_data = ps8xxx_tcpc_transmit_data,
467 .dump_std_reg = ps8xxx_tcpc_dump_std_reg,
468 .alert_handler_cb = ps8xxx_tcpc_alert_handler_cb,
469 .get_status_register = ps8xxx_tcpc_get_status_register,
470 .clear_status_register = ps8xxx_tcpc_clear_status_register,
471 .mask_status_register = ps8xxx_tcpc_mask_status_register,
472 .set_debug_accessory = ps8xxx_tcpc_set_debug_accessory,
473 .set_debug_detach = ps8xxx_tcpc_set_debug_detach,
474 .set_drp_toggle = ps8xxx_tcpc_set_drp_toggle,
475 .get_snk_ctrl = ps8xxx_tcpc_get_snk_ctrl,
476 .set_snk_ctrl = ps8xxx_tcpc_set_snk_ctrl,
477 .get_src_ctrl = ps8xxx_tcpc_get_src_ctrl,
478 .set_src_ctrl = ps8xxx_tcpc_set_src_ctrl,
479 .get_chip_info = ps8xxx_tcpc_get_chip_info,
480 .set_low_power_mode = ps8xxx_tcpc_set_low_power_mode,
481 .sop_prime_enable = ps8xxx_tcpc_sop_prime_enable,
482 .set_bist_test_mode = ps8xxx_tcpc_set_bist_test_mode,
483 .set_alert_handler_cb = ps8xxx_tcpc_set_alert_handler_cb,
484 };
485
ps8xxx_alert_cb(const struct device * port,struct gpio_callback * cb,gpio_port_pins_t pins)486 void ps8xxx_alert_cb(const struct device *port, struct gpio_callback *cb, gpio_port_pins_t pins)
487 {
488 struct ps8xxx_data *data = CONTAINER_OF(cb, struct ps8xxx_data, alert_cb);
489
490 k_work_submit(&data->alert_work);
491 }
492
ps8xxx_alert_work_cb(struct k_work * work)493 void ps8xxx_alert_work_cb(struct k_work *work)
494 {
495 struct ps8xxx_data *data = CONTAINER_OF(work, struct ps8xxx_data, alert_work);
496 const struct device *dev = data->dev;
497 const struct ps8xxx_cfg *cfg = dev->config;
498 uint16_t alert_reg = 0;
499 uint16_t clear_flags = 0;
500
501 if (!data->initialized) {
502 return;
503 }
504
505 tcpci_tcpm_get_status_register(&cfg->bus, TCPC_ALERT_STATUS, &alert_reg);
506
507 while (alert_reg != 0) {
508 enum tcpc_alert alert_type = tcpci_alert_reg_to_enum(alert_reg);
509
510 if (alert_type == TCPC_ALERT_HARD_RESET_RECEIVED) {
511 LOG_DBG("PS8xxx hard rst received");
512 tcpci_init_alert_mask(dev);
513 data->cc_changed = true;
514 } else if (alert_type == TCPC_ALERT_FAULT_STATUS) {
515 uint8_t fault;
516
517 tcpci_tcpm_get_status_register(&cfg->bus, TCPC_FAULT_STATUS,
518 (uint16_t *)&fault);
519 tcpci_tcpm_clear_status_register(&cfg->bus, TCPC_FAULT_STATUS,
520 (uint16_t)fault);
521
522 LOG_DBG("PS8xxx fault: %02x", fault);
523 } else if (alert_type == TCPC_ALERT_EXTENDED_STATUS) {
524 uint8_t ext_status;
525
526 tcpci_tcpm_get_status_register(&cfg->bus, TCPC_EXTENDED_STATUS,
527 (uint16_t *)&ext_status);
528 tcpci_tcpm_clear_status_register(&cfg->bus, TCPC_EXTENDED_STATUS,
529 (uint16_t)ext_status);
530
531 data->cc_changed = true;
532 LOG_DBG("PS8xxx ext status: %02x", ext_status);
533 } else if (alert_type == TCPC_ALERT_POWER_STATUS) {
534 uint8_t pwr_status;
535
536 tcpci_tcpm_get_status_register(&cfg->bus, TCPC_POWER_STATUS,
537 (uint16_t *)&pwr_status);
538
539 LOG_DBG("PS8xxx power status: %02x", pwr_status);
540 } else if (alert_type == TCPC_ALERT_EXTENDED) {
541 uint8_t alert_status;
542
543 tcpci_tcpm_get_status_register(&cfg->bus, TCPC_EXTENDED_ALERT_STATUS,
544 (uint16_t *)&alert_status);
545 tcpci_tcpm_clear_status_register(&cfg->bus, TCPC_EXTENDED_ALERT_STATUS,
546 (uint16_t)alert_status);
547
548 LOG_DBG("PS8xxx ext alert: %02x", alert_status);
549 } else if (alert_type == TCPC_ALERT_MSG_STATUS) {
550 data->msg_pending = true;
551 } else if (alert_type == TCPC_ALERT_CC_STATUS) {
552 data->cc_changed = true;
553 }
554
555 if (data->alert_handler != NULL) {
556 data->alert_handler(dev, data->alert_handler_data, alert_type);
557 }
558
559 clear_flags |= BIT(alert_type);
560 alert_reg &= ~BIT(alert_type);
561 }
562
563 tcpci_tcpm_clear_status_register(&cfg->bus, TCPC_ALERT_STATUS, clear_flags);
564 tcpci_tcpm_get_status_register(&cfg->bus, TCPC_ALERT_STATUS, &alert_reg);
565
566 if (alert_reg != 0) {
567 k_work_submit(work);
568 }
569 }
570
ps8xxx_init_work_cb(struct k_work * work)571 void ps8xxx_init_work_cb(struct k_work *work)
572 {
573 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
574 struct ps8xxx_data *data = CONTAINER_OF(dwork, struct ps8xxx_data, init_dwork);
575
576 const struct ps8xxx_cfg *cfg = data->dev->config;
577 uint8_t power_reg = 0;
578 struct tcpc_chip_info chip_info;
579 int ret;
580
581 LOG_INF("Initializing PS8xxx chip: %s", data->dev->name);
582 ret = tcpci_tcpm_get_status_register(&cfg->bus, TCPC_POWER_STATUS, (uint16_t *)&power_reg);
583 if (ret != 0 || (power_reg & TCPC_REG_POWER_STATUS_UNINIT)) {
584 data->init_retries++;
585
586 if (data->init_retries > CONFIG_USBC_TCPC_PS8XXX_INIT_RETRIES) {
587 LOG_ERR("Chip didn't respond");
588 return;
589 }
590
591 LOG_DBG("Postpone chip initialization %d", data->init_retries);
592 k_work_schedule(&data->init_dwork, K_MSEC(CONFIG_USBC_TCPC_PS8XXX_INIT_DELAY));
593
594 return;
595 }
596
597 ps8xxx_tcpc_get_chip_info(data->dev, &chip_info);
598 LOG_INF("Initialized chip is: %04x:%04x:%04x", chip_info.vendor_id, chip_info.product_id,
599 chip_info.device_id);
600
601 /* Initialize alert interrupt */
602 gpio_pin_configure_dt(&cfg->alert_gpio, GPIO_INPUT);
603
604 gpio_init_callback(&data->alert_cb, ps8xxx_alert_cb, BIT(cfg->alert_gpio.pin));
605 gpio_add_callback(cfg->alert_gpio.port, &data->alert_cb);
606 gpio_pin_interrupt_configure_dt(&cfg->alert_gpio, GPIO_INT_EDGE_TO_ACTIVE);
607
608 tcpci_init_alert_mask(data->dev);
609 data->initialized = true;
610
611 /* Disable the vconn and open CC lines to reinitialize the communication with partner */
612 ps8xxx_tcpc_set_vconn(data->dev, false);
613 ps8xxx_tcpc_set_cc(data->dev, TC_CC_OPEN);
614
615 /* Check and clear any alert set after initialization */
616 k_work_submit(&data->alert_work);
617 }
618
ps8xxx_dev_init(const struct device * dev)619 static int ps8xxx_dev_init(const struct device *dev)
620 {
621 const struct ps8xxx_cfg *cfg = dev->config;
622 struct ps8xxx_data *data = dev->data;
623
624 if (!device_is_ready(cfg->bus.bus)) {
625 return -EIO;
626 }
627
628 k_work_init_delayable(&data->init_dwork, ps8xxx_init_work_cb);
629 k_work_schedule(&data->init_dwork, K_MSEC(CONFIG_USBC_TCPC_PS8XXX_INIT_DELAY));
630
631 k_work_init(&data->alert_work, ps8xxx_alert_work_cb);
632
633 return 0;
634 }
635
636 #define PS8XXX_DRIVER_DATA_INIT(node) \
637 { \
638 .dev = DEVICE_DT_GET(node), \
639 .init_retries = 0, \
640 .cc_changed = true, \
641 }
642
643 #define PS8XXX_DRIVER_CFG_INIT(node) \
644 { \
645 .bus = I2C_DT_SPEC_GET(node), \
646 .alert_gpio = GPIO_DT_SPEC_GET(node, irq_gpios), \
647 .transmit_retries = DT_PROP(node, transmit_retries), \
648 }
649
650 #define PS8XXX_DRIVER_INIT(inst) \
651 static struct ps8xxx_data drv_data_ps8xxx##inst = \
652 PS8XXX_DRIVER_DATA_INIT(DT_DRV_INST(inst)); \
653 static struct ps8xxx_cfg drv_cfg_ps8xxx##inst = PS8XXX_DRIVER_CFG_INIT(DT_DRV_INST(inst)); \
654 DEVICE_DT_INST_DEFINE(inst, &ps8xxx_dev_init, NULL, &drv_data_ps8xxx##inst, \
655 &drv_cfg_ps8xxx##inst, POST_KERNEL, CONFIG_USBC_TCPC_INIT_PRIORITY, \
656 &ps8xxx_driver_api);
657
658 DT_INST_FOREACH_STATUS_OKAY(PS8XXX_DRIVER_INIT)
659