summaryrefslogtreecommitdiff
path: root/common/usb_pd_policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/usb_pd_policy.c')
-rw-r--r--common/usb_pd_policy.c969
1 files changed, 0 insertions, 969 deletions
diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c
deleted file mode 100644
index de6fc63a60..0000000000
--- a/common/usb_pd_policy.c
+++ /dev/null
@@ -1,969 +0,0 @@
-/* Copyright 2014 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 "atomic.h"
-#include "charge_manager.h"
-#include "common.h"
-#include "console.h"
-#include "cros_version.h"
-#include "ec_commands.h"
-#include "flash.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "mkbp_event.h"
-#include "registers.h"
-#include "rsa.h"
-#include "sha256.h"
-#include "system.h"
-#include "task.h"
-#include "tcpm/tcpm.h"
-#include "timer.h"
-#include "util.h"
-#include "usb_api.h"
-#include "usb_common.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
-#include "usbc_ppc.h"
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args)
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args)
-#else
-#define CPRINTS(format, args...)
-#define CPRINTF(format, args...)
-#endif
-
-/*
- * This file is currently only used for TCPMv1, and would need changes before
- * being used for TCPMv2. One example: PD_FLAGS_* are TCPMv1 only.
- */
-#ifndef CONFIG_USB_PD_TCPMV1
-#error This file must only be used with TCPMv1
-#endif
-
-static int rw_flash_changed = 1;
-
-__overridable void pd_check_pr_role(int port, enum pd_power_role pr_role,
- int flags)
-{
- /*
- * If partner is dual-role power and dualrole toggling is on, consider
- * if a power swap is necessary.
- */
- if ((flags & PD_FLAGS_PARTNER_DR_POWER) &&
- pd_get_dual_role(port) == PD_DRP_TOGGLE_ON) {
- /*
- * If we are a sink and partner is not unconstrained, then
- * swap to become a source. If we are source and partner is
- * unconstrained, swap to become a sink.
- */
- int partner_unconstrained = flags & PD_FLAGS_PARTNER_UNCONSTR;
-
- if ((!partner_unconstrained && pr_role == PD_ROLE_SINK) ||
- (partner_unconstrained && pr_role == PD_ROLE_SOURCE))
- pd_request_power_swap(port);
- }
-}
-
-__overridable void pd_check_dr_role(int port, enum pd_data_role dr_role,
- int flags)
-{
- /* If UFP, try to switch to DFP */
- if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_UFP)
- pd_request_data_swap(port);
-}
-
-#ifdef CONFIG_MKBP_EVENT
-static int dp_alt_mode_entry_get_next_event(uint8_t *data)
-{
- return EC_SUCCESS;
-}
-DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_DP_ALT_MODE_ENTERED,
- dp_alt_mode_entry_get_next_event);
-#endif /* CONFIG_MKBP_EVENT */
-
-/* Last received source cap */
-static uint32_t pd_src_caps[CONFIG_USB_PD_PORT_MAX_COUNT][PDO_MAX_OBJECTS];
-static uint8_t pd_src_cap_cnt[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-const uint32_t * const pd_get_src_caps(int port)
-{
- return pd_src_caps[port];
-}
-
-void pd_set_src_caps(int port, int cnt, uint32_t *src_caps)
-{
- int i;
-
- pd_src_cap_cnt[port] = cnt;
-
- for (i = 0; i < cnt; i++)
- pd_src_caps[port][i] = *src_caps++;
-}
-
-uint8_t pd_get_src_cap_cnt(int port)
-{
- return pd_src_cap_cnt[port];
-}
-
-static struct pd_cable cable[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-enum pd_rev_type get_usb_pd_cable_revision(int port)
-{
- return cable[port].rev;
-}
-
-bool consume_sop_prime_repeat_msg(int port, uint8_t msg_id)
-{
- if (cable[port].last_sop_p_msg_id != msg_id) {
- cable[port].last_sop_p_msg_id = msg_id;
- return false;
- }
- CPRINTF("C%d SOP Prime repeat msg_id %d\n", port, msg_id);
- return true;
-}
-
-bool consume_sop_prime_prime_repeat_msg(int port, uint8_t msg_id)
-{
- if (cable[port].last_sop_p_p_msg_id != msg_id) {
- cable[port].last_sop_p_p_msg_id = msg_id;
- return false;
- }
- CPRINTF("C%d SOP Prime Prime repeat msg_id %d\n", port, msg_id);
- return true;
-}
-
-__maybe_unused static uint8_t is_sop_prime_ready(int port)
-{
- /*
- * Ref: USB PD 3.0 sec 2.5.4: When an Explicit Contract is in place the
- * VCONN Source (either the DFP or the UFP) can communicate with the
- * Cable Plug(s) using SOP’/SOP’’ Packets
- *
- * Ref: USB PD 2.0 sec 2.4.4: When an Explicit Contract is in place the
- * DFP (either the Source or the Sink) can communicate with the
- * Cable Plug(s) using SOP’/SOP” Packets.
- * Sec 3.6.11 : Before communicating with a Cable Plug a Port Should
- * ensure that it is the Vconn Source
- */
- return (pd_get_vconn_state(port) &&
- (IS_ENABLED(CONFIG_USB_PD_REV30) ||
- (pd_get_data_role(port) == PD_ROLE_DFP)));
-}
-
-void reset_pd_cable(int port)
-{
- memset(&cable[port], 0, sizeof(cable[port]));
- cable[port].last_sop_p_msg_id = INVALID_MSG_ID_COUNTER;
- cable[port].last_sop_p_p_msg_id = INVALID_MSG_ID_COUNTER;
-}
-
-bool should_enter_usb4_mode(int port)
-{
- return IS_ENABLED(CONFIG_USB_PD_USB4) &&
- cable[port].flags & CABLE_FLAGS_ENTER_USB_MODE;
-}
-
-void enable_enter_usb4_mode(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_USB4))
- cable[port].flags |= CABLE_FLAGS_ENTER_USB_MODE;
-}
-
-void disable_enter_usb4_mode(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_USB4))
- cable[port].flags &= ~CABLE_FLAGS_ENTER_USB_MODE;
-}
-
-#ifdef CONFIG_USB_PD_ALT_MODE
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-
-static struct pd_discovery discovery[CONFIG_USB_PD_PORT_MAX_COUNT]
- [DISCOVERY_TYPE_COUNT];
-static struct partner_active_modes partner_amodes[CONFIG_USB_PD_PORT_MAX_COUNT]
- [AMODE_TYPE_COUNT];
-
-static bool is_vdo_present(int cnt, int index)
-{
- return cnt > index;
-}
-
-static bool is_modal(int port, int cnt, const uint32_t *payload)
-{
- return is_vdo_present(cnt, VDO_INDEX_IDH) &&
- PD_IDH_IS_MODAL(payload[VDO_INDEX_IDH]);
-}
-
-static bool is_tbt_compat_mode(int port, int cnt, const uint32_t *payload)
-{
- /*
- * Ref: USB Type-C cable and connector specification
- * F.2.5 TBT3 Device Discover Mode Responses
- */
- return is_vdo_present(cnt, VDO_INDEX_IDH) &&
- PD_VDO_RESP_MODE_INTEL_TBT(payload[VDO_INDEX_IDH]);
-}
-
-static bool cable_supports_tbt_speed(int port)
-{
- enum tbt_compat_cable_speed tbt_cable_speed = get_tbt_cable_speed(port);
-
- return (tbt_cable_speed == TBT_SS_TBT_GEN3 ||
- tbt_cable_speed == TBT_SS_U32_GEN1_GEN2);
-}
-
-static bool is_tbt_compat_enabled(int port)
-{
- return (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) &&
- (cable[port].flags & CABLE_FLAGS_TBT_COMPAT_ENABLE));
-}
-
-static void enable_tbt_compat_mode(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE))
- cable[port].flags |= CABLE_FLAGS_TBT_COMPAT_ENABLE;
-}
-
-static inline void disable_tbt_compat_mode(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE))
- cable[port].flags &= ~CABLE_FLAGS_TBT_COMPAT_ENABLE;
-}
-
-static inline void limit_tbt_cable_speed(int port)
-{
- /* Cable flags are cleared when cable reset is called */
- cable[port].flags |= CABLE_FLAGS_TBT_COMPAT_LIMIT_SPEED;
-}
-
-static inline bool is_limit_tbt_cable_speed(int port)
-{
- return !!(cable[port].flags & CABLE_FLAGS_TBT_COMPAT_LIMIT_SPEED);
-}
-
-static bool is_intel_svid(int port, enum tcpci_msg_type type)
-{
- int i;
-
- for (i = 0; i < discovery[port][type].svid_cnt; i++) {
- if (pd_get_svid(port, i, type) == USB_VID_INTEL)
- return true;
- }
-
- return false;
-}
-
-static inline bool is_usb4_mode_enabled(int port)
-{
- return (IS_ENABLED(CONFIG_USB_PD_USB4) &&
- (cable[port].flags & CABLE_FLAGS_USB4_CAPABLE));
-}
-
-static inline void enable_usb4_mode(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_USB4))
- cable[port].flags |= CABLE_FLAGS_USB4_CAPABLE;
-}
-
-static inline void disable_usb4_mode(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_USB4))
- cable[port].flags &= ~CABLE_FLAGS_USB4_CAPABLE;
-}
-
-/*
- * Ref: USB Type-C Cable and Connector Specification
- * Figure 5-1 USB4 Discovery and Entry Flow Model.
- *
- * Note: USB Type-C Cable and Connector Specification
- * doesn't include details for Revision 2 cables.
- *
- * Passive Cable
- * |
- * -----------------------------------
- * | |
- * Revision 2 Revision 3
- * USB Signalling USB Signalling
- * | |
- * ------------------ -------------------------
- * | | | | | | |
- * USB2.0 USB3.1 USB3.1 USB3.2 USB4 USB3.2 USB2
- * | Gen1 Gen1 Gen2 Gen2 Gen3 Gen1 |
- * | | | | | | Exit
- * -------- ------------ -------- USB4
- * | | | Discovery.
- * Exit Is DFP Gen3 Capable? Enter USB4
- * USB4 | with respective
- * Discovery. --- No ---|--- Yes --- cable speed.
- * | |
- * Enter USB4 with Is Cable TBT3
- * respective cable |
- * speed. --- No ---|--- Yes ---
- * | |
- * Enter USB4 with Enter USB4 with
- * TBT Gen2 passive TBT Gen3 passive
- * cable. cable.
- *
- */
-static bool is_cable_ready_to_enter_usb4(int port, int cnt)
-{
- /* TODO: USB4 enter mode for Active cables */
- struct pd_discovery *disc = &discovery[port][TCPCI_MSG_SOP_PRIME];
- if (IS_ENABLED(CONFIG_USB_PD_USB4) &&
- (get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE) &&
- is_vdo_present(cnt, VDO_INDEX_PTYPE_CABLE1)) {
- switch (cable[port].rev) {
- case PD_REV30:
- switch (disc->identity.product_t1.p_rev30.ss) {
- case USB_R30_SS_U40_GEN3:
- case USB_R30_SS_U32_U40_GEN1:
- return true;
- case USB_R30_SS_U32_U40_GEN2:
- /* Check if DFP is Gen 3 capable */
- if (IS_ENABLED(CONFIG_USB_PD_TBT_GEN3_CAPABLE))
- return false;
- return true;
- default:
- disable_usb4_mode(port);
- return false;
- }
- case PD_REV20:
- switch (disc->identity.product_t1.p_rev20.ss) {
- case USB_R20_SS_U31_GEN1_GEN2:
- /* Check if DFP is Gen 3 capable */
- if (IS_ENABLED(CONFIG_USB_PD_TBT_GEN3_CAPABLE))
- return false;
- return true;
- default:
- disable_usb4_mode(port);
- return false;
- }
- default:
- disable_usb4_mode(port);
- }
- }
- return false;
-}
-
-void pd_dfp_discovery_init(int port)
-{
- memset(&discovery[port], 0, sizeof(struct pd_discovery));
-}
-
-void pd_dfp_mode_init(int port)
-{
- memset(&partner_amodes[port], 0, sizeof(partner_amodes[0]));
-}
-
-static int dfp_discover_ident(uint32_t *payload)
-{
- payload[0] = VDO(USB_SID_PD, 1, CMD_DISCOVER_IDENT);
- return 1;
-}
-
-static int dfp_discover_svids(uint32_t *payload)
-{
- payload[0] = VDO(USB_SID_PD, 1, CMD_DISCOVER_SVID);
- return 1;
-}
-
-struct pd_discovery *pd_get_am_discovery_and_notify_access(
- int port, enum tcpci_msg_type type)
-{
- return (struct pd_discovery *)pd_get_am_discovery(port, type);
-}
-
-const struct pd_discovery *pd_get_am_discovery(int port,
- enum tcpci_msg_type type)
-{
- return &discovery[port][type];
-}
-
-struct partner_active_modes *
-pd_get_partner_active_modes(int port, enum tcpci_msg_type type)
-{
- assert(type < AMODE_TYPE_COUNT);
- return &partner_amodes[port][type];
-}
-
-/* Note: Enter mode flag is not needed by TCPMv1 */
-void pd_set_dfp_enter_mode_flag(int port, bool set)
-{
-}
-
-/**
- * Return the discover alternate mode payload data
- *
- * @param port USB-C port number
- * @param payload Pointer to payload data to fill
- * @return 1 if valid SVID present else 0
- */
-static int dfp_discover_modes(int port, uint32_t *payload)
-{
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP);
- uint16_t svid = disc->svids[disc->svid_idx].svid;
-
- if (disc->svid_idx >= disc->svid_cnt)
- return 0;
-
- payload[0] = VDO(svid, 1, CMD_DISCOVER_MODES);
-
- return 1;
-}
-
-static bool is_usb4_vdo(int port, int cnt, uint32_t *payload)
-{
- enum idh_ptype ptype = PD_IDH_PTYPE(payload[VDO_I(IDH)]);
-
- if (IS_PD_IDH_UFP_PTYPE(ptype)) {
- /*
- * Ref: USB Type-C Cable and Connector Specification
- * Figure 5-1 USB4 Discovery and Entry Flow Model
- * Device USB4 VDO detection.
- */
- return IS_ENABLED(CONFIG_USB_PD_USB4) &&
- is_vdo_present(cnt, VDO_INDEX_PTYPE_UFP1_VDO) &&
- PD_PRODUCT_IS_USB4(payload[VDO_INDEX_PTYPE_UFP1_VDO]);
- }
- return false;
-}
-
-static int process_am_discover_ident_sop(int port, int cnt, uint32_t head,
- uint32_t *payload,
- enum tcpci_msg_type *rtype)
-{
- pd_dfp_discovery_init(port);
- pd_dfp_mode_init(port);
- dfp_consume_identity(port, TCPCI_MSG_SOP, cnt, payload);
-
- if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP) && is_sop_prime_ready(port) &&
- board_is_tbt_usb4_port(port)) {
- /* Enable USB4 mode if USB4 VDO present and port partner
- * supports USB Rev 3.0.
- */
- if (is_usb4_vdo(port, cnt, payload) &&
- PD_HEADER_REV(head) == PD_REV30)
- enable_usb4_mode(port);
-
- /*
- * Enable Thunderbolt-compatible mode if the modal operation is
- * supported.
- */
- if (is_modal(port, cnt, payload))
- enable_tbt_compat_mode(port);
-
- if (is_modal(port, cnt, payload) ||
- is_usb4_vdo(port, cnt, payload)) {
- *rtype = TCPCI_MSG_SOP_PRIME;
- return dfp_discover_ident(payload);
- }
- }
-
- return dfp_discover_svids(payload);
-}
-
-static int process_am_discover_ident_sop_prime(int port, int cnt, uint32_t head,
- uint32_t *payload)
-{
- dfp_consume_identity(port, TCPCI_MSG_SOP_PRIME, cnt, payload);
- cable[port].rev = PD_HEADER_REV(head);
-
- /*
- * Enter USB4 mode if the cable supports USB4 operation and has USB4
- * VDO.
- */
- if (is_usb4_mode_enabled(port) &&
- is_cable_ready_to_enter_usb4(port, cnt)) {
- enable_enter_usb4_mode(port);
- usb_mux_set_safe_mode(port);
- /*
- * To change the mode of operation from USB4 the port needs to
- * be reconfigured.
- * Ref: USB Type-C Cable and Connectot Spec section 5.4.4.
- */
- disable_tbt_compat_mode(port);
- return 0;
- }
-
- /*
- * Disable Thunderbolt-compatible mode if the cable does not support
- * superspeed.
- */
- if (is_tbt_compat_enabled(port) &&
- get_tbt_cable_speed(port) < TBT_SS_U31_GEN1)
- disable_tbt_compat_mode(port);
-
- return dfp_discover_svids(payload);
-}
-
-static int process_am_discover_svids(int port, int cnt, uint32_t *payload,
- enum tcpci_msg_type sop,
- enum tcpci_msg_type *rtype)
-{
- /*
- * The pd_discovery structure stores SOP and SOP' discovery results
- * separately, but TCPMv1 depends on one-dimensional storage of SVIDs
- * and modes. Therefore, always use TCPCI_MSG_SOP in TCPMv1.
- */
- dfp_consume_svids(port, sop, cnt, payload);
-
- /*
- * Ref: USB Type-C Cable and Connector Specification,
- * figure F-1: TBT3 Discovery Flow
- *
- * For USB4 mode if device or cable doesn't have Intel SVID,
- * disable Thunderbolt-Compatible mode directly enter USB4 mode
- * with USB3.2 Gen1/Gen2 speed.
- *
- * For Thunderbolt-compatible, check if 0x8087 is received for
- * Discover SVID SOP. If not, disable Thunderbolt-compatible mode
- *
- * If 0x8087 is not received for Discover SVID SOP' limit to TBT
- * passive Gen 2 cable.
- */
- if (is_tbt_compat_enabled(port)) {
- bool intel_svid = is_intel_svid(port, sop);
- if (!intel_svid) {
- if (is_usb4_mode_enabled(port)) {
- disable_tbt_compat_mode(port);
- cable[port].cable_mode_resp.tbt_cable_speed =
- TBT_SS_U32_GEN1_GEN2;
- enable_enter_usb4_mode(port);
- usb_mux_set_safe_mode(port);
- return 0;
- }
-
- if (sop == TCPCI_MSG_SOP_PRIME)
- limit_tbt_cable_speed(port);
- else
- disable_tbt_compat_mode(port);
- } else if (sop == TCPCI_MSG_SOP) {
- *rtype = TCPCI_MSG_SOP_PRIME;
- return dfp_discover_svids(payload);
- }
- }
-
- return dfp_discover_modes(port, payload);
-}
-
-static int process_tbt_compat_discover_modes(int port,
- enum tcpci_msg_type sop,
- uint32_t *payload,
- enum tcpci_msg_type *rtype)
-{
- int rsize;
-
- /* Initialize transmit type to SOP */
- *rtype = TCPCI_MSG_SOP;
-
- /*
- * For active cables, Enter mode: SOP', SOP'', SOP
- * Ref: USB Type-C Cable and Connector Specification, figure F-1: TBT3
- * Discovery Flow and Section F.2.7 TBT3 Cable Enter Mode Command.
- */
- if (sop == TCPCI_MSG_SOP_PRIME) {
- /* Store Discover Mode SOP' response */
- cable[port].cable_mode_resp.raw_value = payload[1];
-
- if (is_usb4_mode_enabled(port)) {
- /*
- * If Cable is not Thunderbolt Gen 3
- * capable or Thunderbolt Gen1_Gen2
- * capable, disable USB4 mode and
- * continue flow for
- * Thunderbolt-compatible mode
- */
- if (cable_supports_tbt_speed(port)) {
- enable_enter_usb4_mode(port);
- usb_mux_set_safe_mode(port);
- return 0;
- }
- disable_usb4_mode(port);
- }
-
- /*
- * Send TBT3 Cable Enter Mode (SOP') for active cables,
- * otherwise send TBT3 Device Enter Mode (SOP).
- */
- if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE)
- *rtype = TCPCI_MSG_SOP_PRIME;
-
- rsize = enter_tbt_compat_mode(port, *rtype, payload);
- } else {
- /* Store Discover Mode SOP response */
- cable[port].dev_mode_resp.raw_value = payload[1];
-
- if (is_limit_tbt_cable_speed(port)) {
- /*
- * Passive cable has Nacked for Discover SVID.
- * No need to do Discover modes of cable.
- * Enter into device Thunderbolt-compatible mode.
- */
- rsize = enter_tbt_compat_mode(port, *rtype, payload);
- } else {
- /* Discover modes for SOP' */
- discovery[port][TCPCI_MSG_SOP].svid_idx--;
- rsize = dfp_discover_modes(port, payload);
- *rtype = TCPCI_MSG_SOP_PRIME;
- }
- }
-
- return rsize;
-}
-
-static int obj_cnt_enter_tbt_compat_mode(int port, enum tcpci_msg_type sop,
- uint32_t *payload,
- enum tcpci_msg_type *rtype)
-{
- struct pd_discovery *disc = &discovery[port][TCPCI_MSG_SOP_PRIME];
-
- /* Enter mode SOP' for active cables */
- if (sop == TCPCI_MSG_SOP_PRIME) {
- /* Check if the cable has a SOP'' controller */
- if (disc->identity.product_t1.a_rev20.sop_p_p)
- *rtype = TCPCI_MSG_SOP_PRIME_PRIME;
- return enter_tbt_compat_mode(port, *rtype, payload);
- }
-
- /* Enter Mode SOP'' for active cables with SOP'' controller */
- if (sop == TCPCI_MSG_SOP_PRIME_PRIME)
- return enter_tbt_compat_mode(port, *rtype, payload);
-
- /* Update Mux state to Thunderbolt-compatible mode. */
- set_tbt_compat_mode_ready(port);
- /* No response once device (and cable) acks */
- return 0;
-}
-#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
-
-int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload,
- uint32_t head, enum tcpci_msg_type *rtype)
-{
- int cmd = PD_VDO_CMD(payload[0]);
- int cmd_type = PD_VDO_CMDT(payload[0]);
- int (*func)(int port, uint32_t *payload) = NULL;
-
- int rsize = 1; /* VDM header at a minimum */
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- enum tcpci_msg_type sop = PD_HEADER_GET_SOP(head);
-#endif
-
- /* Transmit SOP messages by default */
- *rtype = TCPCI_MSG_SOP;
-
- payload[0] &= ~VDO_CMDT_MASK;
- *rpayload = payload;
-
- if (cmd_type == CMDT_INIT) {
- switch (cmd) {
- case CMD_DISCOVER_IDENT:
- func = svdm_rsp.identity;
- break;
- case CMD_DISCOVER_SVID:
- func = svdm_rsp.svids;
- break;
- case CMD_DISCOVER_MODES:
- func = svdm_rsp.modes;
- break;
- case CMD_ENTER_MODE:
- func = svdm_rsp.enter_mode;
- break;
- case CMD_DP_STATUS:
- if (svdm_rsp.amode)
- func = svdm_rsp.amode->status;
- break;
- case CMD_DP_CONFIG:
- if (svdm_rsp.amode)
- func = svdm_rsp.amode->config;
- break;
- case CMD_EXIT_MODE:
- func = svdm_rsp.exit_mode;
- break;
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- case CMD_ATTENTION:
- /*
- * attention is only SVDM with no response
- * (just goodCRC) return zero here.
- */
- dfp_consume_attention(port, payload);
- return 0;
-#endif
- default:
- CPRINTF("ERR:CMD:%d\n", cmd);
- rsize = 0;
- }
- if (func)
- rsize = func(port, payload);
- else /* not supported : NACK it */
- rsize = 0;
- if (rsize >= 1)
- payload[0] |= VDO_CMDT(CMDT_RSP_ACK);
- else if (!rsize) {
- payload[0] |= VDO_CMDT(CMDT_RSP_NAK);
- rsize = 1;
- } else {
- payload[0] |= VDO_CMDT(CMDT_RSP_BUSY);
- rsize = 1;
- }
- payload[0] |=
- VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP));
- } else if (cmd_type == CMDT_RSP_ACK) {
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- struct svdm_amode_data *modep;
-
- modep = pd_get_amode_data(port, TCPCI_MSG_SOP,
- PD_VDO_VID(payload[0]));
-#endif
- switch (cmd) {
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- case CMD_DISCOVER_IDENT:
- /* Received a SOP' Discover Ident msg */
- if (sop == TCPCI_MSG_SOP_PRIME) {
- rsize = process_am_discover_ident_sop_prime(
- port, cnt, head, payload);
- /* Received a SOP Discover Ident Message */
- } else {
- rsize = process_am_discover_ident_sop(
- port, cnt, head, payload, rtype);
- }
- break;
- case CMD_DISCOVER_SVID:
- rsize = process_am_discover_svids(port, cnt, payload,
- sop, rtype);
- break;
- case CMD_DISCOVER_MODES:
- dfp_consume_modes(port, sop, cnt, payload);
- if (is_tbt_compat_enabled(port) &&
- is_tbt_compat_mode(port, cnt, payload)) {
- rsize = process_tbt_compat_discover_modes(
- port, sop, payload, rtype);
- break;
- }
-
- rsize = dfp_discover_modes(port, payload);
- /* enter the default mode for DFP */
- if (!rsize) {
- /*
- * Disabling Thunderbolt-Compatible mode if
- * discover mode response doesn't include Intel
- * SVID.
- */
- disable_tbt_compat_mode(port);
- payload[0] = pd_dfp_enter_mode(
- port, TCPCI_MSG_SOP, 0, 0);
- if (payload[0])
- rsize = 1;
- }
- break;
- case CMD_ENTER_MODE:
- if (is_tbt_compat_enabled(port)) {
- rsize = obj_cnt_enter_tbt_compat_mode(
- port, sop, payload, rtype);
- /*
- * Continue with PD flow if
- * Thunderbolt-compatible mode is disabled.
- */
- } else if (!modep) {
- rsize = 0;
- } else {
- if (!modep->opos)
- pd_dfp_enter_mode(port, TCPCI_MSG_SOP,
- 0, 0);
-
- if (modep->opos) {
- rsize = modep->fx->status(port,
- payload);
- payload[0] |= PD_VDO_OPOS(modep->opos);
- }
- }
- break;
- case CMD_DP_STATUS:
- /* DP status response & UFP's DP attention have same
- payload */
- dfp_consume_attention(port, payload);
- if (modep && modep->opos)
- rsize = modep->fx->config(port, payload);
- else
- rsize = 0;
- break;
- case CMD_DP_CONFIG:
- if (modep && modep->opos && modep->fx->post_config)
- modep->fx->post_config(port);
- /* no response after DFPs ack */
- rsize = 0;
- break;
- case CMD_EXIT_MODE:
- /* no response after DFPs ack */
- rsize = 0;
- break;
-#endif
- case CMD_ATTENTION:
- /* no response after DFPs ack */
- rsize = 0;
- break;
- default:
- CPRINTF("ERR:CMD:%d\n", cmd);
- rsize = 0;
- }
-
- payload[0] |= VDO_CMDT(CMDT_INIT);
- payload[0] |=
- VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP));
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- } else if (cmd_type == CMDT_RSP_BUSY) {
- switch (cmd) {
- case CMD_DISCOVER_IDENT:
- case CMD_DISCOVER_SVID:
- case CMD_DISCOVER_MODES:
- /* resend if its discovery */
- rsize = 1;
- break;
- case CMD_ENTER_MODE:
- /* Error */
- CPRINTF("ERR:ENTBUSY\n");
- rsize = 0;
- break;
- case CMD_EXIT_MODE:
- rsize = 0;
- break;
- default:
- rsize = 0;
- }
- } else if (cmd_type == CMDT_RSP_NAK) {
- /* Passive cable Nacked for Discover SVID */
- if (cmd == CMD_DISCOVER_SVID && is_tbt_compat_enabled(port) &&
- sop == TCPCI_MSG_SOP_PRIME &&
- get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE) {
- limit_tbt_cable_speed(port);
- rsize = dfp_discover_modes(port, payload);
- } else {
- rsize = 0;
- }
-#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
- } else {
- CPRINTF("ERR:CMDT:%d\n", cmd);
- /* do not answer */
- rsize = 0;
- }
- return rsize;
-}
-
-#else
-
-int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload,
- uint32_t head, enum tcpci_msg_type *rtype)
-{
- return 0;
-}
-
-#endif /* CONFIG_USB_PD_ALT_MODE */
-
-#define FW_RW_END \
- (CONFIG_EC_WRITABLE_STORAGE_OFF + CONFIG_RW_STORAGE_OFF + \
- CONFIG_RW_SIZE)
-
-uint8_t *flash_hash_rw(void)
-{
- static struct sha256_ctx ctx;
-
- /* re-calculate RW hash when changed as its time consuming */
- if (rw_flash_changed) {
- rw_flash_changed = 0;
- SHA256_init(&ctx);
- SHA256_update(&ctx,
- (void *)CONFIG_PROGRAM_MEMORY_BASE +
- CONFIG_RW_MEM_OFF,
- CONFIG_RW_SIZE - RSANUMBYTES);
- return SHA256_final(&ctx);
- } else {
- return ctx.buf;
- }
-}
-
-void pd_get_info(uint32_t *info_data)
-{
- void *rw_hash = flash_hash_rw();
-
- /* copy first 20 bytes of RW hash */
- memcpy(info_data, rw_hash, 5 * sizeof(uint32_t));
- /* copy other info into data msg */
-#if defined(CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR) && \
- defined(CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR)
- info_data[5] = VDO_INFO(CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR,
- CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR,
- ver_get_num_commits(system_get_image_copy()),
- (system_get_image_copy() != EC_IMAGE_RO));
-#else
- info_data[5] = 0;
-#endif
-}
-
-int pd_custom_flash_vdm(int port, int cnt, uint32_t *payload)
-{
- static int flash_offset;
- int rsize = 1; /* default is just VDM header returned */
-
- switch (PD_VDO_CMD(payload[0])) {
- case VDO_CMD_VERSION:
- memcpy(payload + 1, &current_image_data.version, 24);
- rsize = 7;
- break;
- case VDO_CMD_REBOOT:
- /* ensure the power supply is in a safe state */
- pd_power_supply_reset(0);
- system_reset(0);
- break;
- case VDO_CMD_READ_INFO:
- /* copy info into response */
- pd_get_info(payload + 1);
- rsize = 7;
- break;
- case VDO_CMD_FLASH_ERASE:
- /* do not kill the code under our feet */
- if (system_get_image_copy() != EC_IMAGE_RO)
- break;
- pd_log_event(PD_EVENT_ACC_RW_ERASE, 0, 0, NULL);
- flash_offset =
- CONFIG_EC_WRITABLE_STORAGE_OFF + CONFIG_RW_STORAGE_OFF;
- crec_flash_physical_erase(CONFIG_EC_WRITABLE_STORAGE_OFF +
- CONFIG_RW_STORAGE_OFF,
- CONFIG_RW_SIZE);
- rw_flash_changed = 1;
- break;
- case VDO_CMD_FLASH_WRITE:
- /* do not kill the code under our feet */
- if ((system_get_image_copy() != EC_IMAGE_RO) ||
- (flash_offset <
- CONFIG_EC_WRITABLE_STORAGE_OFF + CONFIG_RW_STORAGE_OFF))
- break;
- crec_flash_physical_write(flash_offset, 4 * (cnt - 1),
- (const char *)(payload + 1));
- flash_offset += 4 * (cnt - 1);
- rw_flash_changed = 1;
- break;
- case VDO_CMD_ERASE_SIG:
- /* this is not touching the code area */
- {
- uint32_t zero = 0;
- int offset;
- /* zeroes the area containing the RSA signature */
- for (offset = FW_RW_END - RSANUMBYTES;
- offset < FW_RW_END; offset += 4)
- crec_flash_physical_write(offset, 4,
- (const char *)&zero);
- }
- break;
- default:
- /* Unknown : do not answer */
- return 0;
- }
- return rsize;
-}