1 /*
2 * Copyright 2022 The Chromium OS Authors
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT st_stm32_ucpd
8
9 #include <zephyr/logging/log.h>
10 LOG_MODULE_REGISTER(ucpd_stm32, CONFIG_USBC_LOG_LEVEL);
11
12 #include <zephyr/device.h>
13 #include <zephyr/sys/util.h>
14 #include <zephyr/kernel.h>
15 #include <soc.h>
16 #include <stddef.h>
17 #include <zephyr/math/ilog2.h>
18 #include <stm32_ll_system.h>
19 #include <zephyr/irq.h>
20
21 #include "ucpd_stm32_priv.h"
22
23 static void config_tcpc_irq(void);
24
25 /**
26 * @brief UCPD TX ORDSET values
27 */
28 static int ucpd_txorderset[] = {
29 /* SOP ORDSET */
30 LL_UCPD_ORDERED_SET_SOP,
31 /* SOP PRIME ORDSET */
32 LL_UCPD_ORDERED_SET_SOP1,
33 /* SOP PRIME PRIME ORDSET */
34 LL_UCPD_ORDERED_SET_SOP2,
35 /* SOP PRIME DEBUG ORDSET */
36 LL_UCPD_ORDERED_SET_SOP1_DEBUG,
37 /* SOP PRIME PRIME DEBUG ORDSET */
38 LL_UCPD_ORDERED_SET_SOP2_DEBUG,
39 /* HARD RESET ORDSET */
40 LL_UCPD_ORDERED_SET_HARD_RESET,
41 /* CABLE RESET ORDSET */
42 LL_UCPD_ORDERED_SET_CABLE_RESET,
43 };
44
45 /**
46 * @brief Test for a goodCRC message
47 *
48 * @retval true if message is goodCRC, else false
49 */
ucpd_msg_is_good_crc(union pd_header header)50 static bool ucpd_msg_is_good_crc(union pd_header header)
51 {
52 /*
53 * Good CRC is a control message (no data objects) with GOOD_CRC
54 * message type in the header.
55 */
56 return (header.number_of_data_objects == 0 &&
57 header.extended == 0 &&
58 header.message_type == PD_CTRL_GOOD_CRC);
59 }
60
61 #ifdef CONFIG_SOC_SERIES_STM32G0X
62 /**
63 * @brief Apply the UCPD CC1 and CC2 pin configurations.
64 *
65 * UCPDx_STROBE: UCPDx pull-down configuration strobe:
66 * when UCPDx is enabled, with CC1 and CC2 pin UCPD
67 * control bits configured: apply that configuration.
68 */
update_stm32g0x_cc_line(UCPD_TypeDef * ucpd_port)69 static void update_stm32g0x_cc_line(UCPD_TypeDef *ucpd_port)
70 {
71 if ((uint32_t)(ucpd_port) == UCPD1_BASE) {
72 SYSCFG->CFGR1 |= SYSCFG_CFGR1_UCPD1_STROBE_Msk;
73 } else {
74 SYSCFG->CFGR1 |= SYSCFG_CFGR1_UCPD2_STROBE_Msk;
75 }
76 }
77 #endif
78
79 /**
80 * @brief Transmits a data byte from the TX data buffer
81 */
ucpd_tx_data_byte(const struct device * dev)82 static void ucpd_tx_data_byte(const struct device *dev)
83 {
84 struct tcpc_data *data = dev->data;
85 const struct tcpc_config *const config = dev->config;
86 int index = data->ucpd_tx_active_buffer->msg_index++;
87
88 LL_UCPD_WriteData(config->ucpd_port,
89 data->ucpd_tx_active_buffer->data.msg[index]);
90 }
91
92 /**
93 * @brief Receives a data byte and store it in the RX data buffer
94 */
ucpd_rx_data_byte(const struct device * dev)95 static void ucpd_rx_data_byte(const struct device *dev)
96 {
97 struct tcpc_data *data = dev->data;
98 const struct tcpc_config *const config = dev->config;
99
100 if (data->ucpd_rx_byte_count < UCPD_BUF_LEN) {
101 data->ucpd_rx_buffer[data->ucpd_rx_byte_count++] =
102 LL_UCPD_ReadData(config->ucpd_port);
103 }
104 }
105
106 /**
107 * @brief Enables or Disables TX interrupts
108 */
ucpd_tx_interrupts_enable(const struct device * dev,bool enable)109 static void ucpd_tx_interrupts_enable(const struct device *dev, bool enable)
110 {
111 const struct tcpc_config *const config = dev->config;
112 uint32_t imr;
113
114 imr = LL_UCPD_ReadReg(config->ucpd_port, IMR);
115
116 if (enable) {
117 LL_UCPD_WriteReg(config->ucpd_port, ICR, UCPD_ICR_TX_INT_MASK);
118 LL_UCPD_WriteReg(config->ucpd_port, IMR,
119 imr | UCPD_IMR_TX_INT_MASK);
120 } else {
121 LL_UCPD_WriteReg(config->ucpd_port, IMR,
122 imr & ~UCPD_IMR_TX_INT_MASK);
123 }
124 }
125
126 /**
127 * @brief Initializes the RX and TX state machine variables
128 */
stm32_ucpd_state_init(const struct device * dev)129 static void stm32_ucpd_state_init(const struct device *dev)
130 {
131 struct tcpc_data *data = dev->data;
132
133 /* Init variables used to manage tx process */
134 data->ucpd_tx_request = 0;
135 data->tx_retry_count = 0;
136 data->ucpd_tx_state = STATE_IDLE;
137
138 /* Init variables used to manage rx */
139 data->ucpd_rx_sop_prime_enabled = false;
140 data->ucpd_rx_msg_active = false;
141 data->ucpd_rx_bist_mode = false;
142
143 /* Vconn tracking variable */
144 data->ucpd_vconn_enable = false;
145 }
146
147 /**
148 * @brief Get the CC enable mask. The mask indicates which CC line
149 * is enabled.
150 *
151 * @retval CC Enable mask (bit 0: CC1, bit 1: CC2)
152 */
ucpd_get_cc_enable_mask(const struct device * dev)153 static uint32_t ucpd_get_cc_enable_mask(const struct device *dev)
154 {
155 struct tcpc_data *data = dev->data;
156 const struct tcpc_config *const config = dev->config;
157 uint32_t mask = UCPD_CR_CCENABLE_Msk;
158
159 /*
160 * When VCONN is enabled, it is supplied on the CC line that's
161 * not being used for Power Delivery messages.
162 */
163 if (data->ucpd_vconn_enable) {
164 uint32_t cr = LL_UCPD_ReadReg(config->ucpd_port, CR);
165 int pol = (cr & UCPD_CR_PHYCCSEL);
166
167 /* Dissable CC line that's used for VCONN */
168 mask &= ~BIT(UCPD_CR_CCENABLE_Pos + !pol);
169 }
170
171 return mask;
172 }
173
174 /**
175 * @brief Get the state of the CC1 and CC2 lines
176 *
177 * @retval 0 on success
178 * @retval -EIO on failure
179 */
ucpd_get_cc(const struct device * dev,enum tc_cc_voltage_state * cc1,enum tc_cc_voltage_state * cc2)180 static int ucpd_get_cc(const struct device *dev,
181 enum tc_cc_voltage_state *cc1,
182 enum tc_cc_voltage_state *cc2)
183 {
184 const struct tcpc_config *const config = dev->config;
185 int vstate_cc1;
186 int vstate_cc2;
187 int anamode;
188 uint32_t sr;
189 uint32_t cc_msk;
190
191 /*
192 * cc_voltage_state is determined from vstate_cc bit field in the
193 * status register. The meaning of the value vstate_cc depends on
194 * current value of ANAMODE (src/snk).
195 *
196 * vstate_cc maps directly to cc_state from tcpci spec when
197 * ANAMODE(snk) = 1, but needs to be modified slightly for case
198 * ANAMODE(src) = 0.
199 *
200 * If presenting Rp (source), then need to do a circular shift of
201 * vstate_ccx value:
202 * vstate_cc | cc_state
203 * ------------------
204 * 0 -> 1
205 * 1 -> 2
206 * 2 -> 0
207 */
208
209 /* Get vstate_ccx values and power role */
210 sr = LL_UCPD_ReadReg(config->ucpd_port, SR);
211
212 /* Get Rp or Rd active */
213 anamode = LL_UCPD_GetRole(config->ucpd_port);
214 vstate_cc1 = (sr & UCPD_SR_TYPEC_VSTATE_CC1_Msk) >>
215 UCPD_SR_TYPEC_VSTATE_CC1_Pos;
216
217 vstate_cc2 = (sr & UCPD_SR_TYPEC_VSTATE_CC2_Msk) >>
218 UCPD_SR_TYPEC_VSTATE_CC2_Pos;
219
220 /* Do circular shift if port == source */
221 if (anamode) {
222 if (vstate_cc1 != STM32_UCPD_SR_VSTATE_RA) {
223 vstate_cc1 += 4;
224 }
225 if (vstate_cc2 != STM32_UCPD_SR_VSTATE_RA) {
226 vstate_cc2 += 4;
227 }
228 } else {
229 if (vstate_cc1 != STM32_UCPD_SR_VSTATE_OPEN) {
230 vstate_cc1 = (vstate_cc1 + 1) % 3;
231 }
232 if (vstate_cc2 != STM32_UCPD_SR_VSTATE_OPEN) {
233 vstate_cc2 = (vstate_cc2 + 1) % 3;
234 }
235 }
236
237 /* CC connection detection */
238 cc_msk = ucpd_get_cc_enable_mask(dev);
239
240 /* CC1 connection detection */
241 if (cc_msk & UCPD_CR_CCENABLE_0) {
242 *cc1 = vstate_cc1;
243 } else {
244 *cc1 = TC_CC_VOLT_OPEN;
245 }
246
247 /* CC2 connection detection */
248 if (cc_msk & UCPD_CR_CCENABLE_1) {
249 *cc2 = vstate_cc2;
250 } else {
251 *cc2 = TC_CC_VOLT_OPEN;
252 }
253
254 return 0;
255 }
256
257 /**
258 * @brief Enable or Disable VCONN
259 *
260 * @retval 0 on success
261 * @retval -EIO on failure
262 * @retval -ENOTSUP if not supported
263 */
ucpd_set_vconn(const struct device * dev,bool enable)264 static int ucpd_set_vconn(const struct device *dev, bool enable)
265 {
266 struct tcpc_data *data = dev->data;
267 const struct tcpc_config *const config = dev->config;
268 int cr;
269 int ret;
270
271 if (data->vconn_cb == NULL) {
272 return -ENOTSUP;
273 }
274
275 /* Update VCONN on/off status. Do this before getting cc enable mask */
276 data->ucpd_vconn_enable = enable;
277
278 cr = LL_UCPD_ReadReg(config->ucpd_port, CR);
279 cr &= ~UCPD_CR_CCENABLE_Msk;
280 cr |= ucpd_get_cc_enable_mask(dev);
281
282 /* Apply cc pull resistor change */
283 LL_UCPD_WriteReg(config->ucpd_port, CR, cr);
284
285 #ifdef CONFIG_SOC_SERIES_STM32G0X
286 update_stm32g0x_cc_line(config->ucpd_port);
287 #endif
288
289 /* Get CC line that VCONN is active on */
290 data->ucpd_vconn_cc = (cr & UCPD_CR_CCENABLE_0) ?
291 TC_POLARITY_CC2 : TC_POLARITY_CC1;
292
293 /* Call user supplied callback to set vconn */
294 ret = data->vconn_cb(dev, data->ucpd_vconn_cc, enable);
295
296 return ret;
297 }
298
299 /**
300 * @brief Discharge VCONN
301 *
302 * @retval 0 on success
303 * @retval -EIO on failure
304 * @retval -ENOTSUP if not supported
305 */
ucpd_vconn_discharge(const struct device * dev,bool enable)306 static int ucpd_vconn_discharge(const struct device *dev, bool enable)
307 {
308 struct tcpc_data *data = dev->data;
309 const struct tcpc_config *const config = dev->config;
310
311 /* VCONN should not be discharged while it's enabled */
312 if (data->ucpd_vconn_enable) {
313 return -EIO;
314 }
315
316 if (data->vconn_discharge_cb) {
317 /* Use DPM supplied VCONN Discharge */
318 return data->vconn_discharge_cb(dev, data->ucpd_vconn_cc, enable);
319 }
320
321 /* Use TCPC VCONN Discharge */
322 if (enable) {
323 LL_UCPD_VconnDischargeEnable(config->ucpd_port);
324 } else {
325 LL_UCPD_VconnDischargeDisable(config->ucpd_port);
326 }
327
328 #ifdef CONFIG_SOC_SERIES_STM32G0X
329 update_stm32g0x_cc_line(config->ucpd_port);
330 #endif
331
332 return 0;
333 }
334
335 /**
336 * @brief Sets the value of the CC pull up resistor used when operating as a Source
337 *
338 * @retval 0 on success
339 */
ucpd_select_rp_value(const struct device * dev,enum tc_rp_value rp)340 static int ucpd_select_rp_value(const struct device *dev, enum tc_rp_value rp)
341 {
342 struct tcpc_data *data = dev->data;
343
344 data->rp = rp;
345
346 return 0;
347 }
348
349 /**
350 * @brief Gets the value of the CC pull up resistor used when operating as a Source
351 *
352 * @retval 0 on success
353 */
ucpd_get_rp_value(const struct device * dev,enum tc_rp_value * rp)354 static int ucpd_get_rp_value(const struct device *dev, enum tc_rp_value *rp)
355 {
356 struct tcpc_data *data = dev->data;
357
358 *rp = data->rp;
359
360 return 0;
361 }
362
363 /**
364 * @brief Enable or disable Dead Battery resistors
365 */
dead_battery(const struct device * dev,bool en)366 static void dead_battery(const struct device *dev, bool en)
367 {
368 struct tcpc_data *data = dev->data;
369
370 #ifdef CONFIG_SOC_SERIES_STM32G0X
371 const struct tcpc_config *const config = dev->config;
372 uint32_t cr;
373
374 cr = LL_UCPD_ReadReg(config->ucpd_port, CR);
375
376 if (en) {
377 cr |= UCPD_CR_DBATTEN;
378 } else {
379 cr &= ~UCPD_CR_DBATTEN;
380 }
381
382 LL_UCPD_WriteReg(config->ucpd_port, CR, cr);
383 update_stm32g0x_cc_line(config->ucpd_port);
384 #else
385 if (en) {
386 CLEAR_BIT(PWR->CR3, PWR_CR3_UCPD_DBDIS);
387 } else {
388 SET_BIT(PWR->CR3, PWR_CR3_UCPD_DBDIS);
389 }
390 #endif
391 data->dead_battery_active = en;
392 }
393
394 /**
395 * @brief Set the CC pull up or pull down resistors
396 *
397 * @retval 0 on success
398 * @retval -EIO on failure
399 */
ucpd_set_cc(const struct device * dev,enum tc_cc_pull cc_pull)400 static int ucpd_set_cc(const struct device *dev,
401 enum tc_cc_pull cc_pull)
402 {
403 const struct tcpc_config *const config = dev->config;
404 struct tcpc_data *data = dev->data;
405 uint32_t cr;
406
407 /* Disable dead battery if it's active */
408 if (data->dead_battery_active) {
409 dead_battery(dev, false);
410 }
411
412 cr = LL_UCPD_ReadReg(config->ucpd_port, CR);
413
414 /*
415 * Always set ANASUBMODE to match desired Rp. TCPM layer has a valid
416 * range of 0, 1, or 2. This range maps to 1, 2, or 3 in ucpd for
417 * ANASUBMODE.
418 */
419 cr &= ~UCPD_CR_ANASUBMODE_Msk;
420 cr |= STM32_UCPD_CR_ANASUBMODE_VAL(UCPD_RP_TO_ANASUB(data->rp));
421
422 /* Disconnect both pull from both CC lines for R_open case */
423 cr &= ~UCPD_CR_CCENABLE_Msk;
424 /* Set ANAMODE if cc_pull is Rd */
425 if (cc_pull == TC_CC_RD) {
426 cr |= (UCPD_CR_ANAMODE | UCPD_CR_CCENABLE_Msk);
427 /* Clear ANAMODE if cc_pull is Rp */
428 } else if (cc_pull == TC_CC_RP) {
429 cr &= ~(UCPD_CR_ANAMODE);
430 cr |= ucpd_get_cc_enable_mask(dev);
431 }
432
433 /* Update pull values */
434 LL_UCPD_WriteReg(config->ucpd_port, CR, cr);
435
436 #ifdef CONFIG_SOC_SERIES_STM32G0X
437 update_stm32g0x_cc_line(config->ucpd_port);
438 #endif
439
440 return 0;
441 }
442
443 /**
444 * @brief Set the polarity of the CC line, which is the active CC line
445 * used for power delivery.
446 *
447 * @retval 0 on success
448 * @retval -EIO on failure
449 * @retval -ENOTSUP if polarity is not supported
450 */
ucpd_cc_set_polarity(const struct device * dev,enum tc_cc_polarity polarity)451 static int ucpd_cc_set_polarity(const struct device *dev,
452 enum tc_cc_polarity polarity)
453 {
454 const struct tcpc_config *const config = dev->config;
455 uint32_t cr;
456
457 cr = LL_UCPD_ReadReg(config->ucpd_port, CR);
458
459 /*
460 * Polarity impacts the PHYCCSEL, CCENABLE, and CCxTCDIS fields. This
461 * function is called when polarity is updated at TCPM layer. STM32Gx
462 * only supports POLARITY_CC1 or POLARITY_CC2 and this is stored in the
463 * PHYCCSEL bit in the CR register.
464 */
465
466 if (polarity == TC_POLARITY_CC1) {
467 cr &= ~UCPD_CR_PHYCCSEL;
468 } else if (polarity == TC_POLARITY_CC2) {
469 cr |= UCPD_CR_PHYCCSEL;
470 } else {
471 return -ENOTSUP;
472 }
473
474 /* Update polarity */
475 LL_UCPD_WriteReg(config->ucpd_port, CR, cr);
476
477 return 0;
478 }
479
480 /**
481 * @brief Enable or Disable Power Delivery
482 *
483 * @retval 0 on success
484 * @retval -EIO on failure
485 */
ucpd_set_rx_enable(const struct device * dev,bool enable)486 static int ucpd_set_rx_enable(const struct device *dev, bool enable)
487 {
488 const struct tcpc_config *const config = dev->config;
489 uint32_t imr;
490 uint32_t cr;
491
492 imr = LL_UCPD_ReadReg(config->ucpd_port, IMR);
493 cr = LL_UCPD_ReadReg(config->ucpd_port, CR);
494
495 /*
496 * USB PD receiver enable is controlled by the bit PHYRXEN in
497 * UCPD_CR. Enable Rx interrupts when RX PD decoder is active.
498 */
499 if (enable) {
500 /* Clear the RX alerts bits */
501 LL_UCPD_WriteReg(config->ucpd_port, ICR, UCPD_ICR_RX_INT_MASK);
502 imr |= UCPD_IMR_RX_INT_MASK;
503 cr |= UCPD_CR_PHYRXEN;
504 LL_UCPD_WriteReg(config->ucpd_port, IMR, imr);
505 LL_UCPD_WriteReg(config->ucpd_port, CR, cr);
506 } else {
507 imr &= ~UCPD_IMR_RX_INT_MASK;
508 cr &= ~UCPD_CR_PHYRXEN;
509 LL_UCPD_WriteReg(config->ucpd_port, CR, cr);
510 LL_UCPD_WriteReg(config->ucpd_port, IMR, imr);
511 }
512
513 return 0;
514 }
515
516 /**
517 * @brief Set the Power and Data role used when sending goodCRC messages
518 *
519 * @retval 0 on success
520 * @retval -EIO on failure
521 */
ucpd_set_roles(const struct device * dev,enum tc_power_role power_role,enum tc_data_role data_role)522 static int ucpd_set_roles(const struct device *dev,
523 enum tc_power_role power_role,
524 enum tc_data_role data_role)
525 {
526 struct tcpc_data *data = dev->data;
527
528 data->msg_header.pr = power_role;
529 data->msg_header.dr = data_role;
530
531 return 0;
532 }
533
534 /**
535 * @brief Enable the reception of SOP Prime messages
536 *
537 * @retval 0 on success
538 * @retval -EIO on failure
539 */
ucpd_sop_prime_enable(const struct device * dev,bool enable)540 static int ucpd_sop_prime_enable(const struct device *dev, bool enable)
541 {
542 struct tcpc_data *data = dev->data;
543
544 /* Update static variable used to filter SOP//SOP'' messages */
545 data->ucpd_rx_sop_prime_enabled = enable;
546
547 return 0;
548 }
549
550 /**
551 * @brief State transmitting a message
552 */
ucpd_start_transmit(const struct device * dev,enum ucpd_tx_msg msg_type)553 static void ucpd_start_transmit(const struct device *dev,
554 enum ucpd_tx_msg msg_type)
555 {
556 struct tcpc_data *data = dev->data;
557 const struct tcpc_config *const config = dev->config;
558 enum pd_packet_type type;
559 uint32_t cr;
560 uint32_t imr;
561
562 cr = LL_UCPD_ReadReg(config->ucpd_port, CR);
563
564 /* Select the correct tx descriptor */
565 data->ucpd_tx_active_buffer = &data->ucpd_tx_buffers[msg_type];
566 type = data->ucpd_tx_active_buffer->type;
567
568 if (type == PD_PACKET_TX_HARD_RESET) {
569 /*
570 * From RM0440 45.4.4:
571 * In order to facilitate generation of a Hard Reset, a special
572 * code of TXMODE field is used. No other fields need to be
573 * written. On writing the correct code, the hardware forces
574 * Hard Reset Tx under the correct (optimal) timings with
575 * respect to an on-going Tx message, which (if still in
576 * progress) is cleanly terminated by truncating the current
577 * sequence and directly appending an EOP K-code sequence. No
578 * specific interrupt is generated relating to this truncation
579 * event.
580 *
581 * Because Hard Reset can interrupt ongoing Tx operations, it is
582 * started differently than all other tx messages. Only need to
583 * enable hard reset interrupts, and then set a bit in the CR
584 * register to initiate.
585 */
586 /* Enable interrupt for Hard Reset sent/discarded */
587 LL_UCPD_WriteReg(config->ucpd_port, ICR,
588 UCPD_ICR_HRSTDISCCF | UCPD_ICR_HRSTSENTCF);
589
590 imr = LL_UCPD_ReadReg(config->ucpd_port, IMR);
591 imr |= UCPD_IMR_HRSTDISCIE | UCPD_IMR_HRSTSENTIE;
592 LL_UCPD_WriteReg(config->ucpd_port, IMR, imr);
593
594 /* Initiate Hard Reset */
595 cr |= UCPD_CR_TXHRST;
596 LL_UCPD_WriteReg(config->ucpd_port, CR, cr);
597 } else if (type != PD_PACKET_MSG_INVALID) {
598 int msg_len = 0;
599 int mode;
600
601 /*
602 * These types are normal transmission, TXMODE = 0. To transmit
603 * regular message, control or data, requires the following:
604 * 1. Set TXMODE:
605 * Normal -> 0
606 * Cable Reset -> 1
607 * Bist -> 2
608 * 2. Set TX_ORDSETR based on message type
609 * 3. Set TX_PAYSZR which must account for 2 bytes of header
610 * 4. Configure DMA (optional if DMA is desired)
611 * 5. Enable transmit interrupts
612 * 6. Start TX by setting TXSEND in CR
613 *
614 */
615
616 /*
617 * Set tx length parameter (in bytes). Note the count field in
618 * the header is number of 32 bit objects. Also, the length
619 * field must account for the 2 header bytes.
620 */
621 if (type == PD_PACKET_TX_BIST_MODE_2) {
622 mode = LL_UCPD_TXMODE_BIST_CARRIER2;
623 } else if (type == PD_PACKET_CABLE_RESET) {
624 mode = LL_UCPD_TXMODE_CABLE_RESET;
625 } else {
626 mode = LL_UCPD_TXMODE_NORMAL;
627 msg_len = data->ucpd_tx_active_buffer->msg_len;
628 }
629
630 LL_UCPD_WriteTxPaySize(config->ucpd_port, msg_len);
631
632 /* Set tx mode */
633 cr &= ~UCPD_CR_TXMODE_Msk;
634 cr |= mode;
635 LL_UCPD_WriteReg(config->ucpd_port, CR, cr);
636
637 /* Index into ordset enum for start of packet */
638 if (type <= PD_PACKET_CABLE_RESET) {
639 LL_UCPD_WriteTxOrderSet(config->ucpd_port,
640 ucpd_txorderset[type]);
641 }
642
643 /* Reset msg byte index */
644 data->ucpd_tx_active_buffer->msg_index = 0;
645
646 /* Enable interrupts */
647 ucpd_tx_interrupts_enable(dev, 1);
648
649 /* Trigger ucpd peripheral to start pd message transmit */
650 LL_UCPD_SendMessage(config->ucpd_port);
651 }
652 }
653
654 /**
655 * @brief Set the current state of the TX state machine
656 */
ucpd_set_tx_state(const struct device * dev,enum ucpd_state state)657 static void ucpd_set_tx_state(const struct device *dev, enum ucpd_state state)
658 {
659 struct tcpc_data *data = dev->data;
660
661 data->ucpd_tx_state = state;
662 }
663
664 /**
665 * @brief Wrapper function for calling alert handler
666 */
ucpd_notify_handler(struct alert_info * info,enum tcpc_alert alert)667 static void ucpd_notify_handler(struct alert_info *info, enum tcpc_alert alert)
668 {
669 if (info->handler) {
670 info->handler(info->dev, info->data, alert);
671 }
672 }
673
674 /**
675 * @brief This is the TX state machine
676 */
ucpd_manage_tx(struct alert_info * info)677 static void ucpd_manage_tx(struct alert_info *info)
678 {
679 struct tcpc_data *data = info->dev->data;
680 enum ucpd_tx_msg msg_src = TX_MSG_NONE;
681 union pd_header hdr;
682
683 if (atomic_test_and_clear_bit(&info->evt, UCPD_EVT_HR_REQ)) {
684 /*
685 * Hard reset control messages are treated as a priority. The
686 * control message will already be set up as it comes from the
687 * PRL layer like any other PD ctrl/data message. So just need
688 * to indicate the correct message source and set the state to
689 * hard reset here.
690 */
691 ucpd_set_tx_state(info->dev, STATE_HARD_RESET);
692 msg_src = TX_MSG_TCPM;
693 data->ucpd_tx_request &= ~BIT(msg_src);
694 }
695
696 switch (data->ucpd_tx_state) {
697 case STATE_IDLE:
698 if (data->ucpd_tx_request & MSG_GOOD_CRC_MASK) {
699 ucpd_set_tx_state(info->dev, STATE_ACTIVE_CRC);
700 msg_src = TX_MSG_GOOD_CRC;
701 } else if (data->ucpd_tx_request & MSG_TCPM_MASK) {
702 if (atomic_test_and_clear_bit(&info->evt, UCPD_EVT_RX_MSG)) {
703 /*
704 * USB-PD Specification rev 3.0, section 6.10
705 * On receiving a received message, the protocol
706 * layer shall discard any pending message.
707 *
708 * Since the pending message from the PRL has
709 * not been sent yet, it needs to be discarded
710 * based on the received message event.
711 */
712 ucpd_notify_handler(info, TCPC_ALERT_TRANSMIT_MSG_DISCARDED);
713 data->ucpd_tx_request &= ~MSG_TCPM_MASK;
714 } else if (!data->ucpd_rx_msg_active) {
715 ucpd_set_tx_state(info->dev, STATE_ACTIVE_TCPM);
716 msg_src = TX_MSG_TCPM;
717 /* Save msgID required for GoodCRC check */
718 hdr.raw_value =
719 data->ucpd_tx_buffers[TX_MSG_TCPM].data.header;
720 data->msg_id_match = hdr.message_id;
721 data->tx_retry_max = hdr.specification_revision == PD_REV30 ?
722 UCPD_N_RETRY_COUNT_REV30 :
723 UCPD_N_RETRY_COUNT_REV20;
724 }
725 }
726
727 /* If state is not idle, then start tx message */
728 if (data->ucpd_tx_state != STATE_IDLE) {
729 data->ucpd_tx_request &= ~BIT(msg_src);
730 data->tx_retry_count = 0;
731 }
732 break;
733
734 case STATE_ACTIVE_TCPM:
735 /*
736 * Check if tx msg has finished. For TCPM messages
737 * transmit is not complete until a GoodCRC message
738 * matching the msgID just sent is received. But, a tx
739 * message can fail due to collision or underrun,
740 * etc. If that failure occurs, dont' wait for GoodCrc
741 * and just go to failure path.
742 */
743 if (atomic_test_and_clear_bit(&info->evt, UCPD_EVT_TX_MSG_SUCCESS)) {
744 ucpd_set_tx_state(info->dev, STATE_WAIT_CRC_ACK);
745 /* Start the GoodCRC RX Timer */
746 k_timer_start(&data->goodcrc_rx_timer, K_USEC(1000), K_NO_WAIT);
747 } else if (atomic_test_and_clear_bit(&info->evt, UCPD_EVT_TX_MSG_DISC) ||
748 atomic_test_and_clear_bit(&info->evt, UCPD_EVT_TX_MSG_FAIL)) {
749 if (data->tx_retry_count < data->tx_retry_max) {
750 if (atomic_test_and_clear_bit(&info->evt, UCPD_EVT_RX_MSG)) {
751 /*
752 * A message was received so there is no
753 * need to retry this tx message which
754 * had failed to send previously.
755 * Likely, due to the wire
756 * being active from the message that
757 * was just received.
758 */
759 ucpd_set_tx_state(info->dev,
760 STATE_IDLE);
761 ucpd_notify_handler(info,
762 TCPC_ALERT_TRANSMIT_MSG_DISCARDED);
763 ucpd_set_tx_state(info->dev,
764 STATE_IDLE);
765 } else {
766 /*
767 * Tx attempt failed. Remain in this
768 * state, but trigger new tx attempt.
769 */
770 msg_src = TX_MSG_TCPM;
771 data->tx_retry_count++;
772 }
773 } else {
774 enum tcpc_alert status;
775
776 status = (atomic_test_and_clear_bit(&info->evt,
777 UCPD_EVT_TX_MSG_FAIL)) ?
778 TCPC_ALERT_TRANSMIT_MSG_FAILED :
779 TCPC_ALERT_TRANSMIT_MSG_DISCARDED;
780 ucpd_set_tx_state(info->dev, STATE_IDLE);
781 ucpd_notify_handler(info, status);
782 }
783 }
784 break;
785
786 case STATE_ACTIVE_CRC:
787 if (atomic_test_bit(&info->evt, UCPD_EVT_TX_MSG_SUCCESS) ||
788 atomic_test_bit(&info->evt, UCPD_EVT_TX_MSG_FAIL) ||
789 atomic_test_bit(&info->evt, UCPD_EVT_TX_MSG_DISC)) {
790 atomic_clear_bit(&info->evt, UCPD_EVT_TX_MSG_SUCCESS);
791 atomic_clear_bit(&info->evt, UCPD_EVT_TX_MSG_FAIL);
792 atomic_clear_bit(&info->evt, UCPD_EVT_TX_MSG_DISC);
793 ucpd_set_tx_state(info->dev, STATE_IDLE);
794 if (atomic_test_and_clear_bit(&info->evt, UCPD_EVT_TX_MSG_FAIL)) {
795 LOG_INF("ucpd: Failed to send GoodCRC!");
796 } else if (atomic_test_and_clear_bit(&info->evt, UCPD_EVT_TX_MSG_DISC)) {
797 LOG_INF("ucpd: GoodCRC message discarded!");
798 }
799 }
800 break;
801
802 case STATE_WAIT_CRC_ACK:
803 if (atomic_test_and_clear_bit(&info->evt, UCPD_EVT_RX_GOOD_CRC) &&
804 data->ucpd_crc_id == data->msg_id_match) {
805 /* GoodCRC with matching ID was received */
806 ucpd_notify_handler(info, TCPC_ALERT_TRANSMIT_MSG_SUCCESS);
807 ucpd_set_tx_state(info->dev, STATE_IDLE);
808 } else if (k_timer_status_get(&data->goodcrc_rx_timer)) {
809 /* Stop the GoodCRC RX Timer */
810 k_timer_stop(&data->goodcrc_rx_timer);
811
812 /* GoodCRC w/out match or timeout waiting */
813 if (data->tx_retry_count < data->tx_retry_max) {
814 ucpd_set_tx_state(info->dev, STATE_ACTIVE_TCPM);
815 msg_src = TX_MSG_TCPM;
816 data->tx_retry_count++;
817 } else {
818 ucpd_set_tx_state(info->dev, STATE_IDLE);
819 ucpd_notify_handler(info, TCPC_ALERT_TRANSMIT_MSG_FAILED);
820 }
821 } else if (atomic_test_and_clear_bit(&info->evt, UCPD_EVT_RX_MSG)) {
822 /*
823 * In the case of a collision, it's possible the port
824 * partner may not send a GoodCRC and instead send the
825 * message that was colliding. If a message is received
826 * in this state, then treat it as a discard from an
827 * incoming message.
828 */
829 ucpd_notify_handler(info, TCPC_ALERT_TRANSMIT_MSG_DISCARDED);
830 ucpd_set_tx_state(info->dev, STATE_IDLE);
831 }
832 break;
833
834 case STATE_HARD_RESET:
835 if (atomic_test_bit(&info->evt, UCPD_EVT_HR_DONE) ||
836 atomic_test_bit(&info->evt, UCPD_EVT_HR_FAIL)) {
837 atomic_clear_bit(&info->evt, UCPD_EVT_HR_DONE);
838 atomic_clear_bit(&info->evt, UCPD_EVT_HR_FAIL);
839 /* HR complete, reset tx state values */
840 ucpd_set_tx_state(info->dev, STATE_IDLE);
841 data->ucpd_tx_request = 0;
842 data->tx_retry_count = 0;
843 }
844 break;
845 }
846
847 /*
848 * NOTE: TX_MSG_GOOD_CRC messages are sent from the ISR to reduce latency
849 * when sending those messages, so don't resend them here.
850 *
851 * If msg_src is valid and not a TX_MSG_GOOD_CRC, then start transmit.
852 */
853 if (msg_src != TX_MSG_GOOD_CRC && msg_src > TX_MSG_NONE) {
854 ucpd_start_transmit(info->dev, msg_src);
855 }
856 }
857
858 /**
859 * @brief Alert handler
860 */
ucpd_alert_handler(struct k_work * item)861 static void ucpd_alert_handler(struct k_work *item)
862 {
863 struct alert_info *info = CONTAINER_OF(item, struct alert_info, work);
864 struct tcpc_data *data = info->dev->data;
865
866 if (atomic_test_and_clear_bit(&info->evt, UCPD_EVT_EVENT_CC)) {
867 ucpd_notify_handler(info, TCPC_ALERT_CC_STATUS);
868 }
869
870 if (atomic_test_and_clear_bit(&info->evt, UCPD_EVT_HARD_RESET_RECEIVED)) {
871 ucpd_notify_handler(info, TCPC_ALERT_HARD_RESET_RECEIVED);
872 }
873
874 if (atomic_test_and_clear_bit(&info->evt, UCPD_EVT_RX_MSG)) {
875 ucpd_notify_handler(info, TCPC_ALERT_MSG_STATUS);
876 }
877
878 /*
879 * USB-PD messages are initiated in TCPM stack (PRL
880 * layer). However, GoodCRC messages are initiated within the
881 * UCPD driver based on USB-PD rx messages. These 2 types of
882 * transmit paths are managed via events.
883 *
884 * UCPD generated GoodCRC messages, are the priority path as
885 * they must be sent immediately following a successful USB-PD
886 * rx message. As long as a transmit operation is not underway,
887 * then a transmit message will be started upon request. The ISR
888 * routine sets the event to indicate that the transmit
889 * operation is complete.
890 *
891 * Hard reset requests are sent as a TCPM message, but in terms
892 * of the ucpd transmitter, they are treated as a 3rd tx msg
893 * source since they can interrupt an ongoing tx msg, and there
894 * is no requirement to wait for a GoodCRC reply message.
895 */
896
897 if (atomic_test_and_clear_bit(&info->evt, UCPD_EVT_GOOD_CRC_REQ)) {
898 data->ucpd_tx_request |= MSG_GOOD_CRC_MASK;
899 }
900
901 if (atomic_test_and_clear_bit(&info->evt, UCPD_EVT_TCPM_MSG_REQ)) {
902 data->ucpd_tx_request |= MSG_TCPM_MASK;
903 }
904
905 /*
906 * Manage PD tx messages. The state machine may need to be
907 * called more than once. For instance, if
908 * the task is woken at the completion of sending a GoodCRC,
909 * there may be a TCPM message request pending and just changing
910 * the state back to idle would not trigger start of transmit.
911 */
912 do {
913 ucpd_manage_tx(info);
914 } while (data->ucpd_tx_state != STATE_IDLE);
915 }
916
917 /**
918 * @brief Sends a goodCRC message
919 */
ucpd_send_good_crc(const struct device * dev,union pd_header rx_header)920 static void ucpd_send_good_crc(const struct device *dev,
921 union pd_header rx_header)
922 {
923 struct tcpc_data *data = dev->data;
924 const struct tcpc_config *const config = dev->config;
925 union pd_header tx_header;
926 enum pd_packet_type tx_type;
927 struct alert_info *info = &data->alert_info;
928
929 /*
930 * A GoodCRC message shall be sent by receiver to ack that the previous
931 * message was correctly received. The GoodCRC message shall return the
932 * rx message's msg_id field. The one exception is for GoodCRC messages,
933 * which do not generate a GoodCRC response
934 */
935 if (ucpd_msg_is_good_crc(rx_header)) {
936 return;
937 }
938
939 /*
940 * Get the rx ordered set code just detected. SOP -> SOP''_Debug are in
941 * the same order as enum tcpc_packet_type and so can be used
942 * directly.
943 */
944 tx_type = LL_UCPD_ReadRxOrderSet(config->ucpd_port);
945
946 /*
947 * PD Header(SOP):
948 * Extended b15 -> set to 0 for control messages
949 * Count b14:12 -> number of 32 bit data objects = 0 for ctrl msg
950 * MsgID b11:9 -> running byte counter (extracted from rx msg)
951 * Power Role b8 -> stored in static, from set_msg_header()
952 * Spec Rev b7:b6 -> PD spec revision (extracted from rx msg)
953 * Data Role b5 -> stored in static, from set_msg_header
954 * Msg Type b4:b0 -> data or ctrl type = PD_CTRL_GOOD_CRC
955 */
956 /* construct header message */
957 tx_header.message_type = PD_CTRL_GOOD_CRC;
958 if (tx_type == PD_PACKET_SOP) {
959 tx_header.port_power_role = data->msg_header.pr;
960 tx_header.port_data_role = data->msg_header.dr;
961 } else {
962 tx_header.port_power_role = 0;
963 tx_header.port_data_role = 0;
964 }
965 tx_header.message_id = rx_header.message_id;
966 tx_header.number_of_data_objects = 0;
967 tx_header.specification_revision = rx_header.specification_revision;
968 tx_header.extended = 0;
969
970 /* Good CRC is header with no other objects */
971 data->ucpd_tx_buffers[TX_MSG_GOOD_CRC].msg_len = MSG_HEADER_SIZE;
972 data->ucpd_tx_buffers[TX_MSG_GOOD_CRC].data.header =
973 tx_header.raw_value;
974 data->ucpd_tx_buffers[TX_MSG_GOOD_CRC].type = tx_type;
975
976 /* Notify ucpd task that a GoodCRC message tx request is pending */
977 atomic_set_bit(&info->evt, UCPD_EVT_GOOD_CRC_REQ);
978
979 /* Send TX_MSG_GOOD_CRC message here to reduce latency */
980 ucpd_start_transmit(dev, TX_MSG_GOOD_CRC);
981 }
982
983 /**
984 * @brief Transmit a power delivery message
985 *
986 * @retval 0 on success
987 * @retval -EFAULT on failure
988 */
ucpd_transmit_data(const struct device * dev,struct pd_msg * msg)989 static int ucpd_transmit_data(const struct device *dev,
990 struct pd_msg *msg)
991 {
992 struct tcpc_data *data = dev->data;
993
994 /* Length in bytes = (4 * object len) + 2 header bytes */
995 int len = PD_CONVERT_PD_HEADER_COUNT_TO_BYTES(msg->header.number_of_data_objects) + 2;
996
997 if (len > UCPD_BUF_LEN) {
998 return -EFAULT;
999 }
1000
1001 /* Store tx msg info in TCPM msg descriptor */
1002 data->ucpd_tx_buffers[TX_MSG_TCPM].msg_len = len;
1003 data->ucpd_tx_buffers[TX_MSG_TCPM].type = msg->type;
1004 data->ucpd_tx_buffers[TX_MSG_TCPM].data.header = msg->header.raw_value;
1005
1006 /* Copy msg objects to ucpd data buffer, after 2 header bytes */
1007 memcpy(data->ucpd_tx_buffers[TX_MSG_TCPM].data.msg + 2,
1008 (uint8_t *)msg->data, len - 2);
1009
1010 /*
1011 * Check for hard reset message here. A different event is used for hard
1012 * resets as they are able to interrupt ongoing transmit, and should
1013 * have priority over any pending message.
1014 */
1015 if (msg->type == PD_PACKET_TX_HARD_RESET) {
1016 atomic_set_bit(&data->alert_info.evt, UCPD_EVT_HR_REQ);
1017 } else {
1018 atomic_set_bit(&data->alert_info.evt, UCPD_EVT_TCPM_MSG_REQ);
1019 }
1020
1021 /* Start transmission */
1022 k_work_submit(&data->alert_info.work);
1023
1024 return 0;
1025 }
1026
1027 /**
1028 * @brief Retrieves the Power Delivery message from the TCPC
1029 *
1030 * @retval number of bytes received if msg parameter is provided
1031 * @retval 0 if there is a message pending and the msg parameter is NULL
1032 * @retval -ENODATA if there is no pending message
1033 */
ucpd_get_rx_pending_msg(const struct device * dev,struct pd_msg * msg)1034 static int ucpd_get_rx_pending_msg(const struct device *dev, struct pd_msg *msg)
1035 {
1036 struct tcpc_data *data = dev->data;
1037 int ret = 0;
1038
1039 /* Make sure we have a message to retrieve */
1040 if (*(uint32_t *)data->ucpd_rx_buffer == 0) {
1041 return -ENODATA;
1042 }
1043
1044 if (msg == NULL) {
1045 return 0;
1046 }
1047
1048 msg->type = *(uint16_t *)data->ucpd_rx_buffer;
1049 msg->header.raw_value = *((uint16_t *)data->ucpd_rx_buffer + 1);
1050 msg->len = PD_CONVERT_PD_HEADER_COUNT_TO_BYTES(msg->header.number_of_data_objects);
1051 memcpy(msg->data, (data->ucpd_rx_buffer +
1052 PACKET_TYPE_SIZE +
1053 MSG_HEADER_SIZE), msg->len);
1054 ret = msg->len + MSG_HEADER_SIZE;
1055
1056 /* All done. Clear type and header */
1057 *(uint32_t *)data->ucpd_rx_buffer = 0;
1058
1059 return ret;
1060 }
1061
1062 /**
1063 * @brief Enable or Disable BIST Test mode
1064 *
1065 * return 0 on success
1066 * return -EIO on failure
1067 */
ucpd_set_bist_test_mode(const struct device * dev,bool enable)1068 static int ucpd_set_bist_test_mode(const struct device *dev,
1069 bool enable)
1070 {
1071 struct tcpc_data *data = dev->data;
1072
1073 data->ucpd_rx_bist_mode = enable;
1074 LOG_INF("ucpd: Bist test mode = %d", enable);
1075
1076 return 0;
1077 }
1078
1079 /**
1080 * @brief UCPD interrupt handler
1081 */
ucpd_isr(const struct device * dev_inst[])1082 static void ucpd_isr(const struct device *dev_inst[])
1083 {
1084 const struct device *dev;
1085 const struct tcpc_config *config;
1086 struct tcpc_data *data;
1087 uint32_t sr;
1088 struct alert_info *info;
1089 uint32_t tx_done_mask = UCPD_SR_TXUND |
1090 UCPD_SR_TXMSGSENT |
1091 UCPD_SR_TXMSGABT |
1092 UCPD_SR_TXMSGDISC |
1093 UCPD_SR_HRSTSENT |
1094 UCPD_SR_HRSTDISC;
1095
1096 #if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) > 1
1097 /*
1098 * Multiple UCPD ports are available
1099 */
1100
1101 uint32_t sr0;
1102 uint32_t sr1;
1103
1104 /*
1105 * Since the UCPD peripherals share the same interrupt line, determine
1106 * which one generated the interrupt.
1107 */
1108
1109 /* Read UCPD1 and UCPD2 Status Registers */
1110
1111 sr0 =
1112 LL_UCPD_ReadReg(((const struct tcpc_config *)dev_inst[0]->config)->ucpd_port, SR);
1113 sr1 =
1114 LL_UCPD_ReadReg(((const struct tcpc_config *)dev_inst[1]->config)->ucpd_port, SR);
1115
1116 if (sr0) {
1117 dev = dev_inst[0];
1118 } else if (sr1) {
1119 dev = dev_inst[1];
1120 } else {
1121 /*
1122 * The interrupt was triggered by some other device sharing this
1123 * interrupt line.
1124 */
1125 return;
1126 }
1127 #else
1128 /*
1129 * Only one UCPD port available
1130 */
1131
1132 dev = dev_inst[0];
1133 #endif /* Get the UCPD port that initiated that interrupt */
1134
1135 config = dev->config;
1136 data = dev->data;
1137 info = &data->alert_info;
1138
1139 /* Read the status register */
1140 sr = LL_UCPD_ReadReg(config->ucpd_port, SR);
1141
1142 /* Check for CC events, set event to wake PD task */
1143 if (sr & (UCPD_SR_TYPECEVT1 | UCPD_SR_TYPECEVT2)) {
1144 /* Set CC event bit */
1145 atomic_set_bit(&info->evt, UCPD_EVT_EVENT_CC);
1146 }
1147
1148 /*
1149 * Check for Tx events. tx_mask includes all status bits related to the
1150 * end of a USB-PD tx message. If any of these bits are set, the
1151 * transmit attempt is completed. Set an event to notify ucpd tx state
1152 * machine that transmit operation is complete.
1153 */
1154 if (sr & tx_done_mask) {
1155 /* Check for tx message complete */
1156 if (sr & UCPD_SR_TXMSGSENT) {
1157 atomic_set_bit(&info->evt, UCPD_EVT_TX_MSG_SUCCESS);
1158 } else if (sr & (UCPD_SR_TXMSGABT | UCPD_SR_TXUND)) {
1159 atomic_set_bit(&info->evt, UCPD_EVT_TX_MSG_FAIL);
1160 } else if (sr & (UCPD_SR_TXMSGDISC | UCPD_SR_HRSTDISC)) {
1161 atomic_set_bit(&info->evt, UCPD_EVT_TX_MSG_DISC);
1162 } else if (sr & UCPD_SR_HRSTSENT) {
1163 atomic_set_bit(&info->evt, UCPD_EVT_HR_DONE);
1164 } else if (sr & UCPD_SR_HRSTDISC) {
1165 atomic_set_bit(&info->evt, UCPD_EVT_HR_FAIL);
1166 }
1167
1168 /* Disable Tx interrupts */
1169 ucpd_tx_interrupts_enable(dev, 0);
1170 }
1171
1172 /* Check for data register empty */
1173 if (sr & UCPD_SR_TXIS) {
1174 ucpd_tx_data_byte(dev);
1175 }
1176
1177 /* Check for Rx Events */
1178 /* Check first for start of new message */
1179 if (sr & UCPD_SR_RXORDDET) {
1180 /* Add message type to pd message buffer */
1181 *(uint16_t *)data->ucpd_rx_buffer =
1182 LL_UCPD_ReadRxOrderSet(config->ucpd_port);
1183
1184 data->ucpd_rx_byte_count = 2;
1185 data->ucpd_rx_msg_active = true;
1186 }
1187 /* Check for byte received */
1188 if (sr & UCPD_SR_RXNE) {
1189 ucpd_rx_data_byte(dev);
1190 }
1191
1192 /* Check for end of message */
1193 if (sr & UCPD_SR_RXMSGEND) {
1194 data->ucpd_rx_msg_active = false;
1195 /* Check for errors */
1196 if (!(sr & UCPD_SR_RXERR)) {
1197 enum pd_packet_type type;
1198 union pd_header rx_header;
1199 int good_crc;
1200
1201 type = *(uint16_t *)data->ucpd_rx_buffer;
1202 rx_header.raw_value =
1203 *((uint16_t *)data->ucpd_rx_buffer + 1);
1204 good_crc = ucpd_msg_is_good_crc(rx_header);
1205
1206 /*
1207 * Don't pass GoodCRC control messages to the TCPM
1208 * layer. In addition, need to filter for SOP'/SOP''
1209 * packets if those are not enabled. SOP'/SOP''
1210 * reception is controlled by a static variable. The
1211 * hardware orderset detection pattern can't be changed
1212 * without disabling the ucpd peripheral.
1213 */
1214 if (!good_crc && (data->ucpd_rx_sop_prime_enabled ||
1215 type == PD_PACKET_SOP)) {
1216
1217 /*
1218 * If BIST test mode is active, then still need
1219 * to send GoodCRC reply, but there is no need
1220 * to send the message up to the tcpm layer.
1221 */
1222 if (!data->ucpd_rx_bist_mode) {
1223 atomic_set_bit(&info->evt, UCPD_EVT_RX_MSG);
1224 }
1225 /* Send GoodCRC message (if required) */
1226 ucpd_send_good_crc(dev, rx_header);
1227 } else if (good_crc) {
1228 atomic_set_bit(&info->evt, UCPD_EVT_RX_GOOD_CRC);
1229 data->ucpd_crc_id = rx_header.message_id;
1230 }
1231 } else {
1232 /* Rx message is complete, but there were bit errors */
1233 LOG_ERR("ucpd: rx message error");
1234 }
1235 }
1236 /* Check for fault conditions */
1237 if (sr & UCPD_SR_RXHRSTDET) {
1238 /* hard reset received */
1239 atomic_set_bit(&info->evt, UCPD_EVT_HARD_RESET_RECEIVED);
1240 }
1241
1242 /* Clear interrupts now that PD events have been set */
1243 LL_UCPD_WriteReg(config->ucpd_port, ICR, sr & UCPD_ICR_ALL_INT_MASK);
1244
1245 /* Notify application of events */
1246 k_work_submit(&info->work);
1247 }
1248
1249 /**
1250 * @brief Dump a set of TCPC registers
1251 *
1252 * @retval 0 on success
1253 * @retval -EIO on failure
1254 */
ucpd_dump_std_reg(const struct device * dev)1255 static int ucpd_dump_std_reg(const struct device *dev)
1256 {
1257 const struct tcpc_config *const config = dev->config;
1258
1259 LOG_INF("CFGR1: %08x", LL_UCPD_ReadReg(config->ucpd_port, CFG1));
1260 LOG_INF("CFGR2: %08x", LL_UCPD_ReadReg(config->ucpd_port, CFG2));
1261 LOG_INF("CR: %08x", LL_UCPD_ReadReg(config->ucpd_port, CR));
1262 LOG_INF("IMR: %08x", LL_UCPD_ReadReg(config->ucpd_port, IMR));
1263 LOG_INF("SR: %08x", LL_UCPD_ReadReg(config->ucpd_port, SR));
1264 LOG_INF("ICR: %08x\n", LL_UCPD_ReadReg(config->ucpd_port, ICR));
1265
1266 return 0;
1267 }
1268
1269 /**
1270 * @brief Sets the alert function that's called when an interrupt is triggered
1271 * due to a TCPC alert
1272 *
1273 * @retval 0 on success
1274 * @retval -EINVAL on failure
1275 */
ucpd_set_alert_handler_cb(const struct device * dev,tcpc_alert_handler_cb_t handler,void * alert_data)1276 static int ucpd_set_alert_handler_cb(const struct device *dev,
1277 tcpc_alert_handler_cb_t handler, void *alert_data)
1278 {
1279 struct tcpc_data *data = dev->data;
1280
1281 data->alert_info.handler = handler;
1282 data->alert_info.data = alert_data;
1283
1284 return 0;
1285 }
1286
1287 /**
1288 * @brief Sets a callback that can enable or disable VCONN if the TCPC is
1289 * unable to or the system is configured in a way that does not use
1290 * the VCONN control capabilities of the TCPC
1291 *
1292 */
ucpd_set_vconn_cb(const struct device * dev,tcpc_vconn_control_cb_t vconn_cb)1293 static void ucpd_set_vconn_cb(const struct device *dev,
1294 tcpc_vconn_control_cb_t vconn_cb)
1295 {
1296 struct tcpc_data *data = dev->data;
1297
1298 data->vconn_cb = vconn_cb;
1299 }
1300
1301 /**
1302 * @brief Sets a callback that can discharge VCONN if the TCPC is
1303 * unable to or the system is configured in a way that does not use
1304 * the VCONN discharge capabilities of the TCPC
1305 *
1306 */
ucpd_set_vconn_discharge_cb(const struct device * dev,tcpc_vconn_discharge_cb_t cb)1307 static void ucpd_set_vconn_discharge_cb(const struct device *dev,
1308 tcpc_vconn_discharge_cb_t cb)
1309 {
1310 struct tcpc_data *data = dev->data;
1311
1312 data->vconn_discharge_cb = cb;
1313 }
1314
1315 /**
1316 * @brief UCPD interrupt init
1317 */
ucpd_isr_init(const struct device * dev)1318 static void ucpd_isr_init(const struct device *dev)
1319 {
1320 const struct tcpc_config *const config = dev->config;
1321 struct tcpc_data *data = dev->data;
1322 struct alert_info *info = &data->alert_info;
1323
1324 /* Init GoodCRC Receive timer */
1325 k_timer_init(&data->goodcrc_rx_timer, NULL, NULL);
1326
1327 /* Disable all alert bits */
1328 LL_UCPD_WriteReg(config->ucpd_port, IMR, 0);
1329
1330 /* Clear all alert handler */
1331 ucpd_set_alert_handler_cb(dev, NULL, NULL);
1332
1333 /* Save device structure for use in the alert handlers */
1334 info->dev = dev;
1335
1336 /* Initialize the work handler */
1337 k_work_init(&info->work, ucpd_alert_handler);
1338
1339 /* Configure CC change alerts */
1340 LL_UCPD_WriteReg(config->ucpd_port, IMR,
1341 UCPD_IMR_TYPECEVT1IE | UCPD_IMR_TYPECEVT2IE);
1342 LL_UCPD_WriteReg(config->ucpd_port, ICR,
1343 UCPD_ICR_TYPECEVT1CF | UCPD_ICR_TYPECEVT2CF);
1344
1345 /* SOP'/SOP'' must be enabled via TCPCI call */
1346 data->ucpd_rx_sop_prime_enabled = false;
1347
1348 stm32_ucpd_state_init(dev);
1349
1350 /* Configure and enable the IRQ */
1351 config_tcpc_irq();
1352 }
1353
1354 /**
1355 * @brief Initializes the TCPC
1356 *
1357 * @retval 0 on success
1358 * @retval -EIO on failure
1359 */
ucpd_init(const struct device * dev)1360 static int ucpd_init(const struct device *dev)
1361 {
1362 const struct tcpc_config *const config = dev->config;
1363 struct tcpc_data *data = dev->data;
1364 uint32_t cfg1;
1365 int ret;
1366
1367 LOG_DBG("Pinctrl signals configuration");
1368 ret = pinctrl_apply_state(config->ucpd_pcfg, PINCTRL_STATE_DEFAULT);
1369 if (ret != 0) {
1370 LOG_ERR("USB pinctrl setup failed (%d)", ret);
1371 return ret;
1372 }
1373
1374 /*
1375 * The UCPD port is disabled in the LL_UCPD_Init function
1376 *
1377 * NOTE: For proper Power Management operation, this function
1378 * should not be used because it circumvents the zephyr
1379 * clock API. Instead, DTS clock settings and the zephyr
1380 * clock API should be used to enable clocks.
1381 */
1382 ret = LL_UCPD_Init(config->ucpd_port,
1383 (LL_UCPD_InitTypeDef *)&config->ucpd_params);
1384
1385 if (ret == SUCCESS) {
1386 /* Init Rp to USB */
1387 data->rp = TC_RP_USB;
1388
1389 /*
1390 * Set RXORDSETEN field to control which types of ordered sets the PD
1391 * receiver must receive.
1392 */
1393 cfg1 = LL_UCPD_ReadReg(config->ucpd_port, CFG1);
1394 cfg1 |= LL_UCPD_ORDERSET_SOP | LL_UCPD_ORDERSET_SOP1 |
1395 LL_UCPD_ORDERSET_SOP2 | LL_UCPD_ORDERSET_HARDRST;
1396 LL_UCPD_WriteReg(config->ucpd_port, CFG1, cfg1);
1397
1398 /* Enable UCPD port */
1399 LL_UCPD_Enable(config->ucpd_port);
1400
1401 /* Enable Dead Battery Support */
1402 if (config->ucpd_dead_battery) {
1403 dead_battery(dev, true);
1404 } else {
1405 /*
1406 * Some devices have dead battery enabled by default
1407 * after power up, so disable it
1408 */
1409 dead_battery(dev, false);
1410 }
1411
1412 /* Initialize the isr */
1413 ucpd_isr_init(dev);
1414 } else {
1415 return -EIO;
1416 }
1417
1418 return 0;
1419 }
1420
1421 static DEVICE_API(tcpc, driver_api) = {
1422 .init = ucpd_init,
1423 .set_alert_handler_cb = ucpd_set_alert_handler_cb,
1424 .get_cc = ucpd_get_cc,
1425 .set_rx_enable = ucpd_set_rx_enable,
1426 .get_rx_pending_msg = ucpd_get_rx_pending_msg,
1427 .transmit_data = ucpd_transmit_data,
1428 .select_rp_value = ucpd_select_rp_value,
1429 .get_rp_value = ucpd_get_rp_value,
1430 .set_cc = ucpd_set_cc,
1431 .set_roles = ucpd_set_roles,
1432 .set_vconn_cb = ucpd_set_vconn_cb,
1433 .set_vconn_discharge_cb = ucpd_set_vconn_discharge_cb,
1434 .set_vconn = ucpd_set_vconn,
1435 .vconn_discharge = ucpd_vconn_discharge,
1436 .set_cc_polarity = ucpd_cc_set_polarity,
1437 .dump_std_reg = ucpd_dump_std_reg,
1438 .set_bist_test_mode = ucpd_set_bist_test_mode,
1439 .sop_prime_enable = ucpd_sop_prime_enable,
1440 };
1441
1442 #define DEV_INST_INIT(n) dev_inst[n] = DEVICE_DT_INST_GET(n);
config_tcpc_irq(void)1443 static void config_tcpc_irq(void)
1444 {
1445 static int inst_num;
1446 static const struct device
1447 *dev_inst[DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT)];
1448
1449 /* Initialize and enable shared irq on last instance */
1450 if (++inst_num == DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT)) {
1451 DT_INST_FOREACH_STATUS_OKAY(DEV_INST_INIT)
1452
1453 IRQ_CONNECT(DT_INST_IRQN(0),
1454 DT_INST_IRQ(0, priority),
1455 ucpd_isr, dev_inst, 0);
1456
1457 irq_enable(DT_INST_IRQN(0));
1458 }
1459 }
1460
1461 BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) > 0,
1462 "No compatible STM32 TCPC instance found");
1463
1464 #define TCPC_DRIVER_INIT(inst) \
1465 PINCTRL_DT_INST_DEFINE(inst); \
1466 static struct tcpc_data drv_data_##inst; \
1467 static const struct tcpc_config drv_config_##inst = { \
1468 .ucpd_pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
1469 .ucpd_port = (UCPD_TypeDef *)DT_INST_REG_ADDR(inst), \
1470 .ucpd_params.psc_ucpdclk = ilog2(DT_INST_PROP(inst, psc_ucpdclk)), \
1471 .ucpd_params.transwin = DT_INST_PROP(inst, transwin) - 1, \
1472 .ucpd_params.IfrGap = DT_INST_PROP(inst, ifrgap) - 1, \
1473 .ucpd_params.HbitClockDiv = DT_INST_PROP(inst, hbitclkdiv) - 1, \
1474 .ucpd_dead_battery = DT_INST_PROP(inst, dead_battery), \
1475 }; \
1476 DEVICE_DT_INST_DEFINE(inst, \
1477 &ucpd_init, \
1478 NULL, \
1479 &drv_data_##inst, \
1480 &drv_config_##inst, \
1481 POST_KERNEL, \
1482 CONFIG_USBC_TCPC_INIT_PRIORITY, \
1483 &driver_api);
1484
1485 DT_INST_FOREACH_STATUS_OKAY(TCPC_DRIVER_INIT)
1486