summaryrefslogtreecommitdiff
path: root/common/usbc/usb_prl_sm.c
diff options
context:
space:
mode:
authorJack Rosenthal <jrosenth@chromium.org>2021-11-04 12:11:58 -0600
committerCommit Bot <commit-bot@chromium.org>2021-11-05 04:22:34 +0000
commit252457d4b21f46889eebad61d4c0a65331919cec (patch)
tree01856c4d31d710b20e85a74c8d7b5836e35c3b98 /common/usbc/usb_prl_sm.c
parent08f5a1e6fc2c9467230444ac9b582dcf4d9f0068 (diff)
downloadchrome-ec-release-R98-14388.B-ish.tar.gz
In the interest of making long-term branch maintenance incur as little technical debt on us as possible, we should not maintain any files on the branch we are not actually using. This has the added effect of making it extremely clear when merging CLs from the main branch when changes have the possibility to affect us. The follow-on CL adds a convenience script to actually pull updates from the main branch and generate a CL for the update. BUG=b:204206272 BRANCH=ish TEST=make BOARD=arcada_ish && make BOARD=drallion_ish Signed-off-by: Jack Rosenthal <jrosenth@chromium.org> Change-Id: I17e4694c38219b5a0823e0a3e55a28d1348f4b18 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3262038 Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Tom Hughes <tomhughes@chromium.org>
Diffstat (limited to 'common/usbc/usb_prl_sm.c')
-rw-r--r--common/usbc/usb_prl_sm.c2471
1 files changed, 0 insertions, 2471 deletions
diff --git a/common/usbc/usb_prl_sm.c b/common/usbc/usb_prl_sm.c
deleted file mode 100644
index a58a579775..0000000000
--- a/common/usbc/usb_prl_sm.c
+++ /dev/null
@@ -1,2471 +0,0 @@
-/* Copyright 2019 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "battery.h"
-#include "battery_smart.h"
-#include "board.h"
-#include "charge_manager.h"
-#include "charge_state.h"
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "cros_version.h"
-#include "ec_commands.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "registers.h"
-#include "system.h"
-#include "task.h"
-#include "tcpm/tcpm.h"
-#include "util.h"
-#include "usb_charge.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "usb_pd_timer.h"
-#include "usb_pe_sm.h"
-#include "usb_prl_sm.h"
-#include "usb_tc_sm.h"
-#include "usb_emsg.h"
-#include "usb_sm.h"
-#include "vpd_api.h"
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#else
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif
-
-/*
- * Define DEBUG_PRINT_FLAG_NAMES to print flag names when set and cleared.
- */
-#undef DEBUG_PRINT_FLAG_NAMES
-
-#ifdef DEBUG_PRINT_FLAG_NAMES
-__maybe_unused static void print_flag(const char *group,
- int set_or_clear,
- int flag);
-#define SET_FLAG(group, flags, flag) \
- do { \
- print_flag(group, 1, flag); \
- atomic_or(flags, (flag)); \
- } while (0)
-#define CLR_FLAG(group, flags, flag) \
- do { \
- int before = *flags; \
- atomic_clear_bits(flags, (flag)); \
- if (*flags != before) \
- print_flag(group, 0, flag); \
- } while (0)
-#else
-#define SET_FLAG(group, flags, flag) atomic_or(flags, (flag))
-#define CLR_FLAG(group, flags, flag) atomic_clear_bits(flags, (flag))
-#endif
-
-
-#define RCH_SET_FLAG(port, flag) SET_FLAG("RCH", &rch[port].flags, (flag))
-#define RCH_CLR_FLAG(port, flag) CLR_FLAG("RCH", &rch[port].flags, (flag))
-#define RCH_CHK_FLAG(port, flag) (rch[port].flags & (flag))
-
-#define TCH_SET_FLAG(port, flag) SET_FLAG("TCH", &tch[port].flags, (flag))
-#define TCH_CLR_FLAG(port, flag) CLR_FLAG("TCH", &tch[port].flags, (flag))
-#define TCH_CHK_FLAG(port, flag) (tch[port].flags & (flag))
-
-#define PRL_TX_SET_FLAG(port, flag) \
- SET_FLAG("PRL_TX", &prl_tx[port].flags, (flag))
-#define PRL_TX_CLR_FLAG(port, flag) \
- CLR_FLAG("PRL_TX", &prl_tx[port].flags, (flag))
-#define PRL_TX_CHK_FLAG(port, flag) (prl_tx[port].flags & (flag))
-
-#define PRL_HR_SET_FLAG(port, flag) \
- SET_FLAG("PRL_HR", &prl_hr[port].flags, (flag))
-#define PRL_HR_CLR_FLAG(port, flag) \
- CLR_FLAG("PRL_HR", &prl_hr[port].flags, (flag))
-#define PRL_HR_CHK_FLAG(port, flag) (prl_hr[port].flags & (flag))
-
-#define PDMSG_SET_FLAG(port, flag) SET_FLAG("PDMSG", &pdmsg[port].flags, (flag))
-#define PDMSG_CLR_FLAG(port, flag) CLR_FLAG("PDMSG", &pdmsg[port].flags, (flag))
-#define PDMSG_CHK_FLAG(port, flag) (pdmsg[port].flags & (flag))
-
-/* Protocol Layer Flags */
-/*
- * NOTE:
- * These flags are used in multiple state machines and could have
- * different meanings in each state machine.
- */
-/* Flag to note message transmission completed */
-#define PRL_FLAGS_TX_COMPLETE BIT(0)
-/* Flag to note that PRL requested to set SINK_NG CC state */
-#define PRL_FLAGS_SINK_NG BIT(1)
-/* Flag to note PRL waited for SINK_OK CC state before transmitting */
-#define PRL_FLAGS_WAIT_SINK_OK BIT(2)
-/* Flag to note transmission error occurred */
-#define PRL_FLAGS_TX_ERROR BIT(3)
-/* Flag to note PE triggered a hard reset */
-#define PRL_FLAGS_PE_HARD_RESET BIT(4)
-/* Flag to note hard reset has completed */
-#define PRL_FLAGS_HARD_RESET_COMPLETE BIT(5)
-/* Flag to note port partner sent a hard reset */
-#define PRL_FLAGS_PORT_PARTNER_HARD_RESET BIT(6)
-/*
- * Flag to note a message transmission has been requested. It is only cleared
- * when we send the message to the TCPC layer.
- */
-#define PRL_FLAGS_MSG_XMIT BIT(7)
-/* Flag to note a message was received */
-#define PRL_FLAGS_MSG_RECEIVED BIT(8)
-/* Flag to note aborting current TX message, not currently set */
-#define PRL_FLAGS_ABORT BIT(9)
-/* Flag to note current TX message uses chunking */
-#define PRL_FLAGS_CHUNKING BIT(10)
-
-struct bit_name {
- int value;
- const char *name;
-};
-
-static __const_data struct bit_name flag_bit_names[] = {
- { PRL_FLAGS_TX_COMPLETE, "PRL_FLAGS_TX_COMPLETE" },
- { PRL_FLAGS_SINK_NG, "PRL_FLAGS_SINK_NG" },
- { PRL_FLAGS_WAIT_SINK_OK, "PRL_FLAGS_WAIT_SINK_OK" },
- { PRL_FLAGS_TX_ERROR, "PRL_FLAGS_TX_ERROR" },
- { PRL_FLAGS_PE_HARD_RESET, "PRL_FLAGS_PE_HARD_RESET" },
- { PRL_FLAGS_HARD_RESET_COMPLETE, "PRL_FLAGS_HARD_RESET_COMPLETE" },
- { PRL_FLAGS_PORT_PARTNER_HARD_RESET,
- "PRL_FLAGS_PORT_PARTNER_HARD_RESET" },
- { PRL_FLAGS_MSG_XMIT, "PRL_FLAGS_MSG_XMIT" },
- { PRL_FLAGS_MSG_RECEIVED, "PRL_FLAGS_MSG_RECEIVED" },
- { PRL_FLAGS_ABORT, "PRL_FLAGS_ABORT" },
- { PRL_FLAGS_CHUNKING, "PRL_FLAGS_CHUNKING" },
-};
-
-__maybe_unused static void print_bits(const char *group,
- const char *desc,
- int value,
- struct bit_name *names,
- int names_size)
-{
- int i;
-
- CPRINTF("%s %s 0x%x : ", group, desc, value);
- for (i = 0; i < names_size; i++) {
- if (value & names[i].value)
- CPRINTF("%s | ", names[i].name);
- value &= ~names[i].value;
- }
- if (value != 0)
- CPRINTF("0x%x", value);
- CPRINTF("\n");
-}
-
-__maybe_unused static void print_flag(const char *group,
- int set_or_clear,
- int flag)
-{
- print_bits(group, set_or_clear ? "Set" : "Clr", flag, flag_bit_names,
- ARRAY_SIZE(flag_bit_names));
-}
-
-/* PD counter definitions */
-#define PD_MESSAGE_ID_COUNT 7
-
-/* Size of PDMSG Chunk Buffer */
-#define CHK_BUF_SIZE 7
-#define CHK_BUF_SIZE_BYTES 28
-
-/*
- * Debug log level - higher number == more log
- * Level 0: disabled
- * Level 1: not currently used
- * Level 2: plus non-ping messages
- * Level 3: plus ping packet and PRL states
- *
- * Note that higher log level causes timing changes and thus may affect
- * performance.
- */
-#ifdef CONFIG_USB_PD_DEBUG_LEVEL
-static const enum debug_level prl_debug_level = CONFIG_USB_PD_DEBUG_LEVEL;
-#else
-static enum debug_level prl_debug_level = DEBUG_LEVEL_1;
-#endif
-
-static enum sm_local_state local_state[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Protocol Transmit States (Section 6.11.2.2) */
-enum usb_prl_tx_state {
- PRL_TX_PHY_LAYER_RESET,
- PRL_TX_WAIT_FOR_MESSAGE_REQUEST,
- PRL_TX_LAYER_RESET_FOR_TRANSMIT,
- PRL_TX_WAIT_FOR_PHY_RESPONSE,
- PRL_TX_SRC_SOURCE_TX,
- PRL_TX_SNK_START_AMS,
- PRL_TX_SRC_PENDING,
- PRL_TX_SNK_PENDING,
- PRL_TX_DISCARD_MESSAGE,
-};
-
-/* Protocol Hard Reset States (Section 6.11.2.4) */
-enum usb_prl_hr_state {
- PRL_HR_WAIT_FOR_REQUEST,
- PRL_HR_RESET_LAYER,
- PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE,
- PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE,
-};
-
-/* Chunked Rx states (Section 6.11.2.1.2) */
-enum usb_rch_state {
- RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER,
- RCH_PASS_UP_MESSAGE,
- RCH_PROCESSING_EXTENDED_MESSAGE,
- RCH_REQUESTING_CHUNK,
- RCH_WAITING_CHUNK,
- RCH_REPORT_ERROR,
-};
-
-/* Chunked Tx states (Section 6.11.2.1.3) */
-enum usb_tch_state {
- TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE,
- TCH_WAIT_FOR_TRANSMISSION_COMPLETE,
- TCH_CONSTRUCT_CHUNKED_MESSAGE,
- TCH_SENDING_CHUNKED_MESSAGE,
- TCH_WAIT_CHUNK_REQUEST,
- TCH_MESSAGE_RECEIVED,
- TCH_MESSAGE_SENT,
- TCH_REPORT_ERROR,
-};
-
-static const char * const prl_tx_state_names[] = {
- [PRL_TX_PHY_LAYER_RESET] = "PRL_TX_PHY_LAYER_RESET",
- [PRL_TX_WAIT_FOR_MESSAGE_REQUEST] = "PRL_TX_WAIT_FOR_MESSAGE_REQUEST",
- [PRL_TX_LAYER_RESET_FOR_TRANSMIT] = "PRL_TX_LAYER_RESET_FOR_TRANSMIT",
- [PRL_TX_WAIT_FOR_PHY_RESPONSE] = "PRL_TX_WAIT_FOR_PHY_RESPONSE",
- [PRL_TX_SRC_SOURCE_TX] = "PRL_TX_SRC_SOURCE_TX",
- [PRL_TX_SNK_START_AMS] = "PRL_TX_SNK_START_AMS",
- [PRL_TX_SRC_PENDING] = "PRL_TX_SRC_PENDING",
- [PRL_TX_SNK_PENDING] = "PRL_TX_SNK_PENDING",
- [PRL_TX_DISCARD_MESSAGE] = "PRL_TX_DISCARD_MESSAGE",
-};
-
-static const char * const prl_hr_state_names[] = {
- [PRL_HR_WAIT_FOR_REQUEST] = "PRL_HR_WAIT_FOR_REQUEST",
- [PRL_HR_RESET_LAYER] = "PRL_HR_RESET_LAYER",
- [PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE]
- = "PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE",
- [PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE]
- = "PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE",
-};
-
-__maybe_unused static const char * const rch_state_names[] = {
- [RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER]
- = "RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER",
- [RCH_PASS_UP_MESSAGE] = "RCH_PASS_UP_MESSAGE",
- [RCH_PROCESSING_EXTENDED_MESSAGE] = "RCH_PROCESSING_EXTENDED_MESSAGE",
- [RCH_REQUESTING_CHUNK] = "RCH_REQUESTING_CHUNK",
- [RCH_WAITING_CHUNK] = "RCH_WAITING_CHUNK",
- [RCH_REPORT_ERROR] = "RCH_REPORT_ERROR",
-};
-
-__maybe_unused static const char * const tch_state_names[] = {
- [TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE]
- = "TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE",
- [TCH_WAIT_FOR_TRANSMISSION_COMPLETE]
- = "TCH_WAIT_FOR_TRANSMISSION_COMPLETE",
- [TCH_CONSTRUCT_CHUNKED_MESSAGE] = "TCH_CONSTRUCT_CHUNKED_MESSAGE",
- [TCH_SENDING_CHUNKED_MESSAGE] = "TCH_SENDING_CHUNKED_MESSAGE",
- [TCH_WAIT_CHUNK_REQUEST] = "TCH_WAIT_CHUNK_REQUEST",
- [TCH_MESSAGE_RECEIVED] = "TCH_MESSAGE_RECEIVED",
- [TCH_MESSAGE_SENT] = "TCH_MESSAGE_SENT",
- [TCH_REPORT_ERROR] = "TCH_REPORT_ERROR",
-};
-
-/* Forward declare full list of states. Index by above enums. */
-static const struct usb_state prl_tx_states[];
-static const struct usb_state prl_hr_states[];
-
-__maybe_unused static const struct usb_state rch_states[];
-__maybe_unused static const struct usb_state tch_states[];
-
-/* Chunked Rx State Machine Object */
-static struct rx_chunked {
- /* state machine context */
- struct sm_ctx ctx;
- /* PRL_FLAGS */
- uint32_t flags;
- /* error to report when moving to rch_report_error state */
- enum pe_error error;
-} rch[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Chunked Tx State Machine Object */
-static struct tx_chunked {
- /* state machine context */
- struct sm_ctx ctx;
- /* state machine flags */
- uint32_t flags;
- /* error to report when moving to tch_report_error state */
- enum pe_error error;
-} tch[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Message Reception State Machine Object */
-static struct protocol_layer_rx {
- /* received message type */
- enum tcpci_msg_type sop;
- /* message ids for all valid port partners */
- int msg_id[NUM_SOP_STAR_TYPES];
-} prl_rx[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Message Transmission State Machine Object */
-static struct protocol_layer_tx {
- /* state machine context */
- struct sm_ctx ctx;
- /* state machine flags */
- uint32_t flags;
- /* last message type we transmitted */
- enum tcpci_msg_type last_xmit_type;
- /* message id counters for all 6 port partners */
- uint32_t msg_id_counter[NUM_SOP_STAR_TYPES];
- /* transmit status */
- int xmit_status;
-} prl_tx[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Hard Reset State Machine Object */
-static struct protocol_hard_reset {
- /* state machine context */
- struct sm_ctx ctx;
- /* state machine flags */
- uint32_t flags;
-} prl_hr[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Chunking Message Object */
-static struct pd_message {
- /* message status flags */
- uint32_t flags;
- /* SOP* */
- enum tcpci_msg_type xmit_type;
- /* type of message */
- uint8_t msg_type;
- /* PD revision */
- enum pd_rev_type rev[NUM_SOP_STAR_TYPES];
- /* Number of 32-bit objects in chk_buf */
- uint16_t data_objs;
- /* temp chunk buffer */
- uint32_t tx_chk_buf[CHK_BUF_SIZE];
- uint32_t rx_chk_buf[CHK_BUF_SIZE];
- uint32_t chunk_number_expected;
- uint32_t num_bytes_received;
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- /* extended message */
- uint8_t ext;
- uint32_t chunk_number_to_send;
- uint32_t send_offset;
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-} pdmsg[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-struct extended_msg rx_emsg[CONFIG_USB_PD_PORT_MAX_COUNT];
-struct extended_msg tx_emsg[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Common Protocol Layer Message Transmission */
-static void prl_tx_construct_message(int port);
-static void prl_rx_wait_for_phy_message(const int port, int evt);
-static void prl_copy_msg_to_buffer(int port);
-
-#ifndef CONFIG_USB_PD_REV30
-GEN_NOT_SUPPORTED(PRL_TX_SRC_SOURCE_TX);
-#define PRL_TX_SRC_SOURCE_TX PRL_TX_SRC_SOURCE_TX_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(PRL_TX_SNK_START_AMS);
-#define PRL_TX_SNK_START_AMS PRL_TX_SNK_START_AMS_NOT_SUPPORTED
-
-GEN_NOT_SUPPORTED(RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER);
-#define RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER \
- RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(RCH_PASS_UP_MESSAGE);
-#define RCH_PASS_UP_MESSAGE RCH_PASS_UP_MESSAGE_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(RCH_PROCESSING_EXTENDED_MESSAGE);
-#define RCH_PROCESSING_EXTENDED_MESSAGE \
- RCH_PROCESSING_EXTENDED_MESSAGE_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(RCH_REQUESTING_CHUNK);
-#define RCH_REQUESTING_CHUNK RCH_REQUESTING_CHUNK_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(RCH_WAITING_CHUNK);
-#define RCH_WAITING_CHUNK RCH_WAITING_CHUNK_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(RCH_REPORT_ERROR);
-#define RCH_REPORT_ERROR RCH_REPORT_ERROR_NOT_SUPPORTED
-
-GEN_NOT_SUPPORTED(TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
-#define TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE \
- TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(TCH_WAIT_FOR_TRANSMISSION_COMPLETE);
-#define TCH_WAIT_FOR_TRANSMISSION_COMPLETE \
- TCH_WAIT_FOR_TRANSMISSION_COMPLETE_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(TCH_CONSTRUCT_CHUNKED_MESSAGE);
-#define TCH_CONSTRUCT_CHUNKED_MESSAGE \
- TCH_CONSTRUCT_CHUNKED_MESSAGE_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(TCH_SENDING_CHUNKED_MESSAGE);
-#define TCH_SENDING_CHUNKED_MESSAGE TCH_SENDING_CHUNKED_MESSAGE_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(TCH_WAIT_CHUNK_REQUEST);
-#define TCH_WAIT_CHUNK_REQUEST TCH_WAIT_CHUNK_REQUEST_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(TCH_MESSAGE_RECEIVED);
-#define TCH_MESSAGE_RECEIVED TCH_MESSAGE_RECEIVED_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(TCH_MESSAGE_SENT);
-#define TCH_MESSAGE_SENT TCH_MESSAGE_SENT_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(TCH_REPORT_ERROR);
-#define TCH_REPORT_ERROR TCH_REPORT_ERROR_NOT_SUPPORTED
-#endif /* !CONFIG_USB_PD_REV30 */
-
-/* To store the time stamp when TCPC sets TX Complete Success */
-static timestamp_t tcpc_tx_success_ts[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Set the protocol transmit statemachine to a new state. */
-static void set_state_prl_tx(const int port,
- const enum usb_prl_tx_state new_state)
-{
- set_state(port, &prl_tx[port].ctx, &prl_tx_states[new_state]);
-}
-
-/* Get the protocol transmit statemachine's current state. */
-test_export_static enum usb_prl_tx_state prl_tx_get_state(const int port)
-{
- return prl_tx[port].ctx.current - &prl_tx_states[0];
-}
-
-/* Print the protocol transmit statemachine's current state. */
-static void print_current_prl_tx_state(const int port)
-{
- if (prl_debug_level >= DEBUG_LEVEL_3)
- CPRINTS("C%d: %s", port,
- prl_tx_state_names[prl_tx_get_state(port)]);
-}
-
-/* Set the hard reset statemachine to a new state. */
-static void set_state_prl_hr(const int port,
- const enum usb_prl_hr_state new_state)
-{
- set_state(port, &prl_hr[port].ctx, &prl_hr_states[new_state]);
-}
-
-/* Get the hard reset statemachine's current state. */
-enum usb_prl_hr_state prl_hr_get_state(const int port)
-{
- return prl_hr[port].ctx.current - &prl_hr_states[0];
-}
-
-/* Print the hard reset statemachine's current state. */
-static void print_current_prl_hr_state(const int port)
-{
- if (prl_debug_level >= DEBUG_LEVEL_3)
- CPRINTS("C%d: %s", port,
- prl_hr_state_names[prl_hr_get_state(port)]);
-}
-
-/* Set the chunked Rx statemachine to a new state. */
-static void set_state_rch(const int port, const enum usb_rch_state new_state)
-{
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES))
- set_state(port, &rch[port].ctx, &rch_states[new_state]);
-}
-
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
-/* Get the chunked Rx statemachine's current state. */
-test_export_static enum usb_rch_state rch_get_state(const int port)
-{
- return rch[port].ctx.current - &rch_states[0];
-}
-
-/* Print the chunked Rx statemachine's current state. */
-static void print_current_rch_state(const int port)
-{
- if (prl_debug_level >= DEBUG_LEVEL_3)
- CPRINTS("C%d: %s", port,
- rch_state_names[rch_get_state(port)]);
-}
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-
-/* Set the chunked Tx statemachine to a new state. */
-static void set_state_tch(const int port, const enum usb_tch_state new_state)
-{
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES))
- set_state(port, &tch[port].ctx, &tch_states[new_state]);
-}
-
-/* Get the chunked Tx statemachine's current state. */
-test_export_static enum usb_tch_state tch_get_state(const int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES))
- return tch[port].ctx.current - &tch_states[0];
- else
- return 0;
-}
-
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
-/* Print the chunked Tx statemachine's current state. */
-static void print_current_tch_state(const int port)
-{
- if (prl_debug_level >= DEBUG_LEVEL_3)
- CPRINTS("C%d: %s", port,
- tch_state_names[tch_get_state(port)]);
-}
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-
-
-timestamp_t prl_get_tcpc_tx_success_ts(int port)
-{
- return tcpc_tx_success_ts[port];
-}
-
-/* Sets the time stamp when TCPC reports TX success. */
-static void set_tcpc_tx_success_ts(int port)
-{
- tcpc_tx_success_ts[port] = get_time();
-}
-
-void pd_transmit_complete(int port, int status)
-{
- if (status == TCPC_TX_COMPLETE_SUCCESS)
- set_tcpc_tx_success_ts(port);
- prl_tx[port].xmit_status = status;
-}
-
-void pd_execute_hard_reset(int port)
-{
- /* Only allow async. function calls when state machine is running */
- if (!prl_is_running(port))
- return;
-
- PRL_HR_SET_FLAG(port, PRL_FLAGS_PORT_PARTNER_HARD_RESET);
- set_state_prl_hr(port, PRL_HR_RESET_LAYER);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void prl_execute_hard_reset(int port)
-{
- /* Only allow async. function calls when state machine is running */
- if (!prl_is_running(port))
- return;
-
- PRL_HR_SET_FLAG(port, PRL_FLAGS_PE_HARD_RESET);
- set_state_prl_hr(port, PRL_HR_RESET_LAYER);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-int prl_is_running(int port)
-{
- return local_state[port] == SM_RUN;
-}
-
-static void prl_init(int port)
-{
- int i;
- const struct sm_ctx cleared = {};
-
- /*
- * flags without PRL_FLAGS_SINK_NG present means we are initially
- * in SinkTxOK state
- */
- prl_tx[port].flags = 0;
- if (IS_ENABLED(CONFIG_USB_PD_REV30))
- typec_select_src_collision_rp(port, SINK_TX_OK);
- prl_tx[port].last_xmit_type = TCPCI_MSG_SOP;
- prl_tx[port].xmit_status = TCPC_TX_UNSET;
-
- if (IS_ENABLED(CONFIG_USB_PD_REV30)) {
- tch[port].flags = 0;
- rch[port].flags = 0;
- }
-
- pdmsg[port].flags = 0;
-
- prl_hr[port].flags = 0;
-
- for (i = 0; i < NUM_SOP_STAR_TYPES; i++) {
- prl_rx[port].msg_id[i] = -1;
- prl_tx[port].msg_id_counter[i] = 0;
- }
-
- pd_timer_disable_range(port, PR_TIMER_RANGE);
-
- /* Clear state machines and set initial states */
- prl_tx[port].ctx = cleared;
- set_state_prl_tx(port, PRL_TX_PHY_LAYER_RESET);
-
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) {
- rch[port].ctx = cleared;
- set_state_rch(port, RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER);
-
- tch[port].ctx = cleared;
- set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
- }
-
- prl_hr[port].ctx = cleared;
- set_state_prl_hr(port, PRL_HR_WAIT_FOR_REQUEST);
-}
-
-bool prl_is_busy(int port)
-{
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- return rch_get_state(port) !=
- RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER ||
- tch_get_state(port) !=
- TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE;
-#else
- return false;
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-}
-
-void prl_set_debug_level(enum debug_level debug_level)
-{
-#ifndef CONFIG_USB_PD_DEBUG_LEVEL
- prl_debug_level = debug_level;
-#endif
-}
-
-void prl_hard_reset_complete(int port)
-{
- PRL_HR_SET_FLAG(port, PRL_FLAGS_HARD_RESET_COMPLETE);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void prl_send_ctrl_msg(int port,
- enum tcpci_msg_type type,
- enum pd_ctrl_msg_type msg)
-{
- pdmsg[port].xmit_type = type;
- pdmsg[port].msg_type = msg;
- pdmsg[port].data_objs = 0;
- tx_emsg[port].len = 0;
-
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- pdmsg[port].ext = 0;
-
- TCH_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
-#else
- PRL_TX_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void prl_send_data_msg(int port,
- enum tcpci_msg_type type,
- enum pd_data_msg_type msg)
-{
- pdmsg[port].xmit_type = type;
- pdmsg[port].msg_type = msg;
-
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- pdmsg[port].ext = 0;
-
- TCH_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
-#else
- prl_copy_msg_to_buffer(port);
- PRL_TX_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
-void prl_send_ext_data_msg(int port,
- enum tcpci_msg_type type,
- enum pd_ext_msg_type msg)
-{
- pdmsg[port].xmit_type = type;
- pdmsg[port].msg_type = msg;
- pdmsg[port].ext = 1;
-
- TCH_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-
-void prl_set_default_pd_revision(int port)
-{
- /*
- * Initialize to highest revision supported. If the port or cable
- * partner doesn't support this revision, the Protocol Engine will
- * lower this value to the revision supported by the partner.
- */
- pdmsg[port].rev[TCPCI_MSG_SOP] = PD_REVISION;
- pdmsg[port].rev[TCPCI_MSG_SOP_PRIME] = PD_REVISION;
- pdmsg[port].rev[TCPCI_MSG_SOP_PRIME_PRIME] = PD_REVISION;
- pdmsg[port].rev[TCPCI_MSG_SOP_DEBUG_PRIME] = PD_REVISION;
- pdmsg[port].rev[TCPCI_MSG_SOP_DEBUG_PRIME_PRIME] = PD_REVISION;
-}
-
-void prl_reset_soft(int port)
-{
- /* Do not change negotiated PD Revision Specification level */
- local_state[port] = SM_INIT;
-
- /* Ensure we process the reset quickly */
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void prl_run(int port, int evt, int en)
-{
- switch (local_state[port]) {
- case SM_PAUSED:
- if (!en)
- break;
- /* fall through */
- case SM_INIT:
- prl_init(port);
- local_state[port] = SM_RUN;
- /* fall through */
- case SM_RUN:
- if (!en) {
- /* Disable RX */
- if (IS_ENABLED(CONFIG_USB_CTVPD) ||
- IS_ENABLED(CONFIG_USB_VPD))
- vpd_rx_enable(0);
- else
- tcpm_set_rx_enable(port, 0);
-
- local_state[port] = SM_PAUSED;
- break;
- }
-
- /* Run Protocol Layer Hard Reset state machine */
- run_state(port, &prl_hr[port].ctx);
-
- /*
- * If the Hard Reset state machine is active, then there is no
- * need to execute any other PRL state machines. When the hard
- * reset is complete, all PRL state machines will have been
- * reset.
- */
- if (prl_hr_get_state(port) == PRL_HR_WAIT_FOR_REQUEST) {
-
- /* Run Protocol Layer Message Reception */
- prl_rx_wait_for_phy_message(port, evt);
-
-
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) {
- /*
- * Run RX Chunked state machine after prl_rx.
- * This is what informs the PE of incoming
- * message. Its input is prl_rx
- */
- run_state(port, &rch[port].ctx);
-
- /*
- * Run TX Chunked state machine before prl_tx
- * in case we need to split an extended message
- * and prl_tx can send it for us
- */
- run_state(port, &tch[port].ctx);
- }
-
- /* Run Protocol Layer Message Tx state machine */
- run_state(port, &prl_tx[port].ctx);
-
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES))
- /*
- * Run TX Chunked state machine again after
- * prl_tx so we can handle passing TX_COMPLETE
- * (or failure) up to PE in a single iteration.
- */
- run_state(port, &tch[port].ctx);
- }
- break;
- }
-}
-
-void prl_set_rev(int port, enum tcpci_msg_type type,
- enum pd_rev_type rev)
-{
- /* We only store revisions for SOP* types. */
- ASSERT(type < NUM_SOP_STAR_TYPES);
-
- pdmsg[port].rev[type] = rev;
-}
-
-enum pd_rev_type prl_get_rev(int port, enum tcpci_msg_type type)
-{
- /* We only store revisions for SOP* types. */
- ASSERT(type < NUM_SOP_STAR_TYPES);
-
- return pdmsg[port].rev[type];
-}
-
-static void prl_copy_msg_to_buffer(int port)
-{
- /*
- * Control Messages will have a length of 0 and
- * no need to spend time with the tx_chk_buf
- * for this path
- */
- if (tx_emsg[port].len == 0) {
- pdmsg[port].data_objs = 0;
- return;
- }
-
- /*
- * Make sure the Policy Engine isn't sending
- * more than CHK_BUF_SIZE_BYTES. If so,
- * truncate len. This will surely send a
- * malformed packet resulting in the port
- * partner soft\hard resetting us.
- */
- if (tx_emsg[port].len > CHK_BUF_SIZE_BYTES)
- tx_emsg[port].len = CHK_BUF_SIZE_BYTES;
-
- /* Copy message to chunked buffer */
- memset((uint8_t *)pdmsg[port].tx_chk_buf, 0, CHK_BUF_SIZE_BYTES);
- memcpy((uint8_t *)pdmsg[port].tx_chk_buf, (uint8_t *)tx_emsg[port].buf,
- tx_emsg[port].len);
- /*
- * Pad length to 4-byte boundary and
- * convert to number of 32-bit objects.
- * Since the value is shifted right by 2,
- * no need to explicitly clear the lower
- * 2-bits.
- */
- pdmsg[port].data_objs = (tx_emsg[port].len + 3) >> 2;
-}
-
-static __maybe_unused int pdmsg_xmit_type_is_rev30(const int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_REV30))
- return ((pdmsg[port].xmit_type < NUM_SOP_STAR_TYPES)
- && (prl_get_rev(port, pdmsg[port].xmit_type) == PD_REV30));
- else
- return 0;
-}
-
-/* Returns true if the SOP port partner operates at PD rev3.0 */
-static bool is_sop_rev30(const int port)
-{
- return IS_ENABLED(CONFIG_USB_PD_REV30) &&
- prl_get_rev(port, TCPCI_MSG_SOP) == PD_REV30;
-}
-
-/* Common Protocol Layer Message Transmission */
-static void prl_tx_phy_layer_reset_entry(const int port)
-{
- print_current_prl_tx_state(port);
-
- if (IS_ENABLED(CONFIG_USB_CTVPD)
- || IS_ENABLED(CONFIG_USB_VPD)) {
- vpd_rx_enable(pd_is_connected(port));
- } else {
- /* Note: can't clear PHY messages due to TCPC architecture */
- /* Enable communications*/
- tcpm_set_rx_enable(port, pd_is_connected(port));
- }
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_MESSAGE_REQUEST);
-}
-
-static void prl_tx_wait_for_message_request_entry(const int port)
-{
- /* No phy layer response is pending */
- prl_tx[port].xmit_status = TCPC_TX_UNSET;
- print_current_prl_tx_state(port);
-}
-
-static void prl_tx_wait_for_message_request_run(const int port)
-{
- /* Clear any AMS flags and state if we are no longer in an AMS */
- if (IS_ENABLED(CONFIG_USB_PD_REV30) && !pe_in_local_ams(port)) {
- /* Note PRL_Tx_Src_Sink_Tx is embedded here. */
- if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_SINK_NG)) {
- typec_select_src_collision_rp(port, SINK_TX_OK);
- typec_update_cc(port);
- }
- PRL_TX_CLR_FLAG(port,
- PRL_FLAGS_SINK_NG | PRL_FLAGS_WAIT_SINK_OK);
- }
-
- /*
- * Check if we are starting an AMS and need to wait and/or set the CC
- * lines appropriately.
- */
- if (IS_ENABLED(CONFIG_USB_PD_REV30) && is_sop_rev30(port) &&
- pe_in_local_ams(port)) {
- if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_SINK_NG |
- PRL_FLAGS_WAIT_SINK_OK)) {
- /*
- * If we are already in an AMS then allow the
- * multi-message AMS to continue, even if we
- * swap power roles.
- *
- * Fall Through using the current AMS
- */
- } else {
- /*
- * Start of SRC AMS notification received from
- * Policy Engine
- */
- if (pd_get_power_role(port) == PD_ROLE_SOURCE) {
- PRL_TX_SET_FLAG(port, PRL_FLAGS_SINK_NG);
- set_state_prl_tx(port, PRL_TX_SRC_SOURCE_TX);
- } else {
- PRL_TX_SET_FLAG(port, PRL_FLAGS_WAIT_SINK_OK);
- set_state_prl_tx(port, PRL_TX_SNK_START_AMS);
- }
- return;
- }
- }
-
- /* Handle non Rev 3.0 or subsequent messages in AMS sequence */
- if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) {
- PRL_TX_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT);
- /*
- * Soft Reset Message Message pending
- */
- if ((pdmsg[port].msg_type == PD_CTRL_SOFT_RESET) &&
- (tx_emsg[port].len == 0)) {
- set_state_prl_tx(port, PRL_TX_LAYER_RESET_FOR_TRANSMIT);
- }
- /*
- * Message pending (except Soft Reset)
- */
- else {
- /* NOTE: PRL_TX_Construct_Message State embedded here */
- prl_tx_construct_message(port);
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_PHY_RESPONSE);
- }
-
- return;
- }
-}
-
-static void increment_msgid_counter(int port)
-{
- /* If the last message wasn't an SOP* message, no need to increment */
- if (prl_tx[port].last_xmit_type >= NUM_SOP_STAR_TYPES)
- return;
-
- prl_tx[port].msg_id_counter[prl_tx[port].last_xmit_type] =
- (prl_tx[port].msg_id_counter[prl_tx[port].last_xmit_type] + 1) &
- PD_MESSAGE_ID_COUNT;
-}
-
-/*
- * PrlTxDiscard
- */
-static void prl_tx_discard_message_entry(const int port)
-{
- print_current_prl_tx_state(port);
-
- /*
- * Discard queued message
- * Note: We differ from spec here, which allows us to not discard on
- * incoming SOP' or SOP''. However this would get the TCH out of sync.
- *
- * prl_tx will be set to this state following message reception in
- * prl_rx. So this path will be entered following each rx message. If
- * this state is entered, and there is either a message from the PE
- * pending, or if a message was passed to the phy and there is either no
- * response yet, or it was discarded in the phy layer, then a tx message
- * discard event has been detected.
- */
- if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT) ||
- prl_tx[port].xmit_status == TCPC_TX_WAIT ||
- prl_tx[port].xmit_status == TCPC_TX_COMPLETE_DISCARDED) {
- PRL_TX_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT);
- increment_msgid_counter(port);
- pe_report_discard(port);
- }
-
- set_state_prl_tx(port, PRL_TX_PHY_LAYER_RESET);
-}
-
-#ifdef CONFIG_USB_PD_REV30
-/*
- * PrlTxSrcSourceTx
- */
-static void prl_tx_src_source_tx_entry(const int port)
-{
- print_current_prl_tx_state(port);
-
- /* Set Rp = SinkTxNG */
- typec_select_src_collision_rp(port, SINK_TX_NG);
- typec_update_cc(port);
-}
-
-static void prl_tx_src_source_tx_run(const int port)
-{
- if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) {
- /*
- * Don't clear pending XMIT flag here. Wait until we send so
- * we can detect if we dropped this message or not.
- */
- set_state_prl_tx(port, PRL_TX_SRC_PENDING);
- }
-}
-
-/*
- * PrlTxSnkStartAms
- */
-static void prl_tx_snk_start_ams_entry(const int port)
-{
- print_current_prl_tx_state(port);
-}
-
-static void prl_tx_snk_start_ams_run(const int port)
-{
- if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) {
- /*
- * Don't clear pending XMIT flag here. Wait until we send so
- * we can detect if we dropped this message or not.
- */
- set_state_prl_tx(port, PRL_TX_SNK_PENDING);
- }
-}
-#endif /* CONFIG_USB_PD_REV30 */
-
-/*
- * PrlTxLayerResetForTransmit
- */
-static void prl_tx_layer_reset_for_transmit_entry(const int port)
-{
- print_current_prl_tx_state(port);
-
- if (pdmsg[port].xmit_type < NUM_SOP_STAR_TYPES) {
- /*
- * This state is only used during soft resets. Reset only the
- * matching message type.
- *
- * From section 6.3.13 Soft Reset Message in the USB PD 3.0
- * v2.0 spec, Soft_Reset Message Shall be targeted at a
- * specific entity depending on the type of SOP* Packet used.
- */
- prl_tx[port].msg_id_counter[pdmsg[port].xmit_type] = 0;
-
- /*
- * From section 6.11.2.3.2, the MessageID should be cleared
- * from the PRL_Rx_Layer_Reset_for_Receive state. However, we
- * don't implement a full state machine for PRL RX states so
- * clear the MessageID here.
- */
- prl_rx[port].msg_id[pdmsg[port].xmit_type] = -1;
- }
-}
-
-static void prl_tx_layer_reset_for_transmit_run(const int port)
-{
- /* NOTE: PRL_Tx_Construct_Message State embedded here */
- prl_tx_construct_message(port);
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_PHY_RESPONSE);
-}
-
-static uint32_t get_sop_star_header(const int port)
-{
- const int is_sop_packet = pdmsg[port].xmit_type == TCPCI_MSG_SOP;
- int ext;
-
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- ext = pdmsg[port].ext;
-#else
- ext = 0;
-#endif
-
- /* SOP vs SOP'/SOP" headers are different. Replace fields as needed */
- return PD_HEADER(
- pdmsg[port].msg_type,
- is_sop_packet ?
- pd_get_power_role(port) : tc_get_cable_plug(port),
- is_sop_packet ?
- pd_get_data_role(port) : 0,
- prl_tx[port].msg_id_counter[pdmsg[port].xmit_type],
- pdmsg[port].data_objs,
- pdmsg[port].rev[pdmsg[port].xmit_type],
- ext);
-}
-
-static void prl_tx_construct_message(const int port)
-{
- /* The header is unused for hard reset, etc. */
- const uint32_t header = pdmsg[port].xmit_type < NUM_SOP_STAR_TYPES ?
- get_sop_star_header(port) : 0;
-
- /* Save SOP* so the correct msg_id_counter can be incremented */
- prl_tx[port].last_xmit_type = pdmsg[port].xmit_type;
-
- /* Indicate that a tx message is being passed to the phy layer */
- prl_tx[port].xmit_status = TCPC_TX_WAIT;
- /*
- * PRL_FLAGS_TX_COMPLETE could be set if this function is called before
- * the Policy Engine is informed of the previous transmission. Clear the
- * flag so that this message can be sent.
- */
- PDMSG_CLR_FLAG(port, PRL_FLAGS_TX_COMPLETE);
-
- /*
- * Pass message to PHY Layer. It handles retries in hardware as the EC
- * cannot handle the required timing ~ 1ms (tReceive + tRetry).
- *
- * Note if we ever start sending large, extendend messages, then we
- * should not retry those messages. We do not support that and probably
- * never will (since we support chunking).
- */
- tcpm_transmit(port, pdmsg[port].xmit_type, header,
- pdmsg[port].tx_chk_buf);
-}
-
-/*
- * PrlTxWaitForPhyResponse
- */
-static void prl_tx_wait_for_phy_response_entry(const int port)
-{
- print_current_prl_tx_state(port);
-
- pd_timer_enable(port, PR_TIMER_TCPC_TX_TIMEOUT, PD_T_TCPC_TX_TIMEOUT);
-}
-
-static void prl_tx_wait_for_phy_response_run(const int port)
-{
- /* Wait until TX is complete */
-
- /*
- * NOTE: The TCPC will set xmit_status to TCPC_TX_COMPLETE_DISCARDED
- * when a GoodCRC containing an incorrect MessageID is received.
- * This condition satisfies the PRL_Tx_Match_MessageID state
- * requirement.
- */
-
- if (prl_tx[port].xmit_status == TCPC_TX_COMPLETE_SUCCESS) {
- /* NOTE: PRL_TX_Message_Sent State embedded here. */
- /* Increment messageId counter */
- increment_msgid_counter(port);
-
- /* Inform Policy Engine Message was sent */
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES))
- PDMSG_SET_FLAG(port, PRL_FLAGS_TX_COMPLETE);
- else
- pe_message_sent(port);
-
- /*
- * This event reduces the time of informing the policy engine of
- * the transmission by one state machine cycle
- */
- task_wake(PD_PORT_TO_TASK_ID(port));
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_MESSAGE_REQUEST);
- } else if (pd_timer_is_expired(port, PR_TIMER_TCPC_TX_TIMEOUT) ||
- prl_tx[port].xmit_status == TCPC_TX_COMPLETE_FAILED) {
- /*
- * NOTE: PRL_Tx_Transmission_Error State embedded
- * here.
- */
-
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) {
- /*
- * State tch_wait_for_transmission_complete will
- * inform policy engine of error
- */
- PDMSG_SET_FLAG(port, PRL_FLAGS_TX_ERROR);
- } else {
- /* Report Error To Policy Engine */
- pe_report_error(port, ERR_TCH_XMIT,
- prl_tx[port].last_xmit_type);
- }
-
- /* Increment message id counter */
- increment_msgid_counter(port);
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_MESSAGE_REQUEST);
- }
-}
-
-static void prl_tx_wait_for_phy_response_exit(const int port)
-{
- pd_timer_disable(port, PR_TIMER_TCPC_TX_TIMEOUT);
-}
-
-/* Source Protocol Layer Message Transmission */
-/*
- * PrlTxSrcPending
- */
-static void prl_tx_src_pending_entry(const int port)
-{
- print_current_prl_tx_state(port);
-
- /* Start SinkTxTimer */
- pd_timer_enable(port, PR_TIMER_SINK_TX, PD_T_SINK_TX);
-}
-
-static void prl_tx_src_pending_run(const int port)
-{
- if (pd_timer_is_expired(port, PR_TIMER_SINK_TX)) {
- /*
- * We clear the pending XMIT flag here right before we send so
- * we can detect if we discarded this message or not
- */
- PRL_TX_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT);
-
- /*
- * Soft Reset Message pending &
- * SinkTxTimer timeout
- */
- if ((tx_emsg[port].len == 0) &&
- (pdmsg[port].msg_type == PD_CTRL_SOFT_RESET)) {
- set_state_prl_tx(port, PRL_TX_LAYER_RESET_FOR_TRANSMIT);
- }
- /* Message pending (except Soft Reset) &
- * SinkTxTimer timeout
- */
- else {
- prl_tx_construct_message(port);
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_PHY_RESPONSE);
- }
-
- return;
- }
-}
-
-static void prl_tx_src_pending_exit(int port)
-{
- pd_timer_disable(port, PR_TIMER_SINK_TX);
-}
-
-/*
- * PrlTxSnkPending
- */
-static void prl_tx_snk_pending_entry(const int port)
-{
- print_current_prl_tx_state(port);
-}
-
-static void prl_tx_snk_pending_run(const int port)
-{
- bool start_tx = false;
-
- /*
- * Wait unit the SRC applies SINK_TX_OK so we can transmit. In FRS mode,
- * don't wait for SINK_TX_OK since either the source (and Rp) could be
- * gone or the TCPC CC_STATUS update time could be too long to meet
- * tFRSwapInit.
- */
- if (pe_in_frs_mode(port)) {
- /* shortcut to save some i2c_xfer calls on the FRS path. */
- start_tx = true;
- } else {
- enum tcpc_cc_voltage_status cc1, cc2;
-
- tcpm_get_cc(port, &cc1, &cc2);
- start_tx = (cc1 == TYPEC_CC_VOLT_RP_3_0 ||
- cc2 == TYPEC_CC_VOLT_RP_3_0);
- }
- if (start_tx) {
- /*
- * We clear the pending XMIT flag here right before we send so
- * we can detect if we discarded this message or not
- */
- PRL_TX_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT);
-
- /*
- * Soft Reset Message Message pending &
- * Rp = SinkTxOk
- */
- if ((pdmsg[port].msg_type == PD_CTRL_SOFT_RESET) &&
- (tx_emsg[port].len == 0)) {
- set_state_prl_tx(port, PRL_TX_LAYER_RESET_FOR_TRANSMIT);
- }
- /*
- * Message pending (except Soft Reset) &
- * Rp = SinkTxOk
- */
- else {
- prl_tx_construct_message(port);
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_PHY_RESPONSE);
- }
- return;
- }
-}
-
-/* Hard Reset Operation */
-void prl_hr_send_msg_to_phy(const int port)
-{
- /* Header is not used for hard reset */
- const uint32_t header = 0;
-
- pdmsg[port].xmit_type = TCPCI_MSG_TX_HARD_RESET;
-
- /*
- * These flags could be set if this function is called before the
- * Policy Engine is informed of the previous transmission. Clear the
- * flags so that this message can be sent.
- */
- prl_tx[port].xmit_status = TCPC_TX_UNSET;
- PDMSG_CLR_FLAG(port, PRL_FLAGS_TX_COMPLETE);
-
- /* Pass message to PHY Layer */
- tcpm_transmit(port, pdmsg[port].xmit_type, header,
- pdmsg[port].tx_chk_buf);
-}
-
-static void prl_hr_wait_for_request_entry(const int port)
-{
- print_current_prl_hr_state(port);
-
- prl_hr[port].flags = 0;
-}
-
-static void prl_hr_wait_for_request_run(const int port)
-{
- if (PRL_HR_CHK_FLAG(port, PRL_FLAGS_PE_HARD_RESET |
- PRL_FLAGS_PORT_PARTNER_HARD_RESET))
- set_state_prl_hr(port, PRL_HR_RESET_LAYER);
-}
-
-/*
- * PrlHrResetLayer
- */
-static void prl_hr_reset_layer_entry(const int port)
-{
- int i;
-
- print_current_prl_hr_state(port);
-
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) {
- tch[port].flags = 0;
- rch[port].flags = 0;
- }
-
- pdmsg[port].flags = 0;
-
- /* Hard reset resets messageIDCounters for all TX types */
- for (i = 0; i < NUM_SOP_STAR_TYPES; i++) {
- prl_rx[port].msg_id[i] = -1;
- prl_tx[port].msg_id_counter[i] = 0;
- }
-
- /* Disable RX */
- if (IS_ENABLED(CONFIG_USB_CTVPD) ||
- IS_ENABLED(CONFIG_USB_VPD))
- vpd_rx_enable(0);
- else
- tcpm_set_rx_enable(port, 0);
-
- /*
- * PD r3.0 v2.0, ss6.2.1.1.5:
- * After a physical or logical (USB Type-C Error Recovery) Attach, a
- * Port discovers the common Specification Revision level between itself
- * and its Port Partner and/or the Cable Plug(s), and uses this
- * Specification Revision level until a Detach, Hard Reset or Error
- * Recovery happens.
- *
- * This covers the Hard Reset case.
- */
- prl_set_default_pd_revision(port);
-
- /* Inform the AP of Hard Reset */
- if (IS_ENABLED(CONFIG_USB_PD_HOST_CMD))
- pd_notify_event(port, PD_STATUS_EVENT_HARD_RESET);
-
- /*
- * Protocol Layer message transmission transitions to
- * PRL_Tx_Wait_For_Message_Request state.
- */
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_MESSAGE_REQUEST);
-
- return;
-}
-
-static void prl_hr_reset_layer_run(const int port)
-{
- /*
- * Protocol Layer reset Complete &
- * Hard Reset was initiated by Policy Engine
- */
- if (PRL_HR_CHK_FLAG(port, PRL_FLAGS_PE_HARD_RESET)) {
- /*
- * Request PHY to perform a Hard Reset. Note
- * PRL_HR_Request_Reset state is embedded here.
- */
- prl_hr_send_msg_to_phy(port);
- set_state_prl_hr(port, PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE);
- }
- /*
- * Protocol Layer reset complete &
- * Hard Reset was initiated by Port Partner
- */
- else {
- /* Inform Policy Engine of the Hard Reset */
- pe_got_hard_reset(port);
- set_state_prl_hr(port, PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE);
- }
-}
-
-/*
- * PrlHrWaitForPhyHardResetComplete
- */
-static void prl_hr_wait_for_phy_hard_reset_complete_entry(const int port)
-{
- print_current_prl_hr_state(port);
-
- /* Start HardResetCompleteTimer */
- pd_timer_enable(port, PR_TIMER_HARD_RESET_COMPLETE,
- PD_T_PS_HARD_RESET);
-}
-
-static void prl_hr_wait_for_phy_hard_reset_complete_run(const int port)
-{
- /*
- * Wait for hard reset from PHY
- * or timeout
- */
- if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_COMPLETE) ||
- pd_timer_is_expired(port, PR_TIMER_HARD_RESET_COMPLETE)) {
- /* PRL_HR_PHY_Hard_Reset_Requested */
-
- /* Inform Policy Engine Hard Reset was sent */
- pe_hard_reset_sent(port);
- set_state_prl_hr(port, PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE);
-
- return;
- }
-}
-
-static void prl_hr_wait_for_phy_hard_reset_complete_exit(int port)
-{
- pd_timer_disable(port, PR_TIMER_HARD_RESET_COMPLETE);
-}
-
-/*
- * PrlHrWaitForPeHardResetComplete
- */
-static void prl_hr_wait_for_pe_hard_reset_complete_entry(const int port)
-{
- print_current_prl_hr_state(port);
-}
-
-static void prl_hr_wait_for_pe_hard_reset_complete_run(const int port)
-{
- /*
- * Wait for Hard Reset complete indication from Policy Engine
- */
- if (PRL_HR_CHK_FLAG(port, PRL_FLAGS_HARD_RESET_COMPLETE))
- set_state_prl_hr(port, PRL_HR_WAIT_FOR_REQUEST);
-}
-
-static void prl_hr_wait_for_pe_hard_reset_complete_exit(const int port)
-{
- /* Exit from Hard Reset */
-
- set_state_prl_tx(port, PRL_TX_PHY_LAYER_RESET);
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) {
- set_state_rch(port, RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER);
- set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
- }
-}
-
-static void copy_chunk_to_ext(int port)
-{
- /* Calculate number of bytes */
- pdmsg[port].num_bytes_received =
- (PD_HEADER_CNT(rx_emsg[port].header) * 4);
-
- /* Copy chunk into extended message */
- memcpy((uint8_t *)rx_emsg[port].buf, (uint8_t *)pdmsg[port].rx_chk_buf,
- pdmsg[port].num_bytes_received);
-
- /* Set extended message length */
- rx_emsg[port].len = pdmsg[port].num_bytes_received;
-}
-
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
-/*
- * Chunked Rx State Machine
- */
-/*
- * RchWaitForMessageFromProtocolLayer
- */
-static void rch_wait_for_message_from_protocol_layer_entry(const int port)
-{
- print_current_rch_state(port);
-
- /* Clear Abort flag */
- PDMSG_CLR_FLAG(port, PRL_FLAGS_ABORT);
-
- /* All Messages are chunked */
- rch[port].flags = PRL_FLAGS_CHUNKING;
-}
-
-static void rch_wait_for_message_from_protocol_layer_run(const int port)
-{
- if (RCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- RCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- /*
- * Are we communicating with a PD3.0 device and is
- * this an extended message?
- */
- if (pdmsg_xmit_type_is_rev30(port)
- && PD_HEADER_EXT(rx_emsg[port].header)) {
- uint16_t exhdr =
- GET_EXT_HEADER(*pdmsg[port].rx_chk_buf);
- uint8_t chunked = PD_EXT_HEADER_CHUNKED(exhdr);
-
- /*
- * Received Extended Message &
- * (Chunking = 1 & Chunked = 1)
- */
- if ((RCH_CHK_FLAG(port, PRL_FLAGS_CHUNKING)) &&
- chunked) {
- /*
- * RCH_Processing_Extended_Message first chunk
- * entry processing embedded here
- *
- * This is the first chunk:
- * Set Chunk_number_expected = 0 and
- * Num_Bytes_Received = 0
- */
- pdmsg[port].chunk_number_expected = 0;
- pdmsg[port].num_bytes_received = 0;
- pdmsg[port].msg_type =
- PD_HEADER_TYPE(rx_emsg[port].header);
-
- set_state_rch(port,
- RCH_PROCESSING_EXTENDED_MESSAGE);
- }
- /*
- * (Received Extended Message &
- * (Chunking = 0 & Chunked = 0))
- */
- else if (!RCH_CHK_FLAG(port, PRL_FLAGS_CHUNKING) &&
- !chunked) {
- /* Copy chunk to extended buffer */
- copy_chunk_to_ext(port);
- set_state_rch(port, RCH_PASS_UP_MESSAGE);
- }
- /*
- * Chunked != Chunking
- */
- else {
- rch[port].error = ERR_RCH_CHUNKED;
- set_state_rch(port, RCH_REPORT_ERROR);
- }
- }
- /*
- * Received Non-Extended Message
- */
- else if (!PD_HEADER_EXT(rx_emsg[port].header)) {
- /* Copy chunk to extended buffer */
- copy_chunk_to_ext(port);
- set_state_rch(port, RCH_PASS_UP_MESSAGE);
- }
- /*
- * Received an Extended Message while communicating at a
- * revision lower than PD3.0
- */
- else {
- rch[port].error = ERR_RCH_CHUNKED;
- set_state_rch(port, RCH_REPORT_ERROR);
- }
- }
-}
-
-/*
- * RchPassUpMessage
- */
-static void rch_pass_up_message_entry(const int port)
-{
- print_current_rch_state(port);
-
- /* Pass Message to Policy Engine */
- pe_message_received(port);
- set_state_rch(port, RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER);
-}
-
-/*
- * RchProcessingExtendedMessage
- */
-static void rch_processing_extended_message_entry(const int port)
-{
- print_current_rch_state(port);
-}
-
-static void rch_processing_extended_message_run(const int port)
-{
- uint16_t exhdr = GET_EXT_HEADER(pdmsg[port].rx_chk_buf[0]);
- uint8_t chunk_num = PD_EXT_HEADER_CHUNK_NUM(exhdr);
- uint32_t data_size = PD_EXT_HEADER_DATA_SIZE(exhdr);
- uint32_t byte_num;
-
- /*
- * Abort Flag Set
- */
- if (PDMSG_CHK_FLAG(port, PRL_FLAGS_ABORT))
- set_state_rch(port, RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER);
-
- /*
- * If expected Chunk Number:
- * Append data to Extended_Message_Buffer
- * Increment Chunk_number_Expected
- * Adjust Num Bytes Received
- */
- else if (chunk_num == pdmsg[port].chunk_number_expected) {
- byte_num = data_size - pdmsg[port].num_bytes_received;
-
- if (byte_num >= PD_MAX_EXTENDED_MSG_CHUNK_LEN)
- byte_num = PD_MAX_EXTENDED_MSG_CHUNK_LEN;
-
- /* Make sure extended message buffer does not overflow */
- if (pdmsg[port].num_bytes_received +
- byte_num > EXTENDED_BUFFER_SIZE) {
- rch[port].error = ERR_RCH_CHUNKED;
- set_state_rch(port, RCH_REPORT_ERROR);
- return;
- }
-
- /* Append data */
- /* Add 2 to chk_buf to skip over extended message header */
- memcpy(((uint8_t *)rx_emsg[port].buf +
- pdmsg[port].num_bytes_received),
- (uint8_t *)pdmsg[port].rx_chk_buf + 2,
- byte_num);
- /* increment chunk number expected */
- pdmsg[port].chunk_number_expected++;
- /* adjust num bytes received */
- pdmsg[port].num_bytes_received += byte_num;
-
- /* Was that the last chunk? */
- if (pdmsg[port].num_bytes_received >= data_size) {
- rx_emsg[port].len = pdmsg[port].num_bytes_received;
- /* Pass Message to Policy Engine */
- set_state_rch(port, RCH_PASS_UP_MESSAGE);
- }
- /*
- * Message not Complete
- */
- else
- set_state_rch(port, RCH_REQUESTING_CHUNK);
- }
- /*
- * Unexpected Chunk Number
- */
- else {
- rch[port].error = ERR_RCH_CHUNKED;
- set_state_rch(port, RCH_REPORT_ERROR);
- }
-}
-
-/*
- * RchRequestingChunk
- */
-static void rch_requesting_chunk_entry(const int port)
-{
- print_current_rch_state(port);
-
- /*
- * Send Chunk Request to Protocol Layer
- * with chunk number = Chunk_Number_Expected
- */
- pdmsg[port].tx_chk_buf[0] = PD_EXT_HEADER(
- pdmsg[port].chunk_number_expected,
- 1, /* Request Chunk */
- 0 /* Data Size */
- );
-
- pdmsg[port].data_objs = 1;
- pdmsg[port].ext = 1;
- pdmsg[port].xmit_type = prl_rx[port].sop;
- PRL_TX_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TX);
-}
-
-static void rch_requesting_chunk_run(const int port)
-{
- /*
- * Message Transmitted received from Protocol Layer
- */
- if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_COMPLETE)) {
- PDMSG_CLR_FLAG(port, PRL_FLAGS_TX_COMPLETE);
- set_state_rch(port, RCH_WAITING_CHUNK);
- } else if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_ERROR)) {
- /* Transmission Error from Protocol Layer detetected */
- rch[port].error = ERR_RCH_CHUNKED;
- set_state_rch(port, RCH_REPORT_ERROR);
- } else if (RCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- /*
- * It is possible to have both message received and the chunk
- * request transmit complete before a full PRL SM run. But, the
- * PRL_RX state machine runs prior to RCH, but before PRL_TX, so
- * PRL_FLAGS_MSG_RECEIVED can be set without
- * PRL_FLAGS_TX_COMPLETE set at this point (though it will be
- * set as soon as PRL_TX is executed next.
- */
- set_state_rch(port, RCH_WAITING_CHUNK);
- }
-}
-
-/*
- * RchWaitingChunk
- */
-static void rch_waiting_chunk_entry(const int port)
-{
- print_current_rch_state(port);
-
- /*
- * Start ChunkSenderResponseTimer
- */
- pd_timer_enable(port, PR_TIMER_CHUNK_SENDER_RESPONSE,
- PD_T_CHUNK_SENDER_RESPONSE);
-}
-
-static void rch_waiting_chunk_run(const int port)
-{
- if (RCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- /*
- * Because of the 5 msec tick time, it is possible to have both
- * msg_received and tx_complete flags set for a given PRL sm
- * run. Since prl_rx runs prior to the tx state machines, clear
- * the tx_complete flag as the next chunk has already been
- * received.
- */
- if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_COMPLETE))
- PDMSG_CLR_FLAG(port, PRL_FLAGS_TX_COMPLETE);
-
- /*
- * Leave PRL_FLAGS_MSG_RECEIVED flag set just in case an error
- * is detected. If an error is detected, PRL_FLAGS_MSG_RECEIVED
- * will be cleared in rch_report_error state.
- */
-
- if (PD_HEADER_EXT(rx_emsg[port].header)) {
- uint16_t exhdr =
- GET_EXT_HEADER(pdmsg[port].rx_chk_buf[0]);
- /*
- * Other Message Received from Protocol Layer
- */
- if (PD_EXT_HEADER_REQ_CHUNK(exhdr) ||
- !PD_EXT_HEADER_CHUNKED(exhdr)) {
- rch[port].error = ERR_RCH_CHUNKED;
- set_state_rch(port, RCH_REPORT_ERROR);
- }
- /*
- * Chunk response Received from Protocol Layer
- */
- else {
- /*
- * No error was detected, so clear
- * PRL_FLAGS_MSG_RECEIVED flag.
- */
- RCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- set_state_rch(port,
- RCH_PROCESSING_EXTENDED_MESSAGE);
- }
- }
- }
- /*
- * ChunkSenderResponseTimer Timeout
- */
- else if (pd_timer_is_expired(port, PR_TIMER_CHUNK_SENDER_RESPONSE)) {
- rch[port].error = ERR_RCH_CHUNK_WAIT_TIMEOUT;
- set_state_rch(port, RCH_REPORT_ERROR);
- }
-}
-
-static void rch_waiting_chunk_exit(int port)
-{
- pd_timer_disable(port, PR_TIMER_CHUNK_SENDER_RESPONSE);
-}
-
-/*
- * RchReportError
- */
-static void rch_report_error_entry(const int port)
-{
- print_current_rch_state(port);
-
- /*
- * If the state was entered because a message was received,
- * this message is passed to the Policy Engine.
- */
- if (RCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- RCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
-
- /* Copy chunk to extended buffer */
- copy_chunk_to_ext(port);
- /* Pass Message to Policy Engine */
- pe_message_received(port);
- /* Report error */
- pe_report_error(port, ERR_RCH_MSG_REC, prl_rx[port].sop);
- } else {
- pe_report_error(port, rch[port].error, prl_rx[port].sop);
- }
-}
-
-static void rch_report_error_run(const int port)
-{
- set_state_rch(port, RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER);
-}
-
-/*
- * Chunked Tx State Machine
- */
-
-/*
- * TchWaitForMessageRequestFromPe
- */
-static void tch_wait_for_message_request_from_pe_entry(const int port)
-{
- print_current_tch_state(port);
-
- /* Clear Abort flag */
- PDMSG_CLR_FLAG(port, PRL_FLAGS_ABORT);
-
- /* All Messages are chunked */
- tch[port].flags = PRL_FLAGS_CHUNKING;
-}
-
-static void tch_wait_for_message_request_from_pe_run(const int port)
-{
- /*
- * Any message received and not in state TCH_Wait_Chunk_Request
- */
- if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- set_state_tch(port, TCH_MESSAGE_RECEIVED);
- } else if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT);
- /*
- * Rx Chunking State != RCH_Wait_For_Message_From_Protocol_Layer
- * & Abort Supported
- *
- * Discard the Message
- */
- if (rch_get_state(port) !=
- RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER) {
- tch[port].error = ERR_TCH_XMIT;
- set_state_tch(port, TCH_REPORT_ERROR);
- } else {
- /*
- * Extended Message Request & Chunking
- */
- if (pdmsg_xmit_type_is_rev30(port)
- && pdmsg[port].ext
- && TCH_CHK_FLAG(port, PRL_FLAGS_CHUNKING)) {
- /*
- * NOTE: TCH_Prepare_To_Send_Chunked_Message
- * embedded here.
- */
- pdmsg[port].send_offset = 0;
- pdmsg[port].chunk_number_to_send = 0;
- set_state_tch(port,
- TCH_CONSTRUCT_CHUNKED_MESSAGE);
- } else
- /*
- * Non-Extended Message Request
- */
- {
- /* NOTE: TCH_Pass_Down_Message embedded here */
- prl_copy_msg_to_buffer(port);
-
- /* Pass Message to Protocol Layer */
- PRL_TX_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
- set_state_tch(port,
- TCH_WAIT_FOR_TRANSMISSION_COMPLETE);
- }
- }
- }
-}
-
-/*
- * TchWaitForTransmissionComplete
- */
-static void tch_wait_for_transmission_complete_entry(const int port)
-{
- print_current_tch_state(port);
-}
-
-static void tch_wait_for_transmission_complete_run(const int port)
-{
- /*
- * Inform Policy Engine that Message was sent.
- */
- if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_COMPLETE)) {
- PDMSG_CLR_FLAG(port, PRL_FLAGS_TX_COMPLETE);
- set_state_tch(port, TCH_MESSAGE_SENT);
- return;
- }
- /*
- * Inform Policy Engine of Tx Error
- */
- else if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_ERROR)) {
- PDMSG_CLR_FLAG(port, PRL_FLAGS_TX_ERROR);
- tch[port].error = ERR_TCH_XMIT;
- set_state_tch(port, TCH_REPORT_ERROR);
- return;
- }
- /*
- * A message was received while TCH is waiting for the phy to complete
- * sending a tx message.
- *
- * Because of our prl_sm architecture and I2C access delays for TCPCs,
- * it's possible to have a message received and the prl_tx state not be
- * in its default waiting state. To avoid a false protocol error, only
- * jump to TCH_MESSAGE_RECEIVED if the phy layer has not indicated that
- * the tx message was sent successfully.
- */
- if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED) &&
- prl_tx[port].xmit_status != TCPC_TX_COMPLETE_SUCCESS) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- set_state_tch(port, TCH_MESSAGE_RECEIVED);
- return;
- }
-}
-
-/*
- * TchConstructChunkedMessage
- */
-static void tch_construct_chunked_message_entry(const int port)
-{
- uint16_t *ext_hdr;
- uint8_t *data;
- uint16_t num;
-
- print_current_tch_state(port);
-
- /*
- * Any message received and not in state TCH_Wait_Chunk_Request
- */
- if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- set_state_tch(port, TCH_MESSAGE_RECEIVED);
- return;
- }
-
- /* Prepare to copy chunk into chk_buf */
-
- ext_hdr = (uint16_t *)pdmsg[port].tx_chk_buf;
- data = ((uint8_t *)pdmsg[port].tx_chk_buf + 2);
- num = tx_emsg[port].len - pdmsg[port].send_offset;
-
- if (num > PD_MAX_EXTENDED_MSG_CHUNK_LEN)
- num = PD_MAX_EXTENDED_MSG_CHUNK_LEN;
-
- /* Set the chunks extended header */
- *ext_hdr = PD_EXT_HEADER(pdmsg[port].chunk_number_to_send,
- 0, /* Chunk Request */
- tx_emsg[port].len);
-
- /* Copy the message chunk into chk_buf */
- memset(data, 0, 28);
- memcpy(data, tx_emsg[port].buf + pdmsg[port].send_offset, num);
- pdmsg[port].send_offset += num;
-
- /*
- * Add in 2 bytes for extended header
- * pad out to 4-byte boundary
- * convert to number of 4-byte words
- * Since the value is shifted right by 2,
- * no need to explicitly clear the lower
- * 2-bits.
- */
- pdmsg[port].data_objs = (num + 2 + 3) >> 2;
-
- /* Pass message chunk to Protocol Layer */
- PRL_TX_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
-}
-
-static void tch_construct_chunked_message_run(const int port)
-{
- if (PDMSG_CHK_FLAG(port, PRL_FLAGS_ABORT))
- set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
- else
- set_state_tch(port, TCH_SENDING_CHUNKED_MESSAGE);
-}
-
-/*
- * TchSendingChunkedMessage
- */
-static void tch_sending_chunked_message_entry(const int port)
-{
- print_current_tch_state(port);
-}
-
-static void tch_sending_chunked_message_run(const int port)
-{
- /*
- * Transmission Error
- */
- if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_ERROR)) {
- tch[port].error = ERR_TCH_XMIT;
- set_state_tch(port, TCH_REPORT_ERROR);
- }
- /*
- * Message Transmitted from Protocol Layer &
- * Last Chunk
- */
- else if (tx_emsg[port].len == pdmsg[port].send_offset)
- set_state_tch(port, TCH_MESSAGE_SENT);
- /*
- * Any message received and not in state TCH_Wait_Chunk_Request
- */
- else if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- set_state_tch(port, TCH_MESSAGE_RECEIVED);
- }
- /*
- * Message Transmitted from Protocol Layer &
- * Not Last Chunk
- */
- else
- set_state_tch(port, TCH_WAIT_CHUNK_REQUEST);
-}
-
-/*
- * TchWaitChunkRequest
- */
-static void tch_wait_chunk_request_entry(const int port)
-{
- print_current_tch_state(port);
-
- /* Increment Chunk Number to Send */
- pdmsg[port].chunk_number_to_send++;
- /* Start Chunk Sender Request Timer */
- pd_timer_enable(port, PR_TIMER_CHUNK_SENDER_REQUEST,
- PD_T_CHUNK_SENDER_REQUEST);
-}
-
-static void tch_wait_chunk_request_run(const int port)
-{
- if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
-
- if (PD_HEADER_EXT(rx_emsg[port].header)) {
- uint16_t exthdr;
-
- exthdr = GET_EXT_HEADER(pdmsg[port].rx_chk_buf[0]);
- if (PD_EXT_HEADER_REQ_CHUNK(exthdr)) {
- /*
- * Chunk Request Received &
- * Chunk Number = Chunk Number to Send
- */
- if (PD_EXT_HEADER_CHUNK_NUM(exthdr) ==
- pdmsg[port].chunk_number_to_send) {
- set_state_tch(port,
- TCH_CONSTRUCT_CHUNKED_MESSAGE);
- }
- /*
- * Chunk Request Received &
- * Chunk Number != Chunk Number to Send
- */
- else {
- tch[port].error = ERR_TCH_CHUNKED;
- set_state_tch(port, TCH_REPORT_ERROR);
- }
- return;
- }
- }
-
- /*
- * Other message received
- */
- set_state_tch(port, TCH_MESSAGE_RECEIVED);
- }
- /*
- * ChunkSenderRequestTimer timeout
- */
- else if (pd_timer_is_expired(port, PR_TIMER_CHUNK_SENDER_REQUEST))
- set_state_tch(port, TCH_MESSAGE_SENT);
-}
-
-static void tch_wait_chunk_request_exit(int port)
-{
- pd_timer_disable(port, PR_TIMER_CHUNK_SENDER_REQUEST);
-}
-
-/*
- * TchMessageReceived
- */
-static void tch_message_received_entry(const int port)
-{
- print_current_tch_state(port);
-
- /* Pass message to chunked Rx */
- RCH_SET_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
-
- /* Clear extended message objects */
- if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT);
- pe_report_discard(port);
- }
- pdmsg[port].data_objs = 0;
-}
-
-static void tch_message_received_run(const int port)
-{
- set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
-}
-
-/*
- * TchMessageSent
- */
-static void tch_message_sent_entry(const int port)
-{
- print_current_tch_state(port);
-
- /* Tell PE message was sent */
- pe_message_sent(port);
-
- /*
- * Any message received and not in state TCH_Wait_Chunk_Request
- * MUST be checked after notifying PE
- */
- if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- set_state_tch(port, TCH_MESSAGE_RECEIVED);
- return;
- }
-
-
-
- set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
-}
-
-/*
- * TchReportError
- */
-static void tch_report_error_entry(const int port)
-{
- print_current_tch_state(port);
-
- /* Report Error To Policy Engine */
- pe_report_error(port, tch[port].error, prl_tx[port].last_xmit_type);
-
- /*
- * Any message received and not in state TCH_Wait_Chunk_Request
- * MUST be checked after notifying PE
- */
- if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- set_state_tch(port, TCH_MESSAGE_RECEIVED);
- return;
- }
-
-
- set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
-}
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-
-/*
- * Protocol Layer Message Reception State Machine
- */
-static void prl_rx_wait_for_phy_message(const int port, int evt)
-{
- uint32_t header;
- uint8_t type;
- uint8_t cnt;
- int8_t msid;
-
- /*
- * If PD3, wait for the RX chunk SM to copy the pdmsg into the extended
- * buffer before overwriting pdmsg.
- */
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES) &&
- RCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED))
- return;
-
- /* If we don't have any message, just stop processing now. */
- if (!tcpm_has_pending_message(port) ||
- tcpm_dequeue_message(port, pdmsg[port].rx_chk_buf, &header))
- return;
-
- rx_emsg[port].header = header;
- type = PD_HEADER_TYPE(header);
- cnt = PD_HEADER_CNT(header);
- msid = PD_HEADER_ID(header);
- prl_rx[port].sop = PD_HEADER_GET_SOP(header);
-
- /* Make sure an incorrect count doesn't overflow the chunk buffer */
- if (cnt > CHK_BUF_SIZE)
- cnt = CHK_BUF_SIZE;
-
- /* dump received packet content (only dump ping at debug level MAX) */
- if ((prl_debug_level >= DEBUG_LEVEL_2 && type != PD_CTRL_PING) ||
- prl_debug_level >= DEBUG_LEVEL_3) {
- int p;
-
- ccprintf("C%d: RECV %04x/%d ", port, header, cnt);
- for (p = 0; p < cnt; p++)
- ccprintf("[%d]%08x ", p, pdmsg[port].rx_chk_buf[p]);
- ccprintf("\n");
- }
-
- /*
- * Ignore messages sent to the cable from our
- * port partner if we aren't Vconn powered device.
- */
- if (!IS_ENABLED(CONFIG_USB_CTVPD) &&
- !IS_ENABLED(CONFIG_USB_VPD) &&
- PD_HEADER_GET_SOP(header) != TCPCI_MSG_SOP &&
- PD_HEADER_PROLE(header) == PD_PLUG_FROM_DFP_UFP)
- return;
-
- /* Handle incoming soft reset as special case */
- if (cnt == 0 && type == PD_CTRL_SOFT_RESET) {
- /* Clear MessageIdCounter */
- prl_tx[port].msg_id_counter[prl_rx[port].sop] = 0;
- /* Clear stored MessageID value */
- prl_rx[port].msg_id[prl_rx[port].sop] = -1;
-
- /* Soft Reset occurred */
- set_state_prl_tx(port, PRL_TX_PHY_LAYER_RESET);
-
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) {
- set_state_rch(port,
- RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER);
- set_state_tch(port,
- TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
- }
-
- /*
- * Inform Policy Engine of Soft Reset. Note perform this after
- * performing the protocol layer reset, otherwise we will lose
- * the PE's outgoing ACCEPT message to the soft reset.
- */
- pe_got_soft_reset(port);
-
- return;
- }
-
- /*
- * Ignore if this is a duplicate message. Stop processing.
- */
- if (prl_rx[port].msg_id[prl_rx[port].sop] == msid)
- return;
-
- /*
- * Discard any pending tx message if this is
- * not a ping message (length must be checked to verify this is a
- * control message, rather than data)
- */
- if ((cnt > 0) || (type != PD_CTRL_PING)) {
- /*
- * Note: Spec dictates that we always go into
- * PRL_Tx_Discard_Message upon receivng a message. However, due
- * to our TCPC architecture we may be receiving a transmit
- * complete at the same time as a response so only do this if a
- * message is pending.
- */
- if (prl_tx[port].xmit_status != TCPC_TX_COMPLETE_SUCCESS ||
- PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT))
- set_state_prl_tx(port, PRL_TX_DISCARD_MESSAGE);
- }
-
- /* Store Message Id */
- prl_rx[port].msg_id[prl_rx[port].sop] = msid;
-
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) {
- /* RTR Chunked Message Router States. */
- /*
- * Received Ping from Protocol Layer
- */
- if (cnt == 0 && type == PD_CTRL_PING) {
- /* NOTE: RTR_PING State embedded here. */
- rx_emsg[port].len = 0;
- pe_message_received(port);
- return;
- }
- /*
- * Message (not Ping) Received from
- * Protocol Layer & Doing Tx Chunks
- *
- * Also, handle the case where a message has been
- * queued for sending but a message is received before
- * tch_wait_for_message_request_from_pe has been run
- */
- else if (tch_get_state(port) !=
- TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE ||
- TCH_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) {
- /* NOTE: RTR_TX_CHUNKS State embedded here. */
- /*
- * Send Message to Tx Chunk
- * Chunk State Machine
- */
- TCH_SET_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- }
- /*
- * Message (not Ping) Received from
- * Protocol Layer & Not Doing Tx Chunks
- */
- else {
- /* NOTE: RTR_RX_CHUNKS State embedded here. */
- /*
- * Send Message to Rx
- * Chunk State Machine
- */
- RCH_SET_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- }
- } else {
- /* Copy chunk to extended buffer */
- copy_chunk_to_ext(port);
- /* Send message to Policy Engine */
- pe_message_received(port);
- }
-
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-/* All necessary Protocol Transmit States (Section 6.11.2.2) */
-static __const_data const struct usb_state prl_tx_states[] = {
- [PRL_TX_PHY_LAYER_RESET] = {
- .entry = prl_tx_phy_layer_reset_entry,
- },
- [PRL_TX_WAIT_FOR_MESSAGE_REQUEST] = {
- .entry = prl_tx_wait_for_message_request_entry,
- .run = prl_tx_wait_for_message_request_run,
- },
- [PRL_TX_LAYER_RESET_FOR_TRANSMIT] = {
- .entry = prl_tx_layer_reset_for_transmit_entry,
- .run = prl_tx_layer_reset_for_transmit_run,
- },
- [PRL_TX_WAIT_FOR_PHY_RESPONSE] = {
- .entry = prl_tx_wait_for_phy_response_entry,
- .run = prl_tx_wait_for_phy_response_run,
- .exit = prl_tx_wait_for_phy_response_exit,
- },
-#ifdef CONFIG_USB_PD_REV30
- [PRL_TX_SRC_SOURCE_TX] = {
- .entry = prl_tx_src_source_tx_entry,
- .run = prl_tx_src_source_tx_run,
- },
- [PRL_TX_SNK_START_AMS] = {
- .entry = prl_tx_snk_start_ams_entry,
- .run = prl_tx_snk_start_ams_run,
- },
-#endif /* CONFIG_USB_PD_REV30 */
- [PRL_TX_SRC_PENDING] = {
- .entry = prl_tx_src_pending_entry,
- .run = prl_tx_src_pending_run,
- .exit = prl_tx_src_pending_exit,
- },
- [PRL_TX_SNK_PENDING] = {
- .entry = prl_tx_snk_pending_entry,
- .run = prl_tx_snk_pending_run,
- },
- [PRL_TX_DISCARD_MESSAGE] = {
- .entry = prl_tx_discard_message_entry,
- },
-};
-
-/* All necessary Protocol Hard Reset States (Section 6.11.2.4) */
-static __const_data const struct usb_state prl_hr_states[] = {
- [PRL_HR_WAIT_FOR_REQUEST] = {
- .entry = prl_hr_wait_for_request_entry,
- .run = prl_hr_wait_for_request_run,
- },
- [PRL_HR_RESET_LAYER] = {
- .entry = prl_hr_reset_layer_entry,
- .run = prl_hr_reset_layer_run,
- },
- [PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE] = {
- .entry = prl_hr_wait_for_phy_hard_reset_complete_entry,
- .run = prl_hr_wait_for_phy_hard_reset_complete_run,
- .exit = prl_hr_wait_for_phy_hard_reset_complete_exit,
- },
- [PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE] = {
- .entry = prl_hr_wait_for_pe_hard_reset_complete_entry,
- .run = prl_hr_wait_for_pe_hard_reset_complete_run,
- .exit = prl_hr_wait_for_pe_hard_reset_complete_exit,
- },
-};
-
-/* All necessary Chunked Rx states (Section 6.11.2.1.2) */
-__maybe_unused static const struct usb_state rch_states[] = {
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- [RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER] = {
- .entry = rch_wait_for_message_from_protocol_layer_entry,
- .run = rch_wait_for_message_from_protocol_layer_run,
- },
- [RCH_PASS_UP_MESSAGE] = {
- .entry = rch_pass_up_message_entry,
- },
- [RCH_PROCESSING_EXTENDED_MESSAGE] = {
- .entry = rch_processing_extended_message_entry,
- .run = rch_processing_extended_message_run,
- },
- [RCH_REQUESTING_CHUNK] = {
- .entry = rch_requesting_chunk_entry,
- .run = rch_requesting_chunk_run,
- },
- [RCH_WAITING_CHUNK] = {
- .entry = rch_waiting_chunk_entry,
- .run = rch_waiting_chunk_run,
- .exit = rch_waiting_chunk_exit,
- },
- [RCH_REPORT_ERROR] = {
- .entry = rch_report_error_entry,
- .run = rch_report_error_run,
- },
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-};
-
-/* All necessary Chunked Tx states (Section 6.11.2.1.3) */
-__maybe_unused static const struct usb_state tch_states[] = {
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- [TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE] = {
- .entry = tch_wait_for_message_request_from_pe_entry,
- .run = tch_wait_for_message_request_from_pe_run,
- },
- [TCH_WAIT_FOR_TRANSMISSION_COMPLETE] = {
- .entry = tch_wait_for_transmission_complete_entry,
- .run = tch_wait_for_transmission_complete_run,
- },
- [TCH_CONSTRUCT_CHUNKED_MESSAGE] = {
- .entry = tch_construct_chunked_message_entry,
- .run = tch_construct_chunked_message_run,
- },
- [TCH_SENDING_CHUNKED_MESSAGE] = {
- .entry = tch_sending_chunked_message_entry,
- .run = tch_sending_chunked_message_run,
- },
- [TCH_WAIT_CHUNK_REQUEST] = {
- .entry = tch_wait_chunk_request_entry,
- .run = tch_wait_chunk_request_run,
- .exit = tch_wait_chunk_request_exit,
- },
- [TCH_MESSAGE_RECEIVED] = {
- .entry = tch_message_received_entry,
- .run = tch_message_received_run,
- },
- [TCH_MESSAGE_SENT] = {
- .entry = tch_message_sent_entry,
- },
- [TCH_REPORT_ERROR] = {
- .entry = tch_report_error_entry,
- },
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-};
-
-#ifdef TEST_BUILD
-
-const struct test_sm_data test_prl_sm_data[] = {
- {
- .base = prl_tx_states,
- .size = ARRAY_SIZE(prl_tx_states),
- .names = prl_tx_state_names,
- .names_size = ARRAY_SIZE(prl_tx_state_names),
- },
- {
- .base = prl_hr_states,
- .size = ARRAY_SIZE(prl_hr_states),
- .names = prl_hr_state_names,
- .names_size = ARRAY_SIZE(prl_hr_state_names),
- },
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- {
- .base = rch_states,
- .size = ARRAY_SIZE(rch_states),
- .names = rch_state_names,
- .names_size = ARRAY_SIZE(rch_state_names),
- },
- {
- .base = tch_states,
- .size = ARRAY_SIZE(tch_states),
- .names = tch_state_names,
- .names_size = ARRAY_SIZE(tch_state_names),
- },
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-};
-BUILD_ASSERT(ARRAY_SIZE(prl_tx_states) == ARRAY_SIZE(prl_tx_state_names));
-BUILD_ASSERT(ARRAY_SIZE(prl_hr_states) == ARRAY_SIZE(prl_hr_state_names));
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
-BUILD_ASSERT(ARRAY_SIZE(rch_states) == ARRAY_SIZE(rch_state_names));
-BUILD_ASSERT(ARRAY_SIZE(tch_states) == ARRAY_SIZE(tch_state_names));
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-const int test_prl_sm_data_size = ARRAY_SIZE(test_prl_sm_data);
-#endif