1 /* 2 * Copyright (c) 2022 The Chromium OS Authors 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #ifndef ZEPHYR_SUBSYS_USBC_PE_COMMON_INTERNAL_H_ 8 #define ZEPHYR_SUBSYS_USBC_PE_COMMON_INTERNAL_H_ 9 10 #include <zephyr/kernel.h> 11 #include <zephyr/usb_c/usbc.h> 12 #include <zephyr/drivers/usb_c/usbc_pd.h> 13 #include <zephyr/drivers/usb_c/usbc_tc.h> 14 #include <zephyr/smf.h> 15 #include "usbc_timer.h" 16 17 /** 18 * @brief Used in sub-machines for message transmit and receive operation 19 */ 20 enum sm_msg_xmit { 21 /* Wait for a message transmission sub-machine state */ 22 SM_WAIT_FOR_TX, 23 /* Wait for a message reception sub-machine state */ 24 SM_WAIT_FOR_RX, 25 }; 26 27 /** 28 * @brief Used in sub-machines for message source hard reset operation 29 */ 30 enum sm_hard_reset { 31 /* Start the hard-reset sub-machine state */ 32 SM_HARD_RESET_START, 33 /* Wait for hard-reset to complete sub-machine state */ 34 SM_HARD_RESET_WAIT, 35 }; 36 37 /** 38 * @brief Policy Engine Errors 39 */ 40 enum pe_error { 41 /** Transmit error */ 42 ERR_XMIT, 43 }; 44 45 /** 46 * @brief Policy Engine Layer States 47 */ 48 enum usbc_pe_state { 49 /** PE_SNK_Startup */ 50 PE_SNK_STARTUP, 51 /** PE_SNK_Discovery */ 52 PE_SNK_DISCOVERY, 53 /** PE_SNK_Wait_for_Capabilities */ 54 PE_SNK_WAIT_FOR_CAPABILITIES, 55 /** PE_SNK_Evaluate_Capability */ 56 PE_SNK_EVALUATE_CAPABILITY, 57 /** PE_SNK_Select_Capability */ 58 PE_SNK_SELECT_CAPABILITY, 59 /** PE_SNK_Transition_Sink */ 60 PE_SNK_TRANSITION_SINK, 61 /** PE_SNK_Ready */ 62 PE_SNK_READY, 63 /** PE_SNK_Hard_Reset */ 64 PE_SNK_HARD_RESET, 65 /** PE_SNK_Transition_to_default */ 66 PE_SNK_TRANSITION_TO_DEFAULT, 67 /** PE_SNK_Give_Sink_Cap */ 68 PE_SNK_GIVE_SINK_CAP, 69 /** PE_SNK_Get_Source_Cap */ 70 PE_SNK_GET_SOURCE_CAP, 71 72 /** PE_SRC_Startup */ 73 PE_SRC_STARTUP, 74 /** PE_SRC_Discovery */ 75 PE_SRC_DISCOVERY, 76 /** PE_SRC_Send_Capabilities */ 77 PE_SRC_SEND_CAPABILITIES, 78 /** PE_SRC_Negotiate_capability */ 79 PE_SRC_NEGOTIATE_CAPABILITY, 80 /** PE_SRC_Capability_Response */ 81 PE_SRC_CAPABILITY_RESPONSE, 82 /** PE_SRC_Transition_Supply */ 83 PE_SRC_TRANSITION_SUPPLY, 84 /** PE_SRC_Ready */ 85 PE_SRC_READY, 86 /** PE_SRC_Disabled */ 87 PE_SRC_DISABLED, 88 /** PE_SRC_Hard_Reset */ 89 PE_SRC_HARD_RESET, 90 /** PE_SRC_Hard_Reset_Received */ 91 PE_SRC_HARD_RESET_RECEIVED, 92 /** PE_SRC_Transition_To_Default */ 93 PE_SRC_TRANSITION_TO_DEFAULT, 94 95 /** PE_SNK_Soft_Reset and PE_SRC_Soft_Reset */ 96 PE_SOFT_RESET, 97 /** PE_SNK_Chunk_Received or PE_SRC_Chunk_Received */ 98 PE_CHUNK_RECEIVED, 99 /**PE_Send_Soft_Reset */ 100 PE_SEND_SOFT_RESET, 101 102 /** PE_Send_Not_Supported */ 103 PE_SEND_NOT_SUPPORTED, 104 /** PE_DRS_Evaluate_Swap */ 105 PE_DRS_EVALUATE_SWAP, 106 /** PE_DRS_Send_Swap */ 107 PE_DRS_SEND_SWAP, 108 /** PE_Get_Sink_Cap */ 109 PE_GET_SINK_CAP, 110 111 /** PE_Suspend. Not part of the PD specification. */ 112 PE_SUSPEND, 113 114 /** 115 * NOTE: The states below should not be called directly. They're used 116 * internally by the state machine. 117 */ 118 119 /** PE_SENDER_RESPONSE_PARENT. Not part of the PD specification. */ 120 PE_SENDER_RESPONSE_PARENT, 121 /** PE_SRC_HARD_RESET_PARENT. Not part of the PD specification. */ 122 PE_SRC_HARD_RESET_PARENT, 123 /** Number of PE States */ 124 PE_STATE_COUNT 125 }; 126 127 /** 128 * @brief Policy Engine Layer Flags 129 */ 130 enum pe_flags { 131 /** Accept message received from port partner */ 132 PE_FLAGS_ACCEPT = 0, 133 /** A message we requested to be sent has been transmitted */ 134 PE_FLAGS_TX_COMPLETE = 1, 135 /** A message sent by a port partner has been received */ 136 PE_FLAGS_MSG_RECEIVED = 2, 137 /** 138 * A hard reset has been requested by the DPM but has not been sent, 139 * not currently used 140 */ 141 PE_FLAGS_HARD_RESET_PENDING = 3, 142 /** An explicit contract is in place with our port partner */ 143 PE_FLAGS_EXPLICIT_CONTRACT = 4, 144 /** 145 * Waiting for Sink Capabailities timed out. Used for retry error 146 * handling 147 */ 148 PE_FLAGS_SNK_WAIT_CAP_TIMEOUT = 5, 149 /** 150 * Flag to note current Atomic Message Sequence (AMS) is interruptible. 151 * If this flag is not set the AMS is non-interruptible. This flag must 152 * be set in the interruptible's message state entry. 153 */ 154 PE_FLAGS_INTERRUPTIBLE_AMS = 6, 155 /** Flag to trigger sending a Data Role Swap */ 156 PE_FLAGS_DR_SWAP_TO_DFP = 7, 157 /** Flag is set when an AMS is initiated by the Device Policy Manager */ 158 PE_FLAGS_DPM_INITIATED_AMS = 8, 159 /** Flag to note message was discarded due to incoming message */ 160 PE_FLAGS_MSG_DISCARDED = 9, 161 /** Flag to trigger sending a soft reset */ 162 PE_FLAGS_SEND_SOFT_RESET = 10, 163 /** 164 * This flag is set when a Wait message is received in response to a 165 * Sink REQUEST 166 */ 167 PE_FLAGS_WAIT_SINK_REQUEST = 11, 168 /** 169 * This flag is set when a Wait message is received in response to a 170 * Data Role Swap 171 */ 172 PE_FLAGS_WAIT_DATA_ROLE_SWAP = 12, 173 /** 174 * This flag is set when a protocol error occurs. 175 */ 176 PE_FLAGS_PROTOCOL_ERROR = 13, 177 /** This flag is set when a transmit error occurs. */ 178 PE_FLAGS_MSG_XMIT_ERROR = 14, 179 180 /* The Port Partner is PD connected */ 181 PE_FLAGS_PD_CONNECTED = 15, 182 /* The Port partner has been PD connected at least once */ 183 PE_FLAGS_HAS_BEEN_PD_CONNECTED = 16, 184 /* A Protocol Error didn't generate a Soft Reset */ 185 PE_FLAGS_PROTOCOL_ERROR_NO_SOFT_RESET = 17, 186 /* This flag is set when the first AMS message is sent */ 187 PE_FLAGS_FIRST_MSG_SENT = 18, 188 /** Number of PE Flags */ 189 PE_FLAGS_COUNT 190 }; 191 192 /** 193 * @brief Policy Engine State Machine Object 194 */ 195 struct policy_engine { 196 /** state machine context */ 197 struct smf_ctx ctx; 198 /** Port device */ 199 const struct device *dev; 200 /** state machine flags */ 201 ATOMIC_DEFINE(flags, PE_FLAGS_COUNT); 202 /** current port power role (SOURCE or SINK) */ 203 enum tc_power_role power_role; 204 /** current port data role (DFP or UFP) */ 205 enum tc_data_role data_role; 206 /** port address where soft resets are sent */ 207 enum pd_packet_type soft_reset_sop; 208 /** DPM request */ 209 enum usbc_policy_request_t dpm_request; 210 /** generic variable used for simple in state statemachines */ 211 uint32_t submachine; 212 #ifdef CONFIG_USBC_CSM_SOURCE_ONLY 213 /** The Sink made a valid request of the Source if true */ 214 bool snk_request_can_be_met; 215 /** Outcome of the Sink request */ 216 enum usbc_snk_req_reply_t snk_request_reply; 217 /** Save Sink Request Object */ 218 uint32_t snk_request; 219 /** Present Contract stores the current Sink Request */ 220 uint32_t present_contract; 221 #endif 222 /* Counters */ 223 224 /** 225 * This counter is used to retry the Hard Reset whenever there is no 226 * response from the remote device. 227 */ 228 uint32_t hard_reset_counter; 229 230 #ifdef CONFIG_USBC_CSM_SOURCE_ONLY 231 /** 232 * This counter tracks the number of times a Source Caps message was 233 * sent. 234 */ 235 uint32_t caps_counter; 236 #endif 237 238 /* Timers */ 239 240 /** tSenderResponse timer */ 241 struct usbc_timer_t pd_t_sender_response; 242 /** tChunkingNotSupported timer */ 243 struct usbc_timer_t pd_t_chunking_not_supported; 244 /** Time to wait before resending message after WAIT reception */ 245 struct usbc_timer_t pd_t_wait_to_resend; 246 247 #ifdef CONFIG_USBC_CSM_SINK_ONLY 248 /** tTypeCSinkWaitCap timer */ 249 struct usbc_timer_t pd_t_typec_sink_wait_cap; 250 /** tPSTransition timer */ 251 struct usbc_timer_t pd_t_ps_transition; 252 /** tSinkRequest timer */ 253 struct usbc_timer_t pd_t_sink_request; 254 #else 255 /** tTypeCSendSourceCap timer */ 256 struct usbc_timer_t pd_t_typec_send_source_cap; 257 /** tNoResponse timer */ 258 struct usbc_timer_t pd_t_no_response; 259 /** tPSHardReset timer */ 260 struct usbc_timer_t pd_t_ps_hard_reset; 261 #endif /* CONFIG_USBC_CSM_SINK_ONLY */ 262 }; 263 264 /** 265 * @brief First message in AMS has been sent 266 * 267 * @param dev Pointer to the device structure for the driver instance 268 */ 269 void pe_first_msg_sent(const struct device *dev); 270 271 /** 272 * @brief Sets a Policy Engine state 273 * 274 * @param dev Pointer to the device structure for the driver instance 275 * @param state next PE State to enter 276 */ 277 void pe_set_state(const struct device *dev, const enum usbc_pe_state state); 278 279 /** 280 * @brief Get the Policy Engine's current state 281 * 282 * @param dev Pointer to the device structure for the driver instance 283 * @retval current PE state 284 */ 285 enum usbc_pe_state pe_get_state(const struct device *dev); 286 287 /** 288 * @brief Get the Policy Engine's previous state 289 * 290 * @param dev Pointer to the device structure for the driver instance 291 * @retval last PE state 292 */ 293 enum usbc_pe_state pe_get_last_state(const struct device *dev); 294 295 /** 296 * @brief Send a soft reset message 297 * 298 * @param dev Pointer to the device structure for the driver instance 299 * @param type SOP* to send soft reset message 300 */ 301 void pe_send_soft_reset(const struct device *dev, const enum pd_packet_type type); 302 303 /** 304 * @brief Send a Power Delivery Data Message 305 * 306 * @param dev Pointer to the device structure for the driver instance 307 * @param type SOP* to send message 308 * @param msg PD data message to send 309 */ 310 void pe_send_data_msg(const struct device *dev, 311 const enum pd_packet_type type, 312 const enum pd_data_msg_type msg); 313 314 /** 315 * @brief Send a Power Delivery Control Message 316 * 317 * @param dev Pointer to the device structure for the driver instance 318 * @param type SOP* to send message 319 * @param msg PD control message to send 320 */ 321 void pe_send_ctrl_msg(const struct device *dev, 322 const enum pd_packet_type type, 323 const enum pd_ctrl_msg_type msg); 324 325 /** 326 * @brief Request desired voltage from source. 327 * 328 * @param dev Pointer to the device structure for the driver instance 329 * @param rdo Request Data Object to send 330 */ 331 void pe_send_request_msg(const struct device *dev, const uint32_t rdo); 332 333 /** 334 * @brief Transitions state after receiving an extended message. 335 * 336 * @param dev Pointer to the device structure for the driver instance 337 */ 338 void extended_message_not_supported(const struct device *dev); 339 340 /** 341 * @brief Check if a specific control message was received 342 * 343 * @param dev Pointer to the device structure for the driver instance 344 * @param header message header containing the message 345 * @param mt message type to check 346 * @retval true if the header contains the message type, else false 347 */ 348 bool received_control_message(const struct device *dev, const union pd_header header, 349 const enum pd_ctrl_msg_type mt); 350 351 /** 352 * @brief Check if a specific data message was received 353 * 354 * @param dev Pointer to the device structure for the driver instance 355 * @param header message header containing the message 356 * @param mt message type to check 357 * @param true if the header contains the message type, else false 358 */ 359 bool received_data_message(const struct device *dev, const union pd_header header, 360 const enum pd_data_msg_type mt); 361 362 /** 363 * @brief Check a DPM policy 364 * 365 * @param dev Pointer to the device structure for the driver instance 366 * @param pc The DPM policy to check 367 * @retval true if the DPM approves the check, else false 368 */ 369 bool policy_check(const struct device *dev, const enum usbc_policy_check_t pc); 370 371 /** 372 * @brief Notify the DPM of a policy change 373 * 374 * @param dev Pointer to the device structure for the driver instance 375 * @param notify The notification to send the DPM 376 */ 377 void policy_notify(const struct device *dev, const enum usbc_policy_notify_t notify); 378 379 /** 380 * @brief Notify the DPM of a WAIT message reception 381 * 382 * @param dev Pointer to the device structure for the driver instance 383 * @param notify Wait message to send to DPM 384 * @retval true if the Policy Engine should wait and try the action again 385 */ 386 bool policy_wait_notify(const struct device *dev, const enum usbc_policy_wait_t notify); 387 388 /** 389 * @brief Send the received source caps to the DPM 390 * 391 * @param dev Pointer to the device structure for the driver instance 392 * @param pdos pointer to pdos to send 393 * @param num_pdos number of pdos to send 394 */ 395 void policy_set_src_cap(const struct device *dev, const uint32_t *pdos, const int num_pdos); 396 397 /** 398 * @brief Check if the sink request can be met by the DPM 399 */ 400 enum usbc_snk_req_reply_t policy_check_sink_request(const struct device *dev, 401 const uint32_t request_msg); 402 403 /** 404 * @brief Check if the Present Contract is still valid. 405 * 406 * @note The contract is considered "invalid" if the previous current/voltage 407 * are no longer available AND the sink fails to make a valid request. 408 */ 409 bool policy_present_contract_is_valid(const struct device *dev, const uint32_t present_contract); 410 411 /** 412 * @brief Get a Request Data Object from the DPM 413 * 414 * @param dev Pointer to the device structure for the driver instance 415 * @retval the RDO from the DPM 416 */ 417 uint32_t policy_get_request_data_object(const struct device *dev); 418 419 /** 420 * @brief Check if the sink is a default level 421 * 422 * @param dev Pointer to the device structure for the driver instance 423 * @retval true if sink is at default value, else false 424 */ 425 bool policy_is_snk_at_default(const struct device *dev); 426 427 /** 428 * @brief Get sink caps from the DPM 429 * 430 * @param dev Pointer to the device structure for the driver instance 431 * @param pdos pointer to pdo sink caps 432 * @param num_pdos number of pdo sink caps 433 */ 434 void policy_get_snk_cap(const struct device *dev, uint32_t **pdos, int *num_pdos); 435 436 /** 437 * @brief Check if Source Power Supply is ready 438 */ 439 bool policy_is_ps_ready(const struct device *dev); 440 441 /** 442 * @brief Informs the Device Policy Manager that the Sink 443 * is unable to use the current Source Caps and should 444 * should enable a different set of Source Caps. True 445 * is returned if new Source Caps are available, else 446 * false. 447 */ 448 bool policy_change_src_caps(const struct device *dev); 449 450 /** 451 * @brief End and atomic messaging sequence 452 */ 453 void pe_dpm_end_ams(const struct device *dev); 454 455 /** 456 * @brief Handle common DPM requests 457 * 458 * @param dev Pointer to the device structure for the driver instance 459 * @retval true if request was handled, else false 460 */ 461 bool common_dpm_requests(const struct device *dev); 462 463 /** 464 * @brief This function must only be called in the subsystem init function. 465 * 466 * @param dev Pointer to the device structure for the driver instance. 467 */ 468 void pe_subsys_init(const struct device *dev); 469 470 /** 471 * @brief Start the Policy Engine Layer state machine. This is only called 472 * from the Type-C state machine. 473 * 474 * @param dev Pointer to the device structure for the driver instance 475 */ 476 void pe_start(const struct device *dev); 477 478 /** 479 * @brief Suspend the Policy Engine Layer state machine. This is only called 480 * from the Type-C state machine. 481 * 482 * @param dev Pointer to the device structure for the driver instance 483 */ 484 void pe_suspend(const struct device *dev); 485 486 /** 487 * @brief Run the Policy Engine Layer state machine. This is called from the 488 * subsystems port stack thread 489 * 490 * @param dev Pointer to the device structure for the driver instance 491 * @param dpm_request Device Policy Manager request 492 */ 493 void pe_run(const struct device *dev, 494 const int32_t dpm_request); 495 496 /** 497 * @brief Query if the Policy Engine is running 498 * 499 * @param dev Pointer to the device structure for the driver instance 500 * 501 * @retval TRUE if the Policy Engine is running 502 * @retval FALSE if the Policy Engine is not running 503 */ 504 bool pe_is_running(const struct device *dev); 505 506 /** 507 * @brief Informs the Policy Engine that a message was successfully sent 508 * 509 * @param dev Pointer to the device structure for the driver instance 510 */ 511 void pe_message_sent(const struct device *dev); 512 513 /** 514 * @brief Informs the Policy Engine of an error. 515 * 516 * @param dev Pointer to the device structure for the driver instance 517 * @param e policy error 518 * @param type port partner address where error was generated 519 */ 520 void pe_report_error(const struct device *dev, 521 const enum pe_error e, 522 const enum pd_packet_type type); 523 524 /** 525 * @brief Informs the Policy Engine that a transmit message was discarded 526 * because of an incoming message. 527 * 528 * @param dev Pointer to the device structure for the driver instance 529 */ 530 void pe_report_discard(const struct device *dev); 531 532 /** 533 * @brief Called by the Protocol Layer to informs the Policy Engine 534 * that a message has been received. 535 * 536 * @param dev Pointer to the device structure for the driver instance 537 */ 538 void pe_message_received(const struct device *dev); 539 540 /** 541 * @brief Informs the Policy Engine that a hard reset was received. 542 * 543 * @param dev Pointer to the device structure for the driver instance 544 */ 545 void pe_got_hard_reset(const struct device *dev); 546 547 /** 548 * @brief Informs the Policy Engine that a soft reset was received. 549 * 550 * @param dev Pointer to the device structure for the driver instance 551 */ 552 void pe_got_soft_reset(const struct device *dev); 553 554 /** 555 * @brief Informs the Policy Engine that a hard reset was sent. 556 * 557 * @param dev Pointer to the device structure for the driver instance 558 */ 559 void pe_hard_reset_sent(const struct device *dev); 560 561 /** 562 * @brief Indicates if an explicit contract is in place 563 * 564 * @param dev Pointer to the device structure for the driver instance 565 * 566 * @retval true if an explicit contract is in place, else false 567 */ 568 bool pe_is_explicit_contract(const struct device *dev); 569 570 /* 571 * @brief Informs the Policy Engine that it should invalidate the 572 * explicit contract. 573 * 574 * @param dev Pointer to the device structure for the driver instance 575 */ 576 void pe_invalidate_explicit_contract(const struct device *dev); 577 578 /** 579 * @brief Return true if the PE is within an atomic messaging sequence 580 * that it initiated with a SOP* port partner. 581 * 582 * @note The PRL layer polls this instead of using AMS_START and AMS_END 583 * notification from the PE that is called out by the spec 584 * 585 * @param dev Pointer to the device structure for the driver instance 586 */ 587 bool pe_dpm_initiated_ams(const struct device *dev); 588 589 /** 590 * @brief Get the current data role 591 * 592 * @param dev Pointer to the device structure for the driver instance 593 * 594 * @retval data role 595 */ 596 enum tc_data_role pe_get_data_role(const struct device *dev); 597 598 /** 599 * @brief Sets the data role and updates the TCPC 600 * 601 * @param dev Pointer to the device structure for the driver instance 602 * @param dr Data Role to be set 603 */ 604 void pe_set_data_role(const struct device *dev, enum tc_data_role dr); 605 606 /** 607 * @brief Get the current power role 608 * 609 * @param dev Pointer to the device structure for the driver instance 610 * 611 * @retval power role 612 */ 613 enum tc_power_role pe_get_power_role(const struct device *dev); 614 615 /** 616 * @brief Get cable plug role 617 * 618 * @param dev Pointer to the device structure for the driver instance 619 * 620 * @retval cable plug role 621 */ 622 enum tc_cable_plug pe_get_cable_plug(const struct device *dev); 623 624 #endif /* ZEPHYR_SUBSYS_USBC_PE_COMMON_INTERNAL_H_ */ 625