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 *)&reg;
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