summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMary Ruthven <mruthven@chromium.org>2021-01-05 13:35:59 -0800
committerCommit Bot <commit-bot@chromium.org>2021-01-06 21:56:53 +0000
commit7103bc89ed2a4460a606b62b63df02e7f0ecb3df (patch)
tree0634b852aff059895a6ced19dcdb52c6570ec5c2
parent2495bc0a9744f9733c59daeeb81c8be3c54243d8 (diff)
downloadchrome-ec-7103bc89ed2a4460a606b62b63df02e7f0ecb3df.tar.gz
coil: remove usbc, usb_pd, charge_manager, and tcpm
This code uses coil terms we're removing, but we don't use it in platform/cr50. Remove the code instead of replacing the terms. BUG=b:175244613 TEST=make buildall -j Change-Id: Ia64e1ff4df941d2fe19e95e84dee8b743616aa88 Signed-off-by: Mary Ruthven <mruthven@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2613135 Reviewed-by: Namyoon Woo <namyoon@chromium.org>
-rw-r--r--board/host/build.mk1
-rw-r--r--board/host/usb_pd_config.c35
-rw-r--r--board/host/usb_pd_config.h24
-rw-r--r--board/host/usb_pd_policy.c96
-rw-r--r--chip/host/build.mk1
-rw-r--r--chip/host/usb_pd_phy.c370
-rw-r--r--common/build.mk13
-rw-r--r--common/charge_manager.c1455
-rw-r--r--common/i2c_master.c21
-rw-r--r--common/mock/usb_mux_mock.c51
-rw-r--r--common/mock/usb_mux_mock.h19
-rw-r--r--common/peripheral.c17
-rw-r--r--common/rwsig.c2
-rw-r--r--common/system.c34
-rw-r--r--common/usb_charger.c120
-rw-r--r--common/usb_common.c381
-rw-r--r--common/usb_pd_policy.c1158
-rw-r--r--common/usb_pd_protocol.c5761
-rw-r--r--common/usb_pd_tcpc.c1463
-rw-r--r--common/usb_port_power_dumb.c162
-rw-r--r--common/usb_port_power_smart.c263
-rw-r--r--common/usbc/build.mk24
-rw-r--r--common/usbc/usb_pe_ctvpd_sm.c217
-rw-r--r--common/usbc/usb_pe_drp_sm.c5244
-rw-r--r--common/usbc/usb_prl_sm.c1762
-rw-r--r--common/usbc/usb_sm.c193
-rw-r--r--common/usbc/usb_tc_ctvpd_sm.c1673
-rw-r--r--common/usbc/usb_tc_drp_acc_trysrc_sm.c3547
-rw-r--r--common/usbc/usb_tc_vpd_sm.c399
-rw-r--r--common/usbc/usbc_task.c204
-rw-r--r--common/usbc_ppc.c358
-rw-r--r--driver/build.mk14
-rw-r--r--driver/tcpm/anx7447.c680
-rw-r--r--driver/tcpm/anx7447.h141
-rw-r--r--driver/tcpm/anx74xx.c1180
-rw-r--r--driver/tcpm/anx74xx.h226
-rw-r--r--driver/tcpm/anx7688.c213
-rw-r--r--driver/tcpm/anx7688.h21
-rw-r--r--driver/tcpm/fusb302.c1036
-rw-r--r--driver/tcpm/fusb302.h213
-rw-r--r--driver/tcpm/it83xx.c644
-rw-r--r--driver/tcpm/it83xx_pd.h109
-rw-r--r--driver/tcpm/mt6370.c218
-rw-r--r--driver/tcpm/mt6370.h200
-rw-r--r--driver/tcpm/nct38xx.c384
-rw-r--r--driver/tcpm/nct38xx.h68
-rw-r--r--driver/tcpm/ps8xxx.c321
-rw-r--r--driver/tcpm/ps8xxx.h81
-rw-r--r--driver/tcpm/stub.c155
-rw-r--r--driver/tcpm/tcpci.c1014
-rw-r--r--driver/tcpm/tcpci.h191
-rw-r--r--driver/tcpm/tcpm.h418
-rw-r--r--driver/tcpm/tusb422.c66
-rw-r--r--driver/tcpm/tusb422.h16
-rw-r--r--include/charge_manager.h301
-rw-r--r--include/config.h35
-rw-r--r--include/usb_charge.h109
-rw-r--r--include/usb_common.h106
-rw-r--r--include/usb_pd.h2362
-rw-r--r--include/usb_pd_tcpc.h66
-rw-r--r--include/usb_pd_tcpm.h429
61 files changed, 0 insertions, 36085 deletions
diff --git a/board/host/build.mk b/board/host/build.mk
index 241f197342..78e4df530c 100644
--- a/board/host/build.mk
+++ b/board/host/build.mk
@@ -12,4 +12,3 @@ board-y=board.o
board-$(HAS_TASK_CHIPSET)+=chipset.o
board-$(CONFIG_BATTERY_MOCK)+=battery.o charger.o
board-$(CONFIG_FANS)+=fan.o
-board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o usb_pd_config.o
diff --git a/board/host/usb_pd_config.c b/board/host/usb_pd_config.c
deleted file mode 100644
index 91c30d1755..0000000000
--- a/board/host/usb_pd_config.c
+++ /dev/null
@@ -1,35 +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.
- */
-
-/* USB Power delivery board configuration */
-
-#include "test_util.h"
-
-test_mockable void pd_select_polarity(int port, int polarity)
-{
- /* Not implemented */
-}
-
-test_mockable void pd_tx_init(void)
-{
- /* Not implemented */
-}
-
-test_mockable void pd_set_host_mode(int port, int enable)
-{
- /* Not implemented */
-}
-
-test_mockable void pd_config_init(int port, uint8_t power_role)
-{
- /* Not implemented */
-}
-
-test_mockable int pd_adc_read(int port, int cc)
-{
- /* Not implemented */
- return 0;
-}
-
diff --git a/board/host/usb_pd_config.h b/board/host/usb_pd_config.h
deleted file mode 100644
index fb12b2ce7d..0000000000
--- a/board/host/usb_pd_config.h
+++ /dev/null
@@ -1,24 +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.
- */
-
-/* USB Power delivery board configuration */
-
-#ifndef __CROS_EC_USB_PD_CONFIG_H
-#define __CROS_EC_USB_PD_CONFIG_H
-
-/* Use software CRC */
-#define CONFIG_SW_CRC
-
-void pd_select_polarity(int port, int polarity);
-
-void pd_tx_init(void);
-
-void pd_set_host_mode(int port, int enable);
-
-void pd_config_init(int port, uint8_t power_role);
-
-int pd_adc_read(int port, int cc);
-
-#endif /* __CROS_EC_USB_PD_CONFIG_H */
diff --git a/board/host/usb_pd_policy.c b/board/host/usb_pd_policy.c
deleted file mode 100644
index 0dcc5942a8..0000000000
--- a/board/host/usb_pd_policy.c
+++ /dev/null
@@ -1,96 +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 "common.h"
-#include "console.h"
-#include "usb_pd.h"
-#include "util.h"
-
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-
-#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP)
-
-const uint32_t pd_src_pdo[] = {
- PDO_FIXED(5000, 900, PDO_FIXED_FLAGS),
- PDO_FIXED(12000, 3000, PDO_FIXED_FLAGS),
-};
-const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo);
-
-const uint32_t pd_snk_pdo[] = {
- PDO_FIXED(5000, 500, PDO_FIXED_FLAGS),
- PDO_BATT(4750, 21000, 15000),
- PDO_VAR(4750, 21000, 3000),
-};
-const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo);
-
-int pd_is_valid_input_voltage(int mv)
-{
- /* Any voltage less than the max is allowed */
- return 1;
-}
-
-void pd_transition_voltage(int idx)
-{
- /* Not implemented */
-}
-
-int pd_set_power_supply_ready(int port)
-{
- /* Not implemented */
- return EC_SUCCESS;
-}
-
-void pd_power_supply_reset(int port)
-{
- /* Not implemented */
-}
-
-void pd_set_input_current_limit(int port, uint32_t max_ma,
- uint32_t supply_voltage)
-{
- /* Not implemented */
-}
-
-test_mockable int pd_snk_is_vbus_provided(int port)
-{
- /* Not implemented */
- return 1;
-}
-
-int pd_board_checks(void)
-{
- return EC_SUCCESS;
-}
-
-int pd_check_power_swap(int port)
-{
- /* Always allow power swap */
- return 1;
-}
-
-int pd_check_data_swap(int port, int data_role)
-{
- /* Always allow data swap */
- return 1;
-}
-
-void pd_execute_data_swap(int port, int data_role)
-{
- /* Do nothing */
-}
-
-void pd_check_pr_role(int port, int pr_role, int flags)
-{
-}
-
-void pd_check_dr_role(int port, int dr_role, int flags)
-{
-}
-
-int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
-{
- return 0;
-}
diff --git a/chip/host/build.mk b/chip/host/build.mk
index f018c2a281..3b71e676a4 100644
--- a/chip/host/build.mk
+++ b/chip/host/build.mk
@@ -13,7 +13,6 @@ chip-y=clock.o flash.o gpio.o i2c.o lpc.o persistence.o reboot.o registers.o \
ifndef CONFIG_KEYBOARD_NOT_RAW
chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o
endif
-chip-$(CONFIG_USB_PD_TCPC)+=usb_pd_phy.o
ifeq ($(CONFIG_DCRYPTO),y)
CPPFLAGS += -I$(abspath ./chip/g)
diff --git a/chip/host/usb_pd_phy.c b/chip/host/usb_pd_phy.c
deleted file mode 100644
index 347035a6d0..0000000000
--- a/chip/host/usb_pd_phy.c
+++ /dev/null
@@ -1,370 +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 "common.h"
-#include "console.h"
-#include "crc.h"
-#include "task.h"
-#include "usb_pd.h"
-#include "usb_pd_config.h"
-#include "util.h"
-
-#define PREAMBLE_OFFSET 60 /* Any number should do */
-
-/*
- * Maximum size of a Power Delivery packet (in bits on the wire) :
- * 16-bit header + 0..7 32-bit data objects (+ 4b5b encoding)
- * 64-bit preamble + SOP (4x 5b) + message in 4b5b + 32-bit CRC + EOP (1x 5b)
- * = 64 + 4*5 + 16 * 5/4 + 7 * 32 * 5/4 + 32 * 5/4 + 5
- */
-#define PD_BIT_LEN 429
-
-static struct pd_physical {
- int hw_init_done;
-
- uint8_t bits[PD_BIT_LEN];
- int total;
- int has_preamble;
- int rx_started;
- int rx_monitoring;
-
- int preamble_written;
- int has_msg;
- int last_edge_written;
- uint8_t out_msg[PD_BIT_LEN / 5];
- int verified_idx;
-} pd_phy[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-static const uint16_t enc4b5b[] = {
- 0x1E, 0x09, 0x14, 0x15, 0x0A, 0x0B, 0x0E, 0x0F, 0x12, 0x13, 0x16,
- 0x17, 0x1A, 0x1B, 0x1C, 0x1D};
-
-/* Test utilities */
-static void pd_test_reset_phy(int port)
-{
- int i;
- int enc_len = PD_BIT_LEN / 5;
-
- for (i = 0; i < PD_BIT_LEN; i++)
- pd_phy[port].bits[i] = 0;
-
- for (i = 0; i < enc_len; i++)
- pd_phy[port].out_msg[i] = 0;
-
- pd_phy[port].total = 0;
- pd_phy[port].has_preamble = 0;
- pd_phy[port].rx_started = 0;
- pd_phy[port].rx_monitoring = 0;
- pd_phy[port].preamble_written = 0;
- pd_phy[port].has_msg = 0;
- pd_phy[port].last_edge_written = 0;
- pd_phy[port].verified_idx = 0;
-}
-
-void pd_test_rx_set_preamble(int port, int has_preamble)
-{
- pd_phy[port].total = 0;
- pd_phy[port].has_preamble = has_preamble;
-}
-
-void pd_test_rx_msg_append_bits(int port, uint32_t bits, int nb)
-{
- int i;
-
- for (i = 0; i < nb; ++i) {
- pd_phy[port].bits[pd_phy[port].total++] = bits & 1;
- bits >>= 1;
- }
-}
-
-void pd_test_rx_msg_append_kcode(int port, uint8_t kcode)
-{
- pd_test_rx_msg_append_bits(port, kcode, 5);
-}
-
-void pd_test_rx_msg_append_sop(int port)
-{
- pd_test_rx_msg_append_kcode(port, PD_SYNC1);
- pd_test_rx_msg_append_kcode(port, PD_SYNC1);
- pd_test_rx_msg_append_kcode(port, PD_SYNC1);
- pd_test_rx_msg_append_kcode(port, PD_SYNC2);
-}
-
-void pd_test_rx_msg_append_sop_prime(int port)
-{
- pd_test_rx_msg_append_kcode(port, PD_SYNC1);
- pd_test_rx_msg_append_kcode(port, PD_SYNC1);
- pd_test_rx_msg_append_kcode(port, PD_SYNC3);
- pd_test_rx_msg_append_kcode(port, PD_SYNC3);
-}
-
-void pd_test_rx_msg_append_sop_prime_prime(int port)
-{
- pd_test_rx_msg_append_kcode(port, PD_SYNC1);
- pd_test_rx_msg_append_kcode(port, PD_SYNC3);
- pd_test_rx_msg_append_kcode(port, PD_SYNC1);
- pd_test_rx_msg_append_kcode(port, PD_SYNC3);
-}
-
-void pd_test_rx_msg_append_eop(int port)
-{
- pd_test_rx_msg_append_kcode(port, PD_EOP);
-}
-
-void pd_test_rx_msg_append_last_edge(int port)
-{
- /* end with 1, 1, 0 similar to pd_write_last_edge() */
- pd_test_rx_msg_append_bits(port, 3, 6);
-}
-
-void pd_test_rx_msg_append_4b(int port, uint8_t val)
-{
- pd_test_rx_msg_append_bits(port, enc4b5b[val & 0xF], 5);
-}
-
-void pd_test_rx_msg_append_short(int port, uint16_t val)
-{
- pd_test_rx_msg_append_4b(port, (val >> 0) & 0xF);
- pd_test_rx_msg_append_4b(port, (val >> 4) & 0xF);
- pd_test_rx_msg_append_4b(port, (val >> 8) & 0xF);
- pd_test_rx_msg_append_4b(port, (val >> 12) & 0xF);
-}
-
-void pd_test_rx_msg_append_word(int port, uint32_t val)
-{
- pd_test_rx_msg_append_short(port, val & 0xFFFF);
- pd_test_rx_msg_append_short(port, val >> 16);
-}
-
-void pd_simulate_rx(int port)
-{
- if (!pd_phy[port].rx_monitoring)
- return;
-
- pd_phy[port].rx_started = 1;
- pd_rx_disable_monitoring(port);
- pd_rx_event(port);
-}
-
-static int pd_test_tx_msg_verify(int port, uint8_t raw)
-{
- int verified_idx = pd_phy[port].verified_idx++;
- return pd_phy[port].out_msg[verified_idx] == raw;
-}
-
-int pd_test_tx_msg_verify_kcode(int port, uint8_t kcode)
-{
- return pd_test_tx_msg_verify(port, kcode);
-}
-
-int pd_test_tx_msg_verify_sop(int port)
-{
- crc32_init();
- return pd_test_tx_msg_verify_kcode(port, PD_SYNC1) &&
- pd_test_tx_msg_verify_kcode(port, PD_SYNC1) &&
- pd_test_tx_msg_verify_kcode(port, PD_SYNC1) &&
- pd_test_tx_msg_verify_kcode(port, PD_SYNC2);
-}
-
-int pd_test_tx_msg_verify_sop_prime(int port)
-{
- crc32_init();
- return pd_test_tx_msg_verify_kcode(port, PD_SYNC1) &&
- pd_test_tx_msg_verify_kcode(port, PD_SYNC1) &&
- pd_test_tx_msg_verify_kcode(port, PD_SYNC3) &&
- pd_test_tx_msg_verify_kcode(port, PD_SYNC3);
-}
-
-int pd_test_tx_msg_verify_sop_prime_prime(int port)
-{
- crc32_init();
- return pd_test_tx_msg_verify_kcode(port, PD_SYNC1) &&
- pd_test_tx_msg_verify_kcode(port, PD_SYNC3) &&
- pd_test_tx_msg_verify_kcode(port, PD_SYNC1) &&
- pd_test_tx_msg_verify_kcode(port, PD_SYNC3);
-}
-
-int pd_test_tx_msg_verify_eop(int port)
-{
- return pd_test_tx_msg_verify_kcode(port, PD_EOP);
-}
-
-int pd_test_tx_msg_verify_4b5b(int port, uint8_t b4)
-{
- return pd_test_tx_msg_verify(port, enc4b5b[b4]);
-}
-
-int pd_test_tx_msg_verify_short(int port, uint16_t val)
-{
- crc32_hash16(val);
- return pd_test_tx_msg_verify_4b5b(port, (val >> 0) & 0xF) &&
- pd_test_tx_msg_verify_4b5b(port, (val >> 4) & 0xF) &&
- pd_test_tx_msg_verify_4b5b(port, (val >> 8) & 0xF) &&
- pd_test_tx_msg_verify_4b5b(port, (val >> 12) & 0xF);
-}
-
-int pd_test_tx_msg_verify_word(int port, uint32_t val)
-{
- return pd_test_tx_msg_verify_short(port, val & 0xFFFF) &&
- pd_test_tx_msg_verify_short(port, val >> 16);
-}
-
-int pd_test_tx_msg_verify_crc(int port)
-{
- return pd_test_tx_msg_verify_word(port, crc32_result());
-}
-
-
-/* Mock functions */
-
-void pd_init_dequeue(int port)
-{
-}
-
-int pd_dequeue_bits(int port, int off, int len, uint32_t *val)
-{
- int i;
-
- /* Rx must have started to receive message */
- ASSERT(pd_phy[port].rx_started);
-
- if (pd_phy[port].total <= off + len - PREAMBLE_OFFSET)
- return -1;
- *val = 0;
- for (i = 0; i < len; ++i)
- *val |= pd_phy[port].bits[off + i - PREAMBLE_OFFSET] << i;
- return off + len;
-}
-
-int pd_find_preamble(int port)
-{
- return pd_phy[port].has_preamble ? PREAMBLE_OFFSET : -1;
-}
-
-int pd_write_preamble(int port)
-{
- ASSERT(pd_phy[port].preamble_written == 0);
- pd_phy[port].preamble_written = 1;
- ASSERT(pd_phy[port].has_msg == 0);
- return 0;
-}
-
-static uint8_t decode_bmc(uint32_t val10)
-{
- uint8_t ret = 0;
- int i;
-
- for (i = 0; i < 5; ++i)
- if (!!(val10 & (1 << (2 * i))) !=
- !!(val10 & (1 << (2 * i + 1))))
- ret |= BIT(i);
- return ret;
-}
-
-int pd_write_sym(int port, int bit_off, uint32_t val10)
-{
- pd_phy[port].out_msg[bit_off] = decode_bmc(val10);
- pd_phy[port].has_msg = 1;
- return bit_off + 1;
-}
-
-int pd_write_last_edge(int port, int bit_off)
-{
- pd_phy[port].last_edge_written = 1;
- return bit_off;
-}
-
-void pd_dump_packet(int port, const char *msg)
-{
- /* Not implemented */
-}
-
-void pd_tx_set_circular_mode(int port)
-{
- /* Not implemented */
-}
-
-void pd_tx_clear_circular_mode(int port)
-{
- /* Not implemented */
-}
-
-int pd_start_tx(int port, int polarity, int bit_len)
-{
- ASSERT(pd_phy[port].hw_init_done);
- pd_phy[port].has_msg = 0;
- pd_phy[port].preamble_written = 0;
- pd_phy[port].verified_idx = 0;
- pd_phy[port].total = 0;
-
- /*
- * Hand over to test runner. The test runner must wake us after
- * processing the packet.
- */
- task_wake(TASK_ID_TEST_RUNNER);
- task_wait_event(-1);
-
- return bit_len;
-}
-
-void pd_tx_done(int port, int polarity)
-{
- pd_test_reset_phy(port);
-}
-
-void pd_rx_start(int port)
-{
- ASSERT(pd_phy[port].hw_init_done);
-
- task_wake(TASK_ID_TEST_RUNNER);
- task_wait_event(-1);
-
- pd_phy[port].rx_started = 1;
-}
-
-void pd_rx_complete(int port)
-{
- ASSERT(pd_phy[port].hw_init_done);
- pd_test_reset_phy(port);
-}
-
-int pd_rx_started(int port)
-{
- return pd_phy[port].rx_started;
-}
-
-void pd_rx_enable_monitoring(int port)
-{
- ASSERT(pd_phy[port].hw_init_done);
- pd_phy[port].rx_monitoring = 1;
-}
-
-void pd_rx_disable_monitoring(int port)
-{
- /*
- * We disabled RX monitoring in TCPMv1 in set_state when
- * transitioning from suspended to disconnected, but we only
- * reinitialize after we have fully transitioned to disconnected. Don't
- * assert that hw_init_done here since we have "valid" code that
- * requires hw_init_done to be false when a port is suspended.
- */
- pd_phy[port].rx_monitoring = 0;
-}
-
-void pd_hw_release(int port)
-{
- pd_phy[port].hw_init_done = 0;
-}
-
-void pd_hw_init(int port, int role)
-{
- pd_config_init(port, role);
- pd_phy[port].hw_init_done = 1;
-}
-
-void pd_set_clock(int port, int freq)
-{
- /* Not implemented */
-}
diff --git a/common/build.mk b/common/build.mk
index ec592b8f9f..aaa3146d11 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -43,9 +43,6 @@ common-$(CONFIG_CAPSENSE)+=capsense.o
common-$(CONFIG_CASE_CLOSED_DEBUG_V1)+=ccd_config.o
common-$(CONFIG_CEC)+=cec.o
common-$(CONFIG_CROS_BOARD_INFO)+=cbi.o
-common-$(CONFIG_CHARGE_MANAGER)+=charge_manager.o
-common-$(CONFIG_CHARGE_RAMP_HW)+=charge_ramp.o
-common-$(CONFIG_CHARGE_RAMP_SW)+=charge_ramp.o charge_ramp_sw.o
common-$(CONFIG_CMD_CHARGEN) += chargen.o
common-$(CONFIG_CHARGER)+=charger.o charge_state_v2.o
common-$(CONFIG_CHARGER_PROFILE_OVERRIDE_COMMON)+=charger_profile_override.o
@@ -136,18 +133,9 @@ common-$(CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT)+=throttle_ap.o
common-$(CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE)+=throttle_ap.o
common-$(CONFIG_TPM_I2CS)+=i2cs_tpm.o
common-$(CONFIG_U2F)+=u2f.o
-common-$(CONFIG_USB_CHARGER)+=usb_charger.o
common-$(CONFIG_USB_CONSOLE_STREAM)+=usb_console_stream.o
common-$(CONFIG_USB_I2C)+=usb_i2c.o
-common-$(CONFIG_USB_PORT_POWER_DUMB)+=usb_port_power_dumb.o
-common-$(CONFIG_USB_PORT_POWER_SMART)+=usb_port_power_smart.o
-common-$(CONFIG_USB_POWER_DELIVERY)+=usb_common.o
-ifeq ($(CONFIG_USB_SM_FRAMEWORK),)
-common-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_protocol.o usb_pd_policy.o
-endif
common-$(CONFIG_USB_PD_LOGGING)+=event_log.o pd_log.o
-common-$(CONFIG_USB_PD_TCPC)+=usb_pd_tcpc.o
-common-$(CONFIG_USBC_PPC)+=usbc_ppc.o
common-$(CONFIG_VBOOT_EFS)+=vboot/vboot.o
common-$(CONFIG_VBOOT_HASH)+=sha256.o vboot_hash.o
common-$(CONFIG_VOLUME_BUTTONS)+=button.o
@@ -281,7 +269,6 @@ $(out)/$(PROJECT).exe: $(out)/cryptoc/libcryptoc.a
endif
include $(_common_dir)fpsensor/build.mk
-include $(_common_dir)usbc/build.mk
include $(_common_dir)mock/build.mk
common-y+=$(foreach m,$(mock-y),mock/$(m))
diff --git a/common/charge_manager.c b/common/charge_manager.c
deleted file mode 100644
index d95f5cb809..0000000000
--- a/common/charge_manager.c
+++ /dev/null
@@ -1,1455 +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 "adc.h"
-#include "atomic.h"
-#include "battery.h"
-#include "charge_manager.h"
-#include "charge_ramp.h"
-#include "charger.h"
-#include "console.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "system.h"
-#include "tcpm.h"
-#include "timer.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
-
-#define POWER(charge_port) ((charge_port.current) * (charge_port.voltage))
-
-/* Timeout for delayed override power swap, allow for 500ms extra */
-#define POWER_SWAP_TIMEOUT (PD_T_SRC_RECOVER_MAX + PD_T_SRC_TURN_ON + \
- PD_T_SAFE_0V + 500 * MSEC)
-
-/*
- * Default charge supplier priority
- *
- * - Always pick dedicated charge if present since that is the best product
- * decision.
- * - Pick PD negotiated chargers over everything else since they have the most
- * power potential and they may not currently be negotiated at a high power.
- * (and they can at least provide 15W)
- * - Pick Type-C which supplier current >= 1.5A, which has higher prioirty
- * than the BC1.2 and Type-C with current under 1.5A. (USB-C spec 1.3
- * Table 4-17: TYPEC 3.0A, 1.5A > BC1.2 > TYPEC under 1.5A)
- * - Then pick among the propreitary and BC1.2 chargers which ever has the
- * highest available power.
- * - Last, pick one from the rest suppliers. Also note that some boards assume
- * wireless suppliers as low priority.
- */
-__overridable const int supplier_priority[] = {
-#if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0
- [CHARGE_SUPPLIER_DEDICATED] = 0,
-#endif
- [CHARGE_SUPPLIER_PD] = 1,
- [CHARGE_SUPPLIER_TYPEC] = 2,
- [CHARGE_SUPPLIER_TYPEC_DTS] = 2,
-#ifdef CHARGE_MANAGER_BC12
- [CHARGE_SUPPLIER_PROPRIETARY] = 3,
- [CHARGE_SUPPLIER_BC12_DCP] = 3,
- [CHARGE_SUPPLIER_BC12_CDP] = 3,
- [CHARGE_SUPPLIER_BC12_SDP] = 3,
- [CHARGE_SUPPLIER_TYPEC_UNDER_1_5A] = 4,
- [CHARGE_SUPPLIER_OTHER] = 4,
- [CHARGE_SUPPLIER_VBUS] = 4,
-#endif
-#ifdef CONFIG_WIRELESS_CHARGER_P9221_R7
- [CHARGE_SUPPLIER_WPC_BPP] = 5,
- [CHARGE_SUPPLIER_WPC_EPP] = 5,
- [CHARGE_SUPPLIER_WPC_GPP] = 5,
-#endif
-
-};
-BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT);
-
-/* Keep track of available charge for each charge port. */
-static struct charge_port_info available_charge[CHARGE_SUPPLIER_COUNT]
- [CHARGE_PORT_COUNT];
-
-/* Keep track of when the supplier on each port is registered. */
-static timestamp_t registration_time[CHARGE_PORT_COUNT];
-
-/*
- * Charge current ceiling (mA) for ports. This can be set to temporarily limit
- * the charge pulled from a port, without influencing the port selection logic.
- * The ceiling can be set independently from several requestors, with the
- * minimum ceiling taking effect.
- */
-static int charge_ceil[CHARGE_PORT_COUNT][CEIL_REQUESTOR_COUNT];
-
-/* Dual-role capability of attached partner port */
-static enum dualrole_capabilities dualrole_capability[CHARGE_PORT_COUNT];
-
-#ifdef CONFIG_USB_PD_LOGGING
-/* Mark port as dirty when making changes, for later logging */
-static int save_log[CHARGE_PORT_COUNT];
-#endif
-
-/* Store current state of port enable / charge current. */
-static int charge_port = CHARGE_PORT_NONE;
-static int charge_current = CHARGE_CURRENT_UNINITIALIZED;
-static int charge_current_uncapped = CHARGE_CURRENT_UNINITIALIZED;
-static int charge_voltage;
-static int charge_supplier = CHARGE_SUPPLIER_NONE;
-static int override_port = OVERRIDE_OFF;
-
-static int delayed_override_port = OVERRIDE_OFF;
-static timestamp_t delayed_override_deadline;
-
-static uint8_t source_port_rp[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-#ifdef CONFIG_USB_PD_MAX_TOTAL_SOURCE_CURRENT
-/* 3A on one port and 1.5A on the rest */
-BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT * 1500 + 1500 <=
- CONFIG_USB_PD_MAX_TOTAL_SOURCE_CURRENT);
-#endif
-
-/*
- * charge_manager initially operates in safe mode until asked to leave (through
- * charge_manager_leave_safe_mode()). While in safe mode, the following
- * behavior is altered:
- *
- * 1) All chargers are considered dedicated (and thus are valid charge source
- * candidates) for the purpose of port selection.
- * 2) Charge ceilings are ignored. Most significantly, ILIM won't drop on PD
- * voltage transition. If current load is high during transition, some
- * chargers may brown-out.
- * 3) CHARGE_PORT_NONE will not be selected (POR default charge port will
- * remain selected rather than CHARGE_PORT_NONE).
- *
- * After leaving safe mode, charge_manager reverts to its normal behavior and
- * immediately selects charge port and current using standard rules.
- */
-#ifdef CONFIG_CHARGE_MANAGER_SAFE_MODE
-static int left_safe_mode;
-#else
-static const int left_safe_mode = 1;
-#endif
-
-enum charge_manager_change_type {
- CHANGE_CHARGE,
- CHANGE_DUALROLE,
-};
-
-static int is_pd_port(int port)
-{
- return port >= 0 && port < board_get_usb_pd_port_count();
-}
-
-static int is_sink(int port)
-{
- if (!is_pd_port(port))
- return board_charge_port_is_sink(port);
-
- return pd_get_role(port) == PD_ROLE_SINK;
-}
-
-/**
- * Some of the SKUs in certain boards have less number of USB PD ports than
- * defined in CONFIG_USB_PD_PORT_MAX_COUNT. With the charge port configuration
- * for DEDICATED_PORT towards the end, this will lead to holes in the static
- * configuration. The ports that fall in that hole are invalid and this function
- * is used to check the validity of the ports.
- */
-static int is_valid_port(int port)
-{
- if (port < 0 || port >= CHARGE_PORT_COUNT)
- return 0;
-
- /* Check if the port falls in the hole */
- if (port >= board_get_usb_pd_port_count() &&
- port < CONFIG_USB_PD_PORT_MAX_COUNT)
- return 0;
- return 1;
-}
-
-#ifndef TEST_BUILD
-static int is_connected(int port)
-{
- if (!is_pd_port(port))
- return board_charge_port_is_connected(port);
-
- return pd_is_connected(port);
-}
-#endif /* !TEST_BUILD */
-
-#ifndef CONFIG_CHARGE_MANAGER_DRP_CHARGING
-/**
- * In certain cases we need to override the default behavior of not charging
- * from non-dedicated chargers. If the system is in RO and locked, we have no
- * way of determining the actual dualrole capability of the charger because
- * PD communication is not allowed, so we must assume that it is dedicated.
- * Also, if no battery is present, the charger may be our only source of power,
- * so again we must assume that the charger is dedicated.
- *
- * @return 1 when we need to override the a non-dedicated charger
- * to be a dedicated one, 0 otherwise.
- */
-static int charge_manager_spoof_dualrole_capability(void)
-{
- return (system_get_image_copy() == SYSTEM_IMAGE_RO &&
- system_is_locked()) || !left_safe_mode;
-
-}
-#endif /* !CONFIG_CHARGE_MANAGER_DRP_CHARGING */
-
-/**
- * Initialize available charge. Run before board init, so board init can
- * initialize data, if needed.
- */
-static void charge_manager_init(void)
-{
- int i, j;
-
- for (i = 0; i < CHARGE_PORT_COUNT; ++i) {
- if (!is_valid_port(i))
- continue;
- for (j = 0; j < CHARGE_SUPPLIER_COUNT; ++j) {
- available_charge[j][i].current =
- CHARGE_CURRENT_UNINITIALIZED;
- available_charge[j][i].voltage =
- CHARGE_VOLTAGE_UNINITIALIZED;
- }
- for (j = 0; j < CEIL_REQUESTOR_COUNT; ++j)
- charge_ceil[i][j] = CHARGE_CEIL_NONE;
- if (!is_pd_port(i))
- dualrole_capability[i] = CAP_DEDICATED;
- if (is_pd_port(i))
- source_port_rp[i] = CONFIG_USB_PD_PULLUP;
- }
-}
-DECLARE_HOOK(HOOK_INIT, charge_manager_init, HOOK_PRIO_CHARGE_MANAGER_INIT);
-
-/**
- * Check if the charge manager is seeded.
- *
- * @return 1 if all ports/suppliers have reported
- * with some initial charge, 0 otherwise.
- */
-static int charge_manager_is_seeded(void)
-{
- /* Once we're seeded, we don't need to check again. */
- static int is_seeded;
- int i, j;
-
- if (is_seeded)
- return 1;
-
- for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i) {
- for (j = 0; j < CHARGE_PORT_COUNT; ++j) {
- if (!is_valid_port(j))
- continue;
- if (available_charge[i][j].current ==
- CHARGE_CURRENT_UNINITIALIZED ||
- available_charge[i][j].voltage ==
- CHARGE_VOLTAGE_UNINITIALIZED)
- return 0;
- }
- }
- is_seeded = 1;
- return 1;
-}
-
-#ifndef TEST_BUILD
-/**
- * Get the maximum charge current for a port.
- *
- * @param port Charge port.
- * @return Charge current (mA).
- */
-static int charge_manager_get_source_current(int port)
-{
- if (!is_pd_port(port))
- return 0;
-
- switch (source_port_rp[port]) {
- case TYPEC_RP_3A0:
- return 3000;
- case TYPEC_RP_1A5:
- return 1500;
- case TYPEC_RP_USB:
- default:
- return 500;
- }
-}
-
-/*
- * Find a supplier considering available current, voltage, power, and priority.
- */
-static enum charge_supplier find_supplier(int port, enum charge_supplier sup,
- int min_cur)
-{
- int i;
- for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i) {
- if (available_charge[i][port].current <= min_cur ||
- available_charge[i][port].voltage <= 0)
- /* Doesn't meet volt or current requirement. Skip it. */
- continue;
- if (sup == CHARGE_SUPPLIER_NONE)
- /* Haven't found any yet. Take it unconditionally. */
- sup = i;
- else if (supplier_priority[sup] < supplier_priority[i])
- /* There is already a higher priority supplier. */
- continue;
- else if (supplier_priority[i] < supplier_priority[sup])
- /* This has a higher priority. Take it. */
- sup = i;
- else if (POWER(available_charge[i][port]) >
- POWER(available_charge[sup][port]))
- /* Priority is tie. Take it if power is higher. */
- sup = i;
- }
- return sup;
-}
-
-/**
- * Fills passed power_info structure with current info about the passed port.
- *
- * @param port Charge port.
- * @param r USB PD power info to be updated.
- */
-static void charge_manager_fill_power_info(int port,
- struct ec_response_usb_pd_power_info *r)
-{
- int sup = CHARGE_SUPPLIER_NONE;
-
- /* Determine supplier information to show. */
- if (port == charge_port) {
- sup = charge_supplier;
- } else {
- /* Consider available current */
- sup = find_supplier(port, sup, 0);
- if (sup == CHARGE_SUPPLIER_NONE)
- /* Ignore available current */
- sup = find_supplier(port, sup, -1);
- }
-
- /* Fill in power role */
- if (charge_port == port)
- r->role = USB_PD_PORT_POWER_SINK;
- else if (is_connected(port) && !is_sink(port))
- r->role = USB_PD_PORT_POWER_SOURCE;
- else if (sup != CHARGE_SUPPLIER_NONE)
- r->role = USB_PD_PORT_POWER_SINK_NOT_CHARGING;
- else
- r->role = USB_PD_PORT_POWER_DISCONNECTED;
-
- /* Is port partner dual-role capable */
- r->dualrole = (dualrole_capability[port] == CAP_DUALROLE);
-
- if (sup == CHARGE_SUPPLIER_NONE ||
- r->role == USB_PD_PORT_POWER_SOURCE) {
- if (is_pd_port(port)) {
- r->type = USB_CHG_TYPE_NONE;
- r->meas.voltage_max = 0;
- r->meas.voltage_now =
- r->role == USB_PD_PORT_POWER_SOURCE ? 5000 : 0;
- r->meas.current_max =
- charge_manager_get_source_current(port);
- r->max_power = 0;
- } else {
- r->type = USB_CHG_TYPE_NONE;
- board_fill_source_power_info(port, r);
- }
- } else {
- int use_ramp_current;
- switch (sup) {
- case CHARGE_SUPPLIER_PD:
- r->type = USB_CHG_TYPE_PD;
- break;
- case CHARGE_SUPPLIER_TYPEC:
- case CHARGE_SUPPLIER_TYPEC_DTS:
- r->type = USB_CHG_TYPE_C;
- break;
-#ifdef CHARGE_MANAGER_BC12
- case CHARGE_SUPPLIER_PROPRIETARY:
- r->type = USB_CHG_TYPE_PROPRIETARY;
- break;
- case CHARGE_SUPPLIER_BC12_DCP:
- r->type = USB_CHG_TYPE_BC12_DCP;
- break;
- case CHARGE_SUPPLIER_BC12_CDP:
- r->type = USB_CHG_TYPE_BC12_CDP;
- break;
- case CHARGE_SUPPLIER_BC12_SDP:
- r->type = USB_CHG_TYPE_BC12_SDP;
- break;
- case CHARGE_SUPPLIER_VBUS:
- r->type = USB_CHG_TYPE_VBUS;
- break;
-#endif
-#ifdef CONFIG_WIRELESS_CHARGER_P9221_R7
- /*
- * Todo:need kernel add wpc device node in power_supply
- * before that use USB_CHG_TYPE_PROPRIETARY to present WPC.
- */
- case CHARGE_SUPPLIER_WPC_BPP:
- case CHARGE_SUPPLIER_WPC_EPP:
- case CHARGE_SUPPLIER_WPC_GPP:
- r->type = USB_CHG_TYPE_PROPRIETARY;
- break;
-#endif
-#if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0
- case CHARGE_SUPPLIER_DEDICATED:
- r->type = USB_CHG_TYPE_DEDICATED;
- break;
-#endif
- default:
-#ifdef CONFIG_WIRELESS_CHARGER_P9221_R7
- r->type = USB_CHG_TYPE_VBUS;
-#else
- r->type = USB_CHG_TYPE_OTHER;
-#endif
- }
- r->meas.voltage_max = available_charge[sup][port].voltage;
-
- /*
- * Report unknown charger CHARGE_DETECT_DELAY after supplier
- * change since PD negotiation may take time.
- */
- if (get_time().val < registration_time[port].val +
- CHARGE_DETECT_DELAY)
- r->type = USB_CHG_TYPE_UNKNOWN;
-
-#if defined(HAS_TASK_CHG_RAMP) || defined(CONFIG_CHARGE_RAMP_HW)
- /* Read ramped current if active charging port */
- use_ramp_current =
- (charge_port == port) && chg_ramp_allowed(sup);
-#else
- use_ramp_current = 0;
-#endif
- if (use_ramp_current) {
- /* Current limit is output of ramp module */
- r->meas.current_lim = chg_ramp_get_current_limit();
-
- /*
- * If ramp is allowed, then the max current depends
- * on if ramp is stable. If ramp is stable, then
- * max current is same as input current limit. If
- * ramp is not stable, then we report the maximum
- * current we could ramp up to for this supplier.
- * If ramp is not allowed, max current is just the
- * available charge current.
- */
- r->meas.current_max = chg_ramp_is_stable() ?
- r->meas.current_lim : chg_ramp_max(sup,
- available_charge[sup][port].current);
-
- r->max_power =
- r->meas.current_max * r->meas.voltage_max;
- } else {
- r->meas.current_max = r->meas.current_lim =
- available_charge[sup][port].current;
- r->max_power = POWER(available_charge[sup][port]);
- }
-
- /*
- * If we are sourcing power, or sinking but not charging, then
- * VBUS must be 5V. If we are charging, then read VBUS ADC.
- */
- if (r->role == USB_PD_PORT_POWER_SINK_NOT_CHARGING)
- r->meas.voltage_now = 5000;
- else {
-#if defined(CONFIG_USB_PD_VBUS_MEASURE_CHARGER)
- r->meas.voltage_now = charger_get_vbus_voltage(port);
-#elif defined(CONFIG_USB_PD_VBUS_MEASURE_ADC_EACH_PORT)
- r->meas.voltage_now =
- adc_read_channel(board_get_vbus_adc(port));
-#elif defined(CONFIG_USB_PD_VBUS_MEASURE_NOT_PRESENT)
- /* No VBUS ADC channel - voltage is unknown */
- r->meas.voltage_now = 0;
-#else
- /* There is a single ADC that measures joint Vbus */
- r->meas.voltage_now = adc_read_channel(ADC_VBUS);
-#endif
- }
- }
-}
-#endif /* TEST_BUILD */
-
-#ifdef CONFIG_USB_PD_LOGGING
-/**
- * Saves a power state log entry with the current info about the passed port.
- */
-void charge_manager_save_log(int port)
-{
- uint16_t flags = 0;
- struct ec_response_usb_pd_power_info pinfo;
-
- if (!is_pd_port(port))
- return;
-
- save_log[port] = 0;
- charge_manager_fill_power_info(port, &pinfo);
-
- /* Flags are stored in the data field */
- if (port == override_port)
- flags |= CHARGE_FLAGS_OVERRIDE;
- if (port == delayed_override_port)
- flags |= CHARGE_FLAGS_DELAYED_OVERRIDE;
- flags |= pinfo.role | (pinfo.type << CHARGE_FLAGS_TYPE_SHIFT) |
- (pinfo.dualrole ? CHARGE_FLAGS_DUAL_ROLE : 0);
-
- pd_log_event(PD_EVENT_MCU_CHARGE,
- PD_LOG_PORT_SIZE(port, sizeof(pinfo.meas)),
- flags, &pinfo.meas);
-}
-#endif /* CONFIG_USB_PD_LOGGING */
-
-/**
- * Attempt to switch to power source on port if applicable.
- *
- * @param port USB-C port to be swapped.
- */
-static void charge_manager_switch_to_source(int port)
-{
- if (!is_pd_port(port))
- return;
-
- /* If connected to dual-role device, then ask for a swap */
- if (dualrole_capability[port] == CAP_DUALROLE && is_sink(port))
- pd_request_power_swap(port);
-}
-
-/**
- * Return the computed charge ceiling for a port, which represents the
- * minimum ceiling among all valid requestors.
- *
- * @param port Charge port.
- * @return Charge ceiling (mA) or CHARGE_CEIL_NONE.
- */
-static int charge_manager_get_ceil(int port)
-{
- int ceil = CHARGE_CEIL_NONE;
- int val, i;
-
- if (!is_valid_port(port))
- return ceil;
-
- for (i = 0; i < CEIL_REQUESTOR_COUNT; ++i) {
- val = charge_ceil[port][i];
- if (val != CHARGE_CEIL_NONE &&
- (ceil == CHARGE_CEIL_NONE || val < ceil))
- ceil = val;
- }
-
- return ceil;
-}
-
-/**
- * Select the 'best' charge port, as defined by the supplier heirarchy and the
- * ability of the port to provide power.
- *
- * @param new_port Pointer to the best charge port by definition.
- * @param new_supplier Pointer to the best charge supplier by definition.
- */
-static void charge_manager_get_best_charge_port(int *new_port,
- int *new_supplier)
-{
- int supplier = CHARGE_SUPPLIER_NONE;
- int port = CHARGE_PORT_NONE;
- int best_port_power = -1, candidate_port_power;
- int i, j;
-
- /* Skip port selection on OVERRIDE_DONT_CHARGE. */
- if (override_port != OVERRIDE_DONT_CHARGE) {
- /*
- * Charge supplier selection logic:
- * 1. Prefer higher priority supply.
- * 2. Prefer higher power over lower in case priority is tied.
- * 3. Prefer current charge port over new port in case (1)
- * and (2) are tied.
- * available_charge can be changed at any time by other tasks,
- * so make no assumptions about its consistency.
- */
- for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i)
- for (j = 0; j < CHARGE_PORT_COUNT; ++j) {
- /* Skip this port if it is not valid. */
- if (!is_valid_port(j))
- continue;
-
- /*
- * Skip this supplier if there is no
- * available charge.
- */
- if (available_charge[i][j].current == 0 ||
- available_charge[i][j].voltage == 0)
- continue;
-
- /*
- * Don't select this port if we have a
- * charge on another override port.
- */
- if (override_port != OVERRIDE_OFF &&
- override_port == port &&
- override_port != j)
- continue;
-
-#ifndef CONFIG_CHARGE_MANAGER_DRP_CHARGING
- /*
- * Don't charge from a dual-role port unless
- * it is our override port.
- */
- if (dualrole_capability[j] != CAP_DEDICATED &&
- override_port != j &&
- !charge_manager_spoof_dualrole_capability())
- continue;
-#endif
-
- candidate_port_power =
- POWER(available_charge[i][j]);
-
- /* Select if no supplier chosen yet. */
- if (supplier == CHARGE_SUPPLIER_NONE ||
- /* ..or if supplier priority is higher. */
- supplier_priority[i] <
- supplier_priority[supplier] ||
- /* ..or if this is our override port. */
- (j == override_port &&
- port != override_port) ||
- /* ..or if priority is tied and.. */
- (supplier_priority[i] ==
- supplier_priority[supplier] &&
- /* candidate port can supply more power or.. */
- (candidate_port_power > best_port_power ||
- /*
- * candidate port is the active port and can
- * supply the same amount of power.
- */
- (candidate_port_power == best_port_power &&
- charge_port == j)))) {
- supplier = i;
- port = j;
- best_port_power = candidate_port_power;
- }
- }
-
- }
-
- *new_port = port;
- *new_supplier = supplier;
-}
-
-/**
- * Charge manager refresh -- responsible for selecting the active charge port
- * and charge power. Called as a deferred task.
- */
-static void charge_manager_refresh(void)
-{
- /* Always initialize charge port on first pass */
- static int active_charge_port_initialized;
- int new_supplier, new_port;
- int new_charge_current, new_charge_current_uncapped;
- int new_charge_voltage, i;
- int updated_new_port = CHARGE_PORT_NONE;
- int updated_old_port = CHARGE_PORT_NONE;
- int ceil;
- int power_changed = 0;
-
- /* Hunt for an acceptable charge port */
- while (1) {
- charge_manager_get_best_charge_port(&new_port, &new_supplier);
-
- if (!left_safe_mode && new_port == CHARGE_PORT_NONE)
- return;
-
- /*
- * If the port or supplier changed, make an attempt to switch to
- * the port. We will re-set the active port on a supplier change
- * to give the board-level function another chance to reject
- * the port, for example, if the port has become a charge
- * source.
- */
- if ((active_charge_port_initialized &&
- new_port == charge_port &&
- new_supplier == charge_supplier) ||
- board_set_active_charge_port(new_port) == EC_SUCCESS)
- break;
-
- /* 'Dont charge' request must be accepted. */
- ASSERT(new_port != CHARGE_PORT_NONE);
-
- /*
- * Zero the available charge on the rejected port so that
- * it is no longer chosen.
- */
- for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i) {
- available_charge[i][new_port].current = 0;
- available_charge[i][new_port].voltage = 0;
- }
- }
-
- active_charge_port_initialized = 1;
-
- /*
- * Clear override if it wasn't selected as the 'best' port -- it means
- * that no charge is available on the port, or the port was rejected.
- */
- if (override_port >= 0 && override_port != new_port)
- override_port = OVERRIDE_OFF;
-
- if (new_supplier == CHARGE_SUPPLIER_NONE) {
- new_charge_current = 0;
- new_charge_current_uncapped = 0;
- new_charge_voltage = 0;
- } else {
- new_charge_current_uncapped =
- available_charge[new_supplier][new_port].current;
-#ifdef CONFIG_CHARGE_RAMP_HW
- /*
- * Allow to set the maximum current value, so the hardware can
- * know the range of acceptable current values for its ramping.
- */
- if (chg_ramp_allowed(new_supplier))
- new_charge_current_uncapped =
- chg_ramp_max(new_supplier,
- new_charge_current_uncapped);
-#endif /* CONFIG_CHARGE_RAMP_HW */
- /* Enforce port charge ceiling. */
- ceil = charge_manager_get_ceil(new_port);
- if (left_safe_mode && ceil != CHARGE_CEIL_NONE)
- new_charge_current = MIN(ceil,
- new_charge_current_uncapped);
- else
- new_charge_current = new_charge_current_uncapped;
-
- new_charge_voltage =
- available_charge[new_supplier][new_port].voltage;
- }
-
- /* Change the charge limit + charge port/supplier if modified. */
- if (new_port != charge_port || new_charge_current != charge_current ||
- new_supplier != charge_supplier) {
-#ifdef HAS_TASK_CHG_RAMP
- chg_ramp_charge_supplier_change(
- new_port, new_supplier, new_charge_current,
- registration_time[new_port],
- new_charge_voltage);
-#else
-#ifdef CONFIG_CHARGE_RAMP_HW
- /* Enable or disable charge ramp */
- charger_set_hw_ramp(chg_ramp_allowed(new_supplier));
-#endif
- board_set_charge_limit(new_port, new_supplier,
- new_charge_current,
- new_charge_current_uncapped,
- new_charge_voltage);
-#endif /* HAS_TASK_CHG_RAMP */
-
- power_changed = 1;
-
- CPRINTS("CL: p%d s%d i%d v%d", new_port, new_supplier,
- new_charge_current, new_charge_voltage);
- }
-
- /*
- * Signal new power request only if the port changed, the voltage
- * on the same port changed, or the actual uncapped current
- * on the same port changed (don't consider ceil).
- */
- if (new_port != CHARGE_PORT_NONE &&
- (new_port != charge_port ||
- new_charge_current_uncapped != charge_current_uncapped ||
- new_charge_voltage != charge_voltage))
- updated_new_port = new_port;
-
- /* If charge port changed, cleanup old port */
- if (charge_port != new_port && charge_port != CHARGE_PORT_NONE) {
- /* Check if need power swap */
- charge_manager_switch_to_source(charge_port);
- /* Signal new power request on old port */
- updated_old_port = charge_port;
- }
-
- /* Update globals to reflect current state. */
- charge_current = new_charge_current;
- charge_current_uncapped = new_charge_current_uncapped;
- charge_voltage = new_charge_voltage;
- charge_supplier = new_supplier;
- charge_port = new_port;
-
-#ifdef CONFIG_USB_PD_LOGGING
- /*
- * Write a log under the following conditions:
- * 1. A port becomes active or
- * 2. A port becomes inactive or
- * 3. The active charge port power limit changes or
- * 4. Any supplier change on an inactive port
- */
- if (updated_new_port != CHARGE_PORT_NONE)
- save_log[updated_new_port] = 1;
- /* Don't log non-meaningful changes on charge port */
- else if (charge_port != CHARGE_PORT_NONE)
- save_log[charge_port] = 0;
-
- if (updated_old_port != CHARGE_PORT_NONE)
- save_log[updated_old_port] = 1;
-
- for (i = 0; i < board_get_usb_pd_port_count(); ++i)
- if (save_log[i])
- charge_manager_save_log(i);
-#endif
-
- /* New power requests must be set only after updating the globals. */
- if (is_pd_port(updated_new_port))
- pd_set_new_power_request(updated_new_port);
- if (is_pd_port(updated_old_port))
- pd_set_new_power_request(updated_old_port);
-
- if (power_changed)
- /* notify host of power info change */
- pd_send_host_event(PD_EVENT_POWER_CHANGE);
-}
-DECLARE_DEFERRED(charge_manager_refresh);
-
-/**
- * Called when charge override times out waiting for power swap.
- */
-static void charge_override_timeout(void)
-{
- delayed_override_port = OVERRIDE_OFF;
- pd_send_host_event(PD_EVENT_POWER_CHANGE);
-}
-DECLARE_DEFERRED(charge_override_timeout);
-
-/**
- * Called CHARGE_DETECT_DELAY after the most recent charge change on a port.
- */
-static void charger_detect_debounced(void)
-{
- /* Inform host that charger detection is debounced. */
- pd_send_host_event(PD_EVENT_POWER_CHANGE);
-}
-DECLARE_DEFERRED(charger_detect_debounced);
-
-/**
- * Update charge parameters for a given port / supplier.
- *
- * @param change Type of change.
- * @param supplier Charge supplier to be updated.
- * @param port Charge port to be updated.
- * @param charge Charge port current / voltage.
- */
-static void charge_manager_make_change(enum charge_manager_change_type change,
- int supplier,
- int port,
- const struct charge_port_info *charge)
-{
- int i;
- int clear_override = 0;
-
- if (!is_valid_port(port)) {
- CPRINTS("%s: p%d invalid", __func__, port);
- return;
- }
-
- /* Determine if this is a change which can affect charge status */
- switch (change) {
- case CHANGE_CHARGE:
- /* Ignore changes where charge is identical */
- if (available_charge[supplier][port].current ==
- charge->current &&
- available_charge[supplier][port].voltage ==
- charge->voltage)
- return;
- if (charge->current > 0 &&
- available_charge[supplier][port].current == 0)
- clear_override = 1;
-#ifdef CONFIG_USB_PD_LOGGING
- save_log[port] = 1;
-#endif
- break;
- case CHANGE_DUALROLE:
- /*
- * Ignore all except for transition to non-dualrole,
- * which may occur some time after we see a charge
- */
-#ifndef CONFIG_CHARGE_MANAGER_DRP_CHARGING
- if (dualrole_capability[port] != CAP_DEDICATED)
-#endif
- return;
- /* Clear override only if a charge is present on the port */
- for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i)
- if (available_charge[i][port].current > 0) {
- clear_override = 1;
- break;
- }
- /*
- * If there is no charge present on the port, the dualrole
- * change is meaningless to charge_manager.
- */
- if (!clear_override)
- return;
- break;
- }
-
- /* Remove override when a charger is plugged */
- if (clear_override && override_port != port
-#ifndef CONFIG_CHARGE_MANAGER_DRP_CHARGING
- /* only remove override when it's a dedicated charger */
- && dualrole_capability[port] == CAP_DEDICATED
-#endif
- ) {
- override_port = OVERRIDE_OFF;
- if (delayed_override_port != OVERRIDE_OFF) {
- delayed_override_port = OVERRIDE_OFF;
- hook_call_deferred(&charge_override_timeout_data, -1);
- }
- }
-
- if (change == CHANGE_CHARGE) {
- available_charge[supplier][port].current = charge->current;
- available_charge[supplier][port].voltage = charge->voltage;
- registration_time[port] = get_time();
-
- /*
- * After CHARGE_DETECT_DELAY, inform the host that charger
- * detection has been debounced. Since only one deferred
- * routine exists for all ports, the deferred call for a given
- * port may potentially be cancelled. This is mostly harmless
- * since cancellation implies that PD_EVENT_POWER_CHANGE was
- * just sent due to the power change on another port.
- */
- if (charge->current > 0)
- hook_call_deferred(&charger_detect_debounced_data,
- CHARGE_DETECT_DELAY);
-
- /*
- * If we have a charge on our delayed override port within
- * the deadline, make it our override port.
- */
- if (port == delayed_override_port && charge->current > 0 &&
- is_sink(delayed_override_port) &&
- get_time().val < delayed_override_deadline.val) {
- delayed_override_port = OVERRIDE_OFF;
- hook_call_deferred(&charge_override_timeout_data, -1);
- charge_manager_set_override(port);
- }
- }
-
- /*
- * Don't call charge_manager_refresh unless all ports +
- * suppliers have reported in. We don't want to make changes
- * to our charge port until we are certain we know what is
- * attached.
- */
- if (charge_manager_is_seeded())
- hook_call_deferred(&charge_manager_refresh_data, 0);
-}
-
-void pd_set_input_current_limit(int port, uint32_t max_ma,
- uint32_t supply_voltage)
-{
- struct charge_port_info charge;
-
- charge.current = max_ma;
- charge.voltage = supply_voltage;
- charge_manager_update_charge(CHARGE_SUPPLIER_PD, port, &charge);
-}
-
-void typec_set_input_current_limit(int port, typec_current_t max_ma,
- uint32_t supply_voltage)
-{
- struct charge_port_info charge;
- int i;
- int supplier;
- int dts = !!(max_ma & TYPEC_CURRENT_DTS_MASK);
- static const enum charge_supplier typec_suppliers[] = {
- CHARGE_SUPPLIER_TYPEC,
- CHARGE_SUPPLIER_TYPEC_DTS,
-#ifdef CHARGE_MANAGER_BC12
- CHARGE_SUPPLIER_TYPEC_UNDER_1_5A,
-#endif /* CHARGE_MANAGER_BC12 */
- };
-
- charge.current = max_ma & TYPEC_CURRENT_ILIM_MASK;
- charge.voltage = supply_voltage;
-#if !defined(HAS_TASK_CHG_RAMP) && !defined(CONFIG_CHARGE_RAMP_HW)
- /*
- * DTS sources such as suzy-q may not be able to actually deliver
- * their advertised current, so limit it to reduce chance of OC,
- * if we can't ramp.
- */
- if (dts)
- charge.current = MIN(charge.current, 500);
-#endif
-
- supplier = dts ? CHARGE_SUPPLIER_TYPEC_DTS : CHARGE_SUPPLIER_TYPEC;
-
-#ifdef CHARGE_MANAGER_BC12
- /*
- * According to USB-C spec 1.3 Table 4-17 "Precedence of power source
- * usage", the priority should be: USB-C 3.0A, 1.5A > BC1.2 > USB-C
- * under 1.5A. Choosed the corresponding supplier type, according to
- * charge current, to update.
- */
- if (charge.current < 1500)
- supplier = CHARGE_SUPPLIER_TYPEC_UNDER_1_5A;
-#endif /* CHARGE_MANAGER_BC12 */
-
- charge_manager_update_charge(supplier, port, &charge);
-
- /*
- * TYPEC / TYPEC-DTS / TYPEC-UNDER_1_5A should be mutually exclusive.
- * Zero'ing all the other suppliers.
- */
- for (i = 0; i < ARRAY_SIZE(typec_suppliers); ++i)
- if (supplier != typec_suppliers[i])
- charge_manager_update_charge(typec_suppliers[i], port,
- NULL);
-}
-
-void charge_manager_update_charge(int supplier,
- int port,
- const struct charge_port_info *charge)
-{
- struct charge_port_info zero = {0};
- if (!charge)
- charge = &zero;
- charge_manager_make_change(CHANGE_CHARGE, supplier, port, charge);
-}
-
-void charge_manager_update_dualrole(int port, enum dualrole_capabilities cap)
-{
- if (!is_pd_port(port))
- return;
-
- /* Ignore when capability is unchanged */
- if (cap != dualrole_capability[port]) {
- dualrole_capability[port] = cap;
- charge_manager_make_change(CHANGE_DUALROLE, 0, port, NULL);
- }
-}
-
-#ifdef CONFIG_CHARGE_MANAGER_SAFE_MODE
-void charge_manager_leave_safe_mode(void)
-{
- if (left_safe_mode)
- return;
-
- CPRINTS("%s()", __func__);
- cflush();
- left_safe_mode = 1;
- if (charge_manager_is_seeded())
- hook_call_deferred(&charge_manager_refresh_data, 0);
-}
-#endif
-
-void charge_manager_set_ceil(int port, enum ceil_requestor requestor, int ceil)
-{
- if (!is_valid_port(port))
- return;
-
- if (charge_ceil[port][requestor] != ceil) {
- charge_ceil[port][requestor] = ceil;
- if (port == charge_port && charge_manager_is_seeded())
- hook_call_deferred(&charge_manager_refresh_data, 0);
- }
-}
-
-void charge_manager_force_ceil(int port, int ceil)
-{
- /*
- * Force our input current to ceil if we're exceeding it, without
- * waiting for our deferred task to run.
- */
- if (left_safe_mode && port == charge_port && ceil < charge_current)
- board_set_charge_limit(port, CHARGE_SUPPLIER_PD, ceil,
- charge_current_uncapped, charge_voltage);
-
- /*
- * Now inform charge_manager so it stays in sync with the state of
- * the world.
- */
- charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, ceil);
-}
-
-int charge_manager_set_override(int port)
-{
- int retval = EC_SUCCESS;
-
- CPRINTS("Charge Override: %d", port);
-
- /*
- * If attempting to change the override port, then return
- * error. Since we may be in the middle of a power swap on
- * the original override port, it's too complicated to
- * guarantee that the original override port is switched back
- * to source.
- */
- if (delayed_override_port != OVERRIDE_OFF)
- return EC_ERROR_BUSY;
-
- /* Set the override port if it's a sink. */
- if (port < 0 || is_sink(port)) {
- if (override_port != port) {
- override_port = port;
- if (charge_manager_is_seeded())
- hook_call_deferred(
- &charge_manager_refresh_data, 0);
- }
- }
- /*
- * If the attached device is capable of being a sink, request a
- * power swap and set the delayed override for swap completion.
- */
- else if (!is_sink(port) && dualrole_capability[port] == CAP_DUALROLE) {
- delayed_override_deadline.val = get_time().val +
- POWER_SWAP_TIMEOUT;
- delayed_override_port = port;
- hook_call_deferred(&charge_override_timeout_data,
- POWER_SWAP_TIMEOUT);
- pd_request_power_swap(port);
- /* Can't charge from requested port -- return error. */
- } else
- retval = EC_ERROR_INVAL;
-
- return retval;
-}
-
-int charge_manager_get_override(void)
-{
- return override_port;
-}
-
-int charge_manager_get_active_charge_port(void)
-{
- return charge_port;
-}
-
-int charge_manager_get_charger_current(void)
-{
- return charge_current;
-}
-
-int charge_manager_get_charger_voltage(void)
-{
- return charge_voltage;
-}
-
-int charge_manager_get_power_limit_uw(void)
-{
- int current_ma = charge_current;
- int voltage_mv = charge_voltage;
-
- if (current_ma == CHARGE_CURRENT_UNINITIALIZED ||
- voltage_mv == CHARGE_VOLTAGE_UNINITIALIZED)
- return 0;
- else
- return current_ma * voltage_mv;
-}
-
-#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT
-
-/* Bitmap of ports used as power source */
-static volatile uint32_t source_port_bitmap;
-BUILD_ASSERT(sizeof(source_port_bitmap)*8 >= CONFIG_USB_PD_PORT_MAX_COUNT);
-
-static inline int has_other_active_source(int port)
-{
- return source_port_bitmap & ~BIT(port);
-}
-
-static inline int is_active_source(int port)
-{
- return source_port_bitmap & BIT(port);
-}
-
-static int can_supply_max_current(int port)
-{
-#ifdef CONFIG_USB_PD_MAX_TOTAL_SOURCE_CURRENT
- /*
- * This guarantees active 3A source continues to supply 3A.
- *
- * Since redistribution occurs sequentially, younger ports get
- * priority. Priority surfaces only when 3A source is released.
- * That is, when 3A source is released, the youngest active
- * port gets 3A.
- */
- int p;
- if (!is_active_source(port))
- /* Non-active ports don't get 3A */
- return 0;
- for (p = 0; p < board_get_usb_pd_port_count(); p++) {
- if (p == port)
- continue;
- if (source_port_rp[p] ==
- CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT)
- return 0;
- }
- return 1;
-#else
- return is_active_source(port) && !has_other_active_source(port);
-#endif /* CONFIG_USB_PD_MAX_TOTAL_SOURCE_CURRENT */
-}
-
-void charge_manager_source_port(int port, int enable)
-{
- uint32_t prev_bitmap = source_port_bitmap;
- int p, rp;
-
- if (enable)
- atomic_or(&source_port_bitmap, 1 << port);
- else
- atomic_clear(&source_port_bitmap, 1 << port);
-
- /* No change, exit early. */
- if (prev_bitmap == source_port_bitmap)
- return;
-
- /* Set port limit according to policy */
- for (p = 0; p < board_get_usb_pd_port_count(); p++) {
- rp = can_supply_max_current(p) ?
- CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT :
- CONFIG_USB_PD_PULLUP;
- source_port_rp[p] = rp;
-
-#ifdef CONFIG_USB_PD_LOGGING
- if (is_connected(p) && !is_sink(p))
- charge_manager_save_log(p);
-#endif
-
- typec_set_source_current_limit(p, rp);
- tcpm_select_rp_value(p, rp);
- pd_update_contract(p);
- }
-}
-
-int charge_manager_get_source_pdo(const uint32_t **src_pdo, const int port)
-{
- if (can_supply_max_current(port)) {
- *src_pdo = pd_src_pdo_max;
- return pd_src_pdo_max_cnt;
- }
-
- *src_pdo = pd_src_pdo;
- return pd_src_pdo_cnt;
-}
-#endif /* CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT */
-
-#ifndef TEST_BUILD
-static enum ec_status hc_pd_power_info(struct host_cmd_handler_args *args)
-{
- const struct ec_params_usb_pd_power_info *p = args->params;
- struct ec_response_usb_pd_power_info *r = args->response;
- int port = p->port;
-
- /* If host is asking for the charging port, set port appropriately */
- if (port == PD_POWER_CHARGING_PORT)
- port = charge_port;
-
- /*
- * Not checking for invalid port here, because it might break existing
- * contract with ectool users. The invalid ports will have the response
- * voltage, current and power parameters set to 0.
- */
- if (port >= CHARGE_PORT_COUNT)
- return EC_RES_INVALID_PARAM;
-
- charge_manager_fill_power_info(port, r);
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_POWER_INFO,
- hc_pd_power_info,
- EC_VER_MASK(0));
-#endif /* TEST_BUILD */
-
-static enum ec_status hc_charge_port_count(struct host_cmd_handler_args *args)
-{
- struct ec_response_charge_port_count *resp = args->response;
-
- args->response_size = sizeof(*resp);
- resp->port_count = CHARGE_PORT_COUNT;
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_CHARGE_PORT_COUNT,
- hc_charge_port_count,
- EC_VER_MASK(0));
-
-static enum ec_status
-hc_charge_port_override(struct host_cmd_handler_args *args)
-{
- const struct ec_params_charge_port_override *p = args->params;
- const int16_t override_port = p->override_port;
-
- if (override_port < OVERRIDE_DONT_CHARGE ||
- override_port >= CHARGE_PORT_COUNT)
- return EC_RES_INVALID_PARAM;
-
- return charge_manager_set_override(override_port) == EC_SUCCESS ?
- EC_RES_SUCCESS : EC_RES_ERROR;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PD_CHARGE_PORT_OVERRIDE,
- hc_charge_port_override,
- EC_VER_MASK(0));
-
-#if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0
-static enum ec_status hc_override_dedicated_charger_limit(
- struct host_cmd_handler_args *args)
-{
- const struct ec_params_dedicated_charger_limit *p = args->params;
- struct charge_port_info ci = {
- .current = p->current_lim,
- .voltage = p->voltage_lim,
- };
-
- /*
- * Allow a change only if the dedicated charge port is used. Host needs
- * to apply a change every time a dedicated charger is plugged.
- */
- if (charge_port != DEDICATED_CHARGE_PORT)
- return EC_RES_UNAVAILABLE;
-
- charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED,
- DEDICATED_CHARGE_PORT, &ci);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_OVERRIDE_DEDICATED_CHARGER_LIMIT,
- hc_override_dedicated_charger_limit,
- EC_VER_MASK(0));
-#endif
-
-static int command_charge_port_override(int argc, char **argv)
-{
- int port = OVERRIDE_OFF;
- int ret = EC_SUCCESS;
- char *e;
-
- if (argc >= 2) {
- port = strtoi(argv[1], &e, 0);
- if (*e || port < OVERRIDE_DONT_CHARGE ||
- port >= CHARGE_PORT_COUNT)
- return EC_ERROR_PARAM1;
- ret = charge_manager_set_override(port);
- }
-
- ccprintf("Override: %d\n", (argc >= 2 && ret == EC_SUCCESS) ?
- port : override_port);
- return ret;
-}
-DECLARE_CONSOLE_COMMAND(chgoverride, command_charge_port_override,
- "[port | -1 | -2]",
- "Force charging from a given port (-1 = off, -2 = disable charging)");
-
-#ifdef CONFIG_CHARGE_MANAGER_EXTERNAL_POWER_LIMIT
-static void charge_manager_set_external_power_limit(int current_lim,
- int voltage_lim)
-{
- int port;
-
- if (current_lim == EC_POWER_LIMIT_NONE)
- current_lim = CHARGE_CEIL_NONE;
- if (voltage_lim == EC_POWER_LIMIT_NONE)
- voltage_lim = PD_MAX_VOLTAGE_MV;
-
- for (port = 0; port < board_get_usb_pd_port_count(); ++port) {
- charge_manager_set_ceil(port, CEIL_REQUESTOR_HOST, current_lim);
- pd_set_external_voltage_limit(port, voltage_lim);
- }
-}
-
-/*
- * On transition out of S0, disable all external power limits, in case AP
- * failed to clear them.
- */
-static void charge_manager_external_power_limit_off(void)
-{
- charge_manager_set_external_power_limit(EC_POWER_LIMIT_NONE,
- EC_POWER_LIMIT_NONE);
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, charge_manager_external_power_limit_off,
- HOOK_PRIO_DEFAULT);
-
-static enum ec_status
-hc_external_power_limit(struct host_cmd_handler_args *args)
-{
- const struct ec_params_external_power_limit_v1 *p = args->params;
-
- charge_manager_set_external_power_limit(p->current_lim,
- p->voltage_lim);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_EXTERNAL_POWER_LIMIT,
- hc_external_power_limit,
- EC_VER_MASK(1));
-
-static int command_external_power_limit(int argc, char **argv)
-{
- int max_current;
- int max_voltage;
- char *e;
-
- if (argc >= 2) {
- max_current = strtoi(argv[1], &e, 10);
- if (*e)
- return EC_ERROR_PARAM1;
- } else
- max_current = EC_POWER_LIMIT_NONE;
-
- if (argc >= 3) {
- max_voltage = strtoi(argv[2], &e, 10);
- if (*e)
- return EC_ERROR_PARAM1;
- } else
- max_voltage = EC_POWER_LIMIT_NONE;
-
- charge_manager_set_external_power_limit(max_current, max_voltage);
- ccprintf("max req: %dmA %dmV\n", max_current, max_voltage);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(chglim, command_external_power_limit,
- "[max_current (mA)] [max_voltage (mV)]",
- "Set max charger current / voltage");
-#endif /* CONFIG_CHARGE_MANAGER_EXTERNAL_POWER_LIMIT */
-
-#ifdef CONFIG_CMD_CHARGE_SUPPLIER_INFO
-static int charge_supplier_info(int argc, char **argv)
-{
- ccprintf("port=%d, type=%d, cur=%dmA, vtg=%dmV, lsm=%d\n",
- charge_manager_get_active_charge_port(),
- charge_supplier,
- charge_current,
- charge_voltage,
- left_safe_mode);
-
- return 0;
-}
-DECLARE_CONSOLE_COMMAND(chgsup, charge_supplier_info,
- NULL, "print chg supplier info");
-#endif
-
-__overridable
-int board_charge_port_is_sink(int port)
-{
- return 1;
-}
-
-__overridable
-int board_charge_port_is_connected(int port)
-{
- return 1;
-}
-
-__overridable
-void board_fill_source_power_info(int port,
- struct ec_response_usb_pd_power_info *r)
-{
- r->meas.voltage_now = 0;
- r->meas.voltage_max = 0;
- r->meas.current_max = 0;
- r->meas.current_lim = 0;
- r->max_power = 0;
-}
diff --git a/common/i2c_master.c b/common/i2c_master.c
index d89e20b920..be371e52ed 100644
--- a/common/i2c_master.c
+++ b/common/i2c_master.c
@@ -15,8 +15,6 @@
#include "i2c.h"
#include "system.h"
#include "task.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
#include "util.h"
#include "watchdog.h"
#include "virtual_battery.h"
@@ -1085,25 +1083,6 @@ static void i2c_passthru_protect_port(uint32_t port)
static void i2c_passthru_protect_tcpc_ports(void)
{
-#ifdef CONFIG_USB_PD_PORT_MAX_COUNT
- int i;
-
- /*
- * If WP is not enabled i.e. system is not locked leave the tunnels open
- * so that factory line can do updates without a new RO BIOS.
- */
- if (!system_is_locked()) {
- CPRINTS("System unlocked, TCPC I2C tunnels may be unprotected");
- return;
- }
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- /* TCPC tunnel not configured. No need to protect anything */
- if (!I2C_GET_ADDR(tcpc_config[i].i2c_info.addr_flags))
- continue;
- i2c_passthru_protect_port(tcpc_config[i].i2c_info.port);
- }
-#endif
}
static enum ec_status
diff --git a/common/mock/usb_mux_mock.c b/common/mock/usb_mux_mock.c
deleted file mode 100644
index 28f07c54f7..0000000000
--- a/common/mock/usb_mux_mock.c
+++ /dev/null
@@ -1,51 +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.
- */
-/* Mock USB Type-C mux */
-
-#include "common.h"
-#include "console.h"
-#include "usb_mux.h"
-#include "usb_mux_mock.h"
-#include "memory.h"
-
-/* Public API for controlling/inspecting this mock */
-struct mock_usb_mux_ctrl mock_usb_mux;
-
-void mock_usb_mux_reset(void)
-{
- memset(&mock_usb_mux, 0, sizeof(mock_usb_mux));
-}
-
-static int mock_init(int port)
-{
- return EC_SUCCESS;
-}
-
-static int mock_set(int port, mux_state_t mux_state)
-{
- mock_usb_mux.state = mux_state;
- ++mock_usb_mux.num_set_calls;
- ccprints("Called into mux with %d", mux_state);
-
- return EC_SUCCESS;
-}
-
-int mock_get(int port, mux_state_t *mux_state)
-{
- *mux_state = mock_usb_mux.state;
- return EC_SUCCESS;
-}
-
-static int mock_enter_low_power_mode(int port)
-{
- return EC_SUCCESS;
-}
-
-const struct usb_mux_driver mock_usb_mux_driver = {
- .init = &mock_init,
- .set = &mock_set,
- .get = &mock_get,
- .enter_low_power_mode = &mock_enter_low_power_mode,
-};
diff --git a/common/mock/usb_mux_mock.h b/common/mock/usb_mux_mock.h
deleted file mode 100644
index 128286796b..0000000000
--- a/common/mock/usb_mux_mock.h
+++ /dev/null
@@ -1,19 +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.
- */
-/* Mock USB Type-C mux */
-
-#include "usb_mux.h"
-
-/* Controller for mux state */
-struct mock_usb_mux_ctrl {
- mux_state_t state;
- int num_set_calls;
-};
-
-/* Resets the state of the mock */
-void mock_usb_mux_reset(void);
-
-extern const struct usb_mux_driver mock_usb_mux_driver;
-extern struct mock_usb_mux_ctrl mock_usb_mux;
diff --git a/common/peripheral.c b/common/peripheral.c
index 79a80b0ef9..9b77d49072 100644
--- a/common/peripheral.c
+++ b/common/peripheral.c
@@ -7,8 +7,6 @@
#include "compile_time_macros.h"
#include "ec_commands.h"
#include "host_command.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
#ifdef CONFIG_HOSTCMD_LOCATE_CHIP
static enum ec_status hc_locate_chip(struct host_cmd_handler_args *args)
@@ -30,22 +28,7 @@ static enum ec_status hc_locate_chip(struct host_cmd_handler_args *args)
#endif /* CONFIG_CROS_BOARD_INFO */
break;
case EC_CHIP_TYPE_TCPC:
-#if defined(CONFIG_USB_PD_PORT_MAX_COUNT) && !defined(CONFIG_USB_PD_TCPC)
- if (params->index >= board_get_usb_pd_port_count())
- return EC_RES_OVERFLOW;
- resp->bus_type = tcpc_config[params->index].bus_type;
- if (resp->bus_type == EC_BUS_TYPE_I2C) {
- resp->i2c_info.port =
- tcpc_config[params->index].i2c_info.port;
- resp->i2c_info.addr_flags =
- tcpc_config[params->index].i2c_info.addr_flags;
- }
-#ifdef CONFIG_INTEL_VIRTUAL_MUX
- resp->reserved = tcpc_config[params->index].usb23;
-#endif
-#else
return EC_RES_UNAVAILABLE;
-#endif /* CONFIG_USB_PD_PORT_MAX_COUNT */
break;
default:
/* The type was unrecognized */
diff --git a/common/rwsig.c b/common/rwsig.c
index 8bccd2acb1..5e57f4cab5 100644
--- a/common/rwsig.c
+++ b/common/rwsig.c
@@ -18,7 +18,6 @@
#include "shared_mem.h"
#include "system.h"
#include "task.h"
-#include "usb_pd.h"
#include "util.h"
#include "vb21_struct.h"
#include "version.h"
@@ -229,7 +228,6 @@ out:
CPRINTS("RW verify %s", good ? "OK" : "FAILED");
if (!good) {
- pd_log_event(PD_EVENT_ACC_RW_FAIL, 0, 0, NULL);
/* RW firmware is invalid : do not jump there */
if (system_is_locked())
system_disable_jump();
diff --git a/common/system.c b/common/system.c
index 036de2235e..62f7e6c40f 100644
--- a/common/system.c
+++ b/common/system.c
@@ -5,7 +5,6 @@
/* System module for Chrome EC : common functions */
#include "battery.h"
-#include "charge_manager.h"
#include "chipset.h"
#include "clock.h"
#include "common.h"
@@ -33,8 +32,6 @@
#include "task.h"
#include "timer.h"
#include "uart.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
#include "util.h"
#include "version.h"
#include "watchdog.h"
@@ -848,24 +845,6 @@ static int handle_pending_reboot(enum ec_reboot_cmd cmd)
case EC_REBOOT_JUMP_RW:
return system_run_image_copy(system_get_active_copy());
case EC_REBOOT_COLD:
-#ifdef HAS_TASK_PDCMD
- /*
- * Reboot the PD chip(s) as well, but first suspend the ports
- * if this board has PD tasks running so they don't query the
- * TCPCs while they reset.
- */
-#ifdef HAS_TASK_PD_C0
- {
- int port;
-
- for (port = 0; port < board_get_usb_pd_port_count();
- port++)
- pd_set_suspend(port, 1);
- }
-#endif
- board_reset_pd_mcu();
-#endif
-
cflush();
system_reset(SYSTEM_RESET_HARD);
/* That shouldn't return... */
@@ -1531,9 +1510,6 @@ DECLARE_HOST_COMMAND(EC_CMD_REBOOT_EC,
int system_can_boot_ap(void)
{
- int soc = -1;
- int pow = -1;
-
#if defined(CONFIG_BATTERY) && \
defined(CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON)
/* Require a minimum battery level to power on. If battery isn't
@@ -1543,18 +1519,8 @@ int system_can_boot_ap(void)
return 1;
#endif
-#if defined(CONFIG_CHARGE_MANAGER) && \
- defined(CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON)
- pow = charge_manager_get_power_limit_uw() / 1000;
- if (pow >= CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON)
- return 1;
-#else
/* For fixed AC system */
return 1;
-#endif
-
- CPRINTS("Not enough power to boot (%d %%, %d mW)", soc, pow);
- return 0;
}
#ifdef CONFIG_SERIALNO_LEN
diff --git a/common/usb_charger.c b/common/usb_charger.c
deleted file mode 100644
index 4a85dc6daf..0000000000
--- a/common/usb_charger.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/* Copyright 2015 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.
- */
-
-/*
- * USB charger interface routines. This code assumes that CONFIG_CHARGE_MANAGER
- * is defined and implemented.
- * usb_charger_set_switches() must be implemented by a companion
- * usb_switch driver.
- * In addition, USB switch-specific usb_charger task or interrupt routine
- * is necessary to update charge_manager with detected charger attributes.
- */
-
-#include "charge_manager.h"
-#include "charger.h"
-#include "common.h"
-#include "console.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "stddef.h"
-#include "task.h"
-#include "usb_charge.h"
-#include "usb_pd.h"
-#include "usbc_ppc.h"
-
-static void update_vbus_supplier(int port, int vbus_level)
-{
- struct charge_port_info charge = {0};
-
- if (vbus_level && !usb_charger_port_is_sourcing_vbus(port)) {
- charge.voltage = USB_CHARGER_VOLTAGE_MV;
- charge.current = USB_CHARGER_MIN_CURR_MA;
- }
-
- charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, port, &charge);
-}
-
-#ifdef CONFIG_USB_PD_5V_EN_CUSTOM
-#define USB_5V_EN(port) board_is_sourcing_vbus(port)
-#elif defined(CONFIG_USBC_PPC)
-#define USB_5V_EN(port) ppc_is_sourcing_vbus(port)
-#elif defined(CONFIG_USB_PD_5V_CHARGER_CTRL)
-#define USB_5V_EN(port) charger_is_sourcing_otg_power(port)
-#elif defined(CONFIG_USB_PD_5V_EN_ACTIVE_LOW)
-#define USB_5V_EN(port) !gpio_get_level(GPIO_USB_C##port##_5V_EN_L)
-#else
-#define USB_5V_EN(port) gpio_get_level(GPIO_USB_C##port##_5V_EN)
-#endif
-
-int usb_charger_port_is_sourcing_vbus(int port)
-{
- if (port == 0)
- return USB_5V_EN(0);
-#if CONFIG_USB_PD_PORT_MAX_COUNT >= 2
- else if (port == 1)
- return USB_5V_EN(1);
-#endif
- /* Not a valid port */
- return 0;
-}
-
-void usb_charger_vbus_change(int port, int vbus_level)
-{
- /* If VBUS has transitioned low, notify PD module directly */
- if (!vbus_level)
- pd_vbus_low(port);
-
- /* Update VBUS supplier and signal VBUS change to USB_CHG task */
- update_vbus_supplier(port, vbus_level);
-
-#ifdef HAS_TASK_USB_CHG_P0
- /* USB Charger task(s) */
- task_set_event(USB_CHG_PORT_TO_TASK_ID(port), USB_CHG_EVENT_VBUS, 0);
-#endif
-
-#if (defined(CONFIG_USB_PD_VBUS_DETECT_CHARGER) \
- || defined(CONFIG_USB_PD_VBUS_DETECT_PPC))
- /* USB PD task */
- task_wake(PD_PORT_TO_TASK_ID(port));
-#endif
-}
-
-void usb_charger_reset_charge(int port)
-{
- charge_manager_update_charge(CHARGE_SUPPLIER_PROPRIETARY,
- port, NULL);
- charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP,
- port, NULL);
- charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP,
- port, NULL);
- charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP,
- port, NULL);
- charge_manager_update_charge(CHARGE_SUPPLIER_OTHER,
- port, NULL);
-#if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0
- charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED,
- port, NULL);
-#endif
-#ifdef CONFIG_WIRELESS_CHARGER_P9221_R7
- charge_manager_update_charge(CHARGE_SUPPLIER_WPC_BPP,
- port, NULL);
- charge_manager_update_charge(CHARGE_SUPPLIER_WPC_EPP,
- port, NULL);
- charge_manager_update_charge(CHARGE_SUPPLIER_WPC_GPP,
- port, NULL);
-#endif
-
-}
-
-static void usb_charger_init(void)
-{
- int i;
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- usb_charger_reset_charge(i);
- /* Initialize VBUS supplier based on whether VBUS is present. */
- update_vbus_supplier(i, pd_is_vbus_present(i));
- }
-}
-DECLARE_HOOK(HOOK_INIT, usb_charger_init, HOOK_PRIO_CHARGE_MANAGER_INIT + 1);
diff --git a/common/usb_common.c b/common/usb_common.c
deleted file mode 100644
index a068142ae5..0000000000
--- a/common/usb_common.c
+++ /dev/null
@@ -1,381 +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.
- */
-
-/*
- * Contains common USB functions shared between the old (i.e. usb_pd_protocol)
- * and the new (i.e. usb_sm_*) USB-C PD stacks.
- */
-
-#include "common.h"
-#include "charge_state.h"
-#include "task.h"
-#include "usb_common.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
-#include "util.h"
-
-int usb_get_battery_soc(void)
-{
-#if defined(CONFIG_CHARGER)
- return charge_get_percent();
-#elif defined(CONFIG_BATTERY)
- return board_get_battery_soc();
-#else
- return 0;
-#endif
-}
-
-/*
- * CC values for regular sources and Debug sources (aka DTS)
- *
- * Source type Mode of Operation CC1 CC2
- * ---------------------------------------------
- * Regular Default USB Power RpUSB Open
- * Regular USB-C @ 1.5 A Rp1A5 Open
- * Regular USB-C @ 3 A Rp3A0 Open
- * DTS Default USB Power Rp3A0 Rp1A5
- * DTS USB-C @ 1.5 A Rp1A5 RpUSB
- * DTS USB-C @ 3 A Rp3A0 RpUSB
- */
-
-typec_current_t usb_get_typec_current_limit(enum pd_cc_polarity_type polarity,
- enum tcpc_cc_voltage_status cc1, enum tcpc_cc_voltage_status cc2)
-{
- typec_current_t charge = 0;
- enum tcpc_cc_voltage_status cc = polarity ? cc2 : cc1;
- enum tcpc_cc_voltage_status cc_alt = polarity ? cc1 : cc2;
-
- switch (cc) {
- case TYPEC_CC_VOLT_RP_3_0:
- if (!cc_is_rp(cc_alt) || cc_alt == TYPEC_CC_VOLT_RP_DEF)
- charge = 3000;
- else if (cc_alt == TYPEC_CC_VOLT_RP_1_5)
- charge = 500;
- break;
- case TYPEC_CC_VOLT_RP_1_5:
- charge = 1500;
- break;
- case TYPEC_CC_VOLT_RP_DEF:
- charge = 500;
- break;
- default:
- break;
- }
-
- if (IS_ENABLED(CONFIG_USBC_DISABLE_CHARGE_FROM_RP_DEF) && charge == 500)
- charge = 0;
-
- if (cc_is_rp(cc_alt))
- charge |= TYPEC_CURRENT_DTS_MASK;
-
- return charge;
-}
-
-enum pd_cc_polarity_type get_snk_polarity(enum tcpc_cc_voltage_status cc1,
- enum tcpc_cc_voltage_status cc2)
-{
- /* The following assumes:
- *
- * TYPEC_CC_VOLT_RP_3_0 > TYPEC_CC_VOLT_RP_1_5
- * TYPEC_CC_VOLT_RP_1_5 > TYPEC_CC_VOLT_RP_DEF
- * TYPEC_CC_VOLT_RP_DEF > TYPEC_CC_VOLT_OPEN
- */
- return cc2 > cc1;
-}
-
-enum pd_cc_states pd_get_cc_state(
- enum tcpc_cc_voltage_status cc1, enum tcpc_cc_voltage_status cc2)
-{
- /* Port partner is a SNK */
- if (cc_is_snk_dbg_acc(cc1, cc2))
- return PD_CC_UFP_DEBUG_ACC;
- if (cc_is_at_least_one_rd(cc1, cc2))
- return PD_CC_UFP_ATTACHED;
- if (cc_is_audio_acc(cc1, cc2))
- return PD_CC_UFP_AUDIO_ACC;
-
- /* Port partner is a SRC */
- if (cc_is_rp(cc1) && cc_is_rp(cc2))
- return PD_CC_DFP_DEBUG_ACC;
- if (cc_is_rp(cc1) || cc_is_rp(cc2))
- return PD_CC_DFP_ATTACHED;
-
- /*
- * 1) Both lines are Vopen or
- * 2) Only an e-marked cabled without a partner on the other side
- */
- return PD_CC_NONE;
-}
-/*
- * Zinger implements a board specific usb policy that does not define
- * PD_MAX_VOLTAGE_MV and PD_OPERATING_POWER_MW. And in turn, does not
- * use the following functions.
- */
-#if defined(PD_MAX_VOLTAGE_MV) && defined(PD_OPERATING_POWER_MW)
-int pd_find_pdo_index(uint32_t src_cap_cnt, const uint32_t * const src_caps,
- int max_mv, uint32_t *selected_pdo)
-{
- int i, uw, mv;
- int ret = 0;
- int cur_uw = 0;
- int prefer_cur;
-
- int __attribute__((unused)) cur_mv = 0;
-
- /* max voltage is always limited by this boards max request */
- max_mv = MIN(max_mv, PD_MAX_VOLTAGE_MV);
-
- /* Get max power that is under our max voltage input */
- for (i = 0; i < src_cap_cnt; i++) {
- /* its an unsupported Augmented PDO (PD3.0) */
- if ((src_caps[i] & PDO_TYPE_MASK) == PDO_TYPE_AUGMENTED)
- continue;
-
- mv = ((src_caps[i] >> 10) & 0x3FF) * 50;
- /* Skip invalid voltage */
- if (!mv)
- continue;
- /* Skip any voltage not supported by this board */
- if (!pd_is_valid_input_voltage(mv))
- continue;
-
- if ((src_caps[i] & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) {
- uw = 250000 * (src_caps[i] & 0x3FF);
- } else {
- int ma = (src_caps[i] & 0x3FF) * 10;
-
- ma = MIN(ma, PD_MAX_CURRENT_MA);
- uw = ma * mv;
- }
-
- if (mv > max_mv)
- continue;
- uw = MIN(uw, PD_MAX_POWER_MW * 1000);
- prefer_cur = 0;
-
- /* Apply special rules in case of 'tie' */
- if (IS_ENABLED(PD_PREFER_LOW_VOLTAGE)) {
- if (uw == cur_uw && mv < cur_mv)
- prefer_cur = 1;
- } else if (IS_ENABLED(PD_PREFER_HIGH_VOLTAGE)) {
- if (uw == cur_uw && mv > cur_mv)
- prefer_cur = 1;
- }
-
- /* Prefer higher power, except for tiebreaker */
- if (uw > cur_uw || prefer_cur) {
- ret = i;
- cur_uw = uw;
- cur_mv = mv;
- }
- }
-
- if (selected_pdo)
- *selected_pdo = src_caps[ret];
-
- return ret;
-}
-
-void pd_extract_pdo_power(uint32_t pdo, uint32_t *ma, uint32_t *mv)
-{
- int max_ma, uw;
-
- *mv = ((pdo >> 10) & 0x3FF) * 50;
-
- if (*mv == 0) {
- *ma = 0;
- return;
- }
-
- if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) {
- uw = 250000 * (pdo & 0x3FF);
- max_ma = 1000 * MIN(1000 * uw, PD_MAX_POWER_MW) / *mv;
- } else {
- max_ma = 10 * (pdo & 0x3FF);
- max_ma = MIN(max_ma, PD_MAX_POWER_MW * 1000 / *mv);
- }
-
- *ma = MIN(max_ma, PD_MAX_CURRENT_MA);
-}
-
-void pd_build_request(uint32_t src_cap_cnt, const uint32_t * const src_caps,
- int32_t vpd_vdo, uint32_t *rdo, uint32_t *ma,
- uint32_t *mv, enum pd_request_type req_type,
- uint32_t max_request_mv)
-{
- uint32_t pdo;
- int pdo_index, flags = 0;
- int uw;
- int max_or_min_ma;
- int max_or_min_mw;
- int max_vbus;
- int vpd_vbus_dcr;
- int vpd_gnd_dcr;
-
- if (req_type == PD_REQUEST_VSAFE5V) {
- /* src cap 0 should be vSafe5V */
- pdo_index = 0;
- pdo = src_caps[0];
- } else {
- /* find pdo index for max voltage we can request */
- pdo_index = pd_find_pdo_index(src_cap_cnt, src_caps,
- max_request_mv, &pdo);
- }
-
- pd_extract_pdo_power(pdo, ma, mv);
-
- /*
- * Adjust VBUS current if CTVPD device was detected.
- */
- if (vpd_vdo > 0) {
- max_vbus = VPD_VDO_MAX_VBUS(vpd_vdo);
- vpd_vbus_dcr = VPD_VDO_VBUS_IMP(vpd_vdo) << 1;
- vpd_gnd_dcr = VPD_VDO_GND_IMP(vpd_vdo);
-
- /*
- * Valid max_vbus values:
- * 00b - 20000 mV
- * 01b - 30000 mV
- * 10b - 40000 mV
- * 11b - 50000 mV
- */
- max_vbus = 20000 + max_vbus * 10000;
- if (*mv > max_vbus)
- *mv = max_vbus;
-
- /*
- * 5000 mA cable: 150 = 750000 / 50000
- * 3000 mA cable: 250 = 750000 / 30000
- */
- if (*ma > 3000)
- *ma = 750000 / (150 + vpd_vbus_dcr + vpd_gnd_dcr);
- else
- *ma = 750000 / (250 + vpd_vbus_dcr + vpd_gnd_dcr);
- }
-
- uw = *ma * *mv;
- /* Mismatch bit set if less power offered than the operating power */
- if (uw < (1000 * PD_OPERATING_POWER_MW))
- flags |= RDO_CAP_MISMATCH;
-
-#ifdef CONFIG_USB_PD_GIVE_BACK
- /* Tell source we are give back capable. */
- flags |= RDO_GIVE_BACK;
-
- /*
- * BATTERY PDO: Inform the source that the sink will reduce
- * power to this minimum level on receipt of a GotoMin Request.
- */
- max_or_min_mw = PD_MIN_POWER_MW;
-
- /*
- * FIXED or VARIABLE PDO: Inform the source that the sink will
- * reduce current to this minimum level on receipt of a GotoMin
- * Request.
- */
- max_or_min_ma = PD_MIN_CURRENT_MA;
-#else
- /*
- * Can't give back, so set maximum current and power to
- * operating level.
- */
- max_or_min_ma = *ma;
- max_or_min_mw = uw / 1000;
-#endif
-
- if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) {
- int mw = uw / 1000;
- *rdo = RDO_BATT(pdo_index + 1, mw, max_or_min_mw, flags);
- } else {
- *rdo = RDO_FIXED(pdo_index + 1, *ma, max_or_min_ma, flags);
- }
-}
-#endif
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-void notify_sysjump_ready(volatile const task_id_t * const sysjump_task_waiting)
-{
- /*
- * If event was set from pd_prepare_sysjump, wake the
- * task waiting on us to complete.
- */
- if (*sysjump_task_waiting != TASK_ID_INVALID)
- task_set_event(*sysjump_task_waiting,
- TASK_EVENT_SYSJUMP_READY, 0);
-}
-#endif
-
-__attribute__((weak)) uint8_t board_get_usb_pd_port_count(void)
-{
- return CONFIG_USB_PD_PORT_MAX_COUNT;
-}
-
-enum pd_drp_next_states drp_auto_toggle_next_state(
- uint64_t *drp_sink_time,
- enum pd_power_role power_role,
- enum pd_dual_role_states drp_state,
- enum tcpc_cc_voltage_status cc1,
- enum tcpc_cc_voltage_status cc2)
-{
- /* Set to appropriate port state */
- if (cc_is_open(cc1, cc2)) {
- /*
- * If nothing is attached then use drp_state to determine next
- * state. If DRP auto toggle is still on, then remain in the
- * DRP_AUTO_TOGGLE state. Otherwise, stop dual role toggling
- * and go to a disconnected state.
- */
- switch (drp_state) {
- case PD_DRP_TOGGLE_OFF:
- return DRP_TC_DEFAULT;
- case PD_DRP_FREEZE:
- if (power_role == PD_ROLE_SINK)
- return DRP_TC_UNATTACHED_SNK;
- else
- return DRP_TC_UNATTACHED_SRC;
- case PD_DRP_FORCE_SINK:
- return DRP_TC_UNATTACHED_SNK;
- case PD_DRP_FORCE_SOURCE:
- return DRP_TC_UNATTACHED_SRC;
- case PD_DRP_TOGGLE_ON:
- default:
- return DRP_TC_DRP_AUTO_TOGGLE;
- }
- } else if ((cc_is_rp(cc1) || cc_is_rp(cc2)) &&
- drp_state != PD_DRP_FORCE_SOURCE) {
- /* SNK allowed unless ForceSRC */
- return DRP_TC_UNATTACHED_SNK;
- } else if (cc_is_at_least_one_rd(cc1, cc2) ||
- cc_is_audio_acc(cc1, cc2)) {
- /*
- * SRC allowed unless ForceSNK or Toggle Off
- *
- * Ideally we wouldn't use auto-toggle when drp_state is
- * TOGGLE_OFF/FORCE_SINK, but for some TCPCs, auto-toggle can't
- * be prevented in low power mode. Try being a sink in case the
- * connected device is dual-role (this ensures reliable charging
- * from a hub, b/72007056). 100 ms is enough time for a
- * dual-role partner to switch from sink to source. If the
- * connected device is sink-only, then we will attempt
- * TC_UNATTACHED_SNK twice (due to debounce time), then return
- * to low power mode (and stay there). After 200 ms, reset
- * ready for a new connection.
- */
- if (drp_state == PD_DRP_TOGGLE_OFF ||
- drp_state == PD_DRP_FORCE_SINK) {
- if (get_time().val > *drp_sink_time + 200*MSEC)
- *drp_sink_time = get_time().val;
- if (get_time().val < *drp_sink_time + 100*MSEC)
- return DRP_TC_UNATTACHED_SNK;
- else
- return DRP_TC_DRP_AUTO_TOGGLE;
- } else {
- return DRP_TC_UNATTACHED_SRC;
- }
- } else {
- /* Anything else, keep toggling */
- return DRP_TC_DRP_AUTO_TOGGLE;
- }
-}
diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c
deleted file mode 100644
index 2a843b97d0..0000000000
--- a/common/usb_pd_policy.c
+++ /dev/null
@@ -1,1158 +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 "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.h"
-#include "timer.h"
-#include "util.h"
-#include "usb_api.h"
-#include "usb_common.h"
-#include "usb_pd.h"
-#include "usbc_ppc.h"
-#include "version.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
-
-static int rw_flash_changed = 1;
-
-#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);
-
-void pd_notify_dp_alt_mode_entry(void)
-{
- CPRINTS("Notifying AP of DP Alt Mode Entry...");
- mkbp_send_event(EC_MKBP_EVENT_DP_ALT_MODE_ENTERED);
-}
-#endif /* CONFIG_MKBP_EVENT */
-
-int pd_check_requested_voltage(uint32_t rdo, const int port)
-{
- int max_ma = rdo & 0x3FF;
- int op_ma = (rdo >> 10) & 0x3FF;
- int idx = RDO_POS(rdo);
- uint32_t pdo;
- uint32_t pdo_ma;
-#if defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \
- defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT)
- const uint32_t *src_pdo;
- const int pdo_cnt = charge_manager_get_source_pdo(&src_pdo, port);
-#else
- const uint32_t *src_pdo = pd_src_pdo;
- const int pdo_cnt = pd_src_pdo_cnt;
-#endif
-
- /* Board specific check for this request */
- if (pd_board_check_request(rdo, pdo_cnt))
- return EC_ERROR_INVAL;
-
- /* check current ... */
- pdo = src_pdo[idx - 1];
- pdo_ma = (pdo & 0x3ff);
- if (op_ma > pdo_ma)
- return EC_ERROR_INVAL; /* too much op current */
- if (max_ma > pdo_ma && !(rdo & RDO_CAP_MISMATCH))
- return EC_ERROR_INVAL; /* too much max current */
-
- CPRINTF("Requested %d mV %d mA (for %d/%d mA)\n",
- ((pdo >> 10) & 0x3ff) * 50, (pdo & 0x3ff) * 10,
- op_ma * 10, max_ma * 10);
-
- /* Accept the requested voltage */
- return EC_SUCCESS;
-}
-
-__attribute__((weak)) int pd_board_check_request(uint32_t rdo, int pdo_cnt)
-{
- int idx = RDO_POS(rdo);
-
- /* Check for invalid index */
- return (!idx || idx > pdo_cnt) ?
- EC_ERROR_INVAL : EC_SUCCESS;
-}
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-/* 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];
-
-/* Cap on the max voltage requested as a sink (in millivolts) */
-static unsigned max_request_mv = PD_MAX_VOLTAGE_MV; /* no cap */
-
-const uint32_t * const pd_get_src_caps(int port)
-{
- ASSERT(port < CONFIG_USB_PD_PORT_MAX_COUNT);
-
- return pd_src_caps[port];
-}
-
-uint8_t pd_get_src_cap_cnt(int port)
-{
- ASSERT(port < CONFIG_USB_PD_PORT_MAX_COUNT);
-
- return pd_src_cap_cnt[port];
-}
-
-void pd_process_source_cap(int port, int cnt, uint32_t *src_caps)
-{
-#ifdef CONFIG_CHARGE_MANAGER
- uint32_t ma, mv, pdo;
-#endif
- int i;
-
- pd_src_cap_cnt[port] = cnt;
- for (i = 0; i < cnt; i++)
- pd_src_caps[port][i] = *src_caps++;
-
-#ifdef CONFIG_CHARGE_MANAGER
- /* Get max power info that we could request */
- pd_find_pdo_index(pd_get_src_cap_cnt(port), pd_get_src_caps(port),
- PD_MAX_VOLTAGE_MV, &pdo);
- pd_extract_pdo_power(pdo, &ma, &mv);
-
- /* Set max. limit, but apply 500mA ceiling */
- charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, PD_MIN_MA);
- pd_set_input_current_limit(port, ma, mv);
-#endif
-}
-
-void pd_set_max_voltage(unsigned mv)
-{
- max_request_mv = mv;
-}
-
-unsigned pd_get_max_voltage(void)
-{
- return max_request_mv;
-}
-
-int pd_charge_from_device(uint16_t vid, uint16_t pid)
-{
- /* TODO: rewrite into table if we get more of these */
- /*
- * Allow-list Apple charge-through accessory since it doesn't set
- * externally powered bit, but we still need to charge from it when
- * we are a sink.
- */
- return (vid == USB_VID_APPLE && (pid == 0x1012 || pid == 0x1013));
-}
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
-
-static struct pd_cable cable[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-static uint8_t is_transmit_msg_sop_prime(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP))
- return !!(cable[port].flags & CABLE_FLAGS_SOP_PRIME_ENABLE);
-
- return 0;
-}
-
-uint8_t is_sop_prime_ready(int port, uint8_t data_role, uint32_t pd_flags)
-{
- /*
- * 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
- */
- if (pd_flags & PD_FLAGS_VCONN_ON && (IS_ENABLED(CONFIG_USB_PD_REV30) ||
- data_role == PD_ROLE_DFP))
- return is_transmit_msg_sop_prime(port);
-
- return 0;
-}
-
-void reset_pd_cable(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP))
- memset(&cable[port], 0, sizeof(cable[port]));
-}
-
-enum idh_ptype get_usb_pd_mux_cable_type(int port)
-{
- return cable[port].type;
-}
-
-#ifdef CONFIG_USB_PD_ALT_MODE
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-
-static struct pd_policy pe[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-static int is_vdo_present(int cnt, int index)
-{
- return cnt > index;
-}
-
-static void enable_transmit_sop_prime(int port)
-{
- cable[port].flags |= CABLE_FLAGS_SOP_PRIME_ENABLE;
-}
-
-static void disable_transmit_sop_prime(int port)
-{
- cable[port].flags &= ~CABLE_FLAGS_SOP_PRIME_ENABLE;
-}
-
-void pd_dfp_pe_init(int port)
-{
- memset(&pe[port], 0, sizeof(struct pd_policy));
-}
-
-static void dfp_consume_identity(int port, int cnt, uint32_t *payload)
-{
- int ptype = PD_IDH_PTYPE(payload[VDO_I(IDH)]);
- size_t identity_size = MIN(sizeof(pe[port].identity),
- (cnt - 1) * sizeof(uint32_t));
- pd_dfp_pe_init(port);
- memcpy(&pe[port].identity, payload + 1, identity_size);
- switch (ptype) {
- case IDH_PTYPE_AMA:
-/* Leave vbus ON if the following macro is false */
-#if defined(CONFIG_USB_PD_DUAL_ROLE) && defined(CONFIG_USBC_VCONN_SWAP)
- /* Adapter is requesting vconn, try to supply it */
- if (PD_VDO_AMA_VCONN_REQ(payload[VDO_I(AMA)]))
- pd_try_vconn_src(port);
-
- /* Only disable vbus if vconn was requested */
- if (PD_VDO_AMA_VCONN_REQ(payload[VDO_I(AMA)]) &&
- !PD_VDO_AMA_VBUS_REQ(payload[VDO_I(AMA)]))
- pd_power_supply_reset(port);
-#endif
- break;
- default:
- break;
- }
-}
-
-static void dfp_consume_cable_response(int port, int cnt, uint32_t *payload)
-{
- if (cable[port].is_identified)
- return;
-
- if (is_vdo_present(cnt, VDO_INDEX_IDH)) {
- cable[port].type = PD_IDH_PTYPE(payload[VDO_INDEX_IDH]);
- if (is_vdo_present(cnt, VDO_INDEX_PTYPE_CABLE1))
- cable[port].attr.raw_value =
- payload[VDO_INDEX_PTYPE_CABLE1];
- }
- /*
- * Ref USB PD Spec 3.0 Pg 145. For active cable there are two VDOs.
- * Hence storing the second VDO.
- */
- if (IS_ENABLED(CONFIG_USB_PD_REV30) &&
- is_vdo_present(cnt, VDO_INDEX_PTYPE_CABLE2) &&
- cable[port].type == IDH_PTYPE_ACABLE) {
- cable[port].rev = PD_REV30;
- cable[port].attr2.raw_value = payload[VDO_INDEX_PTYPE_CABLE2];
- }
- cable[port].is_identified = 1;
-}
-
-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;
-}
-
-static void dfp_consume_svids(int port, int cnt, uint32_t *payload)
-{
- int i;
- uint32_t *ptr = payload + 1;
- int vdo = 1;
- uint16_t svid0, svid1;
-
- for (i = pe[port].svid_cnt; i < pe[port].svid_cnt + 12; i += 2) {
- if (i == SVID_DISCOVERY_MAX) {
- CPRINTF("ERR:SVIDCNT\n");
- break;
- }
- /*
- * Verify we're still within the valid packet (count will be one
- * for the VDM header + xVDOs)
- */
- if (vdo >= cnt)
- break;
-
- svid0 = PD_VDO_SVID_SVID0(*ptr);
- if (!svid0)
- break;
- pe[port].svids[i].svid = svid0;
- pe[port].svid_cnt++;
-
- svid1 = PD_VDO_SVID_SVID1(*ptr);
- if (!svid1)
- break;
- pe[port].svids[i + 1].svid = svid1;
- pe[port].svid_cnt++;
- ptr++;
- vdo++;
- }
- /* TODO(tbroch) need to re-issue discover svids if > 12 */
- if (i && ((i % 12) == 0))
- CPRINTF("ERR:SVID+12\n");
-}
-
-static int dfp_discover_modes(int port, uint32_t *payload)
-{
- uint16_t svid = pe[port].svids[pe[port].svid_idx].svid;
- if (pe[port].svid_idx >= pe[port].svid_cnt)
- return 0;
- payload[0] = VDO(svid, 1, CMD_DISCOVER_MODES);
- return 1;
-}
-
-static void dfp_consume_modes(int port, int cnt, uint32_t *payload)
-{
- int idx = pe[port].svid_idx;
- pe[port].svids[idx].mode_cnt = cnt - 1;
- if (pe[port].svids[idx].mode_cnt < 0) {
- CPRINTF("ERR:NOMODE\n");
- } else {
- memcpy(pe[port].svids[pe[port].svid_idx].mode_vdo, &payload[1],
- sizeof(uint32_t) * pe[port].svids[idx].mode_cnt);
- }
-
- pe[port].svid_idx++;
-}
-
-static int get_mode_idx(int port, uint16_t svid)
-{
- int i;
-
- for (i = 0; i < PD_AMODE_COUNT; i++) {
- if (pe[port].amodes[i].fx->svid == svid)
- return i;
- }
- return -1;
-}
-
-static struct svdm_amode_data *get_modep(int port, uint16_t svid)
-{
- int idx = get_mode_idx(port, svid);
-
- return (idx == -1) ? NULL : &pe[port].amodes[idx];
-}
-
-int pd_alt_mode(int port, uint16_t svid)
-{
- struct svdm_amode_data *modep = get_modep(port, svid);
-
- return (modep) ? modep->opos : -1;
-}
-
-int allocate_mode(int port, uint16_t svid)
-{
- int i, j;
- struct svdm_amode_data *modep;
- int mode_idx = get_mode_idx(port, svid);
-
- if (mode_idx != -1)
- return mode_idx;
-
- /* There's no space to enter another mode */
- if (pe[port].amode_idx == PD_AMODE_COUNT) {
- CPRINTF("ERR:NO AMODE SPACE\n");
- return -1;
- }
-
- /* Allocate ... if SVID == 0 enter default supported policy */
- for (i = 0; i < supported_modes_cnt; i++) {
- for (j = 0; j < pe[port].svid_cnt; j++) {
- struct svdm_svid_data *svidp = &pe[port].svids[j];
- if ((svidp->svid != supported_modes[i].svid) ||
- (svid && (svidp->svid != svid)))
- continue;
-
- modep = &pe[port].amodes[pe[port].amode_idx];
- modep->fx = &supported_modes[i];
- modep->data = &pe[port].svids[j];
- pe[port].amode_idx++;
- return pe[port].amode_idx - 1;
- }
- }
- return -1;
-}
-
-/*
- * Enter default mode ( payload[0] == 0 ) or attempt to enter mode via svid &
- * opos
-*/
-uint32_t pd_dfp_enter_mode(int port, uint16_t svid, int opos)
-{
- int mode_idx = allocate_mode(port, svid);
- struct svdm_amode_data *modep;
- uint32_t mode_caps;
-
- if (mode_idx == -1)
- return 0;
- modep = &pe[port].amodes[mode_idx];
-
- if (!opos) {
- /* choose the lowest as default */
- modep->opos = 1;
- } else if (opos <= modep->data->mode_cnt) {
- modep->opos = opos;
- } else {
- CPRINTF("opos error\n");
- return 0;
- }
-
- mode_caps = modep->data->mode_vdo[modep->opos - 1];
- if (modep->fx->enter(port, mode_caps) == -1)
- return 0;
-
- /* SVDM to send to UFP for mode entry */
- return VDO(modep->fx->svid, 1, CMD_ENTER_MODE | VDO_OPOS(modep->opos));
-}
-
-static int validate_mode_request(struct svdm_amode_data *modep,
- uint16_t svid, int opos)
-{
- if (!modep->fx)
- return 0;
-
- if (svid != modep->fx->svid) {
- CPRINTF("ERR:svid r:0x%04x != c:0x%04x\n",
- svid, modep->fx->svid);
- return 0;
- }
-
- if (opos != modep->opos) {
- CPRINTF("ERR:opos r:%d != c:%d\n",
- opos, modep->opos);
- return 0;
- }
-
- return 1;
-}
-
-static void dfp_consume_attention(int port, uint32_t *payload)
-{
- uint16_t svid = PD_VDO_VID(payload[0]);
- int opos = PD_VDO_OPOS(payload[0]);
- struct svdm_amode_data *modep = get_modep(port, svid);
-
- if (!modep || !validate_mode_request(modep, svid, opos))
- return;
-
- if (modep->fx->attention)
- modep->fx->attention(port, payload);
-}
-
-/*
- * This algorithm defaults to choosing higher pin config over lower ones in
- * order to prefer multi-function if desired.
- *
- * NAME | SIGNALING | OUTPUT TYPE | MULTI-FUNCTION | PIN CONFIG
- * -------------------------------------------------------------
- * A | USB G2 | ? | no | 00_0001
- * B | USB G2 | ? | yes | 00_0010
- * C | DP | CONVERTED | no | 00_0100
- * D | PD | CONVERTED | yes | 00_1000
- * E | DP | DP | no | 01_0000
- * F | PD | DP | yes | 10_0000
- *
- * if UFP has NOT asserted multi-function preferred code masks away B/D/F
- * leaving only A/C/E. For single-output dongles that should leave only one
- * possible pin config depending on whether its a converter DP->(VGA|HDMI) or DP
- * output. If UFP is a USB-C receptacle it may assert C/D/E/F. The DFP USB-C
- * receptacle must always choose C/D in those cases.
- */
-int pd_dfp_dp_get_pin_mode(int port, uint32_t status)
-{
- struct svdm_amode_data *modep = get_modep(port, USB_SID_DISPLAYPORT);
- uint32_t mode_caps;
- uint32_t pin_caps;
- if (!modep)
- return 0;
-
- mode_caps = modep->data->mode_vdo[modep->opos - 1];
-
- /* TODO(crosbug.com/p/39656) revisit with DFP that can be a sink */
- pin_caps = PD_DP_PIN_CAPS(mode_caps);
-
- /* if don't want multi-function then ignore those pin configs */
- if (!PD_VDO_DPSTS_MF_PREF(status))
- pin_caps &= ~MODE_DP_PIN_MF_MASK;
-
- /* TODO(crosbug.com/p/39656) revisit if DFP drives USB Gen 2 signals */
- pin_caps &= ~MODE_DP_PIN_BR2_MASK;
-
- /* if C/D present they have precedence over E/F for USB-C->USB-C */
- if (pin_caps & (MODE_DP_PIN_C | MODE_DP_PIN_D))
- pin_caps &= ~(MODE_DP_PIN_E | MODE_DP_PIN_F);
-
- /* get_next_bit returns undefined for zero */
- if (!pin_caps)
- return 0;
-
- return 1 << get_next_bit(&pin_caps);
-}
-
-int pd_dfp_exit_mode(int port, uint16_t svid, int opos)
-{
- struct svdm_amode_data *modep;
- int idx;
-
- /*
- * Empty svid signals we should reset DFP VDM state by exiting all
- * entered modes then clearing state. This occurs when we've
- * disconnected or for hard reset.
- */
- if (!svid) {
- for (idx = 0; idx < PD_AMODE_COUNT; idx++)
- if (pe[port].amodes[idx].fx)
- pe[port].amodes[idx].fx->exit(port);
-
- pd_dfp_pe_init(port);
- return 0;
- }
-
- /*
- * TODO(crosbug.com/p/33946) : below needs revisited to allow multiple
- * mode exit. Additionally it should honor OPOS == 7 as DFP's request
- * to exit all modes. We currently don't have any UFPs that support
- * multiple modes on one SVID.
- */
- modep = get_modep(port, svid);
- if (!modep || !validate_mode_request(modep, svid, opos))
- return 0;
-
- /* call DFPs exit function */
- modep->fx->exit(port);
- /* exit the mode */
- modep->opos = 0;
- return 1;
-}
-
-uint16_t pd_get_identity_vid(int port)
-{
- return PD_IDH_VID(pe[port].identity[0]);
-}
-
-uint16_t pd_get_identity_pid(int port)
-{
- return PD_PRODUCT_PID(pe[port].identity[2]);
-}
-
-#ifdef CONFIG_CMD_USB_PD_PE
-static void dump_pe(int port)
-{
- const char * const idh_ptype_names[] = {
- "UNDEF", "Hub", "Periph", "PCable", "ACable", "AMA",
- "RSV6", "RSV7"};
-
- int i, j, idh_ptype;
- struct svdm_amode_data *modep;
- uint32_t mode_caps;
-
- if (pe[port].identity[0] == 0) {
- ccprintf("No identity discovered yet.\n");
- return;
- }
- idh_ptype = PD_IDH_PTYPE(pe[port].identity[0]);
- ccprintf("IDENT:\n");
- ccprintf("\t[ID Header] %08x :: %s, VID:%04x\n", pe[port].identity[0],
- idh_ptype_names[idh_ptype], pd_get_identity_vid(port));
- ccprintf("\t[Cert Stat] %08x\n", pe[port].identity[1]);
- for (i = 2; i < ARRAY_SIZE(pe[port].identity); i++) {
- ccprintf("\t");
- if (pe[port].identity[i])
- ccprintf("[%d] %08x ", i, pe[port].identity[i]);
- }
- ccprintf("\n");
-
- if (pe[port].svid_cnt < 1) {
- ccprintf("No SVIDS discovered yet.\n");
- return;
- }
-
- for (i = 0; i < pe[port].svid_cnt; i++) {
- ccprintf("SVID[%d]: %04x MODES:", i, pe[port].svids[i].svid);
- for (j = 0; j < pe[port].svids[j].mode_cnt; j++)
- ccprintf(" [%d] %08x", j + 1,
- pe[port].svids[i].mode_vdo[j]);
- ccprintf("\n");
- modep = get_modep(port, pe[port].svids[i].svid);
- if (modep) {
- mode_caps = modep->data->mode_vdo[modep->opos - 1];
- ccprintf("MODE[%d]: svid:%04x caps:%08x\n", modep->opos,
- modep->fx->svid, mode_caps);
- }
- }
-}
-
-static int command_pe(int argc, char **argv)
-{
- int port;
- char *e;
- if (argc < 3)
- return EC_ERROR_PARAM_COUNT;
- /* command: pe <port> <subcmd> <args> */
- port = strtoi(argv[1], &e, 10);
- if (*e || port >= board_get_usb_pd_port_count())
- return EC_ERROR_PARAM2;
- if (!strncasecmp(argv[2], "dump", 4))
- dump_pe(port);
-
- return EC_SUCCESS;
-}
-
-DECLARE_CONSOLE_COMMAND(pe, command_pe,
- "<port> dump",
- "USB PE");
-#endif /* CONFIG_CMD_USB_PD_PE */
-
-#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
-
-int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
-{
- 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 */
-
- 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));
- } else if (cmd_type == CMDT_RSP_ACK) {
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- struct svdm_amode_data *modep;
-
- modep = get_modep(port, PD_VDO_VID(payload[0]));
-#endif
- switch (cmd) {
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- case CMD_DISCOVER_IDENT:
- /* Received a SOP Prime Discover Ident msg */
- if (is_transmit_msg_sop_prime(port)) {
- /* Store cable type */
- dfp_consume_cable_response(port, cnt, payload);
- disable_transmit_sop_prime(port);
- rsize = dfp_discover_svids(payload);
- /* Received a SOP Discover Ident Message */
- } else if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) {
- dfp_consume_identity(port, cnt, payload);
- /* Send SOP' Discover Ident message */
- if (!cable[port].is_identified) {
- rsize = dfp_discover_ident(payload);
- enable_transmit_sop_prime(port);
- }
- } else {
- dfp_consume_identity(port, cnt, payload);
- rsize = dfp_discover_svids(payload);
- }
-#ifdef CONFIG_CHARGE_MANAGER
- if (pd_charge_from_device(pd_get_identity_vid(port),
- pd_get_identity_pid(port)))
- charge_manager_update_dualrole(port,
- CAP_DEDICATED);
-#endif
- break;
- case CMD_DISCOVER_SVID:
- dfp_consume_svids(port, cnt, payload);
- rsize = dfp_discover_modes(port, payload);
- break;
- case CMD_DISCOVER_MODES:
- dfp_consume_modes(port, cnt, payload);
- rsize = dfp_discover_modes(port, payload);
- /* enter the default mode for DFP */
- if (!rsize) {
- payload[0] = pd_dfp_enter_mode(port, 0, 0);
- if (payload[0])
- rsize = 1;
- }
- break;
- case CMD_ENTER_MODE:
- if (!modep) {
- rsize = 0;
- } else {
- if (!modep->opos)
- pd_dfp_enter_mode(port, 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));
-#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) {
- rsize = 0;
- /* Send SOP' Discover Ident message, if not already received. */
- if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP) &&
- !cable[port].is_identified && (cmd == CMD_DISCOVER_IDENT)) {
- rsize = dfp_discover_ident(payload);
- enable_transmit_sop_prime(port);
- }
-#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)
-{
- return 0;
-}
-
-#endif /* CONFIG_USB_PD_ALT_MODE */
-
-#ifdef CONFIG_CMD_USB_PD_CABLE
-static const char * const cable_type[] = {
- [IDH_PTYPE_PCABLE] = "Passive",
- [IDH_PTYPE_ACABLE] = "Active",
-};
-
-static const char * const cable_curr[] = {
- [CABLE_CURRENT_3A] = "3A",
- [CABLE_CURRENT_5A] = "5A",
-};
-
-static const char * const cable_ss_support[] = {
- [USB_SS_U2_ONLY] = "Not supported",
- [USB_SS_U31_GEN1] = "Gen 1",
- [USB_SS_U31_GEN2] = "Gen 1 and Gen 2",
-};
-
-static const char * const vbus_max[] = {
- [CABLE_VBUS_20V] = "20V",
- [CABLE_VBUS_30V] = "30V",
- [CABLE_VBUS_40V] = "40V",
- [CABLE_VBUS_50V] = "50V",
-};
-static const char * const conn_type[] = {
- [CONNECTOR_ATYPE] = "Type A",
- [CONNECTOR_BTYPE] = "Type B",
- [CONNECTOR_CTYPE] = "Type C",
- [CONNECTOR_CAPTIVE] = "Captive",
-};
-
-static int command_cable(int argc, char **argv)
-{
- int port;
- char *e;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
- port = strtoi(argv[1], &e, 0);
- if (*e || port >= board_get_usb_pd_port_count())
- return EC_ERROR_PARAM2;
-
- if (!cable[port].is_identified) {
- ccprintf("Cable not identified.\n");
- return EC_SUCCESS;
- }
-
- ccprintf("Cable Type: ");
- if (cable[port].type != IDH_PTYPE_PCABLE &&
- cable[port].type != IDH_PTYPE_ACABLE) {
- ccprintf("Not Emark Cable\n");
- return EC_SUCCESS;
- }
- ccprintf("%s\n", cable_type[cable[port].type]);
-
- /*
- * For rev 2.0, rev 3.0 active and passive cables have same bits for
- * connector type (Bit 19:18) and current handling capability bit 6:5
- */
- ccprintf("Connector Type: %s\n",
- cable[port].attr.rev20.connector > ARRAY_SIZE(conn_type) ?
- "Invalid" : conn_type[cable[port].attr.rev20.connector]);
-
- if (cable[port].attr.rev20.current) {
- ccprintf("Cable Current: %s\n",
- cable[port].attr.rev20.current > ARRAY_SIZE(cable_curr) ?
- "Invalid" : cable_curr[cable[port].attr.rev20.current]);
- } else
- ccprintf("Cable Current: Invalid\n");
-
- /*
- * For Rev 3.0 passive cables and Rev 2.0 active and passive cables,
- * USB Superspeed Signaling support have same bits 2:0
- */
- if (cable[port].type == IDH_PTYPE_PCABLE) {
- ccprintf("USB Superspeed Signaling support: %s\n",
- cable[port].attr.rev20.ss >
- ARRAY_SIZE(cable_ss_support) ? "Invalid" :
- cable_ss_support[cable[port].attr.p_rev30.ss]);
- }
-
- /*
- * For Rev 3.0 active cables and Rev 2.0 active and passive cables,
- * SOP" controller preset have same bit 3
- */
- if (cable[port].type == IDH_PTYPE_ACABLE) {
- ccprintf("SOP' ' Controller: %s present\n",
- cable[port].attr.rev20.controller ? "" : "Not");
- }
-
- if (cable[port].rev == PD_REV30) {
- /*
- * For Rev 3.0 active and passive cables, Max Vbus vtg have
- * same bits 10:9.
- */
- ccprintf("Max vbus voltage: %s\n",
- cable[port].attr.p_rev30.vbus_max >
- ARRAY_SIZE(vbus_max) ? "Invaild" :
- vbus_max[cable[port].attr.p_rev30.vbus_max]);
-
- /* For Rev 3.0 Active cables */
- if (cable[port].type == IDH_PTYPE_ACABLE) {
- ccprintf("SS signaling: USB_SS_GEN%u\n",
- cable[port].attr2.a2_rev30.sss ? 2 : 1);
- ccprintf("Number of SS lanes supported: %u\n",
- cable[port].attr2.a2_rev30.lanes);
- }
- }
- return EC_SUCCESS;
-}
-
-DECLARE_CONSOLE_COMMAND(pdcable, command_cable,
- "<port>",
- "Cable Characteristics");
-#endif /* CONFIG_CMD_USB_PD_CABLE */
-
-static void pd_usb_billboard_deferred(void)
-{
-#if defined(CONFIG_USB_PD_ALT_MODE) && !defined(CONFIG_USB_PD_ALT_MODE_DFP) \
- && !defined(CONFIG_USB_PD_SIMPLE_DFP) && defined(CONFIG_USB_BOS)
-
- /*
- * TODO(tbroch)
- * 1. Will we have multiple type-C port UFPs
- * 2. Will there be other modes applicable to DFPs besides DP
- */
- if (!pd_alt_mode(0, USB_SID_DISPLAYPORT))
- usb_connect();
-
-#endif
-}
-DECLARE_DEFERRED(pd_usb_billboard_deferred);
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-static enum ec_status hc_remote_pd_discovery(struct host_cmd_handler_args *args)
-{
- const uint8_t *port = args->params;
- struct ec_params_usb_pd_discovery_entry *r = args->response;
-
- if (*port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- r->vid = pd_get_identity_vid(*port);
- r->ptype = PD_IDH_PTYPE(pe[*port].identity[0]);
- /* pid only included if vid is assigned */
- if (r->vid)
- r->pid = PD_PRODUCT_PID(pe[*port].identity[2]);
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_DISCOVERY,
- hc_remote_pd_discovery,
- EC_VER_MASK(0));
-
-static enum ec_status hc_remote_pd_get_amode(struct host_cmd_handler_args *args)
-{
- struct svdm_amode_data *modep;
- const struct ec_params_usb_pd_get_mode_request *p = args->params;
- struct ec_params_usb_pd_get_mode_response *r = args->response;
-
- if (p->port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- /* no more to send */
- if (p->svid_idx >= pe[p->port].svid_cnt) {
- r->svid = 0;
- args->response_size = sizeof(r->svid);
- return EC_RES_SUCCESS;
- }
-
- r->svid = pe[p->port].svids[p->svid_idx].svid;
- r->opos = 0;
- memcpy(r->vdo, pe[p->port].svids[p->svid_idx].mode_vdo, 24);
- modep = get_modep(p->port, r->svid);
-
- if (modep)
- r->opos = pd_alt_mode(p->port, r->svid);
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_GET_AMODE,
- hc_remote_pd_get_amode,
- EC_VER_MASK(0));
-
-#endif
-
-#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() != SYSTEM_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() != SYSTEM_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;
- 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() != SYSTEM_IMAGE_RO) ||
- (flash_offset < CONFIG_EC_WRITABLE_STORAGE_OFF +
- CONFIG_RW_STORAGE_OFF))
- break;
- 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)
- flash_physical_write(offset, 4,
- (const char *)&zero);
- }
- break;
- default:
- /* Unknown : do not answer */
- return 0;
- }
- return rsize;
-}
-
-#ifdef CONFIG_USB_PD_DISCHARGE
-void pd_set_vbus_discharge(int port, int enable)
-{
- static struct mutex discharge_lock[CONFIG_USB_PD_PORT_MAX_COUNT];
-
- mutex_lock(&discharge_lock[port]);
- enable &= !board_vbus_source_enabled(port);
-#ifdef CONFIG_USB_PD_DISCHARGE_GPIO
- if (!port)
- gpio_set_level(GPIO_USB_C0_DISCHARGE, enable);
-#if CONFIG_USB_PD_PORT_MAX_COUNT > 1
- else
- gpio_set_level(GPIO_USB_C1_DISCHARGE, enable);
-#endif /* CONFIG_USB_PD_PORT_MAX_COUNT */
-#elif defined(CONFIG_USB_PD_DISCHARGE_TCPC)
- tcpc_discharge_vbus(port, enable);
-#elif defined(CONFIG_USB_PD_DISCHARGE_PPC)
- ppc_discharge_vbus(port, enable);
-#else
-#error "PD discharge implementation not defined"
-#endif
- mutex_unlock(&discharge_lock[port]);
-}
-#endif /* CONFIG_USB_PD_DISCHARGE */
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
deleted file mode 100644
index 8303f9de62..0000000000
--- a/common/usb_pd_protocol.c
+++ /dev/null
@@ -1,5761 +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 "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 "ec_commands.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "registers.h"
-#include "system.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-#include "usb_charge.h"
-#include "usb_common.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
-#include "usb_pd_tcpc.h"
-#include "usbc_ppc.h"
-#include "tcpm.h"
-#include "version.h"
-#include "vboot.h"
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-
-BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT <= EC_USB_PD_MAX_PORTS);
-
-/*
- * If we are trying to upgrade the TCPC port that is supplying power, then we
- * need to ensure that the battery has enough charge for the upgrade. 100mAh
- * is about 5% of most batteries, and it should be enough charge to get us
- * through the EC jump to RW and PD upgrade.
- */
-#define MIN_BATTERY_FOR_TCPC_UPGRADE_MAH 100 /* mAH */
-
-/*
- * Debug log level - higher number == more log
- * Level 0: Log state transitions
- * Level 1: Level 0, plus state name
- * Level 2: Level 1, plus packet info
- * Level 3: Level 2, plus ping packet and packet dump on error
- *
- * Note that higher log level causes timing changes and thus may affect
- * performance.
- *
- * Can be limited to constant debug_level by CONFIG_USB_PD_DEBUG_LEVEL
- */
-#ifdef CONFIG_USB_PD_DEBUG_LEVEL
-static const int debug_level = CONFIG_USB_PD_DEBUG_LEVEL;
-#else
-static int debug_level;
-#endif
-
-/*
- * PD communication enabled flag. When false, PD state machine still
- * detects source/sink connection and disconnection, and will still
- * provide VBUS, but never sends any PD communication.
- */
-static uint8_t pd_comm_enabled[CONFIG_USB_PD_PORT_MAX_COUNT];
-#else /* CONFIG_COMMON_RUNTIME */
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-static const int debug_level;
-#endif
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-#define DUAL_ROLE_IF_ELSE(port, sink_clause, src_clause) \
- (pd[port].power_role == PD_ROLE_SINK ? (sink_clause) : (src_clause))
-#else
-#define DUAL_ROLE_IF_ELSE(port, sink_clause, src_clause) (src_clause)
-#endif
-
-#define READY_RETURN_STATE(port) DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_READY, \
- PD_STATE_SRC_READY)
-
-/* Type C supply voltage (mV) */
-#define TYPE_C_VOLTAGE 5000 /* mV */
-
-/* PD counter definitions */
-#define PD_MESSAGE_ID_COUNT 7
-#define PD_HARD_RESET_COUNT 2
-#define PD_CAPS_COUNT 50
-#define PD_SNK_CAP_RETRIES 3
-
-/*
- * The time that we allow the port partner to send any messages after an
- * explicit contract is established. 200ms was chosen somewhat arbitrarily as
- * it should be long enough for sources to decide to send a message if they were
- * going to, but not so long that a "low power charger connected" notification
- * would be shown in the chrome OS UI.
- */
-#define SNK_READY_HOLD_OFF_US (200 * MSEC)
-/*
- * For the same purpose as SNK_READY_HOLD_OFF_US, but this delay can be longer
- * since the concern over "low power charger" is not relevant when connected as
- * a source and the additional delay avoids a race condition where the partner
- * port sends a power role swap request close to when the VDM discover identity
- * message gets sent.
- */
-#define SRC_READY_HOLD_OFF_US (400 * MSEC)
-
-enum vdm_states {
- VDM_STATE_ERR_BUSY = -3,
- VDM_STATE_ERR_SEND = -2,
- VDM_STATE_ERR_TMOUT = -1,
- VDM_STATE_DONE = 0,
- /* Anything >0 represents an active state */
- VDM_STATE_READY = 1,
- VDM_STATE_BUSY = 2,
- VDM_STATE_WAIT_RSP_BUSY = 3,
-};
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-/* Port dual-role state */
-enum pd_dual_role_states drp_state[CONFIG_USB_PD_PORT_MAX_COUNT] = {
- [0 ... (CONFIG_USB_PD_PORT_MAX_COUNT - 1)] =
- CONFIG_USB_PD_INITIAL_DRP_STATE};
-
-/* Enable variable for Try.SRC states */
-static uint8_t pd_try_src_enable;
-#endif
-
-#ifdef CONFIG_USB_PD_REV30
-/*
- * The spec. revision is used to index into this array.
- * Rev 0 (PD 1.0) - return PD_CTRL_REJECT
- * Rev 1 (PD 2.0) - return PD_CTRL_REJECT
- * Rev 2 (PD 3.0) - return PD_CTRL_NOT_SUPPORTED
- */
-static const uint8_t refuse[] = {
- PD_CTRL_REJECT, PD_CTRL_REJECT, PD_CTRL_NOT_SUPPORTED};
-#define REFUSE(r) refuse[r]
-#else
-#define REFUSE(r) PD_CTRL_REJECT
-#endif
-
-#ifdef CONFIG_USB_PD_REV30
-/*
- * The spec. revision is used to index into this array.
- * Rev 0 (VDO 1.0) - return VDM_VER10
- * Rev 1 (VDO 1.0) - return VDM_VER10
- * Rev 2 (VDO 2.0) - return VDM_VER20
- */
-static const uint8_t vdo_ver[] = {
- VDM_VER10, VDM_VER10, VDM_VER20};
-#define VDO_VER(v) vdo_ver[v]
-#else
-#define VDO_VER(v) VDM_VER10
-#endif
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-/* Tracker for which task is waiting on sysjump prep to finish */
-static volatile task_id_t sysjump_task_waiting = TASK_ID_INVALID;
-#endif
-
-static struct pd_protocol {
- /* current port power role (SOURCE or SINK) */
- uint8_t power_role;
- /* current port data role (DFP or UFP) */
- uint8_t data_role;
- /* 3-bit rolling message ID counter */
- uint8_t msg_id;
- /* Port polarity : 0 => CC1 is CC line, 1 => CC2 is CC line */
- uint8_t polarity;
- /* PD state for port */
- enum pd_states task_state;
- /* PD state when we run state handler the last time */
- enum pd_states last_state;
- /* bool: request state change to SUSPENDED */
- uint8_t req_suspend_state;
- /* The state to go to after timeout */
- enum pd_states timeout_state;
- /* port flags, see PD_FLAGS_* */
- uint32_t flags;
- /* Timeout for the current state. Set to 0 for no timeout. */
- uint64_t timeout;
- /* Time for source recovery after hard reset */
- uint64_t src_recover;
- /* Time for CC debounce end */
- uint64_t cc_debounce;
- /* The cc state */
- enum pd_cc_states cc_state;
- /* status of last transmit */
- uint8_t tx_status;
-
- /* Last received */
- uint8_t last_msg_id;
-
- /* last requested voltage PDO index */
- int requested_idx;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /* Current limit / voltage based on the last request message */
- uint32_t curr_limit;
- uint32_t supply_voltage;
- /* Signal charging update that affects the port */
- int new_power_request;
- /* Store previously requested voltage request */
- int prev_request_mv;
- /* Time for Try.SRC states */
- uint64_t try_src_marker;
- uint64_t try_timeout;
-#endif
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /* Time to enter low power mode */
- uint64_t low_power_time;
- /* Tasks to notify after TCPC has been reset */
- int tasks_waiting_on_reset;
- /* Tasks preventing TCPC from entering low power mode */
- int tasks_preventing_lpm;
-#endif
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- /*
- * Timer for handling TOGGLE_OFF/FORCE_SINK mode when auto-toggle
- * enabled. See drp_auto_toggle_next_state() for details.
- */
- uint64_t drp_sink_time;
-#endif
-
- /*
- * Time to ignore Vbus absence due to external IC debounce detection
- * logic immediately after a power role swap.
- */
- uint64_t vbus_debounce_time;
-
- /* PD state for Vendor Defined Messages */
- enum vdm_states vdm_state;
- /* Timeout for the current vdm state. Set to 0 for no timeout. */
- timestamp_t vdm_timeout;
- /* next Vendor Defined Message to send */
- uint32_t vdo_data[VDO_MAX_SIZE];
- uint8_t vdo_count;
- /* VDO to retry if UFP responder replied busy. */
- uint32_t vdo_retry;
-
- /* Attached ChromeOS device id, RW hash, and current RO / RW image */
- uint16_t dev_id;
- uint32_t dev_rw_hash[PD_RW_HASH_SIZE/4];
- enum ec_current_image current_image;
-#ifdef CONFIG_USB_PD_REV30
- /* PD Collision avoidance buffer */
- uint16_t ca_buffered;
- uint16_t ca_header;
- uint32_t ca_buffer[PDO_MAX_OBJECTS];
- enum tcpm_transmit_type ca_type;
- /* protocol revision */
- uint8_t rev;
-#endif
- /*
- * Some port partners are really chatty after an explicit contract is
- * established. Therefore, we allow this time for the port partner to
- * send any messages in order to avoid a collision of sending messages
- * of our own.
- */
- uint64_t ready_state_holdoff_timer;
- /*
- * PD 2.0 spec, section 6.5.11.1
- * When we can give up on a HARD_RESET transmission.
- */
- uint64_t hard_reset_complete_timer;
-} pd[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-#ifdef CONFIG_COMMON_RUNTIME
-static const char * const pd_state_names[] = {
- "DISABLED", "SUSPENDED",
- "SNK_DISCONNECTED", "SNK_DISCONNECTED_DEBOUNCE",
- "SNK_HARD_RESET_RECOVER",
- "SNK_DISCOVERY", "SNK_REQUESTED", "SNK_TRANSITION", "SNK_READY",
- "SNK_SWAP_INIT", "SNK_SWAP_SNK_DISABLE",
- "SNK_SWAP_SRC_DISABLE", "SNK_SWAP_STANDBY", "SNK_SWAP_COMPLETE",
- "SRC_DISCONNECTED", "SRC_DISCONNECTED_DEBOUNCE",
- "SRC_HARD_RESET_RECOVER", "SRC_STARTUP",
- "SRC_DISCOVERY", "SRC_NEGOCIATE", "SRC_ACCEPTED", "SRC_POWERED",
- "SRC_TRANSITION", "SRC_READY", "SRC_GET_SNK_CAP", "DR_SWAP",
- "SRC_SWAP_INIT", "SRC_SWAP_SNK_DISABLE", "SRC_SWAP_SRC_DISABLE",
- "SRC_SWAP_STANDBY",
- "VCONN_SWAP_SEND", "VCONN_SWAP_INIT", "VCONN_SWAP_READY",
- "SOFT_RESET", "HARD_RESET_SEND", "HARD_RESET_EXECUTE", "BIST_RX",
- "BIST_TX",
- "DRP_AUTO_TOGGLE",
-};
-BUILD_ASSERT(ARRAY_SIZE(pd_state_names) == PD_STATE_COUNT);
-#endif
-
-/*
- * 4 entry rw_hash table of type-C devices that AP has firmware updates for.
- */
-#ifdef CONFIG_COMMON_RUNTIME
-#define RW_HASH_ENTRIES 4
-static struct ec_params_usb_pd_rw_hash_entry rw_hash_table[RW_HASH_ENTRIES];
-#endif
-
-int pd_comm_is_enabled(int port)
-{
-#ifdef CONFIG_COMMON_RUNTIME
- return pd_comm_enabled[port];
-#else
- return 1;
-#endif
-}
-
-static inline void set_state_timeout(int port,
- uint64_t timeout,
- enum pd_states timeout_state)
-{
- pd[port].timeout = timeout;
- pd[port].timeout_state = timeout_state;
-}
-
-#ifdef CONFIG_USB_PD_REV30
-int pd_get_rev(int port)
-{
- return pd[port].rev;
-}
-
-int pd_get_vdo_ver(int port)
-{
- return vdo_ver[pd[port].rev];
-}
-#endif
-
-/* Return flag for pd state is connected */
-int pd_is_connected(int port)
-{
- if (pd[port].task_state == PD_STATE_DISABLED)
- return 0;
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- if (pd[port].task_state == PD_STATE_DRP_AUTO_TOGGLE)
- return 0;
-#endif
-
- return DUAL_ROLE_IF_ELSE(port,
- /* sink */
- pd[port].task_state != PD_STATE_SNK_DISCONNECTED &&
- pd[port].task_state != PD_STATE_SNK_DISCONNECTED_DEBOUNCE,
- /* source */
- pd[port].task_state != PD_STATE_SRC_DISCONNECTED &&
- pd[port].task_state != PD_STATE_SRC_DISCONNECTED_DEBOUNCE);
-}
-
-/*
- * Return true if partner port is a DTS or TS capable of entering debug
- * mode (eg. is presenting Rp/Rp or Rd/Rd).
- */
-int pd_ts_dts_plugged(int port)
-{
- return pd[port].flags & PD_FLAGS_TS_DTS_PARTNER;
-}
-
-/* Return true if partner port is known to be PD capable. */
-int pd_capable(int port)
-{
- return pd[port].flags & PD_FLAGS_PREVIOUS_PD_CONN;
-}
-
-/*
- * Return true if partner port is capable of communication over USB data
- * lines.
- */
-int pd_get_partner_usb_comm_capable(int port)
-{
- return pd[port].flags & PD_FLAGS_PARTNER_USB_COMM;
-}
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-void pd_vbus_low(int port)
-{
- pd[port].flags &= ~PD_FLAGS_VBUS_NEVER_LOW;
-}
-#endif
-
-int pd_is_vbus_present(int port)
-{
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
- return tcpm_get_vbus_level(port);
-#else
- return pd_snk_is_vbus_provided(port);
-#endif
-}
-
-/**
- * This function checks the current CC status of the port partner
- * and returns true if the attached partner is UFP.
- */
-int pd_partner_is_ufp(int port)
-{
- return pd[port].cc_state == PD_CC_UFP_ATTACHED ||
- pd[port].cc_state == PD_CC_UFP_DEBUG_ACC ||
- pd[port].cc_state == PD_CC_UFP_AUDIO_ACC;
-}
-
-int pd_is_debug_acc(int port)
-{
- return pd[port].cc_state == PD_CC_UFP_DEBUG_ACC ||
- pd[port].cc_state == PD_CC_DFP_DEBUG_ACC;
-}
-
-static void set_polarity(int port, int polarity)
-{
- tcpm_set_polarity(port, polarity);
-#ifdef CONFIG_USBC_PPC_POLARITY
- ppc_set_polarity(port, polarity);
-#endif /* defined(CONFIG_USBC_PPC_POLARITY) */
-}
-
-#ifdef CONFIG_USBC_VCONN
-static void set_vconn(int port, int enable)
-{
- /*
- * We always need to tell the TCPC to enable Vconn first, otherwise some
- * TCPCs get confused when a PPC sets secondary CC line to 5V and TCPC
- * immediately disconnect. If there is a PPC, both devices will
- * potentially source Vconn, but that should be okay since Vconn has
- * "make before break" electrical requirements when swapping anyway.
- */
- tcpm_set_vconn(port, enable);
-#ifdef CONFIG_USBC_PPC_VCONN
- ppc_set_vconn(port, enable);
-#endif
-}
-#endif /* defined(CONFIG_USBC_VCONN) */
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
-
-/* 10 ms is enough time for any TCPC transaction to complete. */
-#define PD_LPM_DEBOUNCE_US (10 * MSEC)
-
-/* This is only called from the PD tasks that owns the port. */
-static void handle_device_access(int port)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- pd[port].low_power_time = get_time().val + PD_LPM_DEBOUNCE_US;
- if (pd[port].flags & PD_FLAGS_LPM_ENGAGED) {
- CPRINTS("TCPC p%d Exit Low Power Mode", port);
- pd[port].flags &= ~(PD_FLAGS_LPM_ENGAGED |
- PD_FLAGS_LPM_REQUESTED);
- /*
- * Wake to ensure we make another pass through the main task
- * loop after clearing the flags.
- */
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-static int pd_device_in_low_power(int port)
-{
- /*
- * If we are actively waking the device up in the PD task, do not
- * let TCPC operation wait or retry because we are in low power mode.
- */
- if (port == TASK_ID_TO_PD_PORT(task_get_current()) &&
- (pd[port].flags & PD_FLAGS_LPM_TRANSITION))
- return 0;
-
- return pd[port].flags & PD_FLAGS_LPM_ENGAGED;
-}
-
-static int reset_device_and_notify(int port)
-{
- int rv;
- int task, waiting_tasks;
-
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- pd[port].flags |= PD_FLAGS_LPM_TRANSITION;
- rv = tcpm_init(port);
- pd[port].flags &= ~PD_FLAGS_LPM_TRANSITION;
-
- if (rv == EC_SUCCESS)
- CPRINTS("TCPC p%d init ready", port);
- else
- CPRINTS("TCPC p%d init failed!", port);
-
- /*
- * Before getting the other tasks that are waiting, clear the reset
- * event from this PD task to prevent multiple reset/init events
- * occurring.
- *
- * The double reset event happens when the higher priority PD interrupt
- * task gets an interrupt during the above tcpm_init function. When that
- * occurs, the higher priority task waits correctly for us to finish
- * waking the TCPC, but it has also set PD_EVENT_TCPC_RESET again, which
- * would result in a second, unnecessary init.
- */
- atomic_clear(task_get_event_bitmap(task_get_current()),
- PD_EVENT_TCPC_RESET);
-
- waiting_tasks = atomic_read_clear(&pd[port].tasks_waiting_on_reset);
-
- /*
- * Now that we are done waking up the device, handle device access
- * manually because we ignored it while waking up device.
- */
- handle_device_access(port);
-
- /* Clear SW LPM state; the state machine will set it again if needed */
- pd[port].flags &= ~PD_FLAGS_LPM_REQUESTED;
-
- /* Wake up all waiting tasks. */
- while (waiting_tasks) {
- task = __fls(waiting_tasks);
- waiting_tasks &= ~BIT(task);
- task_set_event(task, TASK_EVENT_PD_AWAKE, 0);
- }
-
- return rv;
-}
-
-static void pd_wait_for_wakeup(int port)
-{
- if (port == TASK_ID_TO_PD_PORT(task_get_current())) {
- /* If we are in the PD task, we can directly reset */
- reset_device_and_notify(port);
- } else {
- /* Otherwise, we need to wait for the TCPC reset to complete */
- atomic_or(&pd[port].tasks_waiting_on_reset,
- 1 << task_get_current());
- /*
- * NOTE: We could be sending the PD task the reset event while
- * it is already processing the reset event. If that occurs,
- * then we will reset the TCPC multiple times, which is
- * undesirable but most likely benign. Empirically, this doesn't
- * happen much, but it if starts occurring, we can add a guard
- * to prevent/reduce it.
- */
- task_set_event(PD_PORT_TO_TASK_ID(port),
- PD_EVENT_TCPC_RESET, 0);
- task_wait_event_mask(TASK_EVENT_PD_AWAKE, -1);
- }
-}
-
-void pd_wait_exit_low_power(int port)
-{
- if (pd_device_in_low_power(port))
- pd_wait_for_wakeup(port);
-}
-
-/*
- * This can be called from any task. If we are in the PD task, we can handle
- * immediately. Otherwise, we need to notify the PD task via event.
- */
-void pd_device_accessed(int port)
-{
- if (port == TASK_ID_TO_PD_PORT(task_get_current())) {
- /* Ignore any access to device while it is waking up */
- if (pd[port].flags & PD_FLAGS_LPM_TRANSITION)
- return;
-
- handle_device_access(port);
- } else {
- task_set_event(PD_PORT_TO_TASK_ID(port),
- PD_EVENT_DEVICE_ACCESSED, 0);
- }
-}
-
-void pd_prevent_low_power_mode(int port, int prevent)
-{
- const int current_task_mask = (1 << task_get_current());
-
- if (prevent)
- atomic_or(&pd[port].tasks_preventing_lpm, current_task_mask);
- else
- atomic_clear(&pd[port].tasks_preventing_lpm, current_task_mask);
-}
-
-/* This is only called from the PD tasks that owns the port. */
-static void exit_low_power_mode(int port)
-{
- if (pd[port].flags & PD_FLAGS_LPM_ENGAGED)
- reset_device_and_notify(port);
- else
- pd[port].flags &= ~PD_FLAGS_LPM_REQUESTED;
-}
-
-#else /* !CONFIG_USB_PD_TCPC_LOW_POWER */
-
-/* We don't need to notify anyone if low power mode isn't involved. */
-static int reset_device_and_notify(int port)
-{
- const int rv = tcpm_init(port);
-
- if (rv == EC_SUCCESS)
- CPRINTS("TCPC p%d init ready", port);
- else
- CPRINTS("TCPC p%d init failed!", port);
-
- return rv;
-}
-
-#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-static int get_bbram_idx(int port)
-{
- switch (port) {
- case 2:
- return SYSTEM_BBRAM_IDX_PD2;
- case 1:
- return SYSTEM_BBRAM_IDX_PD1;
- case 0:
- return SYSTEM_BBRAM_IDX_PD0;
- default:
- return -1;
- }
-}
-
-static int pd_get_saved_port_flags(int port, uint8_t *flags)
-{
- if (system_get_bbram(get_bbram_idx(port), flags) != EC_SUCCESS) {
-#ifndef CHIP_HOST
- CPRINTS("PD NVRAM FAIL");
-#endif
- return EC_ERROR_UNKNOWN;
- }
-
- return EC_SUCCESS;
-}
-
-static void pd_set_saved_port_flags(int port, uint8_t flags)
-{
- if (system_set_bbram(get_bbram_idx(port), flags) != EC_SUCCESS) {
-#ifndef CHIP_HOST
- CPRINTS("PD NVRAM FAIL");
-#endif
- }
-}
-
-static void pd_update_saved_port_flags(int port, uint8_t flag, uint8_t val)
-{
- uint8_t saved_flags;
-
- if (pd_get_saved_port_flags(port, &saved_flags) != EC_SUCCESS)
- return;
-
- if (val)
- saved_flags |= flag;
- else
- saved_flags &= ~flag;
-
- pd_set_saved_port_flags(port, saved_flags);
-}
-#endif /* defined(CONFIG_USB_PD_DUAL_ROLE) */
-
-/**
- * Invalidate last message received at the port when the port gets disconnected
- * or reset(soft/hard). This is used to identify and handle the duplicate
- * messages.
- *
- * @param port USB PD TCPC port number
- */
-static void invalidate_last_message_id(int port)
-{
- /*
- * Message id starts from 0 to 7. If last_msg_id is initialized to 0,
- * it will lead to repetitive message id with first received packet,
- * so initialize it with an invalid value 0xff.
- */
- pd[port].last_msg_id = 0xff;
-}
-
-/**
- * Identify and drop any duplicate messages received at the port.
- *
- * @param port USB PD TCPC port number
- * @param msg_header Message Header containing the RX message ID
- * @return 1 if the received message is a duplicate one, 0 otherwise.
- */
-static int consume_repeat_message(int port, uint16_t msg_header)
-{
- uint8_t msg_id = PD_HEADER_ID(msg_header);
-
- /* If repeat message ignore, except softreset control request. */
- if (PD_HEADER_TYPE(msg_header) == PD_CTRL_SOFT_RESET &&
- PD_HEADER_CNT(msg_header) == 0) {
- return 0;
- } else if (pd[port].last_msg_id != msg_id) {
- pd[port].last_msg_id = msg_id;
- } else if (pd[port].last_msg_id == msg_id) {
- CPRINTF("C%d Repeat msg_id %d\n", port, msg_id);
- return 1;
- }
-
- return 0;
-}
-
-/**
- * Returns true if the port is currently in the try src state.
- */
-static inline int is_try_src(int port)
-{
- return pd[port].flags & PD_FLAGS_TRY_SRC;
-}
-
-static inline void set_state(int port, enum pd_states next_state)
-{
- enum pd_states last_state = pd[port].task_state;
-#ifdef CONFIG_LOW_POWER_IDLE
- int i;
-#endif
-
- set_state_timeout(port, 0, 0);
- pd[port].task_state = next_state;
-
- if (last_state == next_state)
- return;
-
-#if defined(CONFIG_USBC_PPC) && defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE)
- /* If we're entering DRP_AUTO_TOGGLE, there is no sink connected. */
- if (next_state == PD_STATE_DRP_AUTO_TOGGLE) {
- ppc_sink_is_connected(port, 0);
- /*
- * Clear the overcurrent event counter
- * since we've detected a disconnect.
- */
- ppc_clear_oc_event_counter(port);
- }
-#endif /* CONFIG_USBC_PPC && CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE */
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- /* Clear flag to allow DRP auto toggle when possible */
- if (last_state != PD_STATE_DRP_AUTO_TOGGLE)
- pd[port].flags &= ~PD_FLAGS_TCPC_DRP_TOGGLE;
-#endif
-
- /* Ignore dual-role toggling between sink and source */
- if ((last_state == PD_STATE_SNK_DISCONNECTED &&
- next_state == PD_STATE_SRC_DISCONNECTED) ||
- (last_state == PD_STATE_SRC_DISCONNECTED &&
- next_state == PD_STATE_SNK_DISCONNECTED))
- return;
-
- if (next_state == PD_STATE_SRC_DISCONNECTED ||
- next_state == PD_STATE_SNK_DISCONNECTED) {
-#ifdef CONFIG_USBC_PPC
- enum tcpc_cc_voltage_status cc1, cc2;
-
- tcpm_get_cc(port, &cc1, &cc2);
- /*
- * Neither a debug accessory nor UFP attached.
- * Tell the PPC module that there is no sink connected.
- */
- if (!cc_is_at_least_one_rd(cc1, cc2)) {
- ppc_sink_is_connected(port, 0);
- /*
- * Clear the overcurrent event counter
- * since we've detected a disconnect.
- */
- ppc_clear_oc_event_counter(port);
- }
-#endif /* CONFIG_USBC_PPC */
- /* Clear the holdoff timer since the port is disconnected. */
- pd[port].ready_state_holdoff_timer = 0;
-
- /*
- * We should not clear any flags when transitioning back to the
- * disconnected state from the debounce state as the two states
- * here are really the same states in the state diagram.
- */
- if (last_state != PD_STATE_SNK_DISCONNECTED_DEBOUNCE &&
- last_state != PD_STATE_SRC_DISCONNECTED_DEBOUNCE) {
- pd[port].flags &= ~PD_FLAGS_RESET_ON_DISCONNECT_MASK;
- reset_pd_cable(port);
- }
-
- /* Clear the input current limit */
- pd_set_input_current_limit(port, 0, 0);
-#ifdef CONFIG_CHARGE_MANAGER
- typec_set_input_current_limit(port, 0, 0);
- charge_manager_set_ceil(port,
- CEIL_REQUESTOR_PD,
- CHARGE_CEIL_NONE);
-#endif
-#ifdef CONFIG_BC12_DETECT_DATA_ROLE_TRIGGER
- /*
- * When data role set events are used to enable BC1.2, then CC
- * detach events are used to notify BC1.2 that it can be powered
- * down.
- */
- task_set_event(USB_CHG_PORT_TO_TASK_ID(port),
- USB_CHG_EVENT_CC_OPEN, 0);
-#endif /* CONFIG_BC12_DETECT_DATA_ROLE_TRIGGER */
-#ifdef CONFIG_USBC_VCONN
- set_vconn(port, 0);
-#endif /* defined(CONFIG_USBC_VCONN) */
- pd_update_saved_port_flags(port, PD_BBRMFLG_EXPLICIT_CONTRACT,
- 0);
-#else /* CONFIG_USB_PD_DUAL_ROLE */
- if (next_state == PD_STATE_SRC_DISCONNECTED) {
-#ifdef CONFIG_USBC_VCONN
- set_vconn(port, 0);
-#endif /* CONFIG_USBC_VCONN */
-#endif /* !CONFIG_USB_PD_DUAL_ROLE */
- /* If we are source, make sure VBUS is off and restore RP */
- if (pd[port].power_role == PD_ROLE_SOURCE) {
- /* Restore non-active ports to CONFIG_USB_PD_PULLUP */
- pd_power_supply_reset(port);
- tcpm_set_cc(port, TYPEC_CC_RP);
- }
-#ifdef CONFIG_USB_PD_REV30
- /* Adjust rev to highest level*/
- pd[port].rev = PD_REV30;
-#endif
- pd[port].dev_id = 0;
-#ifdef CONFIG_CHARGE_MANAGER
- charge_manager_update_dualrole(port, CAP_UNKNOWN);
-#endif
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- pd_dfp_exit_mode(port, 0, 0);
-#endif
- /*
- * Indicate that the port is disconnected by setting role to
- * DFP as SoCs have special signals when they are the UFP ports
- * (e.g. OTG signals)
- */
- pd_execute_data_swap(port, PD_ROLE_DFP);
-#ifdef CONFIG_USBC_SS_MUX
- usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT,
- pd[port].polarity);
-#endif
- /* Disable TCPC RX */
- tcpm_set_rx_enable(port, 0);
-
- /* Invalidate message IDs. */
- invalidate_last_message_id(port);
-#ifdef CONFIG_COMMON_RUNTIME
- /* detect USB PD cc disconnect */
- hook_notify(HOOK_USB_PD_DISCONNECT);
-#endif
- }
-
-#ifdef CONFIG_LOW_POWER_IDLE
- /* If a PD device is attached then disable deep sleep */
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- if (pd_capable(i))
- break;
- }
- if (i == board_get_usb_pd_port_count())
- enable_sleep(SLEEP_MASK_USB_PD);
- else
- disable_sleep(SLEEP_MASK_USB_PD);
-#endif
-
- if (debug_level > 0)
- CPRINTF("C%d st%d %s\n", port, next_state,
- pd_state_names[next_state]);
- else
- CPRINTF("C%d st%d\n", port, next_state);
-}
-
-/* increment message ID counter */
-static void inc_id(int port)
-{
- pd[port].msg_id = (pd[port].msg_id + 1) & PD_MESSAGE_ID_COUNT;
-}
-
-#ifdef CONFIG_USB_PD_REV30
-static void sink_can_xmit(int port, int rp)
-{
- tcpm_select_rp_value(port, rp);
- tcpm_set_cc(port, TYPEC_CC_RP);
-}
-
-static inline void pd_ca_reset(int port)
-{
- pd[port].ca_buffered = 0;
-}
-#endif
-
-void pd_transmit_complete(int port, int status)
-{
- if (status == TCPC_TX_COMPLETE_SUCCESS)
- inc_id(port);
-
- pd[port].tx_status = status;
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TX, 0);
-}
-
-static int pd_transmit(int port, enum tcpm_transmit_type type,
- uint16_t header, const uint32_t *data)
-{
- int evt;
-
- /* If comms are disabled, do not transmit, return error */
- if (!pd_comm_is_enabled(port))
- return -1;
-
- /* Don't try to transmit anything until we have processed
- * all RX messages.
- */
- if (tcpm_has_pending_message(port))
- return -1;
-
-#ifdef CONFIG_USB_PD_REV30
- /* Source-coordinated collision avoidance */
- /*
- * In order to avoid message collisions due to asynchronous Messaging
- * sent from the Sink, the Source sets Rp to SinkTxOk to indicate to
- * the Sink that it is ok to initiate an AMS. When the Source wishes
- * to initiate an AMS it sets Rp to SinkTxNG. When the Sink detects
- * that Rp is set to SinkTxOk it May initiate an AMS. When the Sink
- * detects that Rp is set to SinkTxNG it Shall Not initiate an AMS
- * and Shall only send Messages that are part of an AMS the Source has
- * initiated. Note that this restriction applies to SOP* AMS’s i.e.
- * for both Port to Port and Port to Cable Plug communications.
- *
- * This starts after an Explicit Contract is in place
- * PD R3 V1.1 Section 2.5.2.
- *
- * Note: a Sink can still send Hard Reset signaling at any time.
- */
- if ((pd[port].rev == PD_REV30) &&
- (pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT)) {
- if (pd[port].power_role == PD_ROLE_SOURCE) {
- /*
- * Inform Sink that it can't transmit. If a sink
- * transmition is in progress and a collsion occurs,
- * a reset is generated. This should be rare because
- * all extended messages are chunked. This effectively
- * defaults to PD REV 2.0 collision avoidance.
- */
- sink_can_xmit(port, SINK_TX_NG);
- } else if (type != TCPC_TX_HARD_RESET) {
- enum tcpc_cc_voltage_status cc1, cc2;
-
- tcpm_get_cc(port, &cc1, &cc2);
- if (cc1 == TYPEC_CC_VOLT_RP_1_5 ||
- cc2 == TYPEC_CC_VOLT_RP_1_5) {
- /* Sink can't transmit now. */
- /* Check if message is already buffered. */
- if (pd[port].ca_buffered)
- return -1;
-
- /* Buffer message and send later. */
- pd[port].ca_type = type;
- pd[port].ca_header = header;
- memcpy(pd[port].ca_buffer,
- data, sizeof(uint32_t) *
- PD_HEADER_CNT(header));
- pd[port].ca_buffered = 1;
- return 1;
- }
- }
- }
-#endif
- tcpm_transmit(port, type, header, data);
-
- /* Wait until TX is complete */
- evt = task_wait_event_mask(PD_EVENT_TX, PD_T_TCPC_TX_TIMEOUT);
-
-#ifdef CONFIG_USB_PD_REV30
- /*
- * If the source just completed a transmit, tell
- * the sink it can transmit if it wants to.
- */
- if ((pd[port].rev == PD_REV30) &&
- (pd[port].power_role == PD_ROLE_SOURCE) &&
- (pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT)) {
- sink_can_xmit(port, SINK_TX_OK);
- }
-#endif
-
- if (evt & TASK_EVENT_TIMER)
- return -1;
-
- /* TODO: give different error condition for failed vs discarded */
- return pd[port].tx_status == TCPC_TX_COMPLETE_SUCCESS ? 1 : -1;
-}
-
-#ifdef CONFIG_USB_PD_REV30
-static void pd_ca_send_pending(int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
-
- /* Check if a message has been buffered. */
- if (!pd[port].ca_buffered)
- return;
-
- tcpm_get_cc(port, &cc1, &cc2);
- if ((cc1 != TYPEC_CC_VOLT_RP_1_5) &&
- (cc2 != TYPEC_CC_VOLT_RP_1_5))
- if (pd_transmit(port, pd[port].ca_type,
- pd[port].ca_header,
- pd[port].ca_buffer) < 0)
- return;
-
- /* Message was sent, so free up the buffer. */
- pd[port].ca_buffered = 0;
-}
-#endif
-
-static void pd_update_roles(int port)
-{
- /* Notify TCPC of role update */
- tcpm_set_msg_header(port, pd[port].power_role, pd[port].data_role);
-}
-
-static int send_control(int port, int type)
-{
- int bit_len;
- uint16_t header = PD_HEADER(type, pd[port].power_role,
- pd[port].data_role, pd[port].msg_id, 0,
- pd_get_rev(port), 0);
-
- bit_len = pd_transmit(port, TCPC_TX_SOP, header, NULL);
- if (debug_level >= 2)
- CPRINTF("C%d CTRL[%d]>%d\n", port, type, bit_len);
-
- return bit_len;
-}
-
-static int send_source_cap(int port)
-{
- int bit_len;
-#if defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \
- defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT)
- const uint32_t *src_pdo;
- const int src_pdo_cnt = charge_manager_get_source_pdo(&src_pdo, port);
-#else
- const uint32_t *src_pdo = pd_src_pdo;
- const int src_pdo_cnt = pd_src_pdo_cnt;
-#endif
- uint16_t header;
-
- if (src_pdo_cnt == 0)
- /* No source capabilities defined, sink only */
- header = PD_HEADER(PD_CTRL_REJECT, pd[port].power_role,
- pd[port].data_role, pd[port].msg_id, 0,
- pd_get_rev(port), 0);
- else
- header = PD_HEADER(PD_DATA_SOURCE_CAP, pd[port].power_role,
- pd[port].data_role, pd[port].msg_id, src_pdo_cnt,
- pd_get_rev(port), 0);
-
- bit_len = pd_transmit(port, TCPC_TX_SOP, header, src_pdo);
- if (debug_level >= 2)
- CPRINTF("C%d srcCAP>%d\n", port, bit_len);
-
- return bit_len;
-}
-
-#ifdef CONFIG_USB_PD_REV30
-static int send_battery_cap(int port, uint32_t *payload)
-{
- int bit_len;
- uint16_t msg[6] = {0, 0, 0, 0, 0, 0};
- uint16_t header = PD_HEADER(PD_EXT_BATTERY_CAP,
- pd[port].power_role,
- pd[port].data_role,
- pd[port].msg_id,
- 3, /* Number of Data Objects */
- pd[port].rev,
- 1 /* This is an exteded message */
- );
-
- /* Set extended header */
- msg[0] = PD_EXT_HEADER(0, /* Chunk Number */
- 0, /* Request Chunk */
- 9 /* Data Size in bytes */
- );
- /* Set VID */
- msg[1] = USB_VID_GOOGLE;
-
- /* Set PID */
- msg[2] = CONFIG_USB_PID;
-
- if (battery_is_present()) {
- /*
- * We only have one fixed battery,
- * so make sure batt cap ref is 0.
- */
- if (BATT_CAP_REF(payload[0]) != 0) {
- /* Invalid battery reference */
- msg[5] = 1;
- } else {
- uint32_t v;
- uint32_t c;
-
- /*
- * The Battery Design Capacity field shall return the
- * Battery’s design capacity in tenths of Wh. If the
- * Battery is Hot Swappable and is not present, the
- * Battery Design Capacity field shall be set to 0. If
- * the Battery is unable to report its Design Capacity,
- * it shall return 0xFFFF
- */
- msg[3] = 0xffff;
-
- /*
- * The Battery Last Full Charge Capacity field shall
- * return the Battery’s last full charge capacity in
- * tenths of Wh. If the Battery is Hot Swappable and
- * is not present, the Battery Last Full Charge Capacity
- * field shall be set to 0. If the Battery is unable to
- * report its Design Capacity, the Battery Last Full
- * Charge Capacity field shall be set to 0xFFFF.
- */
- msg[4] = 0xffff;
-
- if (battery_design_voltage(&v) == 0) {
- if (battery_design_capacity(&c) == 0) {
- /*
- * Wh = (c * v) / 1000000
- * 10th of a Wh = Wh * 10
- */
- msg[3] = DIV_ROUND_NEAREST((c * v),
- 100000);
- }
-
- if (battery_full_charge_capacity(&c) == 0) {
- /*
- * Wh = (c * v) / 1000000
- * 10th of a Wh = Wh * 10
- */
- msg[4] = DIV_ROUND_NEAREST((c * v),
- 100000);
- }
- }
- }
- }
-
- bit_len = pd_transmit(port, TCPC_TX_SOP, header, (uint32_t *)msg);
- if (debug_level >= 2)
- CPRINTF("C%d batCap>%d\n", port, bit_len);
- return bit_len;
-}
-
-static int send_battery_status(int port, uint32_t *payload)
-{
- int bit_len;
- uint32_t msg = 0;
- uint16_t header = PD_HEADER(PD_DATA_BATTERY_STATUS,
- pd[port].power_role,
- pd[port].data_role,
- pd[port].msg_id,
- 1, /* Number of Data Objects */
- pd[port].rev,
- 0 /* This is NOT an extended message */
- );
-
- if (battery_is_present()) {
- /*
- * We only have one fixed battery,
- * so make sure batt cap ref is 0.
- */
- if (BATT_CAP_REF(payload[0]) != 0) {
- /* Invalid battery reference */
- msg |= BSDO_INVALID;
- } else {
- uint32_t v;
- uint32_t c;
-
- if (battery_design_voltage(&v) != 0 ||
- battery_remaining_capacity(&c) != 0) {
- msg |= BSDO_CAP(BSDO_CAP_UNKNOWN);
- } else {
- /*
- * Wh = (c * v) / 1000000
- * 10th of a Wh = Wh * 10
- */
- msg |= BSDO_CAP(DIV_ROUND_NEAREST((c * v),
- 100000));
- }
-
- /* Battery is present */
- msg |= BSDO_PRESENT;
-
- /*
- * For drivers that are not smart battery compliant,
- * battery_status() returns EC_ERROR_UNIMPLEMENTED and
- * the battery is assumed to be idle.
- */
- if (battery_status(&c) != 0) {
- msg |= BSDO_IDLE; /* assume idle */
- } else {
- if (c & STATUS_FULLY_CHARGED)
- /* Fully charged */
- msg |= BSDO_IDLE;
- else if (c & STATUS_DISCHARGING)
- /* Discharging */
- msg |= BSDO_DISCHARGING;
- /* else battery is charging.*/
- }
- }
- } else {
- msg = BSDO_CAP(BSDO_CAP_UNKNOWN);
- }
-
- bit_len = pd_transmit(port, TCPC_TX_SOP, header, &msg);
- if (debug_level >= 2)
- CPRINTF("C%d batStat>%d\n", port, bit_len);
-
- return bit_len;
-}
-#endif
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-static void send_sink_cap(int port)
-{
- int bit_len;
- uint16_t header = PD_HEADER(PD_DATA_SINK_CAP, pd[port].power_role,
- pd[port].data_role, pd[port].msg_id, pd_snk_pdo_cnt,
- pd_get_rev(port), 0);
-
- bit_len = pd_transmit(port, TCPC_TX_SOP, header, pd_snk_pdo);
- if (debug_level >= 2)
- CPRINTF("C%d snkCAP>%d\n", port, bit_len);
-}
-
-static int send_request(int port, uint32_t rdo)
-{
- int bit_len;
- uint16_t header = PD_HEADER(PD_DATA_REQUEST, pd[port].power_role,
- pd[port].data_role, pd[port].msg_id, 1,
- pd_get_rev(port), 0);
-
- bit_len = pd_transmit(port, TCPC_TX_SOP, header, &rdo);
- if (debug_level >= 2)
- CPRINTF("C%d REQ>%d\n", port, bit_len);
-
- return bit_len;
-}
-
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
-
-#ifdef CONFIG_COMMON_RUNTIME
-static int send_bist_cmd(int port)
-{
- /* currently only support sending bist carrier 2 */
- uint32_t bdo = BDO(BDO_MODE_CARRIER2, 0);
- int bit_len;
- uint16_t header = PD_HEADER(PD_DATA_BIST, pd[port].power_role,
- pd[port].data_role, pd[port].msg_id, 1,
- pd_get_rev(port), 0);
-
- bit_len = pd_transmit(port, TCPC_TX_SOP, header, &bdo);
- CPRINTF("C%d BIST>%d\n", port, bit_len);
-
- return bit_len;
-}
-#endif
-
-static void queue_vdm(int port, uint32_t *header, const uint32_t *data,
- int data_cnt)
-{
- pd[port].vdo_count = data_cnt + 1;
- pd[port].vdo_data[0] = header[0];
- memcpy(&pd[port].vdo_data[1], data, sizeof(uint32_t) * data_cnt);
- /* Set ready, pd task will actually send */
- pd[port].vdm_state = VDM_STATE_READY;
-}
-
-static void handle_vdm_request(int port, int cnt, uint32_t *payload)
-{
- int rlen = 0;
- uint32_t *rdata;
-
- if (pd[port].vdm_state == VDM_STATE_BUSY) {
- /* If UFP responded busy retry after timeout */
- if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_BUSY) {
- pd[port].vdm_timeout.val = get_time().val +
- PD_T_VDM_BUSY;
- pd[port].vdm_state = VDM_STATE_WAIT_RSP_BUSY;
- pd[port].vdo_retry = (payload[0] & ~VDO_CMDT_MASK) |
- CMDT_INIT;
- return;
- } else {
- pd[port].vdm_state = VDM_STATE_DONE;
- }
- }
-
- if (PD_VDO_SVDM(payload[0]))
- rlen = pd_svdm(port, cnt, payload, &rdata);
- else
- rlen = pd_custom_vdm(port, cnt, payload, &rdata);
-
- if (rlen > 0) {
- queue_vdm(port, rdata, &rdata[1], rlen - 1);
- return;
- }
- if (debug_level >= 2)
- CPRINTF("C%d Unhandled VDM VID %04x CMD %04x\n",
- port, PD_VDO_VID(payload[0]), payload[0] & 0xFFFF);
-}
-
-static __maybe_unused int pd_is_disconnected(int port)
-{
- return pd[port].task_state == PD_STATE_SRC_DISCONNECTED
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- || pd[port].task_state == PD_STATE_SNK_DISCONNECTED
-#endif
- ;
-}
-
-static void set_usb_mux_with_current_data_role(int port)
-{
-#ifdef CONFIG_USBC_SS_MUX
- /*
- * If the SoC is down, then we disconnect the MUX to save power since
- * no one cares about the data lines.
- */
-#ifdef CONFIG_POWER_COMMON
- if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) {
- usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT,
- pd[port].polarity);
- return;
- }
-#endif /* CONFIG_POWER_COMMON */
-
- /*
- * When PD stack is disconnected, then mux should be disconnected, which
- * is also what happens in the set_state disconnection code. Once the
- * PD state machine progresses out of disconnect, the MUX state will
- * be set correctly again.
- */
- if (pd_is_disconnected(port))
- usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT,
- pd[port].polarity);
- /*
- * If new data role isn't DFP and we only support DFP, also disconnect.
- */
- else if (IS_ENABLED(CONFIG_USBC_SS_MUX_DFP_ONLY) &&
- pd[port].data_role != PD_ROLE_DFP)
- usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT,
- pd[port].polarity);
- /*
- * Otherwise connect mux since we are in S3+
- */
- else
- usb_mux_set(port, TYPEC_MUX_USB, USB_SWITCH_CONNECT,
- pd[port].polarity);
-
-#endif /* CONFIG_USBC_SS_MUX */
-}
-
-static void pd_set_data_role(int port, int role)
-{
- pd[port].data_role = role;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- pd_update_saved_port_flags(port, PD_BBRMFLG_DATA_ROLE, role);
-#endif /* defined(CONFIG_USB_PD_DUAL_ROLE) */
- pd_execute_data_swap(port, role);
-
- set_usb_mux_with_current_data_role(port);
- pd_update_roles(port);
-#ifdef CONFIG_BC12_DETECT_DATA_ROLE_TRIGGER
- /*
- * For BC1.2 detection that is triggered on data role change events
- * instead of VBUS changes, need to set an event to wake up the USB_CHG
- * task and indicate the current data role.
- */
- if (role == PD_ROLE_UFP)
- task_set_event(USB_CHG_PORT_TO_TASK_ID(port),
- USB_CHG_EVENT_DR_UFP, 0);
- else if (role == PD_ROLE_DFP)
- task_set_event(USB_CHG_PORT_TO_TASK_ID(port),
- USB_CHG_EVENT_DR_DFP, 0);
-#endif /* CONFIG_BC12_DETECT_DATA_ROLE_TRIGGER */
-}
-
-#ifdef CONFIG_USBC_VCONN
-static void pd_set_vconn_role(int port, int role)
-{
- if (role == PD_ROLE_VCONN_ON)
- pd[port].flags |= PD_FLAGS_VCONN_ON;
- else
- pd[port].flags &= ~PD_FLAGS_VCONN_ON;
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- pd_update_saved_port_flags(port, PD_BBRMFLG_VCONN_ROLE, role);
-#endif
-}
-#endif /* CONFIG_USBC_VCONN */
-
-void pd_execute_hard_reset(int port)
-{
- int hard_rst_tx = pd[port].last_state == PD_STATE_HARD_RESET_SEND;
-
- CPRINTF("C%d HARD RST %cX\n", port, hard_rst_tx ? 'T' : 'R');
-
- pd[port].msg_id = 0;
- invalidate_last_message_id(port);
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- pd_dfp_exit_mode(port, 0, 0);
-#endif
-
-#ifdef CONFIG_USB_PD_REV30
- pd[port].rev = PD_REV30;
- pd_ca_reset(port);
-#endif
- /*
- * Fake set last state to hard reset to make sure that the next
- * state to run knows that we just did a hard reset.
- */
- pd[port].last_state = PD_STATE_HARD_RESET_EXECUTE;
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /*
- * If we are swapping to a source and have changed to Rp, restore back
- * to Rd and turn off vbus to match our power_role.
- */
- if (pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY ||
- pd[port].task_state == PD_STATE_SNK_SWAP_COMPLETE) {
- tcpm_set_cc(port, TYPEC_CC_RD);
- pd_power_supply_reset(port);
- }
-
- /* Set initial data role (matching power role) */
- pd_set_data_role(port, pd[port].power_role);
- if (pd[port].power_role == PD_ROLE_SINK) {
- /* Clear the input current limit */
- pd_set_input_current_limit(port, 0, 0);
-#ifdef CONFIG_CHARGE_MANAGER
- charge_manager_set_ceil(port,
- CEIL_REQUESTOR_PD,
- CHARGE_CEIL_NONE);
-#endif /* CONFIG_CHARGE_MANAGER */
-
-#ifdef CONFIG_USBC_VCONN
- /*
- * Sink must turn off Vconn after a hard reset if it was being
- * sourced previously
- */
- if (pd[port].flags & PD_FLAGS_VCONN_ON) {
- set_vconn(port, 0);
- pd_set_vconn_role(port, PD_ROLE_VCONN_OFF);
- }
-#endif
-
- set_state(port, PD_STATE_SNK_HARD_RESET_RECOVER);
- return;
- }
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
-
- if (!hard_rst_tx)
- usleep(PD_T_PS_HARD_RESET);
-
- /* We are a source, cut power */
- pd_power_supply_reset(port);
- pd[port].src_recover = get_time().val + PD_T_SRC_RECOVER;
-#ifdef CONFIG_USBC_VCONN
- set_vconn(port, 0);
-#endif
- set_state(port, PD_STATE_SRC_HARD_RESET_RECOVER);
-}
-
-static void execute_soft_reset(int port)
-{
- pd[port].msg_id = 0;
- invalidate_last_message_id(port);
- set_state(port, DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_DISCOVERY,
- PD_STATE_SRC_DISCOVERY));
- CPRINTF("C%d Soft Rst\n", port);
-}
-
-void pd_soft_reset(void)
-{
- int i;
-
- for (i = 0; i < board_get_usb_pd_port_count(); ++i)
- if (pd_is_connected(i)) {
- set_state(i, PD_STATE_SOFT_RESET);
- task_wake(PD_PORT_TO_TASK_ID(i));
- }
-}
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-/*
- * Request desired charge voltage from source.
- * Returns EC_SUCCESS on success or non-zero on failure.
- */
-static int pd_send_request_msg(int port, int always_send_request)
-{
- uint32_t rdo, curr_limit, supply_voltage;
- int res;
-
-#ifdef CONFIG_CHARGE_MANAGER
- int charging = (charge_manager_get_active_charge_port() == port);
-#else
- const int charging = 1;
-#endif
-
-#ifdef CONFIG_USB_PD_CHECK_MAX_REQUEST_ALLOWED
- int max_request_allowed = pd_is_max_request_allowed();
-#else
- const int max_request_allowed = 1;
-#endif
-
- /* Clear new power request */
- pd[port].new_power_request = 0;
-
- /* Build and send request RDO */
- /*
- * If this port is not actively charging or we are not allowed to
- * request the max voltage, then select vSafe5V
- */
- pd_build_request(pd_get_src_cap_cnt(port), pd_get_src_caps(port), 0,
- &rdo, &curr_limit, &supply_voltage,
- charging && max_request_allowed ?
- PD_REQUEST_MAX : PD_REQUEST_VSAFE5V,
- pd_get_max_voltage());
-
- if (!always_send_request) {
- /* Don't re-request the same voltage */
- if (pd[port].prev_request_mv == supply_voltage)
- return EC_SUCCESS;
-#ifdef CONFIG_CHARGE_MANAGER
- /* Limit current to PD_MIN_MA during transition */
- else
- charge_manager_force_ceil(port, PD_MIN_MA);
-#endif
- }
-
- CPRINTF("C%d Req [%d] %dmV %dmA", port, RDO_POS(rdo),
- supply_voltage, curr_limit);
- if (rdo & RDO_CAP_MISMATCH)
- CPRINTF(" Mismatch");
- CPRINTF("\n");
-
- pd[port].curr_limit = curr_limit;
- pd[port].supply_voltage = supply_voltage;
- pd[port].prev_request_mv = supply_voltage;
- res = send_request(port, rdo);
- if (res < 0)
- return res;
- set_state(port, PD_STATE_SNK_REQUESTED);
- return EC_SUCCESS;
-}
-#endif
-
-static void pd_update_pdo_flags(int port, uint32_t pdo)
-{
-#ifdef CONFIG_CHARGE_MANAGER
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- int charge_allowlisted =
- (pd[port].power_role == PD_ROLE_SINK &&
- pd_charge_from_device(pd_get_identity_vid(port),
- pd_get_identity_pid(port)));
-#else
- const int charge_allowlisted = 0;
-#endif
-#endif
-
- /* can only parse PDO flags if type is fixed */
- if ((pdo & PDO_TYPE_MASK) != PDO_TYPE_FIXED)
- return;
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- if (pdo & PDO_FIXED_DUAL_ROLE)
- pd[port].flags |= PD_FLAGS_PARTNER_DR_POWER;
- else
- pd[port].flags &= ~PD_FLAGS_PARTNER_DR_POWER;
-
- if (pdo & PDO_FIXED_EXTERNAL)
- pd[port].flags |= PD_FLAGS_PARTNER_EXTPOWER;
- else
- pd[port].flags &= ~PD_FLAGS_PARTNER_EXTPOWER;
-
- if (pdo & PDO_FIXED_COMM_CAP)
- pd[port].flags |= PD_FLAGS_PARTNER_USB_COMM;
- else
- pd[port].flags &= ~PD_FLAGS_PARTNER_USB_COMM;
-#endif
-
- if (pdo & PDO_FIXED_DATA_SWAP)
- pd[port].flags |= PD_FLAGS_PARTNER_DR_DATA;
- else
- pd[port].flags &= ~PD_FLAGS_PARTNER_DR_DATA;
-
-#ifdef CONFIG_CHARGE_MANAGER
- /*
- * Treat device as a dedicated charger (meaning we should charge
- * from it) if it does not support power swap, or if it is externally
- * powered, or if we are a sink and the device identity matches a
- * charging allowlist.
- */
- if (!(pd[port].flags & PD_FLAGS_PARTNER_DR_POWER) ||
- (pd[port].flags & PD_FLAGS_PARTNER_EXTPOWER) ||
- charge_allowlisted)
- charge_manager_update_dualrole(port, CAP_DEDICATED);
- else
- charge_manager_update_dualrole(port, CAP_DUALROLE);
-#endif
-}
-
-static void handle_data_request(int port, uint16_t head,
- uint32_t *payload)
-{
- int type = PD_HEADER_TYPE(head);
- int cnt = PD_HEADER_CNT(head);
-
- switch (type) {
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- case PD_DATA_SOURCE_CAP:
- if ((pd[port].task_state == PD_STATE_SNK_DISCOVERY)
- || (pd[port].task_state == PD_STATE_SNK_TRANSITION)
- || (pd[port].task_state == PD_STATE_SNK_REQUESTED)
-#ifdef CONFIG_USB_PD_VBUS_DETECT_NONE
- || (pd[port].task_state ==
- PD_STATE_SNK_HARD_RESET_RECOVER)
-#endif
- || (pd[port].task_state == PD_STATE_SNK_READY)) {
-#ifdef CONFIG_USB_PD_REV30
- /*
- * Only adjust sink rev if source rev is higher.
- */
- if (PD_HEADER_REV(head) < pd[port].rev)
- pd[port].rev = PD_HEADER_REV(head);
-#endif
- /* Port partner is now known to be PD capable */
- pd[port].flags |= PD_FLAGS_PREVIOUS_PD_CONN;
-
- /* src cap 0 should be fixed PDO */
- pd_update_pdo_flags(port, payload[0]);
-
- pd_process_source_cap(port, cnt, payload);
-
- /* Source will resend source cap on failure */
- pd_send_request_msg(port, 1);
- }
- break;
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
- case PD_DATA_REQUEST:
- if ((pd[port].power_role == PD_ROLE_SOURCE) && (cnt == 1)) {
-#ifdef CONFIG_USB_PD_REV30
- /*
- * Adjust the rev level to what the sink supports. If
- * they're equal, no harm done.
- */
- pd[port].rev = PD_HEADER_REV(head);
-#endif
- if (!pd_check_requested_voltage(payload[0], port)) {
- if (send_control(port, PD_CTRL_ACCEPT) < 0)
- /*
- * if we fail to send accept, do
- * nothing and let sink timeout and
- * send hard reset
- */
- return;
-
- /* explicit contract is now in place */
- pd[port].flags |= PD_FLAGS_EXPLICIT_CONTRACT;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- pd_update_saved_port_flags(
- port, PD_BBRMFLG_EXPLICIT_CONTRACT, 1);
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
-#ifdef CONFIG_USB_PD_REV30
- /*
- * Start Source-coordinated collision
- * avoidance
- */
- if (pd[port].rev == PD_REV30 &&
- pd[port].power_role == PD_ROLE_SOURCE)
- sink_can_xmit(port, SINK_TX_OK);
-#endif
- pd[port].requested_idx = RDO_POS(payload[0]);
- set_state(port, PD_STATE_SRC_ACCEPTED);
- return;
- }
- }
- /* the message was incorrect or cannot be satisfied */
- send_control(port, PD_CTRL_REJECT);
- /* keep last contract in place (whether implicit or explicit) */
- set_state(port, PD_STATE_SRC_READY);
- break;
- case PD_DATA_BIST:
- /* If not in READY state, then don't start BIST */
- if (DUAL_ROLE_IF_ELSE(port,
- pd[port].task_state == PD_STATE_SNK_READY,
- pd[port].task_state == PD_STATE_SRC_READY)) {
- /* currently only support sending bist carrier mode 2 */
- if ((payload[0] >> 28) == 5) {
- /* bist data object mode is 2 */
- pd_transmit(port, TCPC_TX_BIST_MODE_2, 0,
- NULL);
- /* Set to appropriate port disconnected state */
- set_state(port, DUAL_ROLE_IF_ELSE(port,
- PD_STATE_SNK_DISCONNECTED,
- PD_STATE_SRC_DISCONNECTED));
- }
- }
- break;
- case PD_DATA_SINK_CAP:
- pd[port].flags |= PD_FLAGS_SNK_CAP_RECVD;
- /* snk cap 0 should be fixed PDO */
- pd_update_pdo_flags(port, payload[0]);
- if (pd[port].task_state == PD_STATE_SRC_GET_SINK_CAP)
- set_state(port, PD_STATE_SRC_READY);
- break;
-#ifdef CONFIG_USB_PD_REV30
- case PD_DATA_BATTERY_STATUS:
- break;
-#endif
- case PD_DATA_VENDOR_DEF:
- handle_vdm_request(port, cnt, payload);
- break;
- default:
- CPRINTF("C%d Unhandled data message type %d\n", port, type);
- }
-}
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-void pd_request_power_swap(int port)
-{
- if (pd[port].task_state == PD_STATE_SRC_READY)
- set_state(port, PD_STATE_SRC_SWAP_INIT);
- else if (pd[port].task_state == PD_STATE_SNK_READY)
- set_state(port, PD_STATE_SNK_SWAP_INIT);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-#ifdef CONFIG_USBC_VCONN_SWAP
-static void pd_request_vconn_swap(int port)
-{
- if (pd[port].task_state == PD_STATE_SRC_READY ||
- pd[port].task_state == PD_STATE_SNK_READY)
- set_state(port, PD_STATE_VCONN_SWAP_SEND);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void pd_try_vconn_src(int port)
-{
- /*
- * If we don't currently provide vconn, and we can supply it, send
- * a vconn swap request.
- */
- if (!(pd[port].flags & PD_FLAGS_VCONN_ON)) {
- if (pd_check_vconn_swap(port))
- pd_request_vconn_swap(port);
- }
-}
-#endif
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
-
-void pd_request_data_swap(int port)
-{
- if (DUAL_ROLE_IF_ELSE(port,
- pd[port].task_state == PD_STATE_SNK_READY,
- pd[port].task_state == PD_STATE_SRC_READY))
- set_state(port, PD_STATE_DR_SWAP);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-static void pd_set_power_role(int port, int role)
-{
- pd[port].power_role = role;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- pd_update_saved_port_flags(port, PD_BBRMFLG_POWER_ROLE, role);
-#endif /* defined(CONFIG_USB_PD_DUAL_ROLE) */
-}
-
-static void pd_dr_swap(int port)
-{
- pd_set_data_role(port, !pd[port].data_role);
- pd[port].flags |= PD_FLAGS_CHECK_IDENTITY;
-}
-
-static void handle_ctrl_request(int port, uint16_t head,
- uint32_t *payload)
-{
- int type = PD_HEADER_TYPE(head);
- int res;
-
- switch (type) {
- case PD_CTRL_GOOD_CRC:
- /* should not get it */
- break;
- case PD_CTRL_PING:
- /* Nothing else to do */
- break;
- case PD_CTRL_GET_SOURCE_CAP:
- if (pd[port].task_state == PD_STATE_SRC_READY)
- set_state(port, PD_STATE_SRC_DISCOVERY);
- else {
- res = send_source_cap(port);
- if ((res >= 0) &&
- (pd[port].task_state == PD_STATE_SRC_DISCOVERY))
- set_state(port, PD_STATE_SRC_NEGOCIATE);
- }
- break;
- case PD_CTRL_GET_SINK_CAP:
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- send_sink_cap(port);
-#else
- send_control(port, REFUSE(pd[port].rev));
-#endif
- break;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- case PD_CTRL_GOTO_MIN:
-#ifdef CONFIG_USB_PD_GIVE_BACK
- if (pd[port].task_state == PD_STATE_SNK_READY) {
- /*
- * Reduce power consumption now!
- *
- * The source will restore power to this sink
- * by sending a new source cap message at a
- * later time.
- */
- pd_snk_give_back(port, &pd[port].curr_limit,
- &pd[port].supply_voltage);
- set_state(port, PD_STATE_SNK_TRANSITION);
- }
-#endif
-
- break;
- case PD_CTRL_PS_RDY:
- if (pd[port].task_state == PD_STATE_SNK_SWAP_SRC_DISABLE) {
- set_state(port, PD_STATE_SNK_SWAP_STANDBY);
- } else if (pd[port].task_state == PD_STATE_SRC_SWAP_STANDBY) {
- /* reset message ID and swap roles */
- pd[port].msg_id = 0;
- pd_set_power_role(port, PD_ROLE_SINK);
- pd_update_roles(port);
- /*
- * Give the state machine time to read VBUS as high.
- * Note: This is empirically determined, not strictly
- * part of the USB PD spec.
- */
- pd[port].vbus_debounce_time =
- get_time().val + PD_T_DEBOUNCE;
- set_state(port, PD_STATE_SNK_DISCOVERY);
-#ifdef CONFIG_USBC_VCONN_SWAP
- } else if (pd[port].task_state == PD_STATE_VCONN_SWAP_INIT) {
- /*
- * If VCONN is on, then this PS_RDY tells us it's
- * ok to turn VCONN off
- */
- if (pd[port].flags & PD_FLAGS_VCONN_ON)
- set_state(port, PD_STATE_VCONN_SWAP_READY);
-#endif
- } else if (pd[port].task_state == PD_STATE_SNK_DISCOVERY) {
- /* Don't know what power source is ready. Reset. */
- set_state(port, PD_STATE_HARD_RESET_SEND);
- } else if (pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY) {
- /* Do nothing, assume this is a redundant PD_RDY */
- } else if (pd[port].power_role == PD_ROLE_SINK) {
- /*
- * Give the source some time to send any messages before
- * we start our interrogation. Add some jitter of up to
- * ~192ms to prevent multiple collisions.
- */
- if (pd[port].task_state == PD_STATE_SNK_TRANSITION)
- pd[port].ready_state_holdoff_timer =
- get_time().val + SNK_READY_HOLD_OFF_US
- + (get_time().le.lo & 0xf) * 12 * MSEC;
-
- set_state(port, PD_STATE_SNK_READY);
- pd_set_input_current_limit(port, pd[port].curr_limit,
- pd[port].supply_voltage);
-#ifdef CONFIG_CHARGE_MANAGER
- /* Set ceiling based on what's negotiated */
- charge_manager_set_ceil(port,
- CEIL_REQUESTOR_PD,
- pd[port].curr_limit);
-#endif
- }
- break;
-#endif
- case PD_CTRL_REJECT:
- case PD_CTRL_WAIT:
- if (pd[port].task_state == PD_STATE_DR_SWAP) {
- if (type == PD_CTRL_WAIT) /* try again ... */
- pd[port].flags |= PD_FLAGS_CHECK_DR_ROLE;
- set_state(port, READY_RETURN_STATE(port));
- }
-#ifdef CONFIG_USBC_VCONN_SWAP
- else if (pd[port].task_state == PD_STATE_VCONN_SWAP_SEND)
- set_state(port, READY_RETURN_STATE(port));
-#endif
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- else if (pd[port].task_state == PD_STATE_SRC_SWAP_INIT)
- set_state(port, PD_STATE_SRC_READY);
- else if (pd[port].task_state == PD_STATE_SNK_SWAP_INIT)
- set_state(port, PD_STATE_SNK_READY);
- else if (pd[port].task_state == PD_STATE_SNK_REQUESTED) {
- /*
- * On reception of a WAIT message, transition to
- * PD_STATE_SNK_READY after PD_T_SINK_REQUEST ms to
- * send another request.
- *
- * On reception of a REJECT message, transition to
- * PD_STATE_SNK_READY but don't resend the request if
- * we already have a contract in place.
- *
- * On reception of a REJECT message without a contract,
- * transition to PD_STATE_SNK_DISCOVERY instead.
- */
- if (type == PD_CTRL_WAIT) {
- /*
- * Trigger a new power request when
- * we enter PD_STATE_SNK_READY
- */
- pd[port].new_power_request = 1;
-
- /*
- * After the request is triggered,
- * make sure the request is sent.
- */
- pd[port].prev_request_mv = 0;
-
- /*
- * Transition to PD_STATE_SNK_READY
- * after PD_T_SINK_REQUEST ms.
- */
- set_state_timeout(port,
- get_time().val +
- PD_T_SINK_REQUEST,
- PD_STATE_SNK_READY);
- } else {
- /* The request was rejected */
- const int in_contract =
- pd[port].flags &
- PD_FLAGS_EXPLICIT_CONTRACT;
- set_state(port,
- in_contract ? PD_STATE_SNK_READY
- : PD_STATE_SNK_DISCOVERY);
- }
- }
-#endif
- break;
- case PD_CTRL_ACCEPT:
- if (pd[port].task_state == PD_STATE_SOFT_RESET) {
- /*
- * For the case that we sent soft reset in SNK_DISCOVERY
- * on startup due to VBUS never low, clear the flag.
- */
- pd[port].flags &= ~PD_FLAGS_VBUS_NEVER_LOW;
- execute_soft_reset(port);
- } else if (pd[port].task_state == PD_STATE_DR_SWAP) {
- /* switch data role */
- pd_dr_swap(port);
- set_state(port, READY_RETURN_STATE(port));
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-#ifdef CONFIG_USBC_VCONN_SWAP
- } else if (pd[port].task_state == PD_STATE_VCONN_SWAP_SEND) {
- /* switch vconn */
- set_state(port, PD_STATE_VCONN_SWAP_INIT);
-#endif
- } else if (pd[port].task_state == PD_STATE_SRC_SWAP_INIT) {
- /* explicit contract goes away for power swap */
- pd[port].flags &= ~PD_FLAGS_EXPLICIT_CONTRACT;
- pd_update_saved_port_flags(port,
- PD_BBRMFLG_EXPLICIT_CONTRACT,
- 0);
- set_state(port, PD_STATE_SRC_SWAP_SNK_DISABLE);
- } else if (pd[port].task_state == PD_STATE_SNK_SWAP_INIT) {
- /* explicit contract goes away for power swap */
- pd[port].flags &= ~PD_FLAGS_EXPLICIT_CONTRACT;
- pd_update_saved_port_flags(port,
- PD_BBRMFLG_EXPLICIT_CONTRACT,
- 0);
- set_state(port, PD_STATE_SNK_SWAP_SNK_DISABLE);
- } else if (pd[port].task_state == PD_STATE_SNK_REQUESTED) {
- /* explicit contract is now in place */
- pd[port].flags |= PD_FLAGS_EXPLICIT_CONTRACT;
- pd_update_saved_port_flags(port,
- PD_BBRMFLG_EXPLICIT_CONTRACT,
- 1);
- set_state(port, PD_STATE_SNK_TRANSITION);
-#endif
- }
- break;
- case PD_CTRL_SOFT_RESET:
- execute_soft_reset(port);
- /* We are done, acknowledge with an Accept packet */
- send_control(port, PD_CTRL_ACCEPT);
- break;
- case PD_CTRL_PR_SWAP:
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- if (pd_check_power_swap(port)) {
- send_control(port, PD_CTRL_ACCEPT);
- /*
- * Clear flag for checking power role to avoid
- * immediately requesting another swap.
- */
- pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE;
- set_state(port,
- DUAL_ROLE_IF_ELSE(port,
- PD_STATE_SNK_SWAP_SNK_DISABLE,
- PD_STATE_SRC_SWAP_SNK_DISABLE));
- } else {
- send_control(port, REFUSE(pd[port].rev));
- }
-#else
- send_control(port, REFUSE(pd[port].rev));
-#endif
- break;
- case PD_CTRL_DR_SWAP:
- if (pd_check_data_swap(port, pd[port].data_role)) {
- /*
- * Accept switch and perform data swap. Clear
- * flag for checking data role to avoid
- * immediately requesting another swap.
- */
- pd[port].flags &= ~PD_FLAGS_CHECK_DR_ROLE;
- if (send_control(port, PD_CTRL_ACCEPT) >= 0)
- pd_dr_swap(port);
- } else {
- send_control(port, REFUSE(pd[port].rev));
-
- }
- break;
- case PD_CTRL_VCONN_SWAP:
-#ifdef CONFIG_USBC_VCONN_SWAP
- if (pd[port].task_state == PD_STATE_SRC_READY ||
- pd[port].task_state == PD_STATE_SNK_READY) {
- if (pd_check_vconn_swap(port)) {
- if (send_control(port, PD_CTRL_ACCEPT) > 0)
- set_state(port,
- PD_STATE_VCONN_SWAP_INIT);
- } else {
- send_control(port, REFUSE(pd[port].rev));
- }
- }
-#else
- send_control(port, REFUSE(pd[port].rev));
-#endif
- break;
- default:
-#ifdef CONFIG_USB_PD_REV30
- send_control(port, PD_CTRL_NOT_SUPPORTED);
-#endif
- CPRINTF("C%d Unhandled ctrl message type %d\n", port, type);
- }
-}
-
-#ifdef CONFIG_USB_PD_REV30
-static void handle_ext_request(int port, uint16_t head, uint32_t *payload)
-{
- int type = PD_HEADER_TYPE(head);
-
- switch (type) {
- case PD_EXT_GET_BATTERY_CAP:
- send_battery_cap(port, payload);
- break;
- case PD_EXT_GET_BATTERY_STATUS:
- send_battery_status(port, payload);
- break;
- case PD_EXT_BATTERY_CAP:
- break;
- default:
- send_control(port, PD_CTRL_NOT_SUPPORTED);
- }
-}
-#endif
-
-static void handle_request(int port, uint16_t head,
- uint32_t *payload)
-{
- int cnt = PD_HEADER_CNT(head);
- int data_role = PD_HEADER_DROLE(head);
- int p;
-
- /* dump received packet content (only dump ping at debug level 3) */
- if ((debug_level == 2 && PD_HEADER_TYPE(head) != PD_CTRL_PING) ||
- debug_level >= 3) {
- CPRINTF("C%d RECV %04x/%d ", port, head, cnt);
- for (p = 0; p < cnt; p++)
- CPRINTF("[%d]%08x ", p, payload[p]);
- CPRINTF("\n");
- }
-
- /*
- * If we are in disconnected state, we shouldn't get a request. Do
- * a hard reset if we get one.
- */
- if (!pd_is_connected(port))
- set_state(port, PD_STATE_HARD_RESET_SEND);
-
- /*
- * When a data role conflict is detected, USB-C ErrorRecovery
- * actions shall be performed, and transitioning to unattached state
- * is one such legal action.
- */
- if (pd[port].data_role == data_role) {
- /*
- * If the port doesn't support removing the terminations, just
- * go to the unattached state.
- */
- if (tcpm_set_cc(port, TYPEC_CC_OPEN) == EC_SUCCESS) {
- /* Do not drive VBUS or VCONN. */
- pd_power_supply_reset(port);
-#ifdef CONFIG_USBC_VCONN
- set_vconn(port, 0);
-#endif /* defined(CONFIG_USBC_VCONN) */
- usleep(PD_T_ERROR_RECOVERY);
-
- /* Restore terminations. */
- tcpm_set_cc(port, DUAL_ROLE_IF_ELSE(port, TYPEC_CC_RD,
- TYPEC_CC_RP));
- }
- set_state(port,
- DUAL_ROLE_IF_ELSE(port,
- PD_STATE_SNK_DISCONNECTED,
- PD_STATE_SRC_DISCONNECTED));
- return;
- }
-
-#ifdef CONFIG_USB_PD_REV30
- /* Check if this is an extended chunked data message. */
- if (pd[port].rev == PD_REV30 && PD_HEADER_EXT(head)) {
- handle_ext_request(port, head, payload);
- return;
- }
-#endif
- if (cnt)
- handle_data_request(port, head, payload);
- else
- handle_ctrl_request(port, head, payload);
-}
-
-void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data,
- int count)
-{
- if (count > VDO_MAX_SIZE - 1) {
- CPRINTF("C%d VDM over max size\n", port);
- return;
- }
-
- /* set VDM header with VID & CMD */
- pd[port].vdo_data[0] = VDO(vid, ((vid & USB_SID_PD) == USB_SID_PD) ?
- 1 : (PD_VDO_CMD(cmd) <= CMD_ATTENTION), cmd);
-#ifdef CONFIG_USB_PD_REV30
- pd[port].vdo_data[0] |= VDO_SVDM_VERS(vdo_ver[pd[port].rev]);
-#endif
- queue_vdm(port, pd[port].vdo_data, data, count);
-
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-static inline int pdo_busy(int port)
-{
- /*
- * Note, main PDO state machine (pd_task) uses READY state exclusively
- * to denote port partners have successfully negociated a contract. All
- * other protocol actions force state transitions.
- */
- int rv = (pd[port].task_state != PD_STATE_SRC_READY);
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- rv &= (pd[port].task_state != PD_STATE_SNK_READY);
-#endif
- return rv;
-}
-
-static uint64_t vdm_get_ready_timeout(uint32_t vdm_hdr)
-{
- uint64_t timeout;
- int cmd = PD_VDO_CMD(vdm_hdr);
-
- /* its not a structured VDM command */
- if (!PD_VDO_SVDM(vdm_hdr))
- return 500*MSEC;
-
- switch (PD_VDO_CMDT(vdm_hdr)) {
- case CMDT_INIT:
- if ((cmd == CMD_ENTER_MODE) || (cmd == CMD_EXIT_MODE))
- timeout = PD_T_VDM_WAIT_MODE_E;
- else
- timeout = PD_T_VDM_SNDR_RSP;
- break;
- default:
- if ((cmd == CMD_ENTER_MODE) || (cmd == CMD_EXIT_MODE))
- timeout = PD_T_VDM_E_MODE;
- else
- timeout = PD_T_VDM_RCVR_RSP;
- break;
- }
- return timeout;
-}
-
-static void pd_vdm_send_state_machine(int port)
-{
- int res;
- uint16_t header;
-
- switch (pd[port].vdm_state) {
- case VDM_STATE_READY:
- /* Only transmit VDM if connected. */
- if (!pd_is_connected(port)) {
- pd[port].vdm_state = VDM_STATE_ERR_BUSY;
- break;
- }
-
- /*
- * if there's traffic or we're not in PDO ready state don't send
- * a VDM.
- */
- if (pdo_busy(port))
- break;
-
- /*
- * To communicate with the cable plug, an explicit contract
- * should be established, VCONN should be enabled and data role
- * that can communicate with the cable plug should be in place.
- * For USB3.0, UFP/DFP can communicate whereas in case of
- * USB2.0 only DFP can talk to the cable plug.
- *
- * For communication between USB2.0 UFP and cable plug,
- * data role swap takes place during source and sink
- * negotiation and in case of failure, a soft reset is issued.
- */
- if (is_sop_prime_ready(port, pd[port].data_role,
- pd[port].flags)) {
- /* Prepare SOP'/SOP'' header and send VDM */
- header = PD_HEADER(
- PD_DATA_VENDOR_DEF,
- PD_PLUG_FROM_DFP_UFP,
- 0,
- pd[port].msg_id,
- (int)pd[port].vdo_count,
- pd_get_rev(port),
- 0);
- res = pd_transmit(port, TCPC_TX_SOP_PRIME, header,
- pd[port].vdo_data);
- /*
- * If there is no ack from the cable, its a non-emark
- * cable and since, the pd flow should continue
- * irrespective of cable response, sending
- * discover_svid so the pd flow remains intact.
- */
- if (res < 0) {
- header = PD_HEADER(PD_DATA_VENDOR_DEF,
- pd[port].power_role,
- pd[port].data_role,
- pd[port].msg_id,
- (int)pd[port].vdo_count,
- pd_get_rev(port), 0);
- pd[port].vdo_data[0] =
- VDO(USB_SID_PD, 1, CMD_DISCOVER_SVID);
- res = pd_transmit(port, TCPC_TX_SOP, header,
- pd[port].vdo_data);
- reset_pd_cable(port);
- }
- } else {
- /* Prepare SOP header and send VDM */
- header = PD_HEADER(PD_DATA_VENDOR_DEF,
- pd[port].power_role,
- pd[port].data_role,
- pd[port].msg_id,
- (int)pd[port].vdo_count,
- pd_get_rev(port), 0);
- res = pd_transmit(port, TCPC_TX_SOP, header,
- pd[port].vdo_data);
- }
-
- if (res < 0) {
- pd[port].vdm_state = VDM_STATE_ERR_SEND;
- } else {
- pd[port].vdm_state = VDM_STATE_BUSY;
- pd[port].vdm_timeout.val = get_time().val +
- vdm_get_ready_timeout(pd[port].vdo_data[0]);
- }
- break;
- case VDM_STATE_WAIT_RSP_BUSY:
- /* wait and then initiate request again */
- if (get_time().val > pd[port].vdm_timeout.val) {
- pd[port].vdo_data[0] = pd[port].vdo_retry;
- pd[port].vdo_count = 1;
- pd[port].vdm_state = VDM_STATE_READY;
- }
- break;
- case VDM_STATE_BUSY:
- /* Wait for VDM response or timeout */
- if (pd[port].vdm_timeout.val &&
- (get_time().val > pd[port].vdm_timeout.val)) {
- pd[port].vdm_state = VDM_STATE_ERR_TMOUT;
- }
- break;
- default:
- break;
- }
-}
-
-#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO
-static inline void pd_dev_dump_info(uint16_t dev_id, uint8_t *hash)
-{
- int j;
- ccprintf("DevId:%d.%d Hash:", HW_DEV_ID_MAJ(dev_id),
- HW_DEV_ID_MIN(dev_id));
- for (j = 0; j < PD_RW_HASH_SIZE; j += 4) {
- ccprintf(" 0x%02x%02x%02x%02x", hash[j + 3], hash[j + 2],
- hash[j + 1], hash[j]);
- }
- ccprintf("\n");
-}
-#endif /* CONFIG_CMD_PD_DEV_DUMP_INFO */
-
-int pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash,
- uint32_t current_image)
-{
-#ifdef CONFIG_COMMON_RUNTIME
- int i;
-#endif
-
- pd[port].dev_id = dev_id;
- memcpy(pd[port].dev_rw_hash, rw_hash, PD_RW_HASH_SIZE);
-#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO
- if (debug_level >= 2)
- pd_dev_dump_info(dev_id, (uint8_t *)rw_hash);
-#endif
- pd[port].current_image = current_image;
-
-#ifdef CONFIG_COMMON_RUNTIME
- /* Search table for matching device / hash */
- for (i = 0; i < RW_HASH_ENTRIES; i++)
- if (dev_id == rw_hash_table[i].dev_id)
- return !memcmp(rw_hash,
- rw_hash_table[i].dev_rw_hash,
- PD_RW_HASH_SIZE);
-#endif
- return 0;
-}
-
-#if defined(CONFIG_POWER_COMMON) || defined(CONFIG_USB_PD_ALT_MODE_DFP)
-static void exit_dp_mode(int port)
-{
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
-
- if (opos <= 0)
- return;
-
- CPRINTS("C%d Exiting DP mode", port);
- if (!pd_dfp_exit_mode(port, USB_SID_DISPLAYPORT, opos))
- return;
- pd_send_vdm(port, USB_SID_DISPLAYPORT,
- CMD_EXIT_MODE | VDO_OPOS(opos), NULL, 0);
- pd_vdm_send_state_machine(port);
- /* Have to wait for ACK */
-#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
-}
-#endif /* CONFIG_POWER_COMMON */
-
-#ifdef CONFIG_POWER_COMMON
-static void handle_new_power_state(int port)
-{
- if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF))
- /* The SoC will negotiated DP mode again when it boots up */
- exit_dp_mode(port);
-
- /* Ensure mux is set properly after chipset transition */
- set_usb_mux_with_current_data_role(port);
-}
-#endif /* CONFIG_POWER_COMMON */
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-enum pd_dual_role_states pd_get_dual_role(int port)
-{
- return drp_state[port];
-}
-
-#ifdef CONFIG_USB_PD_TRY_SRC
-static void pd_update_try_source(void)
-{
- int i;
- int try_src = 0;
- int batt_soc = usb_get_battery_soc();
-
- try_src = 0;
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- try_src |= drp_state[i] == PD_DRP_TOGGLE_ON;
-
- /*
- * Enable try source when dual-role toggling AND battery is present
- * and at some minimum percentage.
- */
- pd_try_src_enable = try_src &&
- batt_soc >= CONFIG_USB_PD_TRY_SRC_MIN_BATT_SOC;
-
-#ifdef CONFIG_BATTERY_REVIVE_DISCONNECT
- /*
- * Don't attempt Try.Src if the battery is in the disconnect state. The
- * discharge FET may not be enabled and so attempting Try.Src may cut
- * off our only power source at the time.
- */
- pd_try_src_enable &= (battery_get_disconnect_state() ==
- BATTERY_NOT_DISCONNECTED);
-#elif defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \
- defined(CONFIG_BATTERY_PRESENT_GPIO)
- /*
- * When battery is cutoff in ship mode it may not be reliable to
- * check if battery is present with its state of charge.
- * Also check if battery is initialized and ready to provide power.
- */
- pd_try_src_enable &= (battery_is_present() == BP_YES);
-#endif /* CONFIG_BATTERY_PRESENT_[CUSTOM|GPIO] */
-
- /*
- * Clear this flag to cover case where a TrySrc
- * mode went from enabled to disabled and trying_source
- * was active at that time.
- */
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- pd[i].flags &= ~PD_FLAGS_TRY_SRC;
-}
-#endif /* CONFIG_USB_PD_TRY_SRC */
-
-#ifdef CONFIG_USB_PD_RESET_MIN_BATT_SOC
-static void pd_update_snk_reset(void)
-{
- int i;
- int batt_soc = usb_get_battery_soc();
-
- if (batt_soc < CONFIG_USB_PD_RESET_MIN_BATT_SOC)
- return;
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- if (pd[i].flags & PD_FLAGS_SNK_WAITING_BATT) {
- /*
- * Battery has gained sufficient charge to kick off PD
- * negotiation and withstand a hard reset. Clear the
- * flag and let reset begin if task is waiting in
- * SNK_DISCOVERY.
- */
- pd[i].flags &= ~PD_FLAGS_SNK_WAITING_BATT;
-
- if (pd[i].task_state == PD_STATE_SNK_DISCOVERY) {
- CPRINTS("C%d: Starting soft reset timer", i);
- set_state_timeout(i,
- get_time().val + PD_T_SINK_WAIT_CAP,
- PD_STATE_SOFT_RESET);
- }
- }
- }
-}
-#endif
-
-#if defined(CONFIG_USB_PD_TRY_SRC) || defined(CONFIG_USB_PD_RESET_MIN_BATT_SOC)
-static void pd_update_battery_soc_change(void)
-{
-#ifdef CONFIG_USB_PD_TRY_SRC
- pd_update_try_source();
-#endif
-
-#ifdef CONFIG_USB_PD_RESET_MIN_BATT_SOC
- pd_update_snk_reset();
-#endif
-}
-DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, pd_update_battery_soc_change,
- HOOK_PRIO_DEFAULT);
-#endif /* CONFIG_USB_PD_TRY_SRC || CONFIG_USB_PD_RESET_MIN_BATT_SOC */
-
-static inline void pd_set_dual_role_no_wakeup(int port,
- enum pd_dual_role_states state)
-{
- drp_state[port] = state;
-
-#ifdef CONFIG_USB_PD_TRY_SRC
- pd_update_try_source();
-#endif
-}
-
-void pd_set_dual_role(int port, enum pd_dual_role_states state)
-{
- pd_set_dual_role_no_wakeup(port, state);
-
- /* Wake task up to process change */
- task_set_event(PD_PORT_TO_TASK_ID(port),
- PD_EVENT_UPDATE_DUAL_ROLE, 0);
-}
-
-/* This must only be called from the PD task */
-static void pd_update_dual_role_config(int port)
-{
- /*
- * Change to sink if port is currently a source AND (new DRP
- * state is force sink OR new DRP state is either toggle off
- * or debug accessory toggle only and we are in the source
- * disconnected state).
- */
- if (pd[port].power_role == PD_ROLE_SOURCE &&
- ((drp_state[port] == PD_DRP_FORCE_SINK && !pd_ts_dts_plugged(port))
- || (drp_state[port] == PD_DRP_TOGGLE_OFF
- && pd[port].task_state == PD_STATE_SRC_DISCONNECTED))) {
- pd_set_power_role(port, PD_ROLE_SINK);
- set_state(port, PD_STATE_SNK_DISCONNECTED);
- tcpm_set_cc(port, TYPEC_CC_RD);
- /* Make sure we're not sourcing VBUS. */
- pd_power_supply_reset(port);
- }
-
- /*
- * Change to source if port is currently a sink and the
- * new DRP state is force source.
- */
- if (pd[port].power_role == PD_ROLE_SINK &&
- drp_state[port] == PD_DRP_FORCE_SOURCE) {
- pd_set_power_role(port, PD_ROLE_SOURCE);
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- tcpm_set_cc(port, TYPEC_CC_RP);
- }
-}
-
-int pd_get_role(int port)
-{
- return pd[port].power_role;
-}
-
-static int pd_is_power_swapping(int port)
-{
- /* return true if in the act of swapping power roles */
- return pd[port].task_state == PD_STATE_SNK_SWAP_SNK_DISABLE ||
- pd[port].task_state == PD_STATE_SNK_SWAP_SRC_DISABLE ||
- pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY ||
- pd[port].task_state == PD_STATE_SNK_SWAP_COMPLETE ||
- pd[port].task_state == PD_STATE_SRC_SWAP_SNK_DISABLE ||
- pd[port].task_state == PD_STATE_SRC_SWAP_SRC_DISABLE ||
- pd[port].task_state == PD_STATE_SRC_SWAP_STANDBY;
-}
-
-/*
- * Provide Rp to ensure the partner port is in a known state (eg. not
- * PD negotiated, not sourcing 20V).
- */
-static void pd_partner_port_reset(int port)
-{
- uint64_t timeout;
- uint8_t flags;
-
- /*
- * If there is no contract in place (or if we fail to read the BBRAM
- * flags), there is no need to reset the partner.
- */
- if (pd_get_saved_port_flags(port, &flags) != EC_SUCCESS ||
- !(flags & PD_BBRMFLG_EXPLICIT_CONTRACT))
- return;
-
- /*
- * If we reach here, an explicit contract is in place.
- *
- * If PD communications are allowed, don't apply Rp. We'll issue a
- * SoftReset later on and renegotiate our contract. This particular
- * condition only applies to unlocked RO images with an explicit
- * contract in place.
- */
- if (pd_comm_is_enabled(port))
- return;
-
- /* If we just lost power, don't apply Rp. */
- if (system_get_reset_flags() &
- (EC_RESET_FLAG_BROWNOUT | EC_RESET_FLAG_POWER_ON))
- return;
-
- /*
- * Clear the active contract bit before we apply Rp in case we
- * intentionally brown out because we cut off our only power supply.
- */
- pd_update_saved_port_flags(port, PD_BBRMFLG_EXPLICIT_CONTRACT, 0);
-
- /* Provide Rp for 200 msec. or until we no longer have VBUS. */
- CPRINTF("C%d Apply Rp!\n", port);
- cflush();
- tcpm_set_cc(port, TYPEC_CC_RP);
- timeout = get_time().val + 200 * MSEC;
-
- while (get_time().val < timeout && pd_is_vbus_present(port))
- msleep(10);
-}
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
-
-int pd_get_polarity(int port)
-{
- return pd[port].polarity;
-}
-
-int pd_get_partner_data_swap_capable(int port)
-{
- /* return data swap capable status of port partner */
- return pd[port].flags & PD_FLAGS_PARTNER_DR_DATA;
-}
-
-#ifdef CONFIG_COMMON_RUNTIME
-void pd_comm_enable(int port, int enable)
-{
- /* We don't check port >= CONFIG_USB_PD_PORT_MAX_COUNT deliberately */
- pd_comm_enabled[port] = enable;
-
- /* If type-C connection, then update the TCPC RX enable */
- if (pd_is_connected(port))
- tcpm_set_rx_enable(port, enable);
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /*
- * If communications are enabled, start hard reset timer for
- * any port in PD_SNK_DISCOVERY.
- */
- if (enable && pd[port].task_state == PD_STATE_SNK_DISCOVERY)
- set_state_timeout(port,
- get_time().val + PD_T_SINK_WAIT_CAP,
- PD_STATE_HARD_RESET_SEND);
-#endif
-}
-#endif
-
-void pd_ping_enable(int port, int enable)
-{
- if (enable)
- pd[port].flags |= PD_FLAGS_PING_ENABLED;
- else
- pd[port].flags &= ~PD_FLAGS_PING_ENABLED;
-}
-
-__overridable uint8_t board_get_src_dts_polarity(int port)
-{
- /*
- * If the port in SRC DTS, the polarity is determined by the board,
- * i.e. what Rp impedance the CC lines are pulled. If this function
- * is not overridden, assume CC1 is primary.
- */
- return 0;
-}
-
-#if defined(CONFIG_CHARGE_MANAGER)
-
-/**
- * Signal power request to indicate a charger update that affects the port.
- */
-void pd_set_new_power_request(int port)
-{
- pd[port].new_power_request = 1;
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-#endif /* CONFIG_CHARGE_MANAGER */
-
-#if defined(CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP) && defined(CONFIG_USBC_SS_MUX)
-/*
- * Backwards compatible DFP does not support USB SS because it applies VBUS
- * before debouncing CC and setting USB SS muxes, but SS detection will fail
- * before we are done debouncing CC.
- */
-#error "Backwards compatible DFP does not support USB"
-#endif
-
-#ifdef CONFIG_COMMON_RUNTIME
-
-/* Initialize globals based on system state. */
-static void pd_init_tasks(void)
-{
- static int initialized;
- int enable = 1;
- int i;
-
- /* Initialize globals once, for all PD tasks. */
- if (initialized)
- return;
-
-#if defined(HAS_TASK_CHIPSET) && defined(CONFIG_USB_PD_DUAL_ROLE)
- /* Set dual-role state based on chipset power state */
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- drp_state[i] = PD_DRP_FORCE_SINK;
- else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND))
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- drp_state[i] = PD_DRP_TOGGLE_OFF;
- else /* CHIPSET_STATE_ON */
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- drp_state[i] = PD_DRP_TOGGLE_ON;
-#endif
-
-#if defined(CONFIG_USB_PD_COMM_DISABLED)
- enable = 0;
-#elif defined(CONFIG_USB_PD_COMM_LOCKED)
- /* Disable PD communication at init if we're in RO and locked. */
- if (!system_is_in_rw() && system_is_locked())
- enable = 0;
-#ifdef CONFIG_VBOOT_EFS
- if (vboot_need_pd_comm())
- enable = 1;
-#endif
-#endif
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- pd_comm_enabled[i] = enable;
- CPRINTS("PD comm %sabled", enable ? "en" : "dis");
-
- initialized = 1;
-}
-#endif /* CONFIG_COMMON_RUNTIME */
-
-#if !defined(CONFIG_USB_PD_TCPC) && defined(CONFIG_USB_PD_DUAL_ROLE)
-static int pd_restart_tcpc(int port)
-{
- if (board_set_tcpc_power_mode) {
- /* force chip reset */
- board_set_tcpc_power_mode(port, 0);
- }
- return tcpm_init(port);
-}
-#endif
-
-/* High-priority interrupt tasks implementations */
-#if defined(HAS_TASK_PD_INT_C0) || defined(HAS_TASK_PD_INT_C1) || \
- defined(HAS_TASK_PD_INT_C2)
-
-/* Used to conditionally compile code in main pd task. */
-#define HAS_DEFFERED_INTERRUPT_HANDLER
-
-/* Events for pd_interrupt_handler_task */
-#define PD_PROCESS_INTERRUPT BIT(0)
-
-static uint8_t pd_int_task_id[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-void schedule_deferred_pd_interrupt(const int port)
-{
- task_set_event(pd_int_task_id[port], PD_PROCESS_INTERRUPT, 0);
-}
-
-/*
- * Theoretically, we may need to support up to 480 USB-PD packets per second for
- * intensive operations such as FW update over PD. This value has tested well
- * preventing watchdog resets with a single bad port partner plugged in.
- */
-#define ALERT_STORM_MAX_COUNT 480
-#define ALERT_STORM_INTERVAL SECOND
-
-/**
- * Main task entry point that handles PD interrupts for a single port
- *
- * @param p The PD port number for which to handle interrupts (pointer is
- * reinterpreted as an integer directly).
- */
-void pd_interrupt_handler_task(void *p)
-{
- const int port = (int) ((intptr_t) p);
- const int port_mask = (PD_STATUS_TCPC_ALERT_0 << port);
- struct {
- int count;
- timestamp_t time;
- } storm_tracker[CONFIG_USB_PD_PORT_MAX_COUNT] = {};
-
- ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT);
-
- pd_int_task_id[port] = task_get_current();
-
- while (1) {
- const int evt = task_wait_event(-1);
-
- if (evt & PD_PROCESS_INTERRUPT) {
- /*
- * While the interrupt signal is asserted; we have more
- * work to do. This effectively makes the interrupt a
- * level-interrupt instead of an edge-interrupt without
- * having to enable/disable a real level-interrupt in
- * multiple locations.
- *
- * Also, if the port is disabled do not process
- * interrupts. Upon existing suspend, we schedule a
- * PD_PROCESS_INTERRUPT to check if we missed anything.
- */
- while ((tcpc_get_alert_status() & port_mask) &&
- pd_is_port_enabled(port)) {
- timestamp_t now;
-
- tcpc_alert(port);
-
- now = get_time();
- if (timestamp_expired(
- storm_tracker[port].time, &now)) {
- /* Reset timer into future */
- storm_tracker[port].time.val =
- now.val + ALERT_STORM_INTERVAL;
-
- /*
- * Start at 1 since we are processing
- * an interrupt now
- */
- storm_tracker[port].count = 1;
- } else if (++storm_tracker[port].count >
- ALERT_STORM_MAX_COUNT) {
- CPRINTS("C%d Interrupt storm detected. "
- "Disabling port for 5 seconds.",
- port);
-
- pd_set_suspend(port, 1);
- pd_deferred_resume(port);
- }
- }
- }
- }
-}
-#endif /* HAS_TASK_PD_INT_C0 || HAS_TASK_PD_INT_C1 || HAS_TASK_PD_INT_C2 */
-
-void pd_task(void *u)
-{
- int head;
- int port = TASK_ID_TO_PD_PORT(task_get_current());
- uint32_t payload[7];
- int timeout = 10*MSEC;
- enum tcpc_cc_voltage_status cc1, cc2;
- int res, incoming_packet = 0;
- int hard_reset_count = 0;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- uint64_t next_role_swap = PD_T_DRP_SNK;
- uint8_t saved_flgs = 0;
-#ifndef CONFIG_USB_PD_VBUS_DETECT_NONE
- int snk_hard_reset_vbus_off = 0;
-#endif
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- const int auto_toggle_supported = tcpm_auto_toggle_supported(port);
-#endif
-#if defined(CONFIG_CHARGE_MANAGER)
- typec_current_t typec_curr = 0, typec_curr_change = 0;
-#endif /* CONFIG_CHARGE_MANAGER */
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
- enum pd_states this_state;
- enum pd_cc_states new_cc_state;
- timestamp_t now;
- uint64_t next_src_cap = 0;
- int caps_count = 0, hard_reset_sent = 0;
- int snk_cap_count = 0;
- int evt;
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /*
- * Set the ports in Low Power Mode so that other tasks wait until
- * TCPC is initialized and ready.
- */
- pd[port].flags |= PD_FLAGS_LPM_ENGAGED;
-#endif
-
-#ifdef CONFIG_COMMON_RUNTIME
- pd_init_tasks();
-#endif
-
- /*
- * Ensure the power supply is in the default state and ensure we are not
- * sourcing Vconn
- */
- pd_power_supply_reset(port);
-#ifdef CONFIG_USBC_VCONN
- set_vconn(port, 0);
-#endif
-
- /* Initialize TCPM driver and wait for TCPC to be ready */
- res = reset_device_and_notify(port);
- invalidate_last_message_id(port);
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- pd_partner_port_reset(port);
-#endif
-
- this_state = res ? PD_STATE_SUSPENDED : PD_DEFAULT_STATE(port);
-#ifndef CONFIG_USB_PD_TCPC
- if (!res) {
- struct ec_response_pd_chip_info_v1 *info;
-
- if (tcpm_get_chip_info(port, 0, &info) ==
- EC_SUCCESS) {
- CPRINTS("TCPC p%d VID:0x%x PID:0x%x DID:0x%x "
- "FWV:0x%" PRIx64,
- port, info->vendor_id, info->product_id,
- info->device_id, info->fw_version_number);
- }
- }
-#endif
-
-#ifdef CONFIG_USB_PD_REV30
- /* Set Revision to highest */
- pd[port].rev = PD_REV30;
- pd_ca_reset(port);
-#endif
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /*
- * If VBUS is high, then initialize flag for VBUS has always been
- * present. This flag is used to maintain a PD connection after a
- * reset by sending a soft reset.
- */
- pd[port].flags |=
- pd_is_vbus_present(port) ? PD_FLAGS_VBUS_NEVER_LOW : 0;
-#endif
-
- /* Disable TCPC RX until connection is established */
- tcpm_set_rx_enable(port, 0);
-
-#ifdef CONFIG_USBC_SS_MUX
- /* Initialize USB mux to its default state */
- usb_mux_init(port);
-#endif
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /*
- * If there's an explicit contract in place, let's restore the data and
- * power roles such that any messages we send to the port partner will
- * still be valid.
- */
- if (pd_comm_is_enabled(port) &&
- (pd_get_saved_port_flags(port, &saved_flgs) == EC_SUCCESS) &&
- (saved_flgs & PD_BBRMFLG_EXPLICIT_CONTRACT)) {
- /* Only attempt to maintain previous sink contracts */
- if ((saved_flgs & PD_BBRMFLG_POWER_ROLE) == PD_ROLE_SINK) {
- pd_set_power_role(port,
- (saved_flgs & PD_BBRMFLG_POWER_ROLE) ?
- PD_ROLE_SOURCE : PD_ROLE_SINK);
- pd_set_data_role(port,
- (saved_flgs & PD_BBRMFLG_DATA_ROLE) ?
- PD_ROLE_DFP : PD_ROLE_UFP);
-#ifdef CONFIG_USBC_VCONN
- pd_set_vconn_role(port,
- (saved_flgs & PD_BBRMFLG_VCONN_ROLE) ?
- PD_ROLE_VCONN_ON : PD_ROLE_VCONN_OFF);
-#endif /* CONFIG_USBC_VCONN */
-
- /*
- * Since there is an explicit contract in place, let's
- * issue a SoftReset such that we can renegotiate with
- * our port partner in order to synchronize our state
- * machines.
- */
- this_state = PD_STATE_SOFT_RESET;
-
- /*
- * Re-discover any alternate modes we may have been
- * using with this port partner.
- */
- pd[port].flags |= PD_FLAGS_CHECK_IDENTITY;
- } else {
- /*
- * Vbus was turned off during the power supply reset
- * earlier, so clear the contract flag and re-start as
- * default role
- */
- pd_update_saved_port_flags(port,
- PD_BBRMFLG_EXPLICIT_CONTRACT, 0);
-
- }
- /*
- * Set the TCPC reset event such that we can set our CC
- * terminations, determine polarity, and enable RX so we
- * can hear back from our port partner if maintaining our old
- * connection.
- */
- task_set_event(task_get_current(), PD_EVENT_TCPC_RESET, 0);
- }
-#endif /* defined(CONFIG_USB_PD_DUAL_ROLE) */
- /* Set the power role if we haven't already. */
- if (this_state != PD_STATE_SOFT_RESET)
- pd_set_power_role(port, PD_ROLE_DEFAULT(port));
-
- /* Initialize PD protocol state variables for each port. */
- pd[port].vdm_state = VDM_STATE_DONE;
- set_state(port, this_state);
- tcpm_select_rp_value(port, CONFIG_USB_PD_PULLUP);
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /*
- * If we're not in an explicit contract, set our terminations to match
- * our default power role.
- */
- if (!(saved_flgs & PD_BBRMFLG_EXPLICIT_CONTRACT))
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
- tcpm_set_cc(port, PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE ?
- TYPEC_CC_RP : TYPEC_CC_RD);
-
-#ifdef CONFIG_USBC_PPC
- /*
- * Wait to initialize the PPC after setting the correct Rd values in
- * the TCPC otherwise the TCPC might not be pulling the CC lines down
- * when the PPC connects the CC lines from the USB connector to the
- * TCPC cause the source to drop Vbus causing a brown out.
- */
- ppc_init(port);
-#endif
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- /* Initialize PD Policy engine */
- pd_dfp_pe_init(port);
-#endif
-
-#ifdef CONFIG_CHARGE_MANAGER
- /* Initialize PD and type-C supplier current limits to 0 */
- pd_set_input_current_limit(port, 0, 0);
- typec_set_input_current_limit(port, 0, 0);
- charge_manager_update_dualrole(port, CAP_UNKNOWN);
-#endif
-
-#ifdef HAS_DEFFERED_INTERRUPT_HANDLER
- /*
- * Since most boards configure the TCPC interrupt as edge
- * and it is possible that the interrupt line was asserted between init
- * and calling set_state, we need to process any pending interrupts now.
- * Otherwise future interrupts will never fire because another edge
- * never happens. Note this needs to happen after set_state() is called.
- */
- schedule_deferred_pd_interrupt(port);
-#endif
-
- while (1) {
-#ifdef CONFIG_USB_PD_REV30
- /* send any pending messages */
- pd_ca_send_pending(port);
-#endif
- /* process VDM messages last */
- pd_vdm_send_state_machine(port);
-
- /* Verify board specific health status : current, voltages... */
- res = pd_board_checks();
- if (res != EC_SUCCESS) {
- /* cut the power */
- pd_execute_hard_reset(port);
- /* notify the other side of the issue */
- pd_transmit(port, TCPC_TX_HARD_RESET, 0, NULL);
- }
-
- /* wait for next event/packet or timeout expiration */
- evt = task_wait_event(timeout);
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- if (evt & PD_EXIT_LOW_POWER_EVENT_MASK)
- exit_low_power_mode(port);
- if (evt & PD_EVENT_DEVICE_ACCESSED)
- handle_device_access(port);
-#endif
-#ifdef CONFIG_POWER_COMMON
- if (evt & PD_EVENT_POWER_STATE_CHANGE)
- handle_new_power_state(port);
-#endif
-
-#if defined(CONFIG_USB_PD_ALT_MODE_DFP)
- if (evt & PD_EVENT_SYSJUMP) {
- exit_dp_mode(port);
- notify_sysjump_ready(&sysjump_task_waiting);
-
- }
-#endif
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- if (evt & PD_EVENT_UPDATE_DUAL_ROLE)
- pd_update_dual_role_config(port);
-#endif
-
-#ifdef CONFIG_USB_PD_TCPC
- /*
- * run port controller task to check CC and/or read incoming
- * messages
- */
- tcpc_run(port, evt);
-#else
- /* if TCPC has reset, then need to initialize it again */
- if (evt & PD_EVENT_TCPC_RESET) {
- reset_device_and_notify(port);
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- }
-
- if ((evt & PD_EVENT_TCPC_RESET) &&
- (pd[port].task_state != PD_STATE_DRP_AUTO_TOGGLE)) {
-#endif
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- if (pd[port].task_state == PD_STATE_SOFT_RESET) {
- enum tcpc_cc_voltage_status cc1, cc2;
-
- /*
- * Set the terminations to match our power
- * role.
- */
- tcpm_set_cc(port, pd[port].power_role ?
- TYPEC_CC_RP : TYPEC_CC_RD);
-
- /* Determine the polarity. */
- tcpm_get_cc(port, &cc1, &cc2);
- if (pd[port].power_role == PD_ROLE_SINK) {
- pd[port].polarity =
- get_snk_polarity(cc1, cc2);
- } else if (cc_is_snk_dbg_acc(cc1, cc2)) {
- pd[port].polarity =
- board_get_src_dts_polarity(
- port);
- } else {
- pd[port].polarity =
- (cc1 != TYPEC_CC_VOLT_RD);
- }
- } else
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
- {
- /* Ensure CC termination is default */
- tcpm_set_cc(port, PD_ROLE_DEFAULT(port) ==
- PD_ROLE_SOURCE ? TYPEC_CC_RP :
- TYPEC_CC_RD);
- }
-
- /*
- * If we have a stable contract in the default role,
- * then simply update TCPC with some missing info
- * so that we can continue without resetting PD comms.
- * Otherwise, go to the default disconnected state
- * and force renegotiation.
- */
- if (pd[port].vdm_state == VDM_STATE_DONE && (
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- (PD_ROLE_DEFAULT(port) == PD_ROLE_SINK &&
- pd[port].task_state == PD_STATE_SNK_READY) ||
- (pd[port].task_state == PD_STATE_SOFT_RESET) ||
-#endif
- (PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE &&
- pd[port].task_state == PD_STATE_SRC_READY))) {
- set_polarity(port, pd[port].polarity);
- tcpm_set_msg_header(port, pd[port].power_role,
- pd[port].data_role);
- tcpm_set_rx_enable(port, 1);
- } else {
- /* Ensure state variables are at default */
- pd_set_power_role(port, PD_ROLE_DEFAULT(port));
- pd[port].vdm_state = VDM_STATE_DONE;
- set_state(port, PD_DEFAULT_STATE(port));
- }
- }
-#endif
-
-#ifdef CONFIG_USBC_PPC
- /*
- * TODO: Useful for non-PPC cases as well, but only needed
- * for PPC cases right now. Revisit later.
- */
- if (evt & PD_EVENT_SEND_HARD_RESET)
- set_state(port, PD_STATE_HARD_RESET_SEND);
-#endif /* defined(CONFIG_USBC_PPC) */
-
- /* process any potential incoming message */
- incoming_packet = tcpm_has_pending_message(port);
- if (incoming_packet) {
- /* Dequeue and consume duplicate message ID. */
- if (tcpm_dequeue_message(port, payload, &head) ==
- EC_SUCCESS
- && !consume_repeat_message(port, head)
- )
- handle_request(port, head, payload);
-
- /* Check if there are any more messages */
- if (tcpm_has_pending_message(port))
- task_set_event(PD_PORT_TO_TASK_ID(port),
- TASK_EVENT_WAKE, 0);
- }
-
- if (pd[port].req_suspend_state)
- set_state(port, PD_STATE_SUSPENDED);
-
- /* if nothing to do, verify the state of the world in 500ms */
- this_state = pd[port].task_state;
- timeout = 500*MSEC;
- switch (this_state) {
- case PD_STATE_DISABLED:
- /* Nothing to do */
- break;
- case PD_STATE_SRC_DISCONNECTED:
- timeout = 10*MSEC;
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /*
- * If SW decided we should be in a low power state and
- * the CC lines did not change, then don't talk with the
- * TCPC otherwise we might wake it up.
- */
- if (pd[port].flags & PD_FLAGS_LPM_REQUESTED &&
- !(evt & PD_EVENT_CC)) {
- timeout = -1;
- break;
- }
-#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */
-
- tcpm_get_cc(port, &cc1, &cc2);
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- /*
- * Attempt TCPC auto DRP toggle if it is
- * not already auto toggling and not try.src
- */
- if (auto_toggle_supported &&
- !(pd[port].flags & PD_FLAGS_TCPC_DRP_TOGGLE) &&
- !is_try_src(port) &&
- cc_is_open(cc1, cc2)) {
- set_state(port, PD_STATE_DRP_AUTO_TOGGLE);
- timeout = 2*MSEC;
- break;
- }
-#endif
- /*
- * Transition to DEBOUNCE if we detect appropriate
- * signals
- *
- * (from 4.5.2.2.10.2 Exiting from Try.SRC State)
- * If try_src -and-
- * have only one Rd (not both) => DEBOUNCE
- *
- * (from 4.5.2.2.7.2 Exiting from Unattached.SRC State)
- * If not try_src -and-
- * have at least one Rd => DEBOUNCE -or-
- * have audio access => DEBOUNCE
- *
- * try_src should not exit if both pins are Rd
- */
- if ((is_try_src(port) && cc_is_only_one_rd(cc1, cc2)) ||
- (!is_try_src(port) &&
- (cc_is_at_least_one_rd(cc1, cc2) ||
- cc_is_audio_acc(cc1, cc2)))) {
-#ifdef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP
- /* Enable VBUS */
- if (pd_set_power_supply_ready(port))
- break;
-#endif
- pd[port].cc_state = PD_CC_NONE;
- set_state(port,
- PD_STATE_SRC_DISCONNECTED_DEBOUNCE);
- break;
- }
-#if defined(CONFIG_USB_PD_DUAL_ROLE)
- now = get_time();
- /*
- * Try.SRC state is embedded here. The port
- * shall transition to TryWait.SNK after
- * tDRPTry (PD_T_DRP_TRY) and Vbus is within
- * vSafe0V, or after tTryTimeout
- * (PD_T_TRY_TIMEOUT). Otherwise we should stay
- * within Try.SRC (break).
- */
- if (is_try_src(port)) {
- if (now.val < pd[port].try_src_marker) {
- break;
- } else if (now.val < pd[port].try_timeout) {
- if (pd_is_vbus_present(port))
- break;
- }
-
- /*
- * Transition to TryWait.SNK now, so set
- * state and update src marker time.
- */
- set_state(port, PD_STATE_SNK_DISCONNECTED);
- pd_set_power_role(port, PD_ROLE_SINK);
- tcpm_set_cc(port, TYPEC_CC_RD);
- pd[port].try_src_marker =
- get_time().val + PD_T_DEBOUNCE;
- timeout = 2 * MSEC;
- break;
- }
-
- /*
- * If Try.SRC state is not active, then handle
- * the normal DRP toggle from SRC->SNK.
- */
- if (now.val < next_role_swap ||
- drp_state[port] == PD_DRP_FORCE_SOURCE ||
- drp_state[port] == PD_DRP_FREEZE)
- break;
-
- /*
- * Transition to SNK now, so set state and
- * update next role swap time.
- */
- set_state(port, PD_STATE_SNK_DISCONNECTED);
- pd_set_power_role(port, PD_ROLE_SINK);
- tcpm_set_cc(port, TYPEC_CC_RD);
- next_role_swap = get_time().val + PD_T_DRP_SNK;
- /* Swap states quickly */
- timeout = 2 * MSEC;
-#endif
- break;
- case PD_STATE_SRC_DISCONNECTED_DEBOUNCE:
- timeout = 20*MSEC;
- tcpm_get_cc(port, &cc1, &cc2);
-
- if (cc_is_snk_dbg_acc(cc1, cc2)) {
- /* Debug accessory */
- new_cc_state = PD_CC_UFP_DEBUG_ACC;
- } else if (cc_is_at_least_one_rd(cc1, cc2)) {
- /* UFP attached */
- new_cc_state = PD_CC_UFP_ATTACHED;
- } else if (cc_is_audio_acc(cc1, cc2)) {
- /* Audio accessory */
- new_cc_state = PD_CC_UFP_AUDIO_ACC;
- } else {
- /* No UFP */
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- timeout = 5*MSEC;
- break;
- }
-
- /* Set debounce timer */
- if (new_cc_state != pd[port].cc_state) {
- pd[port].cc_debounce =
- get_time().val +
- (is_try_src(port) ? PD_T_DEBOUNCE
- : PD_T_CC_DEBOUNCE);
- pd[port].cc_state = new_cc_state;
- break;
- }
-
- /* Debounce the cc state */
- if (get_time().val < pd[port].cc_debounce)
- break;
-
- /* Debounce complete */
- if (IS_ENABLED(CONFIG_COMMON_RUNTIME))
- hook_notify(HOOK_USB_PD_CONNECT);
-
-#ifdef CONFIG_USBC_PPC
- /*
- * If the port is latched off, just continue to
- * monitor for a detach.
- */
- if (ppc_is_port_latched_off(port))
- break;
-#endif /* CONFIG_USBC_PPC */
-
- /* UFP is attached */
- if (new_cc_state == PD_CC_UFP_ATTACHED ||
- new_cc_state == PD_CC_UFP_DEBUG_ACC) {
-#ifdef CONFIG_USBC_PPC
- /* Inform PPC that a sink is connected. */
- ppc_sink_is_connected(port, 1);
-#endif /* CONFIG_USBC_PPC */
- if (new_cc_state == PD_CC_UFP_DEBUG_ACC) {
- pd[port].polarity =
- board_get_src_dts_polarity(
- port);
- } else {
- pd[port].polarity =
- (cc1 != TYPEC_CC_VOLT_RD);
- }
- set_polarity(port, pd[port].polarity);
-
- /* initial data role for source is DFP */
- pd_set_data_role(port, PD_ROLE_DFP);
-
- if (new_cc_state == PD_CC_UFP_DEBUG_ACC)
- pd[port].flags |=
- PD_FLAGS_TS_DTS_PARTNER;
-
-#ifdef CONFIG_USBC_VCONN
- /*
- * Do not source Vconn when debug accessory is
- * detected. Section 4.5.2.2.17.1 in USB spec
- * v1-3
- */
- if (new_cc_state != PD_CC_UFP_DEBUG_ACC) {
- /*
- * Start sourcing Vconn before Vbus to
- * ensure we are within USB Type-C
- * Spec 1.3 tVconnON.
- */
- set_vconn(port, 1);
- pd_set_vconn_role(port,
- PD_ROLE_VCONN_ON);
- }
-#endif
-
-#ifndef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP
- /* Enable VBUS */
- if (pd_set_power_supply_ready(port)) {
-#ifdef CONFIG_USBC_VCONN
- /* Stop sourcing Vconn if Vbus failed */
- set_vconn(port, 0);
- pd_set_vconn_role(port,
- PD_ROLE_VCONN_OFF);
-#endif /* CONFIG_USBC_VCONN */
-#ifdef CONFIG_USBC_SS_MUX
- usb_mux_set(port, TYPEC_MUX_NONE,
- USB_SWITCH_DISCONNECT,
- pd[port].polarity);
-#endif /* CONFIG_USBC_SS_MUX */
- break;
- }
- /*
- * Set correct Rp value determined during
- * pd_set_power_supply_ready. This should be
- * safe because Vconn is being sourced,
- * preventing incorrect CCD detection.
- */
- tcpm_set_cc(port, TYPEC_CC_RP);
-#endif /* CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP */
- /* If PD comm is enabled, enable TCPC RX */
- if (pd_comm_is_enabled(port))
- tcpm_set_rx_enable(port, 1);
-
- pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE |
- PD_FLAGS_CHECK_DR_ROLE;
- hard_reset_count = 0;
- timeout = 5*MSEC;
- set_state(port, PD_STATE_SRC_STARTUP);
- }
- /*
- * AUDIO_ACC will remain in this state indefinitely
- * until disconnect.
- */
- break;
- case PD_STATE_SRC_HARD_RESET_RECOVER:
- /* Do not continue until hard reset recovery time */
- if (get_time().val < pd[port].src_recover) {
- timeout = 50*MSEC;
- break;
- }
-
-#ifdef CONFIG_USBC_VCONN
- /*
- * Start sourcing Vconn again and set the flag, in case
- * it was 0 due to a previous swap
- */
- set_vconn(port, 1);
- pd_set_vconn_role(port, PD_ROLE_VCONN_ON);
-#endif
-
- /* Enable VBUS */
- timeout = 10*MSEC;
- if (pd_set_power_supply_ready(port)) {
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- break;
- }
-#ifdef CONFIG_USB_PD_TCPM_TCPCI
- /*
- * After transmitting hard reset, TCPM writes
- * to RECEIVE_DETECT register to enable
- * PD message passing.
- */
- if (pd_comm_is_enabled(port))
- tcpm_set_rx_enable(port, 1);
-#endif /* CONFIG_USB_PD_TCPM_TCPCI */
-
- set_state(port, PD_STATE_SRC_STARTUP);
- break;
- case PD_STATE_SRC_STARTUP:
- /* Reset cable attributes and flags */
- reset_pd_cable(port);
- /* Wait for power source to enable */
- if (pd[port].last_state != pd[port].task_state) {
- pd[port].flags |= PD_FLAGS_CHECK_IDENTITY;
- /* reset various counters */
- caps_count = 0;
- pd[port].msg_id = 0;
- snk_cap_count = 0;
- set_state_timeout(
- port,
-#ifdef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP
- /*
- * delay for power supply to start up.
- * subtract out debounce time if coming
- * from debounce state since vbus is
- * on during debounce.
- */
- get_time().val +
- PD_POWER_SUPPLY_TURN_ON_DELAY -
- (pd[port].last_state ==
- PD_STATE_SRC_DISCONNECTED_DEBOUNCE
- ? PD_T_CC_DEBOUNCE : 0),
-#else
- get_time().val +
- PD_POWER_SUPPLY_TURN_ON_DELAY,
-#endif
- PD_STATE_SRC_DISCOVERY);
- }
- break;
- case PD_STATE_SRC_DISCOVERY:
- now = get_time();
- if (pd[port].last_state != pd[port].task_state) {
- caps_count = 0;
- next_src_cap = now.val;
- /*
- * If we have had PD connection with this port
- * partner, then start NoResponseTimer.
- */
- if (pd_capable(port))
- set_state_timeout(port,
- get_time().val +
- PD_T_NO_RESPONSE,
- hard_reset_count <
- PD_HARD_RESET_COUNT ?
- PD_STATE_HARD_RESET_SEND :
- PD_STATE_SRC_DISCONNECTED);
- }
-
- /* Send source cap some minimum number of times */
- if (caps_count < PD_CAPS_COUNT &&
- next_src_cap <= now.val) {
- /* Query capabilities of the other side */
- res = send_source_cap(port);
- /* packet was acked => PD capable device) */
- if (res >= 0) {
- set_state(port,
- PD_STATE_SRC_NEGOCIATE);
- timeout = 10*MSEC;
- hard_reset_count = 0;
- caps_count = 0;
- /* Port partner is PD capable */
- pd[port].flags |=
- PD_FLAGS_PREVIOUS_PD_CONN;
- } else { /* failed, retry later */
- timeout = PD_T_SEND_SOURCE_CAP;
- next_src_cap = now.val +
- PD_T_SEND_SOURCE_CAP;
- caps_count++;
- }
- } else if (caps_count < PD_CAPS_COUNT) {
- timeout = next_src_cap - now.val;
- }
- break;
- case PD_STATE_SRC_NEGOCIATE:
- /* wait for a "Request" message */
- if (pd[port].last_state != pd[port].task_state)
- set_state_timeout(port,
- get_time().val +
- PD_T_SENDER_RESPONSE,
- PD_STATE_HARD_RESET_SEND);
- break;
- case PD_STATE_SRC_ACCEPTED:
- /* Accept sent, wait for enabling the new voltage */
- if (pd[port].last_state != pd[port].task_state)
- set_state_timeout(
- port,
- get_time().val +
- PD_T_SINK_TRANSITION,
- PD_STATE_SRC_POWERED);
- break;
- case PD_STATE_SRC_POWERED:
- /* Switch to the new requested voltage */
- if (pd[port].last_state != pd[port].task_state) {
- pd_transition_voltage(pd[port].requested_idx);
- set_state_timeout(
- port,
- get_time().val +
- PD_POWER_SUPPLY_TURN_ON_DELAY,
- PD_STATE_SRC_TRANSITION);
- }
- break;
- case PD_STATE_SRC_TRANSITION:
- /* the voltage output is good, notify the source */
- res = send_control(port, PD_CTRL_PS_RDY);
- if (res >= 0) {
- timeout = 10*MSEC;
-
- /*
- * Give the sink some time to send any messages
- * before we may send messages of our own. Add
- * some jitter of up to ~192ms, to prevent
- * multiple collisions. This delay also allows
- * the sink device to request power role swap
- * and allow the the accept message to be sent
- * prior to CMD_DISCOVER_IDENT being sent in the
- * SRC_READY state.
- */
- pd[port].ready_state_holdoff_timer =
- get_time().val + SRC_READY_HOLD_OFF_US
- + (get_time().le.lo & 0xf) * 12 * MSEC;
-
- /* it's time to ping regularly the sink */
- set_state(port, PD_STATE_SRC_READY);
- } else {
- /* The sink did not ack, cut the power... */
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- }
- break;
- case PD_STATE_SRC_READY:
- timeout = PD_T_SOURCE_ACTIVITY;
-
- /*
- * Don't send any traffic yet until our holdoff timer
- * has expired. Some devices are chatty once we reach
- * the SRC_READY state and we may end up in a collision
- * of messages if we try to immediately send our
- * interrogations.
- */
- if (get_time().val <=
- pd[port].ready_state_holdoff_timer)
- break;
-
- /*
- * Don't send any PD traffic if we woke up due to
- * incoming packet or if VDO response pending to avoid
- * collisions.
- */
- if (incoming_packet ||
- (pd[port].vdm_state == VDM_STATE_BUSY))
- break;
-
- /* Send updated source capabilities to our partner */
- if (pd[port].flags & PD_FLAGS_UPDATE_SRC_CAPS) {
- res = send_source_cap(port);
- if (res >= 0) {
- set_state(port,
- PD_STATE_SRC_NEGOCIATE);
- pd[port].flags &=
- ~PD_FLAGS_UPDATE_SRC_CAPS;
- }
- break;
- }
-
- /* Send get sink cap if haven't received it yet */
- if (!(pd[port].flags & PD_FLAGS_SNK_CAP_RECVD)) {
- if (++snk_cap_count <= PD_SNK_CAP_RETRIES) {
- /* Get sink cap to know if dual-role device */
- send_control(port, PD_CTRL_GET_SINK_CAP);
- set_state(port, PD_STATE_SRC_GET_SINK_CAP);
- break;
- } else if (debug_level >= 2 &&
- snk_cap_count == PD_SNK_CAP_RETRIES+1) {
- CPRINTF("C%d ERR SNK_CAP\n", port);
- }
- }
-
- /* Check power role policy, which may trigger a swap */
- if (pd[port].flags & PD_FLAGS_CHECK_PR_ROLE) {
- pd_check_pr_role(port, PD_ROLE_SOURCE,
- pd[port].flags);
- pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE;
- break;
- }
-
- /* Check data role policy, which may trigger a swap */
- if (pd[port].flags & PD_FLAGS_CHECK_DR_ROLE) {
- pd_check_dr_role(port, pd[port].data_role,
- pd[port].flags);
- pd[port].flags &= ~PD_FLAGS_CHECK_DR_ROLE;
- break;
- }
-
- /* Send discovery SVDMs last */
- if (pd[port].data_role == PD_ROLE_DFP &&
- (pd[port].flags & PD_FLAGS_CHECK_IDENTITY)) {
-#ifndef CONFIG_USB_PD_SIMPLE_DFP
- pd_send_vdm(port, USB_SID_PD,
- CMD_DISCOVER_IDENT, NULL, 0);
-#endif
- pd[port].flags &= ~PD_FLAGS_CHECK_IDENTITY;
- break;
- }
-
- if (!(pd[port].flags & PD_FLAGS_PING_ENABLED))
- break;
-
- /* Verify that the sink is alive */
- res = send_control(port, PD_CTRL_PING);
- if (res >= 0)
- break;
-
- /* Ping dropped. Try soft reset. */
- set_state(port, PD_STATE_SOFT_RESET);
- timeout = 10 * MSEC;
- break;
- case PD_STATE_SRC_GET_SINK_CAP:
- if (pd[port].last_state != pd[port].task_state)
- set_state_timeout(port,
- get_time().val +
- PD_T_SENDER_RESPONSE,
- PD_STATE_SRC_READY);
- break;
- case PD_STATE_DR_SWAP:
- if (pd[port].last_state != pd[port].task_state) {
- res = send_control(port, PD_CTRL_DR_SWAP);
- if (res < 0) {
- timeout = 10*MSEC;
- /*
- * If failed to get goodCRC, send
- * soft reset, otherwise ignore
- * failure.
- */
- set_state(port, res == -1 ?
- PD_STATE_SOFT_RESET :
- READY_RETURN_STATE(port));
- break;
- }
- /* Wait for accept or reject */
- set_state_timeout(port,
- get_time().val +
- PD_T_SENDER_RESPONSE,
- READY_RETURN_STATE(port));
- }
- break;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- case PD_STATE_SRC_SWAP_INIT:
- if (pd[port].last_state != pd[port].task_state) {
- res = send_control(port, PD_CTRL_PR_SWAP);
- if (res < 0) {
- timeout = 10*MSEC;
- /*
- * If failed to get goodCRC, send
- * soft reset, otherwise ignore
- * failure.
- */
- set_state(port, res == -1 ?
- PD_STATE_SOFT_RESET :
- PD_STATE_SRC_READY);
- break;
- }
- /* Wait for accept or reject */
- set_state_timeout(port,
- get_time().val +
- PD_T_SENDER_RESPONSE,
- PD_STATE_SRC_READY);
- }
- break;
- case PD_STATE_SRC_SWAP_SNK_DISABLE:
- /* Give time for sink to stop drawing current */
- if (pd[port].last_state != pd[port].task_state)
- set_state_timeout(port,
- get_time().val +
- PD_T_SINK_TRANSITION,
- PD_STATE_SRC_SWAP_SRC_DISABLE);
- break;
- case PD_STATE_SRC_SWAP_SRC_DISABLE:
- if (pd[port].last_state != pd[port].task_state) {
- /* Turn power off */
- pd_power_supply_reset(port);
-
- /*
- * Switch to Rd and swap roles to sink
- *
- * The reason we do this as early as possible is
- * to help prevent CC disconnection cases where
- * both partners are applying an Rp. Certain PD
- * stacks (e.g. qualcomm), reflexively apply
- * their Rp once VBUS falls beneath
- * ~3.67V. (b/77827528).
- */
- tcpm_set_cc(port, TYPEC_CC_RD);
- pd_set_power_role(port, PD_ROLE_SINK);
-
- /* Inform TCPC of power role update. */
- pd_update_roles(port);
-
- set_state_timeout(port,
- get_time().val +
- PD_POWER_SUPPLY_TURN_OFF_DELAY,
- PD_STATE_SRC_SWAP_STANDBY);
- }
- break;
- case PD_STATE_SRC_SWAP_STANDBY:
- /* Send PS_RDY to let sink know our power is off */
- if (pd[port].last_state != pd[port].task_state) {
- /* Send PS_RDY */
- res = send_control(port, PD_CTRL_PS_RDY);
- if (res < 0) {
- timeout = 10*MSEC;
- set_state(port,
- PD_STATE_SRC_DISCONNECTED);
- break;
- }
- /* Wait for PS_RDY from new source */
- set_state_timeout(port,
- get_time().val +
- PD_T_PS_SOURCE_ON,
- PD_STATE_SNK_DISCONNECTED);
- }
- break;
- case PD_STATE_SUSPENDED: {
-#ifndef CONFIG_USB_PD_TCPC
- int rstatus;
-#endif
- CPRINTS("TCPC p%d suspended!", port);
- pd[port].req_suspend_state = 0;
-#ifdef CONFIG_USB_PD_TCPC
- pd_rx_disable_monitoring(port);
- pd_hw_release(port);
- pd_power_supply_reset(port);
-#else
- pd_power_supply_reset(port);
-#ifdef CONFIG_USBC_VCONN
- set_vconn(port, 0);
-#endif
- rstatus = tcpm_release(port);
- if (rstatus != 0 && rstatus != EC_ERROR_UNIMPLEMENTED)
- CPRINTS("TCPC p%d release failed!", port);
-#endif
- /* Drain any outstanding software message queues. */
- tcpm_clear_pending_messages(port);
-
- /* Wait for resume */
- while (pd[port].task_state == PD_STATE_SUSPENDED) {
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- int evt = task_wait_event(-1);
-
- if (evt & PD_EVENT_SYSJUMP)
- /* Nothing to do for sysjump prep */
- notify_sysjump_ready(
- &sysjump_task_waiting);
-#else
- task_wait_event(-1);
-#endif
- }
-#ifdef CONFIG_USB_PD_TCPC
- pd_hw_init(port, PD_ROLE_DEFAULT(port));
- CPRINTS("TCPC p%d resumed!", port);
-#else
- if (rstatus != EC_ERROR_UNIMPLEMENTED &&
- pd_restart_tcpc(port) != 0) {
- /* stay in PD_STATE_SUSPENDED */
- CPRINTS("TCPC p%d restart failed!", port);
- break;
- }
- /* Set the CC termination and state back to default */
- tcpm_set_cc(port,
- PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE ?
- TYPEC_CC_RP :
- TYPEC_CC_RD);
- set_state(port, PD_DEFAULT_STATE(port));
- CPRINTS("TCPC p%d resumed!", port);
-#endif
- break;
- }
- case PD_STATE_SNK_DISCONNECTED:
-#ifdef CONFIG_USB_PD_LOW_POWER
- timeout = (drp_state[port] !=
- PD_DRP_TOGGLE_ON ? SECOND : 10*MSEC);
-#else
- timeout = 10*MSEC;
-#endif
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /*
- * If SW decided we should be in a low power state and
- * the CC lines did not change, then don't talk with the
- * TCPC otherwise we might wake it up.
- */
- if (pd[port].flags & PD_FLAGS_LPM_REQUESTED &&
- !(evt & PD_EVENT_CC)) {
- timeout = -1;
- break;
- }
-#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */
-
- tcpm_get_cc(port, &cc1, &cc2);
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- /*
- * Attempt TCPC auto DRP toggle if it is not already
- * auto toggling and not try.src, and dual role toggling
- * is allowed.
- */
- if (auto_toggle_supported &&
- !(pd[port].flags & PD_FLAGS_TCPC_DRP_TOGGLE) &&
- !is_try_src(port) &&
- cc_is_open(cc1, cc2) &&
- (drp_state[port] == PD_DRP_TOGGLE_ON)) {
- set_state(port, PD_STATE_DRP_AUTO_TOGGLE);
- timeout = 2*MSEC;
- break;
- }
-#endif
-
- /* Source connection monitoring */
- if (!cc_is_open(cc1, cc2)) {
- pd[port].cc_state = PD_CC_NONE;
- hard_reset_count = 0;
- new_cc_state = PD_CC_NONE;
- pd[port].cc_debounce = get_time().val +
- PD_T_CC_DEBOUNCE;
- set_state(port,
- PD_STATE_SNK_DISCONNECTED_DEBOUNCE);
- timeout = 10*MSEC;
- break;
- }
-
- /*
- * If Try.SRC is active and failed to detect a SNK,
- * then it transitions to TryWait.SNK. Need to prevent
- * normal dual role toggle until tDRPTryWait timer
- * expires.
- */
- if (pd[port].flags & PD_FLAGS_TRY_SRC) {
- if (get_time().val > pd[port].try_src_marker)
- pd[port].flags &= ~PD_FLAGS_TRY_SRC;
- break;
- }
-
- /* If no source detected, check for role toggle. */
- if (drp_state[port] == PD_DRP_TOGGLE_ON &&
- get_time().val >= next_role_swap) {
- /* Swap roles to source */
- pd_set_power_role(port, PD_ROLE_SOURCE);
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- tcpm_set_cc(port, TYPEC_CC_RP);
- next_role_swap = get_time().val + PD_T_DRP_SRC;
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /*
- * Clear low power mode flag as we are swapping
- * states quickly.
- */
- pd[port].flags &= ~PD_FLAGS_LPM_REQUESTED;
-#endif
-
- /* Swap states quickly */
- timeout = 2*MSEC;
- break;
- }
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /*
- * If we are remaining in the SNK_DISCONNECTED state,
- * let's go into low power mode and wait for a change on
- * CC status.
- */
- pd[port].flags |= PD_FLAGS_LPM_REQUESTED;
-#endif/* CONFIG_USB_PD_TCPC_LOW_POWER */
- break;
-
- case PD_STATE_SNK_DISCONNECTED_DEBOUNCE:
- tcpm_get_cc(port, &cc1, &cc2);
-
- if (cc_is_rp(cc1) && cc_is_rp(cc2)) {
- /* Debug accessory */
- new_cc_state = PD_CC_DFP_DEBUG_ACC;
- } else if (cc_is_rp(cc1) || cc_is_rp(cc2)) {
- new_cc_state = PD_CC_DFP_ATTACHED;
- } else {
- /* No connection any more */
- set_state(port, PD_STATE_SNK_DISCONNECTED);
- timeout = 5*MSEC;
- break;
- }
-
- timeout = 20*MSEC;
-
- /* Debounce the cc state */
- if (new_cc_state != pd[port].cc_state) {
- pd[port].cc_debounce = get_time().val +
- PD_T_CC_DEBOUNCE;
- pd[port].cc_state = new_cc_state;
- break;
- }
- /* Wait for CC debounce and VBUS present */
- if (get_time().val < pd[port].cc_debounce ||
- !pd_is_vbus_present(port))
- break;
-
- if (pd_try_src_enable &&
- !(pd[port].flags & PD_FLAGS_TRY_SRC)) {
- /*
- * If TRY_SRC is enabled, but not active,
- * then force attempt to connect as source.
- */
- pd[port].try_src_marker = get_time().val
- + PD_T_DRP_TRY;
- pd[port].try_timeout = get_time().val
- + PD_T_TRY_TIMEOUT;
- /* Swap roles to source */
- pd_set_power_role(port, PD_ROLE_SOURCE);
- tcpm_set_cc(port, TYPEC_CC_RP);
- timeout = 2*MSEC;
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- /* Set flag after the state change */
- pd[port].flags |= PD_FLAGS_TRY_SRC;
- break;
- }
-
- /* We are attached */
- if (IS_ENABLED(CONFIG_COMMON_RUNTIME))
- hook_notify(HOOK_USB_PD_CONNECT);
- pd[port].polarity = get_snk_polarity(cc1, cc2);
- set_polarity(port, pd[port].polarity);
- /* reset message ID on connection */
- pd[port].msg_id = 0;
- /* initial data role for sink is UFP */
- pd_set_data_role(port, PD_ROLE_UFP);
-#if defined(CONFIG_CHARGE_MANAGER)
- typec_curr = usb_get_typec_current_limit(
- pd[port].polarity, cc1, cc2);
- typec_set_input_current_limit(
- port, typec_curr, TYPE_C_VOLTAGE);
-#endif
- /* If PD comm is enabled, enable TCPC RX */
- if (pd_comm_is_enabled(port))
- tcpm_set_rx_enable(port, 1);
-
- /* DFP is attached */
- if (new_cc_state == PD_CC_DFP_ATTACHED ||
- new_cc_state == PD_CC_DFP_DEBUG_ACC) {
- pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE |
- PD_FLAGS_CHECK_DR_ROLE |
- PD_FLAGS_CHECK_IDENTITY;
- /* Reset cable attributes and flags */
- reset_pd_cable(port);
-
- if (new_cc_state == PD_CC_DFP_DEBUG_ACC)
- pd[port].flags |=
- PD_FLAGS_TS_DTS_PARTNER;
- set_state(port, PD_STATE_SNK_DISCOVERY);
- timeout = 10*MSEC;
- hook_call_deferred(
- &pd_usb_billboard_deferred_data,
- PD_T_AME);
- }
- break;
- case PD_STATE_SNK_HARD_RESET_RECOVER:
- if (pd[port].last_state != pd[port].task_state)
- pd[port].flags |= PD_FLAGS_CHECK_IDENTITY;
-#ifdef CONFIG_USB_PD_VBUS_DETECT_NONE
- /*
- * Can't measure vbus state so this is the maximum
- * recovery time for the source.
- */
- if (pd[port].last_state != pd[port].task_state)
- set_state_timeout(port, get_time().val +
- PD_T_SAFE_0V +
- PD_T_SRC_RECOVER_MAX +
- PD_T_SRC_TURN_ON,
- PD_STATE_SNK_DISCONNECTED);
-#else
- /* Wait for VBUS to go low and then high*/
- if (pd[port].last_state != pd[port].task_state) {
- snk_hard_reset_vbus_off = 0;
- set_state_timeout(port,
- get_time().val +
- PD_T_SAFE_0V,
- hard_reset_count <
- PD_HARD_RESET_COUNT ?
- PD_STATE_HARD_RESET_SEND :
- PD_STATE_SNK_DISCOVERY);
- }
-
- if (!pd_is_vbus_present(port) &&
- !snk_hard_reset_vbus_off) {
- /* VBUS has gone low, reset timeout */
- snk_hard_reset_vbus_off = 1;
- set_state_timeout(port,
- get_time().val +
- PD_T_SRC_RECOVER_MAX +
- PD_T_SRC_TURN_ON,
- PD_STATE_SNK_DISCONNECTED);
- }
- if (pd_is_vbus_present(port) &&
- snk_hard_reset_vbus_off) {
-#ifdef CONFIG_USB_PD_TCPM_TCPCI
- /*
- * After transmitting hard reset, TCPM writes
- * to RECEIVE_MESSAGE register to enable
- * PD message passing.
- */
- if (pd_comm_is_enabled(port))
- tcpm_set_rx_enable(port, 1);
-#endif /* CONFIG_USB_PD_TCPM_TCPCI */
-
- /* VBUS went high again */
- set_state(port, PD_STATE_SNK_DISCOVERY);
- timeout = 10*MSEC;
- }
-
- /*
- * Don't need to set timeout because VBUS changing
- * will trigger an interrupt and wake us up.
- */
-#endif
- break;
- case PD_STATE_SNK_DISCOVERY:
- /* Wait for source cap expired only if we are enabled */
- if ((pd[port].last_state != pd[port].task_state)
- && pd_comm_is_enabled(port)) {
-#ifdef CONFIG_USB_PD_RESET_MIN_BATT_SOC
- /*
- * If the battery has not met a configured safe
- * level for hard resets, refrain from starting
- * reset timers as a hard reset could brown out
- * the board. Note this may mean that
- * high-power chargers will stay at 15W until a
- * reset is sent, depending on boot timing.
- */
- int batt_soc = usb_get_battery_soc();
-
- if (batt_soc < CONFIG_USB_PD_RESET_MIN_BATT_SOC)
- pd[port].flags |=
- PD_FLAGS_SNK_WAITING_BATT;
- else
- pd[port].flags &=
- ~PD_FLAGS_SNK_WAITING_BATT;
-#endif
-
- if (pd[port].flags &
- PD_FLAGS_SNK_WAITING_BATT) {
-#ifdef CONFIG_CHARGE_MANAGER
- /*
- * Configure this port as dedicated for
- * now, so it won't be de-selected by
- * the charge manager leaving safe mode.
- */
- charge_manager_update_dualrole(port,
- CAP_DEDICATED);
-#endif
- CPRINTS("C%d: Battery low. "
- "Hold reset timer", port);
- /*
- * If VBUS has never been low, and we timeout
- * waiting for source cap, try a soft reset
- * first, in case we were already in a stable
- * contract before this boot.
- */
- } else if (pd[port].flags &
- PD_FLAGS_VBUS_NEVER_LOW) {
- set_state_timeout(port,
- get_time().val +
- PD_T_SINK_WAIT_CAP,
- PD_STATE_SOFT_RESET);
- /*
- * If we haven't passed hard reset counter,
- * start SinkWaitCapTimer, otherwise start
- * NoResponseTimer.
- */
- } else if (hard_reset_count <
- PD_HARD_RESET_COUNT) {
- set_state_timeout(port,
- get_time().val +
- PD_T_SINK_WAIT_CAP,
- PD_STATE_HARD_RESET_SEND);
- } else if (pd_capable(port)) {
- /* ErrorRecovery */
- set_state_timeout(port,
- get_time().val +
- PD_T_NO_RESPONSE,
- PD_STATE_SNK_DISCONNECTED);
- }
-#if defined(CONFIG_CHARGE_MANAGER)
- /*
- * If we didn't come from disconnected, must
- * have come from some path that did not set
- * typec current limit. So, set to 0 so that
- * we guarantee this is revised below.
- */
- if (pd[port].last_state !=
- PD_STATE_SNK_DISCONNECTED_DEBOUNCE)
- typec_curr = 0;
-#endif
- }
-
-#if defined(CONFIG_CHARGE_MANAGER)
- timeout = PD_T_SINK_ADJ - PD_T_DEBOUNCE;
-
- /* Check if CC pull-up has changed */
- tcpm_get_cc(port, &cc1, &cc2);
- if (typec_curr != usb_get_typec_current_limit(
- pd[port].polarity, cc1, cc2)) {
- /* debounce signal by requiring two reads */
- if (typec_curr_change) {
- /* set new input current limit */
- typec_curr =
- usb_get_typec_current_limit(
- pd[port].polarity,
- cc1, cc2);
- typec_set_input_current_limit(
- port, typec_curr, TYPE_C_VOLTAGE);
- } else {
- /* delay for debounce */
- timeout = PD_T_DEBOUNCE;
- }
- typec_curr_change = !typec_curr_change;
- } else {
- typec_curr_change = 0;
- }
-#endif
- break;
- case PD_STATE_SNK_REQUESTED:
- /* Wait for ACCEPT or REJECT */
- if (pd[port].last_state != pd[port].task_state) {
- hard_reset_count = 0;
- set_state_timeout(port,
- get_time().val +
- PD_T_SENDER_RESPONSE,
- PD_STATE_HARD_RESET_SEND);
- }
- break;
- case PD_STATE_SNK_TRANSITION:
- /* Wait for PS_RDY */
- if (pd[port].last_state != pd[port].task_state)
- set_state_timeout(port,
- get_time().val +
- PD_T_PS_TRANSITION,
- PD_STATE_HARD_RESET_SEND);
- break;
- case PD_STATE_SNK_READY:
- timeout = 20*MSEC;
-
- /*
- * Don't send any traffic yet until our holdoff timer
- * has expired. Some devices are chatty once we reach
- * the SNK_READY state and we may end up in a collision
- * of messages if we try to immediately send our
- * interrogations.
- */
- if (get_time().val <=
- pd[port].ready_state_holdoff_timer)
- break;
-
- /*
- * Don't send any PD traffic if we woke up due to
- * incoming packet or if VDO response pending to avoid
- * collisions.
- */
- if (incoming_packet ||
- (pd[port].vdm_state == VDM_STATE_BUSY))
- break;
-
- /* Check for new power to request */
- if (pd[port].new_power_request) {
- if (pd_send_request_msg(port, 0) != EC_SUCCESS)
- set_state(port, PD_STATE_SOFT_RESET);
- break;
- }
-
- /* Check power role policy, which may trigger a swap */
- if (pd[port].flags & PD_FLAGS_CHECK_PR_ROLE) {
- pd_check_pr_role(port, PD_ROLE_SINK,
- pd[port].flags);
- pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE;
- break;
- }
-
- /* Check data role policy, which may trigger a swap */
- if (pd[port].flags & PD_FLAGS_CHECK_DR_ROLE) {
- pd_check_dr_role(port, pd[port].data_role,
- pd[port].flags);
- pd[port].flags &= ~PD_FLAGS_CHECK_DR_ROLE;
- break;
- }
-
- /* If DFP, send discovery SVDMs */
- if (pd[port].data_role == PD_ROLE_DFP &&
- (pd[port].flags & PD_FLAGS_CHECK_IDENTITY)) {
- pd_send_vdm(port, USB_SID_PD,
- CMD_DISCOVER_IDENT, NULL, 0);
- pd[port].flags &= ~PD_FLAGS_CHECK_IDENTITY;
- break;
- }
-
- /* Sent all messages, don't need to wake very often */
- timeout = 200*MSEC;
- break;
- case PD_STATE_SNK_SWAP_INIT:
- if (pd[port].last_state != pd[port].task_state) {
- res = send_control(port, PD_CTRL_PR_SWAP);
- if (res < 0) {
- timeout = 10*MSEC;
- /*
- * If failed to get goodCRC, send
- * soft reset, otherwise ignore
- * failure.
- */
- set_state(port, res == -1 ?
- PD_STATE_SOFT_RESET :
- PD_STATE_SNK_READY);
- break;
- }
- /* Wait for accept or reject */
- set_state_timeout(port,
- get_time().val +
- PD_T_SENDER_RESPONSE,
- PD_STATE_SNK_READY);
- }
- break;
- case PD_STATE_SNK_SWAP_SNK_DISABLE:
- /* Stop drawing power */
- pd_set_input_current_limit(port, 0, 0);
-#ifdef CONFIG_CHARGE_MANAGER
- typec_set_input_current_limit(port, 0, 0);
- charge_manager_set_ceil(port,
- CEIL_REQUESTOR_PD,
- CHARGE_CEIL_NONE);
-#endif
- set_state(port, PD_STATE_SNK_SWAP_SRC_DISABLE);
- timeout = 10*MSEC;
- break;
- case PD_STATE_SNK_SWAP_SRC_DISABLE:
- /* Wait for PS_RDY */
- if (pd[port].last_state != pd[port].task_state)
- set_state_timeout(port,
- get_time().val +
- PD_T_PS_SOURCE_OFF,
- PD_STATE_HARD_RESET_SEND);
- break;
- case PD_STATE_SNK_SWAP_STANDBY:
- if (pd[port].last_state != pd[port].task_state) {
- /* Switch to Rp and enable power supply. */
- tcpm_set_cc(port, TYPEC_CC_RP);
- if (pd_set_power_supply_ready(port)) {
- /* Restore Rd */
- tcpm_set_cc(port, TYPEC_CC_RD);
- timeout = 10*MSEC;
- set_state(port,
- PD_STATE_SNK_DISCONNECTED);
- break;
- }
- /* Wait for power supply to turn on */
- set_state_timeout(
- port,
- get_time().val +
- PD_POWER_SUPPLY_TURN_ON_DELAY,
- PD_STATE_SNK_SWAP_COMPLETE);
- }
- break;
- case PD_STATE_SNK_SWAP_COMPLETE:
- /* Send PS_RDY and change to source role */
- res = send_control(port, PD_CTRL_PS_RDY);
- if (res < 0) {
- /* Restore Rd */
- tcpm_set_cc(port, TYPEC_CC_RD);
- pd_power_supply_reset(port);
- timeout = 10 * MSEC;
- set_state(port, PD_STATE_SNK_DISCONNECTED);
- break;
- }
-
- /* Don't send GET_SINK_CAP on swap */
- snk_cap_count = PD_SNK_CAP_RETRIES+1;
- caps_count = 0;
- pd[port].msg_id = 0;
- pd_set_power_role(port, PD_ROLE_SOURCE);
- pd_update_roles(port);
- set_state(port, PD_STATE_SRC_DISCOVERY);
- timeout = 10*MSEC;
- break;
-#ifdef CONFIG_USBC_VCONN_SWAP
- case PD_STATE_VCONN_SWAP_SEND:
- if (pd[port].last_state != pd[port].task_state) {
- res = send_control(port, PD_CTRL_VCONN_SWAP);
- if (res < 0) {
- timeout = 10*MSEC;
- /*
- * If failed to get goodCRC, send
- * soft reset, otherwise ignore
- * failure.
- */
- set_state(port, res == -1 ?
- PD_STATE_SOFT_RESET :
- READY_RETURN_STATE(port));
- break;
- }
- /* Wait for accept or reject */
- set_state_timeout(port,
- get_time().val +
- PD_T_SENDER_RESPONSE,
- READY_RETURN_STATE(port));
- }
- break;
- case PD_STATE_VCONN_SWAP_INIT:
- if (pd[port].last_state != pd[port].task_state) {
- if (!(pd[port].flags & PD_FLAGS_VCONN_ON)) {
- /* Turn VCONN on and wait for it */
- set_vconn(port, 1);
- set_state_timeout(port,
- get_time().val + PD_VCONN_SWAP_DELAY,
- PD_STATE_VCONN_SWAP_READY);
- } else {
- set_state_timeout(port,
- get_time().val + PD_T_VCONN_SOURCE_ON,
- READY_RETURN_STATE(port));
- }
- }
- break;
- case PD_STATE_VCONN_SWAP_READY:
- if (pd[port].last_state != pd[port].task_state) {
- if (!(pd[port].flags & PD_FLAGS_VCONN_ON)) {
- /* VCONN is now on, send PS_RDY */
- pd_set_vconn_role(port,
- PD_ROLE_VCONN_ON);
- res = send_control(port,
- PD_CTRL_PS_RDY);
- if (res == -1) {
- timeout = 10*MSEC;
- /*
- * If failed to get goodCRC,
- * send soft reset
- */
- set_state(port,
- PD_STATE_SOFT_RESET);
- break;
- }
- set_state(port,
- READY_RETURN_STATE(port));
- } else {
- /* Turn VCONN off and wait for it */
- set_vconn(port, 0);
- pd_set_vconn_role(port,
- PD_ROLE_VCONN_OFF);
- set_state_timeout(port,
- get_time().val + PD_VCONN_SWAP_DELAY,
- READY_RETURN_STATE(port));
- }
- }
- break;
-#endif /* CONFIG_USBC_VCONN_SWAP */
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
- case PD_STATE_SOFT_RESET:
- if (pd[port].last_state != pd[port].task_state) {
- /* Message ID of soft reset is always 0 */
- pd[port].msg_id = 0;
- res = send_control(port, PD_CTRL_SOFT_RESET);
-
- /* if soft reset failed, try hard reset. */
- if (res < 0) {
- set_state(port,
- PD_STATE_HARD_RESET_SEND);
- timeout = 5*MSEC;
- break;
- }
-
- set_state_timeout(
- port,
- get_time().val + PD_T_SENDER_RESPONSE,
- PD_STATE_HARD_RESET_SEND);
- }
- break;
- case PD_STATE_HARD_RESET_SEND:
- hard_reset_count++;
- if (pd[port].last_state != pd[port].task_state) {
- hard_reset_sent = 0;
- pd[port].hard_reset_complete_timer = 0;
- }
-#ifdef CONFIG_CHARGE_MANAGER
- if (pd[port].last_state == PD_STATE_SNK_DISCOVERY ||
- (pd[port].last_state == PD_STATE_SOFT_RESET &&
- (pd[port].flags & PD_FLAGS_VBUS_NEVER_LOW))) {
- pd[port].flags &= ~PD_FLAGS_VBUS_NEVER_LOW;
- /*
- * If discovery timed out, assume that we
- * have a dedicated charger attached. This
- * may not be a correct assumption according
- * to the specification, but it generally
- * works in practice and the harmful
- * effects of a wrong assumption here
- * are minimal.
- */
- charge_manager_update_dualrole(port,
- CAP_DEDICATED);
- }
-#endif
-
- if (hard_reset_sent)
- break;
-
- if (pd_transmit(port, TCPC_TX_HARD_RESET, 0, NULL) <
- 0) {
- /*
- * likely a non-idle channel
- * TCPCI r2.0 v1.0 4.4.15:
- * the TCPC does not retry HARD_RESET
- * but we can try periodically until the timer
- * expires.
- */
- now = get_time();
- if (pd[port].hard_reset_complete_timer == 0) {
- pd[port].hard_reset_complete_timer =
- now.val +
- PD_T_HARD_RESET_COMPLETE;
- timeout = PD_T_HARD_RESET_RETRY;
- break;
- }
- if (now.val <
- pd[port].hard_reset_complete_timer) {
- CPRINTS("C%d: Retrying hard reset",
- port);
- timeout = PD_T_HARD_RESET_RETRY;
- break;
- }
- /*
- * PD 2.0 spec, section 6.5.11.1
- * Pretend TX_HARD_RESET succeeded after
- * timeout.
- */
- }
-
- hard_reset_sent = 1;
- /*
- * If we are source, delay before cutting power
- * to allow sink time to get hard reset.
- */
- if (pd[port].power_role == PD_ROLE_SOURCE) {
- set_state_timeout(port,
- get_time().val + PD_T_PS_HARD_RESET,
- PD_STATE_HARD_RESET_EXECUTE);
- } else {
- set_state(port, PD_STATE_HARD_RESET_EXECUTE);
- timeout = 10 * MSEC;
- }
- break;
- case PD_STATE_HARD_RESET_EXECUTE:
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /*
- * If hard reset while in the last stages of power
- * swap, then we need to restore our CC resistor.
- */
- if (pd[port].last_state == PD_STATE_SNK_SWAP_STANDBY)
- tcpm_set_cc(port, TYPEC_CC_RD);
-#endif
-
- /* reset our own state machine */
- pd_execute_hard_reset(port);
- timeout = 10*MSEC;
- break;
-#ifdef CONFIG_COMMON_RUNTIME
- case PD_STATE_BIST_RX:
- send_bist_cmd(port);
- /* Delay at least enough for partner to finish BIST */
- timeout = PD_T_BIST_RECEIVE + 20*MSEC;
- /* Set to appropriate port disconnected state */
- set_state(port, DUAL_ROLE_IF_ELSE(port,
- PD_STATE_SNK_DISCONNECTED,
- PD_STATE_SRC_DISCONNECTED));
- break;
- case PD_STATE_BIST_TX:
- pd_transmit(port, TCPC_TX_BIST_MODE_2, 0, NULL);
- /* Delay at least enough to finish sending BIST */
- timeout = PD_T_BIST_TRANSMIT + 20*MSEC;
- /* Set to appropriate port disconnected state */
- set_state(port, DUAL_ROLE_IF_ELSE(port,
- PD_STATE_SNK_DISCONNECTED,
- PD_STATE_SRC_DISCONNECTED));
- break;
-#endif
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- case PD_STATE_DRP_AUTO_TOGGLE:
- {
- enum pd_drp_next_states next_state;
-
- assert(auto_toggle_supported);
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /*
- * If SW decided we should be in a low power state and
- * the CC lines did not change, then don't talk with the
- * TCPC otherwise we might wake it up.
- */
- if (pd[port].flags & PD_FLAGS_LPM_REQUESTED &&
- !(evt & PD_EVENT_CC))
- break;
-#endif
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- next_state = drp_auto_toggle_next_state(
- &pd[port].drp_sink_time,
- pd[port].power_role,
- drp_state[port],
- cc1, cc2);
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /*
- * The next state is not determined just by what is
- * attached, but also depends on DRP_STATE. Regardless
- * of next state, if nothing is attached, then always
- * request low power mode.
- */
- if (cc_is_open(cc1, cc2))
- pd[port].flags |= PD_FLAGS_LPM_REQUESTED;
-#endif
- if (next_state == DRP_TC_DEFAULT) {
- if (PD_DEFAULT_STATE(port) ==
- PD_STATE_SNK_DISCONNECTED)
- next_state = DRP_TC_UNATTACHED_SNK;
- else
- next_state = DRP_TC_UNATTACHED_SRC;
- }
-
- if (next_state == DRP_TC_UNATTACHED_SNK) {
- tcpm_set_cc(port, TYPEC_CC_RD);
- pd_set_power_role(port, PD_ROLE_SINK);
- timeout = 2*MSEC;
- set_state(port, PD_STATE_SNK_DISCONNECTED);
- } else if (next_state == DRP_TC_UNATTACHED_SRC) {
- tcpm_set_cc(port, TYPEC_CC_RP);
- pd_set_power_role(port, PD_ROLE_SOURCE);
- timeout = 2*MSEC;
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- } else {
- /*
- * We are staying in PD_STATE_DRP_AUTO_TOGGLE,
- * therefore enable auto-toggle.
- */
- tcpm_enable_drp_toggle(port);
- pd[port].flags |= PD_FLAGS_TCPC_DRP_TOGGLE;
- timeout = -1;
- set_state(port, PD_STATE_DRP_AUTO_TOGGLE);
- }
-
- break;
- }
-#endif
- default:
- break;
- }
-
- pd[port].last_state = this_state;
-
- /*
- * Check for state timeout, and if not check if need to adjust
- * timeout value to wake up on the next state timeout.
- */
- now = get_time();
- if (pd[port].timeout) {
- if (now.val >= pd[port].timeout) {
- set_state(port, pd[port].timeout_state);
- /* On a state timeout, run next state soon */
- timeout = timeout < 10*MSEC ? timeout : 10*MSEC;
- } else if (pd[port].timeout - now.val < timeout) {
- timeout = pd[port].timeout - now.val;
- }
- }
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /* Determine if we need to put the TCPC in low power mode */
- if (pd[port].flags & PD_FLAGS_LPM_REQUESTED &&
- !(pd[port].flags & PD_FLAGS_LPM_ENGAGED)) {
- int64_t time_left;
-
- /* If any task prevents LPM, wait another debounce */
- if (pd[port].tasks_preventing_lpm) {
- pd[port].low_power_time =
- PD_LPM_DEBOUNCE_US + now.val;
- }
-
- time_left = pd[port].low_power_time - now.val;
- if (time_left <= 0) {
- pd[port].flags |= PD_FLAGS_LPM_ENGAGED;
- pd[port].flags |= PD_FLAGS_LPM_TRANSITION;
- tcpm_enter_low_power_mode(port);
- pd[port].flags &= ~PD_FLAGS_LPM_TRANSITION;
- CPRINTS("TCPC p%d Enter Low Power Mode", port);
- timeout = -1;
- } else if (timeout < 0 || timeout > time_left) {
- timeout = time_left;
- }
- }
-#endif
-
- /* Check for disconnection if we're connected */
- if (!pd_is_connected(port))
- continue;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- if (pd_is_power_swapping(port))
- continue;
-#endif
- if (pd[port].power_role == PD_ROLE_SOURCE) {
- /* Source: detect disconnect by monitoring CC */
- tcpm_get_cc(port, &cc1, &cc2);
- if (pd[port].polarity)
- cc1 = cc2;
- if (cc1 == TYPEC_CC_VOLT_OPEN) {
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- /* Debouncing */
- timeout = 10*MSEC;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /*
- * If Try.SRC is configured, then ATTACHED_SRC
- * needs to transition to TryWait.SNK. Change
- * power role to SNK and start state timer.
- */
- if (pd_try_src_enable) {
- /* Swap roles to sink */
- pd_set_power_role(port, PD_ROLE_SINK);
- tcpm_set_cc(port, TYPEC_CC_RD);
- /* Set timer for TryWait.SNK state */
- pd[port].try_src_marker = get_time().val
- + PD_T_DEBOUNCE;
- /* Advance to TryWait.SNK state */
- set_state(port,
- PD_STATE_SNK_DISCONNECTED);
- /* Mark state as TryWait.SNK */
- pd[port].flags |= PD_FLAGS_TRY_SRC;
- }
-#endif
- }
- }
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /*
- * Sink disconnect if VBUS is low and
- * 1) we are not waiting for VBUS to debounce after a power
- * role swap.
- * 2) we are not recovering from a hard reset.
- */
- if (pd[port].power_role == PD_ROLE_SINK &&
- pd[port].vbus_debounce_time < get_time().val &&
- !pd_is_vbus_present(port) &&
- pd[port].task_state != PD_STATE_SNK_HARD_RESET_RECOVER &&
- pd[port].task_state != PD_STATE_HARD_RESET_EXECUTE) {
- /* Sink: detect disconnect by monitoring VBUS */
- set_state(port, PD_STATE_SNK_DISCONNECTED);
- /* set timeout small to reconnect fast */
- timeout = 5*MSEC;
- }
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
- }
-}
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-static void pd_chipset_resume(void)
-{
- int i;
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
-#ifdef CONFIG_CHARGE_MANAGER
- if (charge_manager_get_active_charge_port() != i)
-#endif
- pd[i].flags |= PD_FLAGS_CHECK_PR_ROLE |
- PD_FLAGS_CHECK_DR_ROLE;
- pd_set_dual_role(i, PD_DRP_TOGGLE_ON);
- }
-
- CPRINTS("PD:S3->S0");
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, pd_chipset_resume, HOOK_PRIO_DEFAULT);
-
-static void pd_chipset_suspend(void)
-{
- int i;
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- pd_set_dual_role(i, PD_DRP_TOGGLE_OFF);
- CPRINTS("PD:S0->S3");
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, pd_chipset_suspend, HOOK_PRIO_DEFAULT);
-
-static void pd_chipset_startup(void)
-{
- int i;
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- pd_set_dual_role_no_wakeup(i, PD_DRP_TOGGLE_OFF);
- pd[i].flags |= PD_FLAGS_CHECK_IDENTITY;
- /* Reset cable attributes and flags */
- reset_pd_cable(i);
- task_set_event(PD_PORT_TO_TASK_ID(i),
- PD_EVENT_POWER_STATE_CHANGE |
- PD_EVENT_UPDATE_DUAL_ROLE,
- 0);
- }
- CPRINTS("PD:S5->S3");
-}
-DECLARE_HOOK(HOOK_CHIPSET_STARTUP, pd_chipset_startup, HOOK_PRIO_DEFAULT);
-
-static void pd_chipset_shutdown(void)
-{
- int i;
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- pd_set_dual_role_no_wakeup(i, PD_DRP_FORCE_SINK);
- task_set_event(PD_PORT_TO_TASK_ID(i),
- PD_EVENT_POWER_STATE_CHANGE |
- PD_EVENT_UPDATE_DUAL_ROLE,
- 0);
- }
- CPRINTS("PD:S3->S5");
-}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pd_chipset_shutdown, HOOK_PRIO_DEFAULT);
-
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-void pd_prepare_sysjump(void)
-{
- int i;
-
- /* Exit modes before sysjump so we can cleanly enter again later */
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- /*
- * We can't be in an alternate mode if PD comm is disabled or
- * the port is suspended, so no need to send the event
- */
- if (!pd_comm_is_enabled(i) ||
- pd[i].task_state == PD_STATE_SUSPENDED)
- continue;
-
- sysjump_task_waiting = task_get_current();
- task_set_event(PD_PORT_TO_TASK_ID(i), PD_EVENT_SYSJUMP, 0);
- task_wait_event_mask(TASK_EVENT_SYSJUMP_READY, -1);
- sysjump_task_waiting = TASK_ID_INVALID;
- }
-}
-#endif
-
-#ifdef CONFIG_COMMON_RUNTIME
-
-static void pd_control_resume(int port)
-{
- if (pd[port].task_state != PD_STATE_SUSPENDED)
- return;
-
- set_state(port, PD_DEFAULT_STATE(port));
- /*
- * Since we did not service interrupts while we were suspended,
- * see if there is a waiting interrupt to be serviced. If the
- * interrupt line isn't asserted, we won't communicate with the
- * TCPC.
- */
- if (IS_ENABLED(HAS_TASK_PD_INT_C0))
- schedule_deferred_pd_interrupt(port);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-/*
- * (enable=1) request pd_task transition to the suspended state. hang
- * around for a while until we observe the state change. this can
- * take a while (like 300ms) on startup when pd_task is sleeping in
- * tcpci_tcpm_init.
- *
- * (enable=0) force pd_task out of the suspended state and into the
- * port's default state.
- */
-
-void pd_set_suspend(int port, int enable)
-{
- int tries = 300;
-
- if (enable) {
- pd[port].req_suspend_state = 1;
- do {
- task_wake(PD_PORT_TO_TASK_ID(port));
- if (pd[port].task_state == PD_STATE_SUSPENDED)
- break;
- msleep(1);
- } while (--tries != 0);
- if (!tries)
- CPRINTS("TCPC p%d set_suspend failed!", port);
- } else {
- pd_control_resume(port);
- }
-}
-
-#ifdef CONFIG_USB_PD_TCPM_TCPCI
-static uint32_t pd_ports_to_resume;
-static void resume_pd_port(void)
-{
- uint32_t port;
- uint32_t suspended_ports = atomic_read_clear(&pd_ports_to_resume);
-
- while (suspended_ports) {
- port = __builtin_ctz(suspended_ports);
- suspended_ports &= ~BIT(port);
- pd_set_suspend(port, 0);
- }
-}
-DECLARE_DEFERRED(resume_pd_port);
-
-void pd_deferred_resume(int port)
-{
- atomic_or(&pd_ports_to_resume, 1 << port);
- hook_call_deferred(&resume_pd_port_data, 5 * SECOND);
-}
-
-#endif /* CONFIG_USB_PD_DEFERRED_RESUME */
-
-int pd_is_port_enabled(int port)
-{
- switch (pd[port].task_state) {
- case PD_STATE_DISABLED:
- case PD_STATE_SUSPENDED:
- return 0;
- default:
- return 1;
- }
-}
-
-#if defined(CONFIG_CMD_PD) && defined(CONFIG_CMD_PD_FLASH)
-static int hex8tou32(char *str, uint32_t *val)
-{
- char *ptr = str;
- uint32_t tmp = 0;
-
- while (*ptr) {
- char c = *ptr++;
- if (c >= '0' && c <= '9')
- tmp = (tmp << 4) + (c - '0');
- else if (c >= 'A' && c <= 'F')
- tmp = (tmp << 4) + (c - 'A' + 10);
- else if (c >= 'a' && c <= 'f')
- tmp = (tmp << 4) + (c - 'a' + 10);
- else
- return EC_ERROR_INVAL;
- }
- if (ptr != str + 8)
- return EC_ERROR_INVAL;
- *val = tmp;
- return EC_SUCCESS;
-}
-
-static int remote_flashing(int argc, char **argv)
-{
- int port, cnt, cmd;
- uint32_t data[VDO_MAX_SIZE-1];
- char *e;
- static int flash_offset[CONFIG_USB_PD_PORT_MAX_COUNT];
-
- if (argc < 4 || argc > (VDO_MAX_SIZE + 4 - 1))
- return EC_ERROR_PARAM_COUNT;
-
- port = strtoi(argv[1], &e, 10);
- if (*e || port >= board_get_usb_pd_port_count())
- return EC_ERROR_PARAM2;
-
- cnt = 0;
- if (!strcasecmp(argv[3], "erase")) {
- cmd = VDO_CMD_FLASH_ERASE;
- flash_offset[port] = 0;
- ccprintf("ERASE ...");
- } else if (!strcasecmp(argv[3], "reboot")) {
- cmd = VDO_CMD_REBOOT;
- ccprintf("REBOOT ...");
- } else if (!strcasecmp(argv[3], "signature")) {
- cmd = VDO_CMD_ERASE_SIG;
- ccprintf("ERASE SIG ...");
- } else if (!strcasecmp(argv[3], "info")) {
- cmd = VDO_CMD_READ_INFO;
- ccprintf("INFO...");
- } else if (!strcasecmp(argv[3], "version")) {
- cmd = VDO_CMD_VERSION;
- ccprintf("VERSION...");
- } else {
- int i;
- argc -= 3;
- for (i = 0; i < argc; i++)
- if (hex8tou32(argv[i+3], data + i))
- return EC_ERROR_INVAL;
- cmd = VDO_CMD_FLASH_WRITE;
- cnt = argc;
- ccprintf("WRITE %d @%04x ...", argc * 4,
- flash_offset[port]);
- flash_offset[port] += argc * 4;
- }
-
- pd_send_vdm(port, USB_VID_GOOGLE, cmd, data, cnt);
-
- /* Wait until VDM is done */
- while (pd[port].vdm_state > 0)
- task_wait_event(100*MSEC);
-
- ccprintf("DONE %d\n", pd[port].vdm_state);
- return EC_SUCCESS;
-}
-#endif /* defined(CONFIG_CMD_PD) && defined(CONFIG_CMD_PD_FLASH) */
-
-#if defined(CONFIG_USB_PD_ALT_MODE) && !defined(CONFIG_USB_PD_ALT_MODE_DFP)
-void pd_send_hpd(int port, enum hpd_event hpd)
-{
- uint32_t data[1];
- int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
- if (!opos)
- return;
-
- data[0] = VDO_DP_STATUS((hpd == hpd_irq), /* IRQ_HPD */
- (hpd != hpd_low), /* HPD_HI|LOW */
- 0, /* request exit DP */
- 0, /* request exit USB */
- 0, /* MF pref */
- 1, /* enabled */
- 0, /* power low */
- 0x2);
- pd_send_vdm(port, USB_SID_DISPLAYPORT,
- VDO_OPOS(opos) | CMD_ATTENTION, data, 1);
- /* Wait until VDM is done. */
- while (pd[0].vdm_state > 0)
- task_wait_event(USB_PD_RX_TMOUT_US * (PD_RETRY_COUNT + 1));
-}
-#endif
-
-int pd_fetch_acc_log_entry(int port)
-{
- timestamp_t timeout;
-
- /* Cannot send a VDM now, the host should retry */
- if (pd[port].vdm_state > 0)
- return pd[port].vdm_state == VDM_STATE_BUSY ?
- EC_RES_BUSY : EC_RES_UNAVAILABLE;
-
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_GET_LOG, NULL, 0);
- timeout.val = get_time().val + 75*MSEC;
-
- /* Wait until VDM is done */
- while ((pd[port].vdm_state > 0) &&
- (get_time().val < timeout.val))
- task_wait_event(10*MSEC);
-
- if (pd[port].vdm_state > 0)
- return EC_RES_TIMEOUT;
- else if (pd[port].vdm_state < 0)
- return EC_RES_ERROR;
-
- return EC_RES_SUCCESS;
-}
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-void pd_request_source_voltage(int port, int mv)
-{
- pd_set_max_voltage(mv);
-
- if (pd[port].task_state == PD_STATE_SNK_READY ||
- pd[port].task_state == PD_STATE_SNK_TRANSITION) {
- /* Set flag to send new power request in pd_task */
- pd[port].new_power_request = 1;
- } else {
- pd_set_power_role(port, PD_ROLE_SINK);
- tcpm_set_cc(port, TYPEC_CC_RD);
- set_state(port, PD_STATE_SNK_DISCONNECTED);
- }
-
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void pd_set_external_voltage_limit(int port, int mv)
-{
- pd_set_max_voltage(mv);
-
- if (pd[port].task_state == PD_STATE_SNK_READY ||
- pd[port].task_state == PD_STATE_SNK_TRANSITION) {
- /* Set flag to send new power request in pd_task */
- pd[port].new_power_request = 1;
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-void pd_update_contract(int port)
-{
- if ((pd[port].task_state >= PD_STATE_SRC_NEGOCIATE) &&
- (pd[port].task_state <= PD_STATE_SRC_GET_SINK_CAP)) {
- pd[port].flags |= PD_FLAGS_UPDATE_SRC_CAPS;
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
-
-#ifdef CONFIG_USBC_PPC
-static void pd_send_hard_reset(int port)
-{
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SEND_HARD_RESET, 0);
-}
-
-static uint32_t port_oc_reset_req;
-
-static void re_enable_ports(void)
-{
- uint32_t ports = atomic_read_clear(&port_oc_reset_req);
-
- while (ports) {
- int port = __fls(ports);
-
- ports &= ~BIT(port);
-
- /*
- * Let the board know that the overcurrent is
- * over since we're going to attempt re-enabling
- * the port.
- */
- board_overcurrent_event(port, 0);
-
- pd_send_hard_reset(port);
- /*
- * TODO(b/117854867): PD3.0 to send an alert message
- * indicating OCP after explicit contract.
- */
- }
-}
-DECLARE_DEFERRED(re_enable_ports);
-
-void pd_handle_overcurrent(int port)
-{
- /* Keep track of the overcurrent events. */
- CPRINTS("C%d: overcurrent!", port);
-#ifdef CONFIG_USB_PD_LOGGING
- pd_log_event(PD_EVENT_PS_FAULT, PD_LOG_PORT_SIZE(port, 0), PS_FAULT_OCP,
- NULL);
-#endif /* defined(CONFIG_USB_PD_LOGGING) */
- ppc_add_oc_event(port);
- /* Let the board specific code know about the OC event. */
- board_overcurrent_event(port, 1);
-
- /* Wait 1s before trying to re-enable the port. */
- atomic_or(&port_oc_reset_req, BIT(port));
- hook_call_deferred(&re_enable_ports_data, SECOND);
-}
-#endif /* defined(CONFIG_USBC_PPC) */
-
-static int command_pd(int argc, char **argv)
-{
- int port;
- char *e;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- if (!strcasecmp(argv[1], "dump")) {
- if (argc >= 3) {
-#ifdef CONFIG_USB_PD_DEBUG_LEVEL
- return EC_ERROR_PARAM2;
-#else
- int level = strtoi(argv[2], &e, 10);
- if (*e)
- return EC_ERROR_PARAM2;
- debug_level = level;
-#endif
- }
- ccprintf("debug=%d\n", debug_level);
-
- return EC_SUCCESS;
- }
-
-#ifdef CONFIG_CMD_PD
-#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO
- else if (!strncasecmp(argv[1], "rwhashtable", 3)) {
- int i;
- struct ec_params_usb_pd_rw_hash_entry *p;
- for (i = 0; i < RW_HASH_ENTRIES; i++) {
- p = &rw_hash_table[i];
- pd_dev_dump_info(p->dev_id, p->dev_rw_hash);
- }
- return EC_SUCCESS;
- }
-#endif /* CONFIG_CMD_PD_DEV_DUMP_INFO */
-#ifdef CONFIG_USB_PD_TRY_SRC
- else if (!strncasecmp(argv[1], "trysrc", 6)) {
- int enable;
-
- if (argc >= 3) {
- enable = strtoi(argv[2], &e, 10);
- if (*e)
- return EC_ERROR_PARAM3;
- pd_try_src_enable = enable ? 1 : 0;
- }
-
- ccprintf("Try.SRC %s\n", pd_try_src_enable ? "on" : "off");
- return EC_SUCCESS;
- }
-#endif
-#endif
- /* command: pd <port> <subcmd> [args] */
- port = strtoi(argv[1], &e, 10);
- if (argc < 3)
- return EC_ERROR_PARAM_COUNT;
- if (*e || port >= board_get_usb_pd_port_count())
- return EC_ERROR_PARAM2;
-#if defined(CONFIG_CMD_PD) && defined(CONFIG_USB_PD_DUAL_ROLE)
-
- if (!strcasecmp(argv[2], "tx")) {
- set_state(port, PD_STATE_SNK_DISCOVERY);
- task_wake(PD_PORT_TO_TASK_ID(port));
- } else if (!strcasecmp(argv[2], "bist_rx")) {
- set_state(port, PD_STATE_BIST_RX);
- task_wake(PD_PORT_TO_TASK_ID(port));
- } else if (!strcasecmp(argv[2], "bist_tx")) {
- if (*e)
- return EC_ERROR_PARAM3;
- set_state(port, PD_STATE_BIST_TX);
- task_wake(PD_PORT_TO_TASK_ID(port));
- } else if (!strcasecmp(argv[2], "charger")) {
- pd_set_power_role(port, PD_ROLE_SOURCE);
- tcpm_set_cc(port, TYPEC_CC_RP);
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- task_wake(PD_PORT_TO_TASK_ID(port));
- } else if (!strncasecmp(argv[2], "dev", 3)) {
- int max_volt;
- if (argc >= 4)
- max_volt = strtoi(argv[3], &e, 10) * 1000;
- else
- max_volt = pd_get_max_voltage();
-
- pd_request_source_voltage(port, max_volt);
- ccprintf("max req: %dmV\n", max_volt);
- } else if (!strcasecmp(argv[2], "disable")) {
- pd_comm_enable(port, 0);
- ccprintf("Port C%d disable\n", port);
- return EC_SUCCESS;
- } else if (!strcasecmp(argv[2], "enable")) {
- pd_comm_enable(port, 1);
- ccprintf("Port C%d enabled\n", port);
- return EC_SUCCESS;
- } else if (!strncasecmp(argv[2], "hard", 4)) {
- set_state(port, PD_STATE_HARD_RESET_SEND);
- task_wake(PD_PORT_TO_TASK_ID(port));
- } else if (!strncasecmp(argv[2], "info", 4)) {
- int i;
- ccprintf("Hash ");
- for (i = 0; i < PD_RW_HASH_SIZE / 4; i++)
- ccprintf("%08x ", pd[port].dev_rw_hash[i]);
- ccprintf("\nImage %s\n", system_image_copy_t_to_string(
- (enum system_image_copy_t)pd[port].current_image));
- } else if (!strncasecmp(argv[2], "soft", 4)) {
- set_state(port, PD_STATE_SOFT_RESET);
- task_wake(PD_PORT_TO_TASK_ID(port));
- } else if (!strncasecmp(argv[2], "swap", 4)) {
- if (argc < 4)
- return EC_ERROR_PARAM_COUNT;
-
- if (!strncasecmp(argv[3], "power", 5))
- pd_request_power_swap(port);
- else if (!strncasecmp(argv[3], "data", 4))
- pd_request_data_swap(port);
-#ifdef CONFIG_USBC_VCONN_SWAP
- else if (!strncasecmp(argv[3], "vconn", 5))
- pd_request_vconn_swap(port);
-#endif
- else
- return EC_ERROR_PARAM3;
- } else if (!strncasecmp(argv[2], "ping", 4)) {
- int enable;
-
- if (argc > 3) {
- enable = strtoi(argv[3], &e, 10);
- if (*e)
- return EC_ERROR_PARAM3;
- pd_ping_enable(port, enable);
- }
-
- ccprintf("Pings %s\n",
- (pd[port].flags & PD_FLAGS_PING_ENABLED) ?
- "on" : "off");
- } else if (!strncasecmp(argv[2], "vdm", 3)) {
- if (argc < 4)
- return EC_ERROR_PARAM_COUNT;
-
- if (!strncasecmp(argv[3], "ping", 4)) {
- uint32_t enable;
- if (argc < 5)
- return EC_ERROR_PARAM_COUNT;
- enable = strtoi(argv[4], &e, 10);
- if (*e)
- return EC_ERROR_PARAM4;
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_PING_ENABLE,
- &enable, 1);
- } else if (!strncasecmp(argv[3], "curr", 4)) {
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_CURRENT,
- NULL, 0);
- } else if (!strncasecmp(argv[3], "vers", 4)) {
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_VERSION,
- NULL, 0);
- } else {
- return EC_ERROR_PARAM_COUNT;
- }
-#if defined(CONFIG_CMD_PD) && defined(CONFIG_CMD_PD_FLASH)
- } else if (!strncasecmp(argv[2], "flash", 4)) {
- return remote_flashing(argc, argv);
-#endif
-#if defined(CONFIG_CMD_PD) && defined(CONFIG_USB_PD_DUAL_ROLE)
- } else if (!strcasecmp(argv[2], "dualrole")) {
- if (argc < 4) {
- ccprintf("dual-role toggling: ");
- switch (drp_state[port]) {
- case PD_DRP_TOGGLE_ON:
- ccprintf("on\n");
- break;
- case PD_DRP_TOGGLE_OFF:
- ccprintf("off\n");
- break;
- case PD_DRP_FREEZE:
- ccprintf("freeze\n");
- break;
- case PD_DRP_FORCE_SINK:
- ccprintf("force sink\n");
- break;
- case PD_DRP_FORCE_SOURCE:
- ccprintf("force source\n");
- break;
- }
- } else {
- if (!strcasecmp(argv[3], "on"))
- pd_set_dual_role(port, PD_DRP_TOGGLE_ON);
- else if (!strcasecmp(argv[3], "off"))
- pd_set_dual_role(port, PD_DRP_TOGGLE_OFF);
- else if (!strcasecmp(argv[3], "freeze"))
- pd_set_dual_role(port, PD_DRP_FREEZE);
- else if (!strcasecmp(argv[3], "sink"))
- pd_set_dual_role(port, PD_DRP_FORCE_SINK);
- else if (!strcasecmp(argv[3], "source"))
- pd_set_dual_role(port,
- PD_DRP_FORCE_SOURCE);
- else
- return EC_ERROR_PARAM4;
- }
- return EC_SUCCESS;
-#endif
- } else
-#endif
- if (!strncasecmp(argv[2], "state", 5)) {
- ccprintf("Port C%d CC%d, %s - Role: %s-%s%s "
- "State: %d(%s), Flags: 0x%04x\n",
- port, pd[port].polarity + 1,
- pd_comm_is_enabled(port) ? "Ena" : "Dis",
- pd[port].power_role == PD_ROLE_SOURCE ? "SRC" : "SNK",
- pd[port].data_role == PD_ROLE_DFP ? "DFP" : "UFP",
- (pd[port].flags & PD_FLAGS_VCONN_ON) ? "-VC" : "",
- pd[port].task_state,
- debug_level > 0 ?
- pd_state_names[pd[port].task_state] : "",
- pd[port].flags);
- } else {
- return EC_ERROR_PARAM1;
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(pd, command_pd,
- "dump"
-#ifdef CONFIG_USB_PD_TRY_SRC
- "|trysrc"
-#endif
- " [0|1|2]"
-#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO
- "|rwhashtable"
-#endif
- "\n\t<port> state"
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- "|tx|bist_rx|bist_tx|charger|dev"
- "\n\t<port> disable|enable|soft|info|hard|ping"
- "\n\t<port> dualrole [on|off|freeze|sink|source]"
- "\n\t<port> swap [power|data|vconn]"
- "\n\t<port> vdm [ping|curr|vers]"
-#ifdef CONFIG_CMD_PD_FLASH
- "\n\t<port> flash [erase|reboot|signature|info|version]"
-#endif /* CONFIG_CMD_PD_FLASH */
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
- ,
- "USB PD");
-
-#ifdef HAS_TASK_HOSTCMD
-
-static enum ec_status hc_pd_ports(struct host_cmd_handler_args *args)
-{
- struct ec_response_usb_pd_ports *r = args->response;
- r->num_ports = board_get_usb_pd_port_count();
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_PORTS,
- hc_pd_ports,
- EC_VER_MASK(0));
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-static const enum pd_dual_role_states dual_role_map[USB_PD_CTRL_ROLE_COUNT] = {
- [USB_PD_CTRL_ROLE_TOGGLE_ON] = PD_DRP_TOGGLE_ON,
- [USB_PD_CTRL_ROLE_TOGGLE_OFF] = PD_DRP_TOGGLE_OFF,
- [USB_PD_CTRL_ROLE_FORCE_SINK] = PD_DRP_FORCE_SINK,
- [USB_PD_CTRL_ROLE_FORCE_SOURCE] = PD_DRP_FORCE_SOURCE,
- [USB_PD_CTRL_ROLE_FREEZE] = PD_DRP_FREEZE,
-};
-#endif
-
-#ifdef CONFIG_USBC_SS_MUX
-static const enum typec_mux typec_mux_map[USB_PD_CTRL_MUX_COUNT] = {
- [USB_PD_CTRL_MUX_NONE] = TYPEC_MUX_NONE,
- [USB_PD_CTRL_MUX_USB] = TYPEC_MUX_USB,
- [USB_PD_CTRL_MUX_AUTO] = TYPEC_MUX_DP,
- [USB_PD_CTRL_MUX_DP] = TYPEC_MUX_DP,
- [USB_PD_CTRL_MUX_DOCK] = TYPEC_MUX_DOCK,
-};
-#endif
-
-__attribute__((weak)) uint8_t board_get_dp_pin_mode(int port)
-{
- return 0;
-}
-
-static enum ec_status hc_usb_pd_control(struct host_cmd_handler_args *args)
-{
- const struct ec_params_usb_pd_control *p = args->params;
- struct ec_response_usb_pd_control_v2 *r_v2 = args->response;
- struct ec_response_usb_pd_control_v1 *r_v1 = args->response;
- struct ec_response_usb_pd_control *r = args->response;
-
- if (p->port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- if (p->role >= USB_PD_CTRL_ROLE_COUNT ||
- p->mux >= USB_PD_CTRL_MUX_COUNT)
- return EC_RES_INVALID_PARAM;
-
- if (p->role != USB_PD_CTRL_ROLE_NO_CHANGE)
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- pd_set_dual_role(p->port, dual_role_map[p->role]);
-#else
- return EC_RES_INVALID_PARAM;
-#endif
-
-#ifdef CONFIG_USBC_SS_MUX
- if (p->mux != USB_PD_CTRL_MUX_NO_CHANGE)
- usb_mux_set(p->port, typec_mux_map[p->mux],
- typec_mux_map[p->mux] == TYPEC_MUX_NONE ?
- USB_SWITCH_DISCONNECT :
- USB_SWITCH_CONNECT,
- pd_get_polarity(p->port));
-#endif /* CONFIG_USBC_SS_MUX */
-
- if (p->swap == USB_PD_CTRL_SWAP_DATA)
- pd_request_data_swap(p->port);
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- else if (p->swap == USB_PD_CTRL_SWAP_POWER)
- pd_request_power_swap(p->port);
-#ifdef CONFIG_USBC_VCONN_SWAP
- else if (p->swap == USB_PD_CTRL_SWAP_VCONN)
- pd_request_vconn_swap(p->port);
-#endif
-#endif
-
- switch (args->version) {
- case 0:
- r->enabled = pd_comm_is_enabled(p->port);
- r->role = pd[p->port].power_role;
- r->polarity = pd[p->port].polarity;
- r->state = pd[p->port].task_state;
- args->response_size = sizeof(*r);
- break;
- case 1:
- case 2:
- r_v2->enabled =
- (pd_comm_is_enabled(p->port) ?
- PD_CTRL_RESP_ENABLED_COMMS : 0) |
- (pd_is_connected(p->port) ?
- PD_CTRL_RESP_ENABLED_CONNECTED : 0) |
- ((pd[p->port].flags & PD_FLAGS_PREVIOUS_PD_CONN) ?
- PD_CTRL_RESP_ENABLED_PD_CAPABLE : 0);
- r_v2->role =
- (pd[p->port].power_role ? PD_CTRL_RESP_ROLE_POWER : 0) |
- (pd[p->port].data_role ? PD_CTRL_RESP_ROLE_DATA : 0) |
- ((pd[p->port].flags & PD_FLAGS_VCONN_ON) ?
- PD_CTRL_RESP_ROLE_VCONN : 0) |
- ((pd[p->port].flags & PD_FLAGS_PARTNER_DR_POWER) ?
- PD_CTRL_RESP_ROLE_DR_POWER : 0) |
- ((pd[p->port].flags & PD_FLAGS_PARTNER_DR_DATA) ?
- PD_CTRL_RESP_ROLE_DR_DATA : 0) |
- ((pd[p->port].flags & PD_FLAGS_PARTNER_USB_COMM) ?
- PD_CTRL_RESP_ROLE_USB_COMM : 0) |
- ((pd[p->port].flags & PD_FLAGS_PARTNER_EXTPOWER) ?
- PD_CTRL_RESP_ROLE_EXT_POWERED : 0);
- r_v2->polarity = pd[p->port].polarity;
-
- if (debug_level > 0)
- strzcpy(r_v2->state,
- pd_state_names[pd[p->port].task_state],
- sizeof(r_v2->state));
- else
- r_v2->state[0] = '\0';
-
- r_v2->cc_state = pd[p->port].cc_state;
- r_v2->dp_mode = board_get_dp_pin_mode(p->port);
- r_v2->cable_type = get_usb_pd_mux_cable_type(p->port);
-
- if (args->version == 1)
- args->response_size = sizeof(*r_v1);
- else
- args->response_size = sizeof(*r_v2);
- break;
- default:
- return EC_RES_INVALID_PARAM;
- }
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_CONTROL,
- hc_usb_pd_control,
- EC_VER_MASK(0) | EC_VER_MASK(1) | EC_VER_MASK(2));
-
-#ifdef CONFIG_HOSTCMD_FLASHPD
-static enum ec_status hc_remote_flash(struct host_cmd_handler_args *args)
-{
- const struct ec_params_usb_pd_fw_update *p = args->params;
- int port = p->port;
- const uint32_t *data = &(p->size) + 1;
- int i, size, rv = EC_RES_SUCCESS;
- timestamp_t timeout;
-
- if (port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- if (p->size + sizeof(*p) > args->params_size)
- return EC_RES_INVALID_PARAM;
-
-#if defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \
- defined(CONFIG_BATTERY_PRESENT_GPIO)
- /*
- * Do not allow PD firmware update if no battery and this port
- * is sinking power, because we will lose power.
- */
- if (battery_is_present() != BP_YES &&
- charge_manager_get_active_charge_port() == port)
- return EC_RES_UNAVAILABLE;
-#endif
-
- /*
- * Busy still with a VDM that host likely generated. 1 deep VDM queue
- * so just return for retry logic on host side to deal with.
- */
- if (pd[port].vdm_state > 0)
- return EC_RES_BUSY;
-
- switch (p->cmd) {
- case USB_PD_FW_REBOOT:
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_REBOOT, NULL, 0);
-
- /*
- * Return immediately to free pending i2c bus. Host needs to
- * manage this delay.
- */
- return EC_RES_SUCCESS;
-
- case USB_PD_FW_FLASH_ERASE:
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_ERASE, NULL, 0);
-
- /*
- * Return immediately. Host needs to manage delays here which
- * can be as long as 1.2 seconds on 64KB RW flash.
- */
- return EC_RES_SUCCESS;
-
- case USB_PD_FW_ERASE_SIG:
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_ERASE_SIG, NULL, 0);
- timeout.val = get_time().val + 500*MSEC;
- break;
-
- case USB_PD_FW_FLASH_WRITE:
- /* Data size must be a multiple of 4 */
- if (!p->size || p->size % 4)
- return EC_RES_INVALID_PARAM;
-
- size = p->size / 4;
- for (i = 0; i < size; i += VDO_MAX_SIZE - 1) {
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_WRITE,
- data + i, MIN(size - i, VDO_MAX_SIZE - 1));
- timeout.val = get_time().val + 500*MSEC;
-
- /* Wait until VDM is done */
- while ((pd[port].vdm_state > 0) &&
- (get_time().val < timeout.val))
- task_wait_event(10*MSEC);
-
- if (pd[port].vdm_state > 0)
- return EC_RES_TIMEOUT;
- }
- return EC_RES_SUCCESS;
-
- default:
- return EC_RES_INVALID_PARAM;
- break;
- }
-
- /* Wait until VDM is done or timeout */
- while ((pd[port].vdm_state > 0) && (get_time().val < timeout.val))
- task_wait_event(50*MSEC);
-
- if ((pd[port].vdm_state > 0) ||
- (pd[port].vdm_state == VDM_STATE_ERR_TMOUT))
- rv = EC_RES_TIMEOUT;
- else if (pd[port].vdm_state < 0)
- rv = EC_RES_ERROR;
-
- return rv;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_FW_UPDATE,
- hc_remote_flash,
- EC_VER_MASK(0));
-#endif /* CONFIG_HOSTCMD_FLASHPD */
-
-#ifdef CONFIG_HOSTCMD_RWHASHPD
-static enum ec_status
-hc_remote_rw_hash_entry(struct host_cmd_handler_args *args)
-{
- int i, idx = 0, found = 0;
- const struct ec_params_usb_pd_rw_hash_entry *p = args->params;
- static int rw_hash_next_idx;
-
- if (!p->dev_id)
- return EC_RES_INVALID_PARAM;
-
- for (i = 0; i < RW_HASH_ENTRIES; i++) {
- if (p->dev_id == rw_hash_table[i].dev_id) {
- idx = i;
- found = 1;
- break;
- }
- }
- if (!found) {
- idx = rw_hash_next_idx;
- rw_hash_next_idx = rw_hash_next_idx + 1;
- if (rw_hash_next_idx == RW_HASH_ENTRIES)
- rw_hash_next_idx = 0;
- }
- memcpy(&rw_hash_table[idx], p, sizeof(*p));
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_RW_HASH_ENTRY,
- hc_remote_rw_hash_entry,
- EC_VER_MASK(0));
-#endif /* CONFIG_HOSTCMD_RWHASHPD */
-
-static enum ec_status hc_remote_pd_dev_info(struct host_cmd_handler_args *args)
-{
- const uint8_t *port = args->params;
- struct ec_params_usb_pd_rw_hash_entry *r = args->response;
-
- if (*port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- r->dev_id = pd[*port].dev_id;
-
- if (r->dev_id) {
- memcpy(r->dev_rw_hash, pd[*port].dev_rw_hash,
- PD_RW_HASH_SIZE);
- }
-
- r->current_image = pd[*port].current_image;
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_DEV_INFO,
- hc_remote_pd_dev_info,
- EC_VER_MASK(0));
-
-#ifndef CONFIG_USB_PD_TCPC
-#ifdef CONFIG_EC_CMD_PD_CHIP_INFO
-static enum ec_status hc_remote_pd_chip_info(struct host_cmd_handler_args *args)
-{
- const struct ec_params_pd_chip_info *p = args->params;
- struct ec_response_pd_chip_info_v1 *info;
-
- if (p->port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- if (tcpm_get_chip_info(p->port, p->live, &info))
- return EC_RES_ERROR;
-
- /*
- * Take advantage of the fact that v0 and v1 structs have the
- * same layout for v0 data. (v1 just appends data)
- */
- args->response_size =
- args->version ? sizeof(struct ec_response_pd_chip_info_v1)
- : sizeof(struct ec_response_pd_chip_info);
-
- memcpy(args->response, info, args->response_size);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PD_CHIP_INFO,
- hc_remote_pd_chip_info,
- EC_VER_MASK(0) | EC_VER_MASK(1));
-#endif
-#endif
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-static enum ec_status hc_remote_pd_set_amode(struct host_cmd_handler_args *args)
-{
- const struct ec_params_usb_pd_set_mode_request *p = args->params;
-
- if ((p->port >= board_get_usb_pd_port_count()) ||
- (!p->svid) || (!p->opos))
- return EC_RES_INVALID_PARAM;
-
- switch (p->cmd) {
- case PD_EXIT_MODE:
- if (pd_dfp_exit_mode(p->port, p->svid, p->opos))
- pd_send_vdm(p->port, p->svid,
- CMD_EXIT_MODE | VDO_OPOS(p->opos), NULL, 0);
- else {
- CPRINTF("Failed exit mode\n");
- return EC_RES_ERROR;
- }
- break;
- case PD_ENTER_MODE:
- if (pd_dfp_enter_mode(p->port, p->svid, p->opos))
- pd_send_vdm(p->port, p->svid, CMD_ENTER_MODE |
- VDO_OPOS(p->opos), NULL, 0);
- break;
- default:
- return EC_RES_INVALID_PARAM;
- }
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_SET_AMODE,
- hc_remote_pd_set_amode,
- EC_VER_MASK(0));
-#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
-
-#endif /* HAS_TASK_HOSTCMD */
-
-#ifdef CONFIG_CMD_PD_CONTROL
-
-static enum ec_status pd_control(struct host_cmd_handler_args *args)
-{
- static int pd_control_disabled[CONFIG_USB_PD_PORT_MAX_COUNT];
- const struct ec_params_pd_control *cmd = args->params;
- int enable = 0;
-
- if (cmd->chip >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- /* Always allow disable command */
- if (cmd->subcmd == PD_CONTROL_DISABLE) {
- pd_control_disabled[cmd->chip] = 1;
- return EC_RES_SUCCESS;
- }
-
- if (pd_control_disabled[cmd->chip])
- return EC_RES_ACCESS_DENIED;
-
- if (cmd->subcmd == PD_SUSPEND) {
- /*
- * The AP is requesting to suspend PD traffic on the EC so it
- * can perform a firmware upgrade. If Vbus is present on the
- * connector (it is either a source or sink), then we will
- * prevent the upgrade if there is not enough battery to finish
- * the upgrade. We cannot rely on the EC's active charger data
- * as the EC just rebooted into RW and has not necessarily
- * picked the active charger yet.
- */
-#ifdef HAS_TASK_CHARGER
- if (pd_is_vbus_present(cmd->chip)) {
- struct batt_params batt = { 0 };
- /*
- * The charger task has not re-initialized, so we need
- * to ask the battery directly.
- */
- battery_get_params(&batt);
- if (batt.remaining_capacity <
- MIN_BATTERY_FOR_TCPC_UPGRADE_MAH ||
- batt.flags & BATT_FLAG_BAD_REMAINING_CAPACITY) {
- CPRINTS("C%d: Cannot suspend for upgrade, not "
- "enough battery (%dmAh)!",
- cmd->chip, batt.remaining_capacity);
- return EC_RES_BUSY;
- }
- }
-#else
- if (pd_is_vbus_present(cmd->chip)) {
- CPRINTS("C%d: Cannot suspend for upgrade, Vbus "
- "present!",
- cmd->chip);
- return EC_RES_BUSY;
- }
-#endif
- enable = 0;
- } else if (cmd->subcmd == PD_RESUME) {
- enable = 1;
- } else if (cmd->subcmd == PD_RESET) {
-#ifdef HAS_TASK_PDCMD
- board_reset_pd_mcu();
-#else
- return EC_RES_INVALID_COMMAND;
-#endif
- } else if (cmd->subcmd == PD_CHIP_ON && board_set_tcpc_power_mode) {
- board_set_tcpc_power_mode(cmd->chip, 1);
- return EC_RES_SUCCESS;
- } else {
- return EC_RES_INVALID_COMMAND;
- }
-
- pd_comm_enable(cmd->chip, enable);
- pd_set_suspend(cmd->chip, !enable);
-
- return EC_RES_SUCCESS;
-}
-
-DECLARE_HOST_COMMAND(EC_CMD_PD_CONTROL, pd_control, EC_VER_MASK(0));
-#endif /* CONFIG_CMD_PD_CONTROL */
-
-#endif /* CONFIG_COMMON_RUNTIME */
diff --git a/common/usb_pd_tcpc.c b/common/usb_pd_tcpc.c
deleted file mode 100644
index 2e1cbf73d7..0000000000
--- a/common/usb_pd_tcpc.c
+++ /dev/null
@@ -1,1463 +0,0 @@
-/* Copyright 2015 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 "adc.h"
-#include "common.h"
-#include "config.h"
-#include "console.h"
-#include "crc.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 "tcpci.h"
-#include "tcpm.h"
-#include "timer.h"
-#include "util.h"
-#include "usb_pd.h"
-#include "usb_pd_config.h"
-#include "usb_pd_tcpm.h"
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-
-/*
- * Debug log level - higher number == more log
- * Level 0: Log state transitions
- * Level 1: Level 0, plus packet info
- * Level 2: Level 1, plus ping packet and packet dump on error
- *
- * Note that higher log level causes timing changes and thus may affect
- * performance.
- */
-static int debug_level;
-
-static struct mutex pd_crc_lock;
-#else
-#define CPRINTF(format, args...)
-static const int debug_level;
-#endif
-
-/* Encode 5 bits using Biphase Mark Coding */
-#define BMC(x) ((x & 1 ? 0x001 : 0x3FF) \
- ^ (x & 2 ? 0x004 : 0x3FC) \
- ^ (x & 4 ? 0x010 : 0x3F0) \
- ^ (x & 8 ? 0x040 : 0x3C0) \
- ^ (x & 16 ? 0x100 : 0x300))
-
-/* 4b/5b + Bimark Phase encoding */
-static const uint16_t bmc4b5b[] = {
-/* 0 = 0000 */ BMC(0x1E) /* 11110 */,
-/* 1 = 0001 */ BMC(0x09) /* 01001 */,
-/* 2 = 0010 */ BMC(0x14) /* 10100 */,
-/* 3 = 0011 */ BMC(0x15) /* 10101 */,
-/* 4 = 0100 */ BMC(0x0A) /* 01010 */,
-/* 5 = 0101 */ BMC(0x0B) /* 01011 */,
-/* 6 = 0110 */ BMC(0x0E) /* 01110 */,
-/* 7 = 0111 */ BMC(0x0F) /* 01111 */,
-/* 8 = 1000 */ BMC(0x12) /* 10010 */,
-/* 9 = 1001 */ BMC(0x13) /* 10011 */,
-/* A = 1010 */ BMC(0x16) /* 10110 */,
-/* B = 1011 */ BMC(0x17) /* 10111 */,
-/* C = 1100 */ BMC(0x1A) /* 11010 */,
-/* D = 1101 */ BMC(0x1B) /* 11011 */,
-/* E = 1110 */ BMC(0x1C) /* 11100 */,
-/* F = 1111 */ BMC(0x1D) /* 11101 */,
-/* Sync-1 K-code 11000 Startsynch #1 */
-/* Sync-2 K-code 10001 Startsynch #2 */
-/* RST-1 K-code 00111 Hard Reset #1 */
-/* RST-2 K-code 11001 Hard Reset #2 */
-/* EOP K-code 01101 EOP End Of Packet */
-/* Reserved Error 00000 */
-/* Reserved Error 00001 */
-/* Reserved Error 00010 */
-/* Reserved Error 00011 */
-/* Reserved Error 00100 */
-/* Reserved Error 00101 */
-/* Reserved Error 00110 */
-/* Reserved Error 01000 */
-/* Reserved Error 01100 */
-/* Reserved Error 10000 */
-/* Reserved Error 11111 */
-};
-
-static const uint8_t dec4b5b[] = {
-/* Error */ 0x10 /* 00000 */,
-/* Error */ 0x10 /* 00001 */,
-/* Error */ 0x10 /* 00010 */,
-/* Error */ 0x10 /* 00011 */,
-/* Error */ 0x10 /* 00100 */,
-/* Error */ 0x10 /* 00101 */,
-/* Error */ 0x10 /* 00110 */,
-/* RST-1 */ 0x13 /* 00111 K-code: Hard Reset #1 */,
-/* Error */ 0x10 /* 01000 */,
-/* 1 = 0001 */ 0x01 /* 01001 */,
-/* 4 = 0100 */ 0x04 /* 01010 */,
-/* 5 = 0101 */ 0x05 /* 01011 */,
-/* Error */ 0x10 /* 01100 */,
-/* EOP */ 0x15 /* 01101 K-code: EOP End Of Packet */,
-/* 6 = 0110 */ 0x06 /* 01110 */,
-/* 7 = 0111 */ 0x07 /* 01111 */,
-/* Error */ 0x10 /* 10000 */,
-/* Sync-2 */ 0x12 /* 10001 K-code: Startsynch #2 */,
-/* 8 = 1000 */ 0x08 /* 10010 */,
-/* 9 = 1001 */ 0x09 /* 10011 */,
-/* 2 = 0010 */ 0x02 /* 10100 */,
-/* 3 = 0011 */ 0x03 /* 10101 */,
-/* A = 1010 */ 0x0A /* 10110 */,
-/* B = 1011 */ 0x0B /* 10111 */,
-/* Sync-1 */ 0x11 /* 11000 K-code: Startsynch #1 */,
-/* RST-2 */ 0x14 /* 11001 K-code: Hard Reset #2 */,
-/* C = 1100 */ 0x0C /* 11010 */,
-/* D = 1101 */ 0x0D /* 11011 */,
-/* E = 1110 */ 0x0E /* 11100 */,
-/* F = 1111 */ 0x0F /* 11101 */,
-/* 0 = 0000 */ 0x00 /* 11110 */,
-/* Error */ 0x10 /* 11111 */,
-};
-
-/* Start of Packet sequence : three Sync-1 K-codes, then one Sync-2 K-code */
-#define PD_SOP (PD_SYNC1 | (PD_SYNC1<<5) | (PD_SYNC1<<10) | (PD_SYNC2<<15))
-#define PD_SOP_PRIME (PD_SYNC1 | (PD_SYNC1<<5) | \
- (PD_SYNC3<<10) | (PD_SYNC3<<15))
-#define PD_SOP_PRIME_PRIME (PD_SYNC1 | (PD_SYNC3<<5) | \
- (PD_SYNC1<<10) | (PD_SYNC3<<15))
-
-/* Hard Reset sequence : three RST-1 K-codes, then one RST-2 K-code */
-#define PD_HARD_RESET (PD_RST1 | (PD_RST1 << 5) |\
- (PD_RST1 << 10) | (PD_RST2 << 15))
-
-/*
- * Polarity based on 'DFP Perspective' (see table USB Type-C Cable and Connector
- * Specification)
- *
- * CC1 CC2 STATE POSITION
- * ----------------------------------------
- * open open NC N/A
- * Rd open UFP attached 1
- * open Rd UFP attached 2
- * open Ra pwr cable no UFP N/A
- * Ra open pwr cable no UFP N/A
- * Rd Ra pwr cable & UFP 1
- * Ra Rd pwr cable & UFP 2
- * Rd Rd dbg accessory N/A
- * Ra Ra audio accessory N/A
- *
- * Note, V(Rd) > V(Ra)
- */
-#ifndef PD_SRC_RD_THRESHOLD
-#define PD_SRC_RD_THRESHOLD PD_SRC_DEF_RD_THRESH_MV
-#endif
-#ifndef PD_SRC_VNC
-#define PD_SRC_VNC PD_SRC_DEF_VNC_MV
-#endif
-
-#ifndef CC_RA
-#define CC_RA(port, cc, sel) (cc < PD_SRC_RD_THRESHOLD)
-#endif
-#define CC_RD(cc) ((cc >= PD_SRC_RD_THRESHOLD) && (cc < PD_SRC_VNC))
-#ifndef CC_NC
-#define CC_NC(port, cc, sel) (cc >= PD_SRC_VNC)
-#endif
-
-/*
- * Polarity based on 'UFP Perspective'.
- *
- * CC1 CC2 STATE POSITION
- * ----------------------------------------
- * open open NC N/A
- * Rp open DFP attached 1
- * open Rp DFP attached 2
- * Rp Rp Accessory attached N/A
- */
-#ifndef PD_SNK_VA
-#define PD_SNK_VA PD_SNK_VA_MV
-#endif
-
-#define CC_RP(cc) (cc >= PD_SNK_VA)
-
-/*
- * Type C power source charge current limits are identified by their cc
- * voltage (set by selecting the proper Rd resistor). Any voltage below
- * TYPE_C_SRC_500_THRESHOLD will not be identified as a type C charger.
- */
-#define TYPE_C_SRC_500_THRESHOLD PD_SRC_RD_THRESHOLD
-#define TYPE_C_SRC_1500_THRESHOLD 660 /* mV */
-#define TYPE_C_SRC_3000_THRESHOLD 1230 /* mV */
-
-/* Convert TCPC Alert register to index into pd.alert[] */
-#define ALERT_REG_TO_INDEX(reg) (reg - TCPC_REG_ALERT)
-
-/* PD transmit errors */
-enum pd_tx_errors {
- PD_TX_ERR_GOODCRC = -1, /* Failed to receive goodCRC */
- PD_TX_ERR_DISABLED = -2, /* Attempted transmit even though disabled */
- PD_TX_ERR_INV_ACK = -4, /* Received different packet instead of gCRC */
- PD_TX_ERR_COLLISION = -5 /* Collision detected during transmit */
-};
-
-/* PD Header with SOP* encoded in bits 31 - 28 */
-union pd_header_sop {
- uint16_t pd_header;
- uint32_t head;
-};
-
-/*
- * If TCPM is not on this chip, and PD low power is defined, then use low
- * power task delay logic.
- */
-#if !defined(CONFIG_USB_POWER_DELIVERY) && defined(CONFIG_USB_PD_LOW_POWER)
-#define TCPC_LOW_POWER
-#endif
-
-/*
- * Receive message buffer size. Buffer physical size is RX_BUFFER_SIZE + 1,
- * but only RX_BUFFER_SIZE of that memory is used to store messages that can
- * be retrieved from TCPM. The last slot is a temporary buffer for collecting
- * a message before deciding whether or not to keep it.
- */
-#ifdef CONFIG_USB_POWER_DELIVERY
-#define RX_BUFFER_SIZE 1
-#else
-#define RX_BUFFER_SIZE 2
-#endif
-
-static struct pd_port_controller {
- /* current port power role (SOURCE or SINK) */
- uint8_t power_role;
- /* current port data role (DFP or UFP) */
- uint8_t data_role;
- /* Port polarity : 0 => CC1 is CC line, 1 => CC2 is CC line */
- uint8_t polarity;
- /* Our CC pull resistor setting */
- uint8_t cc_pull;
- /* CC status */
- uint8_t cc_status[2];
- /* TCPC alert status */
- uint16_t alert;
- uint16_t alert_mask;
- /* RX enabled */
- uint8_t rx_enabled;
- /* Power status */
- uint8_t power_status;
- uint8_t power_status_mask;
-
-#ifdef TCPC_LOW_POWER
- /* Timestamp beyond which we allow low power task sampling */
- timestamp_t low_power_ts;
-#endif
-
- /* Last received */
- int rx_head[RX_BUFFER_SIZE+1];
- uint32_t rx_payload[RX_BUFFER_SIZE+1][7];
- int rx_buf_head, rx_buf_tail;
-
- /* Next transmit */
- enum tcpm_transmit_type tx_type;
- uint16_t tx_head;
- uint32_t tx_payload[7];
- const uint32_t *tx_data;
-} pd[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-static int rx_buf_is_full(int port)
-{
- /*
- * TODO: Refactor these to use the incrementing-counter idiom instead of
- * the wrapping-counter idiom to reclaim the last buffer entry.
- *
- * Buffer is full if the tail is 1 ahead of head.
- */
- int diff = pd[port].rx_buf_tail - pd[port].rx_buf_head;
- return (diff == 1) || (diff == -RX_BUFFER_SIZE);
-}
-
-int rx_buf_is_empty(int port)
-{
- /* Buffer is empty if the head and tail are the same */
- return pd[port].rx_buf_tail == pd[port].rx_buf_head;
-}
-
-void rx_buf_clear(int port)
-{
- pd[port].rx_buf_tail = pd[port].rx_buf_head;
-}
-
-static void rx_buf_increment(int port, int *buf_ptr)
-{
- *buf_ptr = *buf_ptr == RX_BUFFER_SIZE ? 0 : *buf_ptr + 1;
-}
-
-static inline int encode_short(int port, int off, uint16_t val16)
-{
- off = pd_write_sym(port, off, bmc4b5b[(val16 >> 0) & 0xF]);
- off = pd_write_sym(port, off, bmc4b5b[(val16 >> 4) & 0xF]);
- off = pd_write_sym(port, off, bmc4b5b[(val16 >> 8) & 0xF]);
- return pd_write_sym(port, off, bmc4b5b[(val16 >> 12) & 0xF]);
-}
-
-int encode_word(int port, int off, uint32_t val32)
-{
- off = encode_short(port, off, (val32 >> 0) & 0xFFFF);
- return encode_short(port, off, (val32 >> 16) & 0xFFFF);
-}
-
-/* prepare a 4b/5b-encoded PD message to send */
-int prepare_message(int port, uint16_t header, uint8_t cnt,
- const uint32_t *data)
-{
- int off, i;
- /* 64-bit preamble */
- off = pd_write_preamble(port);
-#if defined(CONFIG_USB_TYPEC_VPD) || defined(CONFIG_USB_TYPEC_CTVPD)
- /* Start Of Packet Prime: 2x Sync-1 + 2x Sync-3 */
- off = pd_write_sym(port, off, BMC(PD_SYNC1));
- off = pd_write_sym(port, off, BMC(PD_SYNC1));
- off = pd_write_sym(port, off, BMC(PD_SYNC3));
- off = pd_write_sym(port, off, BMC(PD_SYNC3));
-#else
- /* Start Of Packet: 3x Sync-1 + 1x Sync-2 */
- off = pd_write_sym(port, off, BMC(PD_SYNC1));
- off = pd_write_sym(port, off, BMC(PD_SYNC1));
- off = pd_write_sym(port, off, BMC(PD_SYNC1));
- off = pd_write_sym(port, off, BMC(PD_SYNC2));
-#endif
- /* header */
- off = encode_short(port, off, header);
-
-#ifdef CONFIG_COMMON_RUNTIME
- mutex_lock(&pd_crc_lock);
-#endif
-
- crc32_init();
- crc32_hash16(header);
- /* data payload */
- for (i = 0; i < cnt; i++) {
- off = encode_word(port, off, data[i]);
- crc32_hash32(data[i]);
- }
- /* CRC */
- off = encode_word(port, off, crc32_result());
-
-#ifdef CONFIG_COMMON_RUNTIME
- mutex_unlock(&pd_crc_lock);
-#endif
-
- /* End Of Packet */
- off = pd_write_sym(port, off, BMC(PD_EOP));
- /* Ensure that we have a final edge */
- return pd_write_last_edge(port, off);
-}
-
-static int send_hard_reset(int port)
-{
- int off;
-
- if (debug_level >= 1)
- CPRINTF("C%d Send hard reset\n", port);
-
- /* 64-bit preamble */
- off = pd_write_preamble(port);
- /* Hard-Reset: 3x RST-1 + 1x RST-2 */
- off = pd_write_sym(port, off, BMC(PD_RST1));
- off = pd_write_sym(port, off, BMC(PD_RST1));
- off = pd_write_sym(port, off, BMC(PD_RST1));
- off = pd_write_sym(port, off, BMC(PD_RST2));
- /* Ensure that we have a final edge */
- off = pd_write_last_edge(port, off);
- /* Transmit the packet */
- if (pd_start_tx(port, pd[port].polarity, off) < 0)
- return PD_TX_ERR_COLLISION;
- pd_tx_done(port, pd[port].polarity);
- /* Keep RX monitoring on */
- pd_rx_enable_monitoring(port);
- return 0;
-}
-
-static int send_validate_message(int port, uint16_t header,
- const uint32_t *data)
-{
- int r;
- static uint32_t payload[7];
- uint8_t expected_msg_id = PD_HEADER_ID(header);
- uint8_t cnt = PD_HEADER_CNT(header);
- int retries = PD_HEADER_TYPE(header) == PD_DATA_SOURCE_CAP ?
- 0 : PD_RETRY_COUNT;
-
- /* retry 3 times if we are not getting a valid answer */
- for (r = 0; r <= retries; r++) {
- int bit_len, head;
- /* write the encoded packet in the transmission buffer */
- bit_len = prepare_message(port, header, cnt, data);
- /* Transmit the packet */
- if (pd_start_tx(port, pd[port].polarity, bit_len) < 0) {
- /*
- * Collision detected, return immediately so we can
- * respond to what we have received.
- */
- return PD_TX_ERR_COLLISION;
- }
- pd_tx_done(port, pd[port].polarity);
- /*
- * If this is the first attempt, leave RX monitoring off,
- * and do a blocking read of the channel until timeout or
- * packet received. If we failed the first try, enable
- * interrupt and yield to other tasks, so that we don't
- * starve them.
- */
- if (r) {
- pd_rx_enable_monitoring(port);
- /* Wait for message receive timeout */
- if (task_wait_event(USB_PD_RX_TMOUT_US) ==
- TASK_EVENT_TIMER)
- continue;
- /*
- * Make sure we woke up due to rx recd, otherwise
- * we need to manually start
- */
- if (!pd_rx_started(port)) {
- pd_rx_disable_monitoring(port);
- pd_rx_start(port);
- }
- } else {
- /* starting waiting for GoodCrc */
- pd_rx_start(port);
- }
- /* read the incoming packet if any */
- head = pd_analyze_rx(port, payload);
- pd_rx_complete(port);
- /* keep RX monitoring on to avoid collisions */
- pd_rx_enable_monitoring(port);
- if (head > 0) { /* we got a good packet, analyze it */
- int type = PD_HEADER_TYPE(head);
- int nb = PD_HEADER_CNT(head);
- uint8_t id = PD_HEADER_ID(head);
- if (type == PD_CTRL_GOOD_CRC && nb == 0 &&
- id == expected_msg_id) {
- /* got the GoodCRC we were expecting */
- /* do not catch last edges as a new packet */
- udelay(20);
- return bit_len;
- } else {
- /*
- * we have received a good packet
- * but not the expected GoodCRC,
- * the other side is trying to contact us,
- * bail out immediately so we can get the retry.
- */
- return PD_TX_ERR_INV_ACK;
- }
- }
- }
- /* we failed all the re-transmissions */
- if (debug_level >= 1)
- CPRINTF("TX NOACK%d %04x/%d\n", port, header, cnt);
- return PD_TX_ERR_GOODCRC;
-}
-
-static void send_goodcrc(int port, int id)
-{
- uint16_t header = PD_HEADER(PD_CTRL_GOOD_CRC, pd[port].power_role,
- pd[port].data_role, id, 0, 0, 0);
- int bit_len = prepare_message(port, header, 0, NULL);
-
- if (pd_start_tx(port, pd[port].polarity, bit_len) < 0)
- /* another packet recvd before we could send goodCRC */
- return;
- pd_tx_done(port, pd[port].polarity);
- /* Keep RX monitoring on */
- pd_rx_enable_monitoring(port);
-}
-
-#if 0
-/* TODO: when/how do we trigger this ? */
-static int analyze_rx_bist(int port);
-
-void bist_mode_2_rx(int port)
-{
- int analyze_bist = 0;
- int num_bits;
- timestamp_t start_time;
-
- /* monitor for incoming packet */
- pd_rx_enable_monitoring(port);
-
- /* loop until we start receiving data */
- start_time.val = get_time().val;
- while ((get_time().val - start_time.val) < (500*MSEC)) {
- task_wait_event(10*MSEC);
- /* incoming packet ? */
- if (pd_rx_started(port)) {
- analyze_bist = 1;
- break;
- }
- }
-
- if (analyze_bist) {
- /*
- * once we start receiving bist data, analyze 40 bytes
- * every 10 msec. Continue analyzing until BIST data
- * is no longer received. The standard limits the max
- * BIST length to 60 msec.
- */
- start_time.val = get_time().val;
- while ((get_time().val - start_time.val)
- < (PD_T_BIST_RECEIVE)) {
- num_bits = analyze_rx_bist(port);
- pd_rx_complete(port);
- /*
- * If no data was received, then analyze_rx_bist()
- * will return a -1 and there is no need to stay
- * in this mode
- */
- if (num_bits == -1)
- break;
- msleep(10);
- pd_rx_enable_monitoring(port);
- }
- } else {
- CPRINTF("BIST RX TO\n");
- }
-}
-#endif
-
-static void bist_mode_2_tx(int port)
-{
- int bit;
-
- CPRINTF("BIST 2: p%d\n", port);
- /*
- * build context buffer with 5 bytes, where the data is
- * alternating 1's and 0's.
- */
- bit = pd_write_sym(port, 0, BMC(0x15));
- bit = pd_write_sym(port, bit, BMC(0x0a));
- bit = pd_write_sym(port, bit, BMC(0x15));
- bit = pd_write_sym(port, bit, BMC(0x0a));
-
- /* start a circular DMA transfer */
- pd_tx_set_circular_mode(port);
- pd_start_tx(port, pd[port].polarity, bit);
-
- task_wait_event(PD_T_BIST_TRANSMIT);
-
- /* clear dma circular mode, will also stop dma */
- pd_tx_clear_circular_mode(port);
- /* finish and cleanup transmit */
- pd_tx_done(port, pd[port].polarity);
-}
-
-static inline int decode_short(int port, int off, uint16_t *val16)
-{
- uint32_t w;
- int end;
-
- end = pd_dequeue_bits(port, off, 20, &w);
-
-#if 0 /* DEBUG */
- CPRINTS("%d-%d: %05x %x:%x:%x:%x",
- off, end, w,
- dec4b5b[(w >> 15) & 0x1f], dec4b5b[(w >> 10) & 0x1f],
- dec4b5b[(w >> 5) & 0x1f], dec4b5b[(w >> 0) & 0x1f]);
-#endif
- *val16 = dec4b5b[w & 0x1f] |
- (dec4b5b[(w >> 5) & 0x1f] << 4) |
- (dec4b5b[(w >> 10) & 0x1f] << 8) |
- (dec4b5b[(w >> 15) & 0x1f] << 12);
- return end;
-}
-
-static inline int decode_word(int port, int off, uint32_t *val32)
-{
- off = decode_short(port, off, (uint16_t *)val32);
- return decode_short(port, off, ((uint16_t *)val32 + 1));
-}
-
-#ifdef CONFIG_COMMON_RUNTIME
-#if 0
-/*
- * TODO: when/how do we trigger this ? Could add custom vendor command
- * to TCPCI to enter bist verification? Is there an easier way?
- */
-static int count_set_bits(int n)
-{
- int count = 0;
- while (n) {
- n &= (n - 1);
- count++;
- }
- return count;
-}
-
-static int analyze_rx_bist(int port)
-{
- int i = 0, bit = -1;
- uint32_t w, match;
- int invalid_bits = 0;
- int bits_analyzed = 0;
- static int total_invalid_bits;
-
- /* dequeue bits until we see a full byte of alternating 1's and 0's */
- while (i < 10 && (bit < 0 || (w != 0xaa && w != 0x55)))
- bit = pd_dequeue_bits(port, i++, 8, &w);
-
- /* if we didn't find any bytes that match criteria, display error */
- if (i == 10) {
- CPRINTF("invalid pattern\n");
- return -1;
- }
- /*
- * now we know what matching byte we are looking for, dequeue a bunch
- * more data and count how many bits differ from expectations.
- */
- match = w;
- bit = i - 1;
- for (i = 0; i < 40; i++) {
- bit = pd_dequeue_bits(port, bit, 8, &w);
- if (i && (i % 20 == 0))
- CPRINTF("\n");
- CPRINTF("%02x ", w);
- bits_analyzed += 8;
- invalid_bits += count_set_bits(w ^ match);
- }
-
- total_invalid_bits += invalid_bits;
-
- CPRINTF("\nInvalid: %d/%d\n",
- invalid_bits, total_invalid_bits);
- return bits_analyzed;
-}
-#endif
-#endif
-
-int pd_analyze_rx(int port, uint32_t *payload)
-{
- int bit;
- char *msg = "---";
- uint32_t val = 0;
- union pd_header_sop phs;
- uint32_t pcrc, ccrc;
- int p, cnt;
- uint32_t eop;
-
- pd_init_dequeue(port);
-
- /* Detect preamble */
- bit = pd_find_preamble(port);
- if (bit == PD_RX_ERR_HARD_RESET || bit == PD_RX_ERR_CABLE_RESET) {
- /* Hard reset or cable reset */
- return bit;
- } else if (bit < 0) {
- msg = "Preamble";
- goto packet_err;
- }
-
- /* Find the Start Of Packet sequence */
- while (bit > 0) {
- bit = pd_dequeue_bits(port, bit, 20, &val);
-#if defined(CONFIG_USB_TYPEC_VPD) || defined(CONFIG_USB_TYPEC_CTVPD)
- if (val == PD_SOP_PRIME) {
- break;
- } else if (val == PD_SOP) {
- CPRINTF("SOP\n");
- return PD_RX_ERR_UNSUPPORTED_SOP;
- } else if (val == PD_SOP_PRIME_PRIME) {
- CPRINTF("SOP''\n");
- return PD_RX_ERR_UNSUPPORTED_SOP;
- }
-#else /* CONFIG_USB_TYPEC_VPD || CONFIG_USB_TYPEC_CTVPD */
-#ifdef CONFIG_USB_PD_DECODE_SOP
- if (val == PD_SOP || val == PD_SOP_PRIME ||
- val == PD_SOP_PRIME_PRIME)
- break;
-#else
- if (val == PD_SOP) {
- break;
- } else if (val == PD_SOP_PRIME) {
- CPRINTF("SOP'\n");
- return PD_RX_ERR_UNSUPPORTED_SOP;
- } else if (val == PD_SOP_PRIME_PRIME) {
- CPRINTF("SOP''\n");
- return PD_RX_ERR_UNSUPPORTED_SOP;
- }
-#endif /* CONFIG_USB_PD_DECODE_SOP */
-#endif /* CONFIG_USB_TYPEC_VPD || CONFIG_USB_TYPEC_CTVPD */
- }
- if (bit < 0) {
-#ifdef CONFIG_USB_PD_DECODE_SOP
- if (val == PD_SOP)
- msg = "SOP";
- else if (val == PD_SOP_PRIME)
- msg = "SOP'";
- else if (val == PD_SOP_PRIME_PRIME)
- msg = "SOP''";
- else
- msg = "SOP*";
-#else
- msg = "SOP";
-#endif
- goto packet_err;
- }
-
- phs.head = 0;
-
- /* read header */
- bit = decode_short(port, bit, &phs.pd_header);
-
-#ifdef CONFIG_COMMON_RUNTIME
- mutex_lock(&pd_crc_lock);
-#endif
-
- crc32_init();
- crc32_hash16(phs.pd_header);
- cnt = PD_HEADER_CNT(phs.pd_header);
-
-#ifdef CONFIG_USB_PD_DECODE_SOP
- /* Encode message address */
- if (val == PD_SOP) {
- phs.head |= PD_HEADER_SOP(PD_MSG_SOP);
- } else if (val == PD_SOP_PRIME) {
- phs.head |= PD_HEADER_SOP(PD_MSG_SOPP);
- } else if (val == PD_SOP_PRIME_PRIME) {
- phs.head |= PD_HEADER_SOP(PD_MSG_SOPPP);
- } else {
- msg = "SOP*";
- goto packet_err;
- }
-#endif
-
- /* read payload data */
- for (p = 0; p < cnt && bit > 0; p++) {
- bit = decode_word(port, bit, payload+p);
- crc32_hash32(payload[p]);
- }
- ccrc = crc32_result();
-
-#ifdef CONFIG_COMMON_RUNTIME
- mutex_unlock(&pd_crc_lock);
-#endif
-
- if (bit < 0) {
- msg = "len";
- goto packet_err;
- }
-
- /* check transmitted CRC */
- bit = decode_word(port, bit, &pcrc);
- if (bit < 0 || pcrc != ccrc) {
- msg = "CRC";
- if (pcrc != ccrc)
- bit = PD_RX_ERR_CRC;
- if (debug_level >= 1)
- CPRINTF("CRC%d %08x <> %08x\n", port, pcrc, ccrc);
- goto packet_err;
- }
-
- /*
- * Check EOP. EOP is 5 bits, but last bit may not be able to
- * be dequeued, depending on ending state of CC line, so stop
- * at 4 bits (assumes last bit is 0).
- */
- bit = pd_dequeue_bits(port, bit, 4, &eop);
- if (bit < 0 || eop != PD_EOP) {
- msg = "EOP";
- goto packet_err;
- }
-
- return phs.head;
-packet_err:
- if (debug_level >= 2)
- pd_dump_packet(port, msg);
- else
- CPRINTF("RXERR%d %s\n", port, msg);
- return bit;
-}
-
-static void handle_request(int port, uint16_t head)
-{
- int cnt = PD_HEADER_CNT(head);
-
- if (PD_HEADER_TYPE(head) != PD_CTRL_GOOD_CRC || cnt)
- send_goodcrc(port, PD_HEADER_ID(head));
- else
- /* keep RX monitoring on to avoid collisions */
- pd_rx_enable_monitoring(port);
-}
-
-/* Convert CC voltage to CC status */
-static int cc_voltage_to_status(int port, int cc_volt, int cc_sel)
-{
- /* If we have a pull-up, then we are source, check for Rd. */
- if (pd[port].cc_pull == TYPEC_CC_RP) {
- if (CC_NC(port, cc_volt, cc_sel))
- return TYPEC_CC_VOLT_OPEN;
- else if (CC_RA(port, cc_volt, cc_sel))
- return TYPEC_CC_VOLT_RA;
- else
- return TYPEC_CC_VOLT_RD;
- /* If we have a pull-down, then we are sink, check for Rp. */
- }
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- else if (pd[port].cc_pull == TYPEC_CC_RD) {
- if (cc_volt >= TYPE_C_SRC_3000_THRESHOLD)
- return TYPEC_CC_VOLT_RP_3_0;
- else if (cc_volt >= TYPE_C_SRC_1500_THRESHOLD)
- return TYPEC_CC_VOLT_RP_1_5;
- else if (CC_RP(cc_volt))
- return TYPEC_CC_VOLT_RP_DEF;
- else
- return TYPEC_CC_VOLT_OPEN;
- }
-#endif
- /* If we are open, then always return 0 */
- else
- return 0;
-}
-
-static void alert(int port, int mask)
-{
- /* Always update the Alert status register */
- pd[port].alert |= mask;
- /*
- * Only send interrupt to TCPM if corresponding
- * bit in the alert_enable register is set.
- */
- if (pd[port].alert_mask & mask)
- tcpc_alert(port);
-}
-
-int tcpc_run(int port, int evt)
-{
- int cc, i, res;
-
- /* incoming packet ? */
- if (pd_rx_started(port) && pd[port].rx_enabled) {
- /* Get message and place at RX buffer head */
- res = pd[port].rx_head[pd[port].rx_buf_head] =
- pd_analyze_rx(port,
- pd[port].rx_payload[pd[port].rx_buf_head]);
- pd_rx_complete(port);
-
- /*
- * If there is space in buffer, then increment head to keep
- * the message and send goodCRC. If this is a hard reset,
- * send alert regardless of rx buffer status. Else if there is
- * no space in buffer, then do not send goodCRC and drop
- * message.
- */
- if (res > 0 && !rx_buf_is_full(port)) {
- rx_buf_increment(port, &pd[port].rx_buf_head);
- handle_request(port, res);
- alert(port, TCPC_REG_ALERT_RX_STATUS);
- } else if (res == PD_RX_ERR_HARD_RESET) {
- alert(port, TCPC_REG_ALERT_RX_HARD_RST);
- }
- }
-
- /* outgoing packet ? */
- if ((evt & PD_EVENT_TX) && pd[port].rx_enabled) {
- switch (pd[port].tx_type) {
-#if defined(CONFIG_USB_TYPEC_VPD) || defined(CONFIG_USB_TYPEC_CTVPD)
- case TCPC_TX_SOP_PRIME:
-#else
- case TCPC_TX_SOP:
-#endif
- res = send_validate_message(port,
- pd[port].tx_head,
- pd[port].tx_data);
- break;
- case TCPC_TX_BIST_MODE_2:
- bist_mode_2_tx(port);
- res = 0;
- break;
- case TCPC_TX_HARD_RESET:
- res = send_hard_reset(port);
- break;
- default:
- res = PD_TX_ERR_DISABLED;
- break;
- }
-
- /* send appropriate alert for tx completion */
- if (res >= 0)
- alert(port, TCPC_REG_ALERT_TX_SUCCESS);
- else if (res == PD_TX_ERR_GOODCRC)
- alert(port, TCPC_REG_ALERT_TX_FAILED);
- else
- alert(port, TCPC_REG_ALERT_TX_DISCARDED);
- } else {
- /* If we have nothing to transmit, then sample CC lines */
-
- /* CC pull changed, wait 1ms for CC voltage to stabilize */
- if (evt & PD_EVENT_CC)
- usleep(MSEC);
-
- /* check CC lines */
- for (i = 0; i < 2; i++) {
- /* read CC voltage */
- cc = pd_adc_read(port, i);
-
- /* convert voltage to status, and check status change */
- cc = cc_voltage_to_status(port, cc, i);
- if (pd[port].cc_status[i] != cc) {
- pd[port].cc_status[i] = cc;
- alert(port, TCPC_REG_ALERT_CC_STATUS);
- }
- }
- }
-
- /* make sure PD monitoring is enabled to wake on PD RX */
- if (pd[port].rx_enabled)
- pd_rx_enable_monitoring(port);
-
-#ifdef TCPC_LOW_POWER
- /*
- * If we are presenting Rd with no connection, and timestamp is
- * past the low power timestamp, then we don't need to sample
- * CC lines as often. In this case, our connection delay should not
- * actually increased because we will get an interrupt on VBUS detect.
- */
- return (get_time().val >= pd[port].low_power_ts.val &&
- pd[port].cc_pull == TYPEC_CC_RD &&
- cc_is_open(pd[port].cc_status[0], pd[port].cc_status[1]))
- ? 200 * MSEC
- : 10 * MSEC;
-#else
- return 10*MSEC;
-#endif
-}
-
-#if !defined(CONFIG_USB_POWER_DELIVERY) && !defined(CONFIG_USB_SM_FRAMEWORK)
-void pd_task(void *u)
-{
- int port = TASK_ID_TO_PD_PORT(task_get_current());
- int timeout = 10*MSEC;
- int evt;
-
- /* initialize phy task */
- tcpc_init(port);
-
- /* we are now initialized */
- pd[port].power_status &= ~TCPC_REG_POWER_STATUS_UNINIT;
-
- while (1) {
- /* wait for next event/packet or timeout expiration */
- evt = task_wait_event(timeout);
-
- /* run phy task once */
- timeout = tcpc_run(port, evt);
- }
-}
-#endif
-
-void pd_rx_event(int port)
-{
- task_set_event(PD_PORT_TO_TASK_ID(port), TASK_EVENT_WAKE, 0);
-}
-
-int tcpc_alert_status(int port, int *alert)
-{
- /* return the value of the TCPC Alert register */
- uint16_t ret = pd[port].alert;
- *alert = ret;
- return EC_SUCCESS;
-}
-
-int tcpc_alert_status_clear(int port, uint16_t mask)
-{
- /*
- * If the RX status alert is attempting to be cleared, then increment
- * rx buffer tail pointer. if the RX buffer is not empty, then keep
- * the RX status alert active.
- */
- if (mask & TCPC_REG_ALERT_RX_STATUS) {
- if (!rx_buf_is_empty(port)) {
- rx_buf_increment(port, &pd[port].rx_buf_tail);
- if (!rx_buf_is_empty(port))
- /* buffer is not empty, keep alert active */
- mask &= ~TCPC_REG_ALERT_RX_STATUS;
- }
- }
-
- /* clear only the bits specified by the TCPM */
- pd[port].alert &= ~mask;
-#ifndef CONFIG_USB_POWER_DELIVERY
- /* Set Alert# inactive if all alert bits clear */
- if (!pd[port].alert)
- tcpc_alert_clear(port);
-#endif
- return EC_SUCCESS;
-}
-
-int tcpc_alert_mask_set(int port, uint16_t mask)
-{
- /* Update the alert mask as specificied by the TCPM */
- pd[port].alert_mask = mask;
- return EC_SUCCESS;
-}
-
-int tcpc_set_cc(int port, int pull)
-{
- /* If CC pull resistor not changing, then nothing to do */
- if (pd[port].cc_pull == pull)
- return EC_SUCCESS;
-
- /* Change CC pull resistor */
- pd[port].cc_pull = pull;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- pd_set_host_mode(port, pull == TYPEC_CC_RP);
-#endif
-
-#ifdef TCPC_LOW_POWER
- /*
- * Reset the low power timestamp every time CC termination toggles,
- * because we only want to go into low power mode when we are not
- * dual-role toggling.
- */
- pd[port].low_power_ts.val = get_time().val +
- 2*(PD_T_DRP_SRC + PD_T_DRP_SNK);
-#endif
-
- /*
- * Before CC pull can be changed and the task can read the new
- * status, we should set the CC status to open, in case TCPM
- * asks before it is known for sure.
- */
- pd[port].cc_status[0] = TYPEC_CC_VOLT_OPEN;
- pd[port].cc_status[1] = pd[port].cc_status[0];
-
- /* Wake the PD phy task with special CC event mask */
- /* TODO: use top case if no TCPM on same CPU */
-#ifdef CONFIG_USB_POWER_DELIVERY
- tcpc_run(port, PD_EVENT_CC);
-#else
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC, 0);
-#endif
- return EC_SUCCESS;
-}
-
-int tcpc_get_cc(int port, enum tcpc_cc_voltage_status *cc1,
- enum tcpc_cc_voltage_status *cc2)
-{
- *cc2 = pd[port].cc_status[1];
- *cc1 = pd[port].cc_status[0];
-
- return EC_SUCCESS;
-}
-
-int board_select_rp_value(int port, int rp) __attribute__((weak));
-
-int tcpc_select_rp_value(int port, int rp)
-{
- if (board_select_rp_value)
- return board_select_rp_value(port, rp);
- else
- return EC_ERROR_UNIMPLEMENTED;
-}
-
-int tcpc_set_polarity(int port, int polarity)
-{
- pd[port].polarity = polarity;
- pd_select_polarity(port, pd[port].polarity);
-
- return EC_SUCCESS;
-}
-
-#ifdef CONFIG_USB_PD_TCPC_TRACK_VBUS
-static int tcpc_set_power_status(int port, int vbus_present)
-{
- /* Update VBUS present bit */
- if (vbus_present)
- pd[port].power_status |= TCPC_REG_POWER_STATUS_VBUS_PRES;
- else
- pd[port].power_status &= ~TCPC_REG_POWER_STATUS_VBUS_PRES;
-
- /* Set bit Port Power Status bit in Alert register */
- if (pd[port].power_status_mask & TCPC_REG_POWER_STATUS_VBUS_PRES)
- alert(port, TCPC_REG_ALERT_POWER_STATUS);
-
- return EC_SUCCESS;
-}
-#endif /* CONFIG_USB_PD_TCPC_TRACK_VBUS */
-
-int tcpc_set_power_status_mask(int port, uint8_t mask)
-{
- pd[port].power_status_mask = mask;
- return EC_SUCCESS;
-}
-
-int tcpc_set_vconn(int port, int enable)
-{
-#ifdef CONFIG_USBC_VCONN
- pd_set_vconn(port, pd[port].polarity, enable);
-#endif
- return EC_SUCCESS;
-}
-
-int tcpc_set_rx_enable(int port, int enable)
-{
-#if defined(CONFIG_LOW_POWER_IDLE) && !defined(CONFIG_USB_POWER_DELIVERY)
- int i;
-#endif
- pd[port].rx_enabled = enable;
-
- if (!enable)
- pd_rx_disable_monitoring(port);
-
-#if defined(CONFIG_LOW_POWER_IDLE) && !defined(CONFIG_USB_POWER_DELIVERY)
- /* If any PD port is connected, then disable deep sleep */
- for (i = 0; i < board_get_usb_pd_port_count(); ++i)
- if (pd[i].rx_enabled)
- break;
-
- if (i == board_get_usb_pd_port_count())
- enable_sleep(SLEEP_MASK_USB_PD);
- else
- disable_sleep(SLEEP_MASK_USB_PD);
-#endif
- return EC_SUCCESS;
-}
-
-int tcpc_transmit(int port, enum tcpm_transmit_type type, uint16_t header,
- const uint32_t *data)
-{
- /* Store data to transmit and wake task to send it */
- pd[port].tx_type = type;
- pd[port].tx_head = header;
- pd[port].tx_data = data;
- /* TODO: use top case if no TCPM on same CPU */
-#ifdef CONFIG_USB_POWER_DELIVERY
- tcpc_run(port, PD_EVENT_TX);
-#else
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TX, 0);
-#endif
- return EC_SUCCESS;
-}
-
-int tcpc_set_msg_header(int port, int power_role, int data_role)
-{
- pd[port].power_role = power_role;
- pd[port].data_role = data_role;
-
- return EC_SUCCESS;
-}
-
-int tcpc_get_message(int port, uint32_t *payload, int *head)
-{
- /* Get message at tail of RX buffer */
- int idx = pd[port].rx_buf_tail;
-
- memcpy(payload, pd[port].rx_payload[idx],
- sizeof(pd[port].rx_payload[idx]));
- *head = pd[port].rx_head[idx];
- return EC_SUCCESS;
-}
-
-void tcpc_pre_init(void)
-{
- int i;
-
- /* Mark as uninitialized */
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- pd[i].power_status |= TCPC_REG_POWER_STATUS_UNINIT |
- TCPC_REG_POWER_STATUS_VBUS_DET;
-}
-/* Must be prioritized above i2c init */
-DECLARE_HOOK(HOOK_INIT, tcpc_pre_init, HOOK_PRIO_INIT_I2C - 1);
-
-void tcpc_init(int port)
-{
- int i;
-
- if (port >= board_get_usb_pd_port_count())
- return;
-
- /* Initialize physical layer */
- pd_hw_init(port, PD_ROLE_DEFAULT(port));
- pd[port].cc_pull = PD_ROLE_DEFAULT(port) ==
- PD_ROLE_SOURCE ? TYPEC_CC_RP : TYPEC_CC_RD;
-#ifdef TCPC_LOW_POWER
- /* Don't use low power immediately after boot */
- pd[port].low_power_ts.val = get_time().val + SECOND;
-#endif
-
- /* make sure PD monitoring is disabled initially */
- pd[port].rx_enabled = 0;
-
- /* make initial readings of CC voltages */
- for (i = 0; i < 2; i++) {
- pd[port].cc_status[i] = cc_voltage_to_status(port,
- pd_adc_read(port, i),
- i);
- }
-
-#ifdef CONFIG_USB_PD_TCPC_TRACK_VBUS
-#if CONFIG_USB_PD_PORT_MAX_COUNT >= 2
- tcpc_set_power_status(port, !gpio_get_level(port ?
- GPIO_USB_C1_VBUS_WAKE_L :
- GPIO_USB_C0_VBUS_WAKE_L));
-#else
- tcpc_set_power_status(port, !gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L));
-#endif /* CONFIG_USB_PD_PORT_MAX_COUNT >= 2 */
-#endif /* CONFIG_USB_PD_TCPC_TRACK_VBUS */
-
- /* set default alert and power mask register values */
- pd[port].alert_mask = TCPC_REG_ALERT_MASK_ALL;
- pd[port].power_status_mask = TCPC_REG_POWER_STATUS_MASK_ALL;
-
- /* set power status alert since the UNINIT bit has been set */
- alert(port, TCPC_REG_ALERT_POWER_STATUS);
-}
-
-#ifdef CONFIG_USB_PD_TCPC_TRACK_VBUS
-void pd_vbus_evt_p0(enum gpio_signal signal)
-{
- tcpc_set_power_status(TASK_ID_TO_PD_PORT(TASK_ID_PD_C0),
- !gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L));
- task_wake(TASK_ID_PD_C0);
-}
-
-#if CONFIG_USB_PD_PORT_MAX_COUNT >= 2
-void pd_vbus_evt_p1(enum gpio_signal signal)
-{
- if (board_get_usb_pd_port_count() == 1)
- return;
-
- tcpc_set_power_status(TASK_ID_TO_PD_PORT(TASK_ID_PD_C1),
- !gpio_get_level(GPIO_USB_C1_VBUS_WAKE_L));
- task_wake(TASK_ID_PD_C1);
-}
-#endif /* PD_PORT_COUNT >= 2 */
-#endif /* CONFIG_USB_PD_TCPC_TRACK_VBUS */
-
-#ifndef CONFIG_USB_POWER_DELIVERY
-static void tcpc_i2c_write(int port, int reg, int len, uint8_t *payload)
-{
- uint16_t alert;
-
- /* If we are not yet initialized, ignore any write command */
- if (pd[port].power_status & TCPC_REG_POWER_STATUS_UNINIT)
- return;
-
- switch (reg) {
- case TCPC_REG_ROLE_CTRL:
- tcpc_set_cc(port, TCPC_REG_ROLE_CTRL_CC1(payload[1]));
- break;
- case TCPC_REG_POWER_CTRL:
- tcpc_set_vconn(port, TCPC_REG_POWER_CTRL_VCONN(payload[1]));
- break;
- case TCPC_REG_TCPC_CTRL:
- tcpc_set_polarity(port,
- TCPC_REG_TCPC_CTRL_POLARITY(payload[1]));
- break;
- case TCPC_REG_MSG_HDR_INFO:
- tcpc_set_msg_header(port,
- TCPC_REG_MSG_HDR_INFO_PROLE(payload[1]),
- TCPC_REG_MSG_HDR_INFO_DROLE(payload[1]));
- break;
- case TCPC_REG_ALERT:
- alert = payload[1];
- alert |= (payload[2] << 8);
- /* clear alert bits specified by the TCPM */
- tcpc_alert_status_clear(port, alert);
- break;
- case TCPC_REG_ALERT_MASK:
- alert = payload[1];
- alert |= (payload[2] << 8);
- tcpc_alert_mask_set(port, alert);
- break;
- case TCPC_REG_RX_DETECT:
- tcpc_set_rx_enable(port, payload[1] &
- TCPC_REG_RX_DETECT_SOP_HRST_MASK);
- break;
- case TCPC_REG_POWER_STATUS_MASK:
- tcpc_set_power_status_mask(port, payload[1]);
- break;
- case TCPC_REG_TX_HDR:
- pd[port].tx_head = (payload[2] << 8) | payload[1];
- break;
- case TCPC_REG_TX_DATA:
- memcpy(pd[port].tx_payload, &payload[1], len - 1);
- break;
- case TCPC_REG_TRANSMIT:
- tcpc_transmit(port, TCPC_REG_TRANSMIT_TYPE(payload[1]),
- pd[port].tx_head, pd[port].tx_payload);
- break;
- }
-}
-
-static int tcpc_i2c_read(int port, int reg, uint8_t *payload)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
- int alert;
-
- switch (reg) {
- case TCPC_REG_VENDOR_ID:
- *(uint16_t *)payload = USB_VID_GOOGLE;
- return 2;
- case TCPC_REG_CC_STATUS:
- tcpc_get_cc(port, &cc1, &cc2);
- payload[0] = TCPC_REG_CC_STATUS_SET(
- pd[port].cc_pull == TYPEC_CC_RD,
- pd[port].cc_status[0], pd[port].cc_status[1]);
- return 1;
- case TCPC_REG_ROLE_CTRL:
- payload[0] = TCPC_REG_ROLE_CTRL_SET(0, 0,
- pd[port].cc_pull,
- pd[port].cc_pull);
- return 1;
- case TCPC_REG_TCPC_CTRL:
- payload[0] = TCPC_REG_TCPC_CTRL_SET(pd[port].polarity);
- return 1;
- case TCPC_REG_MSG_HDR_INFO:
- payload[0] = TCPC_REG_MSG_HDR_INFO_SET(pd[port].data_role,
- pd[port].power_role);
- return 1;
- case TCPC_REG_RX_DETECT:
- payload[0] = pd[port].rx_enabled ?
- TCPC_REG_RX_DETECT_SOP_HRST_MASK : 0;
- return 1;
- case TCPC_REG_ALERT:
- tcpc_alert_status(port, &alert);
- payload[0] = alert & 0xff;
- payload[1] = (alert >> 8) & 0xff;
- return 2;
- case TCPC_REG_ALERT_MASK:
- payload[0] = pd[port].alert_mask & 0xff;
- payload[1] = (pd[port].alert_mask >> 8) & 0xff;
- return 2;
- case TCPC_REG_RX_BYTE_CNT:
- payload[0] = 3 + 4 *
- PD_HEADER_CNT(pd[port].rx_head[pd[port].rx_buf_tail]);
- return 1;
- case TCPC_REG_RX_HDR:
- payload[0] = pd[port].rx_head[pd[port].rx_buf_tail] & 0xff;
- payload[1] =
- (pd[port].rx_head[pd[port].rx_buf_tail] >> 8) & 0xff;
- return 2;
- case TCPC_REG_RX_DATA:
- memcpy(payload, pd[port].rx_payload[pd[port].rx_buf_tail],
- sizeof(pd[port].rx_payload[pd[port].rx_buf_tail]));
- return sizeof(pd[port].rx_payload[pd[port].rx_buf_tail]);
- case TCPC_REG_POWER_STATUS:
- payload[0] = pd[port].power_status;
- return 1;
- case TCPC_REG_POWER_STATUS_MASK:
- payload[0] = pd[port].power_status_mask;
- return 1;
- case TCPC_REG_TX_HDR:
- payload[0] = pd[port].tx_head & 0xff;
- payload[1] = (pd[port].tx_head >> 8) & 0xff;
- return 2;
- case TCPC_REG_TX_DATA:
- memcpy(payload, pd[port].tx_payload,
- sizeof(pd[port].tx_payload));
- return sizeof(pd[port].tx_payload);
- default:
- return 0;
- }
-}
-
-void tcpc_i2c_process(int read, int port, int len, uint8_t *payload,
- void (*send_response)(int))
-{
- int i, reg;
-
- if (debug_level >= 1) {
- CPRINTF("tcpci p%d: ", port);
- for (i = 0; i < len; i++)
- CPRINTF("0x%02x ", payload[i]);
- CPRINTF("\n");
- }
-
- /* length must always be at least 1 */
- if (len == 0) {
- /*
- * if this is a read, we must call send_response() for
- * i2c transaction to finishe properly
- */
- if (read)
- (*send_response)(0);
- }
-
- /* if this is a write, length must be at least 2 */
- if (!read && len < 2)
- return;
-
- /* register is always first byte */
- reg = payload[0];
-
- /* perform read or write */
- if (read) {
- len = tcpc_i2c_read(port, reg, payload);
- (*send_response)(len);
- } else {
- tcpc_i2c_write(port, reg, len, payload);
- }
-}
-#endif
-
-#ifdef CONFIG_COMMON_RUNTIME
-static int command_tcpc(int argc, char **argv)
-{
- int port;
- char *e;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- if (!strcasecmp(argv[1], "dump")) {
- int level;
-
- if (argc < 3)
- ccprintf("lvl: %d\n", debug_level);
- else {
- level = strtoi(argv[2], &e, 10);
- if (*e)
- return EC_ERROR_PARAM2;
- debug_level = level;
- }
- return EC_SUCCESS;
- }
-
- /* command: pd <port> <subcmd> [args] */
- port = strtoi(argv[1], &e, 10);
- if (argc < 3)
- return EC_ERROR_PARAM_COUNT;
- if (*e || port >= board_get_usb_pd_port_count())
- return EC_ERROR_PARAM2;
-
- if (!strcasecmp(argv[2], "clock")) {
- int freq;
-
- if (argc < 4)
- return EC_ERROR_PARAM2;
-
- freq = strtoi(argv[3], &e, 10);
- if (*e)
- return EC_ERROR_PARAM2;
- pd_set_clock(port, freq);
- ccprintf("set TX frequency to %d Hz\n", freq);
- return EC_SUCCESS;
- } else if (!strncasecmp(argv[2], "state", 5)) {
- ccprintf("Port C%d, %s - CC:%d, CC0:%d, CC1:%d\n"
- "Alert: 0x%02x Mask: 0x%04x\n"
- "Power Status: 0x%02x Mask: 0x%02x\n", port,
- pd[port].rx_enabled ? "Ena" : "Dis",
- pd[port].cc_pull,
- pd[port].cc_status[0], pd[port].cc_status[1],
- pd[port].alert, pd[port].alert_mask,
- pd[port].power_status, pd[port].power_status_mask);
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(tcpc, command_tcpc,
- "dump [0|1]\n\t<port> [clock|state]",
- "Type-C Port Controller");
-#endif
diff --git a/common/usb_port_power_dumb.c b/common/usb_port_power_dumb.c
deleted file mode 100644
index 5cdf6005a6..0000000000
--- a/common/usb_port_power_dumb.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/* Copyright 2012 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.
- */
-
-/* USB charging control module for Chrome EC */
-
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "system.h"
-#include "usb_charge.h"
-#include "util.h"
-
-#define CPUTS(outstr) cputs(CC_USBCHARGE, outstr)
-#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
-
-#define USB_SYSJUMP_TAG 0x5550 /* "UP" - Usb Port */
-#define USB_HOOK_VERSION 1
-
-static uint8_t charge_mode[USB_PORT_COUNT];
-extern const int usb_port_enable[USB_PORT_COUNT];
-
-static void usb_port_set_enabled(int port_id, int en)
-{
- gpio_set_level(usb_port_enable[port_id], en);
- charge_mode[port_id] = en;
-}
-
-static void usb_port_all_ports_on(void)
-{
- int i;
- for (i = 0; i < USB_PORT_COUNT; i++)
- usb_port_set_enabled(i, 1);
-}
-
-static void usb_port_all_ports_off(void)
-{
- int i;
- for (i = 0; i < USB_PORT_COUNT; i++)
- usb_port_set_enabled(i, 0);
-}
-
-/*****************************************************************************/
-/* Host commands */
-
-int usb_charge_set_mode(int port_id, enum usb_charge_mode mode,
- enum usb_suspend_charge inhibit_charge)
-{
- CPRINTS("USB port p%d %d", port_id, mode);
-
- if (port_id < 0 || port_id >= USB_PORT_COUNT)
- return EC_ERROR_INVAL;
-
- switch (mode) {
- case USB_CHARGE_MODE_DISABLED:
- usb_port_set_enabled(port_id, 0);
- break;
- case USB_CHARGE_MODE_ENABLED:
- usb_port_set_enabled(port_id, 1);
- break;
- default:
- return EC_ERROR_UNKNOWN;
- }
-
- return EC_SUCCESS;
-}
-
-static enum ec_status
-usb_port_command_set_mode(struct host_cmd_handler_args *args)
-{
- const struct ec_params_usb_charge_set_mode *p = args->params;
-
- if (usb_charge_set_mode(p->usb_port_id, p->mode,
- p->inhibit_charge) != EC_SUCCESS)
- return EC_RES_ERROR;
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_CHARGE_SET_MODE,
- usb_port_command_set_mode,
- EC_VER_MASK(0));
-
-/*****************************************************************************/
-/* Console commands */
-
-static int command_set_mode(int argc, char **argv)
-{
- int port_id = -1;
- int mode = -1;
- int i;
- char *e;
-
- switch (argc) {
- case 3:
- port_id = strtoi(argv[1], &e, 0);
- if (*e || port_id < 0 || port_id >= USB_PORT_COUNT)
- return EC_ERROR_PARAM1;
-
- if (!parse_bool(argv[2], &mode))
- return EC_ERROR_PARAM2;
-
- usb_port_set_enabled(port_id, mode);
- /* fallthrough */
- case 1:
- for (i = 0; i < USB_PORT_COUNT; i++)
- ccprintf("Port %d: %s\n",
- i, charge_mode[i] ? "on" : "off");
- return EC_SUCCESS;
- }
-
- return EC_ERROR_PARAM_COUNT;
-}
-DECLARE_CONSOLE_COMMAND(usbchargemode, command_set_mode,
- "[<port> <on | off>]",
- "Set USB charge mode");
-
-
-/*****************************************************************************/
-/* Hooks */
-
-static void usb_port_preserve_state(void)
-{
- system_add_jump_tag(USB_SYSJUMP_TAG, USB_HOOK_VERSION,
- sizeof(charge_mode), charge_mode);
-}
-DECLARE_HOOK(HOOK_SYSJUMP, usb_port_preserve_state, HOOK_PRIO_DEFAULT);
-
-static void usb_port_init(void)
-{
- const uint8_t *prev;
- int version, size, i;
-
- prev = (const uint8_t *)system_get_jump_tag(USB_SYSJUMP_TAG,
- &version, &size);
- if (!prev || version != USB_HOOK_VERSION ||
- size != sizeof(charge_mode)) {
- usb_port_all_ports_off();
- return;
- }
-
- for (i = 0; i < USB_PORT_COUNT; i++)
- usb_port_set_enabled(i, prev[i]);
-}
-DECLARE_HOOK(HOOK_INIT, usb_port_init, HOOK_PRIO_DEFAULT);
-
-static void usb_port_resume(void)
-{
- /* Turn on USB ports on as we go into S0 from S3 or S5. */
- usb_port_all_ports_on();
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, usb_port_resume, HOOK_PRIO_DEFAULT);
-
-static void usb_port_shutdown(void)
-{
- /* Turn on USB ports off as we go back to S5. */
- usb_port_all_ports_off();
-}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, usb_port_shutdown, HOOK_PRIO_DEFAULT);
diff --git a/common/usb_port_power_smart.c b/common/usb_port_power_smart.c
deleted file mode 100644
index 59474ff7fe..0000000000
--- a/common/usb_port_power_smart.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/* Copyright 2012 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.
- */
-
-/* USB charging control module for Chrome EC */
-
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "system.h"
-#include "usb_charge.h"
-#include "util.h"
-
-#define CPUTS(outstr) cputs(CC_USBCHARGE, outstr)
-#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
-
-#define USB_SYSJUMP_TAG 0x5550 /* "UP" - Usb Port */
-#define USB_HOOK_VERSION 1
-
-#ifndef CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE
-#define CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE USB_CHARGE_MODE_SDP2
-#endif
-
-struct charge_mode_t {
- uint8_t mode:7;
- uint8_t inhibit_charging_in_suspend:1;
-} __pack;
-
-static struct charge_mode_t charge_mode[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT];
-
-/* GPIOs to enable/disable USB ports. Board specific. */
-extern const int usb_port_enable[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT];
-
-#ifdef CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY
-/*
- * If we only support CDP and SDP, the control signals are hard-wired so
- * there's nothing to do. The only to do is set ILIM_SEL.
- */
-static void usb_charge_set_control_mode(int port_id, int mode) {}
-#else /* !defined(CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY) */
-static void usb_charge_set_control_mode(int port_id, int mode)
-{
-#ifdef CONFIG_USB_PORT_POWER_SMART_SIMPLE
- /*
- * One single shared control signal, so the last mode set to either
- * port wins. Also, only CTL1 can be set; the other pins are
- * hard-wired.
- */
- gpio_or_ioex_set_level(GPIO_USB_CTL1, mode & 0x4);
-#else
- if (port_id == 0) {
- gpio_or_ioex_set_level(GPIO_USB1_CTL1, mode & 0x4);
- gpio_or_ioex_set_level(GPIO_USB1_CTL2, mode & 0x2);
- gpio_or_ioex_set_level(GPIO_USB1_CTL3, mode & 0x1);
- } else {
- gpio_or_ioex_set_level(GPIO_USB2_CTL1, mode & 0x4);
- gpio_or_ioex_set_level(GPIO_USB2_CTL2, mode & 0x2);
- gpio_or_ioex_set_level(GPIO_USB2_CTL3, mode & 0x1);
- }
-#endif /* defined(CONFIG_USB_PORT_POWER_SMART_SIMPLE) */
-}
-#endif /* defined(CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY) */
-
-static void usb_charge_set_enabled(int port_id, int en)
-{
- ASSERT(port_id < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT);
- gpio_or_ioex_set_level(usb_port_enable[port_id], en);
-}
-
-static void usb_charge_set_ilim(int port_id, int sel)
-{
- int ilim_sel;
-
-#if defined(CONFIG_USB_PORT_POWER_SMART_SIMPLE) || \
- defined(CONFIG_USB_PORT_POWER_SMART_INVERTED)
- /* ILIM_SEL is inverted. */
- sel = !sel;
-#endif
-
- ilim_sel = GPIO_USB1_ILIM_SEL;
-#if !defined(CONFIG_USB_PORT_POWER_SMART_SIMPLE) && \
- CONFIG_USB_PORT_POWER_SMART_PORT_COUNT == 2
- if (port_id != 0)
- ilim_sel = GPIO_USB2_ILIM_SEL;
-#endif
-
- gpio_or_ioex_set_level(ilim_sel, sel);
-}
-
-static void usb_charge_all_ports_ctrl(enum usb_charge_mode mode)
-{
- int i;
-
- for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++)
- usb_charge_set_mode(i, mode, USB_ALLOW_SUSPEND_CHARGE);
-}
-
-int usb_charge_set_mode(int port_id, enum usb_charge_mode mode,
- enum usb_suspend_charge inhibit_charge)
-{
- CPRINTS("USB charge p%d m%d i%d", port_id, mode, inhibit_charge);
-
- if (port_id >= CONFIG_USB_PORT_POWER_SMART_PORT_COUNT)
- return EC_ERROR_INVAL;
-
- if (mode == USB_CHARGE_MODE_DEFAULT)
- mode = CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE;
-
- switch (mode) {
- case USB_CHARGE_MODE_DISABLED:
- usb_charge_set_enabled(port_id, 0);
- break;
- case USB_CHARGE_MODE_SDP2:
- usb_charge_set_control_mode(port_id, 7);
- usb_charge_set_ilim(port_id, 0);
- usb_charge_set_enabled(port_id, 1);
- break;
- case USB_CHARGE_MODE_CDP:
- usb_charge_set_control_mode(port_id, 7);
- usb_charge_set_ilim(port_id, 1);
- usb_charge_set_enabled(port_id, 1);
- break;
-#ifndef CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY
- case USB_CHARGE_MODE_DCP_SHORT:
- usb_charge_set_control_mode(port_id, 4);
- usb_charge_set_enabled(port_id, 1);
- break;
-#endif /* !defined(CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY) */
- default:
- return EC_ERROR_UNKNOWN;
- }
-
- charge_mode[port_id].mode = mode;
- charge_mode[port_id].inhibit_charging_in_suspend = inhibit_charge;
-
- return EC_SUCCESS;
-}
-
-/*****************************************************************************/
-/* Console commands */
-
-static int command_set_mode(int argc, char **argv)
-{
- int port_id = -1;
- int mode = -1, inhibit_charge = 0;
- char *e;
- int i;
-
- if (argc == 1) {
- for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++)
- ccprintf("Port %d: %d,%d\n", i, charge_mode[i].mode,
- charge_mode[i].inhibit_charging_in_suspend);
- return EC_SUCCESS;
- }
-
- if (argc != 3 && argc != 4)
- return EC_ERROR_PARAM_COUNT;
-
- port_id = strtoi(argv[1], &e, 0);
- if (*e || port_id < 0 ||
- port_id >= CONFIG_USB_PORT_POWER_SMART_PORT_COUNT)
- return EC_ERROR_PARAM1;
-
- mode = strtoi(argv[2], &e, 0);
- if (*e || mode < 0 || mode >= USB_CHARGE_MODE_COUNT)
- return EC_ERROR_PARAM2;
-
- if (argc == 4) {
- inhibit_charge = strtoi(argv[3], &e, 0);
- if (*e || (inhibit_charge != 0 && inhibit_charge != 1))
- return EC_ERROR_PARAM3;
- }
-
- return usb_charge_set_mode(port_id, mode, inhibit_charge);
-}
-DECLARE_CONSOLE_COMMAND(usbchargemode, command_set_mode,
- "[<port> <0 | 1 | 2 | 3> [<0 | 1>]]",
- "Set USB charge mode");
-
-/*****************************************************************************/
-/* Host commands */
-
-static enum ec_status
-usb_charge_command_set_mode(struct host_cmd_handler_args *args)
-{
- const struct ec_params_usb_charge_set_mode *p = args->params;
-
- if (usb_charge_set_mode(p->usb_port_id, p->mode,
- p->inhibit_charge) != EC_SUCCESS)
- return EC_RES_ERROR;
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_CHARGE_SET_MODE,
- usb_charge_command_set_mode,
- EC_VER_MASK(0));
-
-/*****************************************************************************/
-/* Hooks */
-
-static void usb_charge_preserve_state(void)
-{
- system_add_jump_tag(USB_SYSJUMP_TAG, USB_HOOK_VERSION,
- sizeof(charge_mode), charge_mode);
-}
-DECLARE_HOOK(HOOK_SYSJUMP, usb_charge_preserve_state, HOOK_PRIO_DEFAULT);
-
-static void usb_charge_init(void)
-{
- const struct charge_mode_t *prev;
- int version, size, i;
-
- prev = (const struct charge_mode_t *)system_get_jump_tag(USB_SYSJUMP_TAG,
- &version, &size);
-
- if (!prev || version != USB_HOOK_VERSION ||
- size != sizeof(charge_mode)) {
- usb_charge_all_ports_ctrl(USB_CHARGE_MODE_DISABLED);
- return;
- }
-
- for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++)
- usb_charge_set_mode(i, prev[i].mode,
- prev[i].inhibit_charging_in_suspend);
-}
-DECLARE_HOOK(HOOK_INIT, usb_charge_init, HOOK_PRIO_DEFAULT);
-
-static void usb_charge_resume(void)
-{
- int i;
-
- /* Turn on USB ports on as we go into S0 from S3 or S5. */
- for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++)
- usb_charge_set_mode(i,
- CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE,
- charge_mode[i].inhibit_charging_in_suspend);
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, usb_charge_resume, HOOK_PRIO_DEFAULT);
-
-static void usb_charge_suspend(void)
-{
- int i;
-
- /*
- * Inhibit charging during suspend if the inhibit_charging_in_suspend
- * is set to 1.
- */
- for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++)
- if (charge_mode[i].inhibit_charging_in_suspend)
- usb_charge_set_enabled(i, 0 /* disabled */);
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, usb_charge_suspend, HOOK_PRIO_DEFAULT);
-
-static void usb_charge_shutdown(void)
-{
- /* Turn on USB ports off as we go back to S5. */
- usb_charge_all_ports_ctrl(USB_CHARGE_MODE_DISABLED);
-}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, usb_charge_shutdown, HOOK_PRIO_DEFAULT);
diff --git a/common/usbc/build.mk b/common/usbc/build.mk
deleted file mode 100644
index 69e540ed67..0000000000
--- a/common/usbc/build.mk
+++ /dev/null
@@ -1,24 +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.
-
-# Build for USB Type-C and Power Delivery
-
-# Note that this variable includes the trailing "/"
-_usbc_dir:=$(dir $(lastword $(MAKEFILE_LIST)))
-
-ifneq ($(CONFIG_USB_SM_FRAMEWORK),)
-all-obj-$(CONFIG_USB_SM_FRAMEWORK)+=$(_usbc_dir)usb_sm.o
-all-obj-$(CONFIG_USB_TYPEC_SM)+=$(_usbc_dir)usbc_task.o
-all-obj-$(CONFIG_USB_PRL_SM)+=$(_usbc_dir)usb_prl_sm.o
-ifneq ($(CONFIG_USB_PE_SM),)
-all-obj-$(CONFIG_USB_TYPEC_VPD)+=$(_usbc_dir)usb_pe_ctvpd_sm.o
-all-obj-$(CONFIG_USB_TYPEC_CTVPD)+=$(_usbc_dir)usb_pe_ctvpd_sm.o
-all-obj-$(CONFIG_USB_TYPEC_DRP_ACC_TRYSRC)+=$(_usbc_dir)usb_pe_drp_sm.o
-all-obj-$(CONFIG_TEST_USB_PE_SM)+=$(_usbc_dir)usb_pe_drp_sm.o
-endif
-all-obj-$(CONFIG_USB_TYPEC_VPD)+=$(_usbc_dir)usb_tc_vpd_sm.o
-all-obj-$(CONFIG_USB_TYPEC_CTVPD)+=$(_usbc_dir)usb_tc_ctvpd_sm.o
-all-obj-$(CONFIG_USB_TYPEC_DRP_ACC_TRYSRC)+=\
- $(_usbc_dir)usb_tc_drp_acc_trysrc_sm.o
-endif
diff --git a/common/usbc/usb_pe_ctvpd_sm.c b/common/usbc/usb_pe_ctvpd_sm.c
deleted file mode 100644
index 3e78ebcbb5..0000000000
--- a/common/usbc/usb_pe_ctvpd_sm.c
+++ /dev/null
@@ -1,217 +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 "common.h"
-#include "console.h"
-#include "task.h"
-#include "util.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
-#include "usb_pe_sm.h"
-#include "usb_prl_sm.h"
-#include "usb_tc_sm.h"
-#include "usb_emsg.h"
-#include "usb_sm.h"
-
-/* USB Policy Engine Charge-Through VCONN Powered Device module */
-
-/* Policy Engine Flags */
-#define PE_FLAGS_MSG_RECEIVED BIT(0)
-
-/**
- * This is the PE Port object that contains information needed to
- * implement a VCONN and Charge-Through VCONN Powered Device.
- */
-static struct policy_engine {
- /* state machine context */
- struct sm_ctx ctx;
- /* port flags, see PE_FLAGS_* */
- uint32_t flags;
-} pe[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* List of all policy-engine-level states */
-enum usb_pe_state {
- PE_REQUEST,
-};
-
-/* Forward declare the full list of states. This is indexed by usb_pe_states */
-static const struct usb_state pe_states[];
-
-static void set_state_pe(const int port, enum usb_pe_state new_state)
-{
- set_state(port, &pe[port].ctx, &pe_states[new_state]);
-}
-
-static void pe_init(int port)
-{
- const struct sm_ctx cleared = {};
-
- pe[port].flags = 0;
- pe[port].ctx = cleared;
- set_state_pe(port, PE_REQUEST);
-}
-
-void pe_run(int port, int evt, int en)
-{
- static enum sm_local_state local_state[CONFIG_USB_PD_PORT_MAX_COUNT];
-
- switch (local_state[port]) {
- case SM_PAUSED:
- if (!en)
- break;
- /* fall through */
- case SM_INIT:
- pe_init(port);
- local_state[port] = SM_RUN;
- /* fall through */
- case SM_RUN:
- if (en)
- run_state(port, &pe[port].ctx);
- else
- local_state[port] = SM_PAUSED;
- break;
- }
-}
-
-void pe_message_received(int port)
-{
- pe[port].flags |= PE_FLAGS_MSG_RECEIVED;
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SM, 0);
-}
-
-/**
- * NOTE:
- * The Charge-Through Vconn Powered Device's Policy Engine is very
- * simple and no implementation is needed for the following functions
- * that might be called by the Protocol Layer.
- */
-
-void pe_hard_reset_sent(int port)
-{
- /* No implementation needed by this policy engine */
-}
-
-void pe_got_hard_reset(int port)
-{
- /* No implementation needed by this policy engine */
-}
-
-void pe_report_error(int port, enum pe_error e)
-{
- /* No implementation needed by this policy engine */
-}
-
-void pe_got_soft_reset(int port)
-{
- /* No implementation needed by this policy engine */
-}
-
-void pe_message_sent(int port)
-{
- /* No implementation needed by this policy engine */
-}
-
-static void pe_request_run(const int port)
-{
- uint32_t *payload = (uint32_t *)emsg[port].buf;
- uint32_t header = emsg[port].header;
- uint32_t vdo = payload[0];
-
- if (pe[port].flags & PE_FLAGS_MSG_RECEIVED) {
- pe[port].flags &= ~PE_FLAGS_MSG_RECEIVED;
-
- /*
- * Only support Structured VDM Discovery
- * Identity message
- */
-
- if (PD_HEADER_TYPE(header) != PD_DATA_VENDOR_DEF)
- return;
-
- if (PD_HEADER_CNT(header) == 0)
- return;
-
- if (!PD_VDO_SVDM(vdo))
- return;
-
- if (PD_VDO_CMD(vdo) != CMD_DISCOVER_IDENT)
- return;
-
-#ifdef CONFIG_USB_TYPEC_CTVPD
- /*
- * We have a valid DISCOVER IDENTITY message.
- * Attempt to reset support timer
- */
- tc_reset_support_timer(port);
-#endif
- /* Prepare to send ACK */
-
- /* VDM Header */
- payload[0] = VDO(
- USB_VID_GOOGLE,
- 1, /* Structured VDM */
- VDO_SVDM_VERS(1) |
- VDO_CMDT(CMDT_RSP_ACK) |
- CMD_DISCOVER_IDENT);
-
- /* ID Header VDO */
- payload[1] = VDO_IDH(
- 0, /* Not a USB Host */
- 1, /* Capable of being enumerated as USB Device */
- IDH_PTYPE_VPD,
- 0, /* Modal Operation Not Supported */
- USB_VID_GOOGLE);
-
- /* Cert State VDO */
- payload[2] = 0;
-
- /* Product VDO */
- payload[3] = VDO_PRODUCT(
- CONFIG_USB_PID,
- USB_BCD_DEVICE);
-
- /* VPD VDO */
- payload[4] = VDO_VPD(
- VPD_HW_VERSION,
- VPD_FW_VERSION,
- VPD_MAX_VBUS_20V,
- VPD_VBUS_IMP(VPD_VBUS_IMPEDANCE),
- VPD_GND_IMP(VPD_GND_IMPEDANCE),
-#ifdef CONFIG_USB_TYPEC_CTVPD
- VPD_CTS_SUPPORTED
-#else
- VPD_CTS_NOT_SUPPORTED
-#endif
- );
-
- /* 20 bytes, 5 data objects */
- emsg[port].len = 20;
-
- /* Set to highest revision supported by both ports. */
- prl_set_rev(port, TCPC_TX_SOP_PRIME,
- (PD_HEADER_REV(header) > PD_REV30) ?
- PD_REV30 : PD_HEADER_REV(header));
- /* Send the ACK */
- prl_send_data_msg(port, TCPC_TX_SOP_PRIME,
- PD_DATA_VENDOR_DEF);
- }
-}
-
-/* All policy-engine-level states. */
-static const struct usb_state pe_states[] = {
- [PE_REQUEST] = {
- .run = pe_request_run,
- },
-};
-
-#ifdef TEST_BUILD
-const struct test_sm_data test_pe_sm_data[] = {
- {
- .base = pe_states,
- .size = ARRAY_SIZE(pe_states),
- },
-};
-const int test_pe_sm_data_size = ARRAY_SIZE(test_pe_sm_data);
-#endif
diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c
deleted file mode 100644
index cf9945abdc..0000000000
--- a/common/usbc/usb_pe_drp_sm.c
+++ /dev/null
@@ -1,5244 +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 "atomic.h"
-#include "battery.h"
-#include "battery_smart.h"
-#include "charge_manager.h"
-#include "charge_state.h"
-#include "common.h"
-#include "console.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "task.h"
-#include "tcpm.h"
-#include "util.h"
-#include "usb_common.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpm.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 "usbc_ppc.h"
-
-/*
- * USB Policy Engine Sink / Source module
- *
- * Based on Revision 3.0, Version 1.2 of
- * the USB Power Delivery Specification.
- */
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#endif
-
-#define PE_SET_FLAG(port, flag) atomic_or(&pe[port].flags, (flag))
-#define PE_CLR_FLAG(port, flag) atomic_clear(&pe[port].flags, (flag))
-#define PE_CHK_FLAG(port, flag) (pe[port].flags & (flag))
-
-/*
- * These macros SET, CLEAR, and CHECK, a DPM (Device Policy Manager)
- * Request. The Requests are listed in usb_pe_sm.h.
- */
-#define PE_SET_DPM_REQUEST(port, req) (pe[port].dpm_request |= (req))
-#define PE_CLR_DPM_REQUEST(port, req) (pe[port].dpm_request &= ~(req))
-#define PE_CHK_DPM_REQUEST(port, req) (pe[port].dpm_request & (req))
-
-/*
- * Policy Engine Layer Flags
- */
-
-/* At least one successful PD communication packet received from port partner */
-#define PE_FLAGS_PD_CONNECTION BIT(0)
-/* Accept message received from port partner */
-#define PE_FLAGS_ACCEPT BIT(1)
-/* Power Supply Ready message received from port partner */
-#define PE_FLAGS_PS_READY BIT(2)
-/* Protocol Error was determined based on error recovery current state */
-#define PE_FLAGS_PROTOCOL_ERROR BIT(3)
-/* Set if we are in Modal Operation */
-#define PE_FLAGS_MODAL_OPERATION BIT(4)
-/* A message we requested to be sent has been transmitted */
-#define PE_FLAGS_TX_COMPLETE BIT(5)
-/* A message sent by a port partner has been received */
-#define PE_FLAGS_MSG_RECEIVED BIT(6)
-/* A hard reset has been requested but has not been sent, not currently used */
-#define PE_FLAGS_HARD_RESET_PENDING BIT(7)
-/* Port partner sent a Wait message. Wait before we resend our message */
-#define PE_FLAGS_WAIT BIT(8)
-/* An explicit contract is in place with our port partner */
-#define PE_FLAGS_EXPLICIT_CONTRACT BIT(9)
-/* Waiting for Sink Capabailities timed out. Used for retry error handling */
-#define PE_FLAGS_SNK_WAIT_CAP_TIMEOUT BIT(10)
-/* Power Supply voltage/current transition timed out */
-#define PE_FLAGS_PS_TRANSITION_TIMEOUT BIT(11)
-/* Flag to note current Atomic Message Sequence is interruptible */
-#define PE_FLAGS_INTERRUPTIBLE_AMS BIT(12)
-/* Flag to note Power Supply reset has completed */
-#define PE_FLAGS_PS_RESET_COMPLETE BIT(13)
-/* Flag to note a Structured Vendor Defined Message should be sent */
-#define PE_FLAGS_SEND_SVDM BIT(14)
-/* VCONN swap operation has completed */
-#define PE_FLAGS_VCONN_SWAP_COMPLETE BIT(15)
-/* Flag to note no more discover identity messages should be sent */
-#define PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE BIT(16)
-/* Flag to note Swap Source Start timer should be set at PE_SRC_Startup entry */
-#define PE_FLAGS_RUN_SOURCE_START_TIMER BIT(17)
-/* Flag to note Port Discovery port partner replied with BUSY */
-#define PE_FLAGS_VDM_REQUEST_BUSY BIT(18)
-/* Flag to note Port Discovery port partner replied with NAK */
-#define PE_FLAGS_VDM_REQUEST_NAKED BIT(19)
-/* Flag to note FRS/PRS context in shared state machine path */
-#define PE_FLAGS_FAST_ROLE_SWAP_PATH BIT(20)
-/* Flag to note if FRS listening is enabled */
-#define PE_FLAGS_FAST_ROLE_SWAP_ENABLED BIT(21)
-/* Flag to note TCPC passed on FRS signal from port partner */
-#define PE_FLAGS_FAST_ROLE_SWAP_SIGNALED BIT(22)
-/* For PD2.0, triggers a DR SWAP from UFP to DFP before sending a DiscID msg */
-#define PE_FLAGS_DR_SWAP_TO_DFP BIT(23)
-/* Flag to trigger a message resend after receiving a WAIT from port partner */
-#define PE_FLAGS_WAITING_DR_SWAP BIT(24)
-/* FLAG to track if port partner is dualrole capable */
-#define PE_FLAGS_PORT_PARTNER_IS_DUALROLE BIT(25)
-
-/* 6.7.3 Hard Reset Counter */
-#define N_HARD_RESET_COUNT 2
-
-/* 6.7.4 Capabilities Counter */
-#define N_CAPS_COUNT 25
-
-/* 6.7.5 Discover Identity Counter */
-/*
- * NOTE: The Protocol Layer tries to send a message 4 time before giving up,
- * so a Discover Identity message will be sent 4*5 = 20 times.
- */
-#define N_DISCOVER_IDENTITY_COUNT 5
-/*
- * ChromeOS policy:
- * For PD2.0, We must be DFP before sending Discover Identity message
- * to the port partner. Attempt to DR SWAP from UFP to DFP
- * N_DR_SWAP_ATTEMPT_COUNT times before giving up on sending a
- * Discover Identity message.
- */
-#define N_DR_SWAP_ATTEMPT_COUNT 5
-
-#define TIMER_DISABLED 0xffffffffffffffff /* Unreachable time in future */
-
-/*
- * Function pointer to a Structured Vendor Defined Message (SVDM) response
- * function defined in the board's usb_pd_policy.c file.
- */
-typedef int (*svdm_rsp_func)(int port, uint32_t *payload);
-
-/* List of all Policy Engine level states */
-enum usb_pe_state {
- /* Normal States */
- PE_SRC_STARTUP,
- PE_SRC_DISCOVERY,
- PE_SRC_SEND_CAPABILITIES,
- PE_SRC_NEGOTIATE_CAPABILITY,
- PE_SRC_TRANSITION_SUPPLY,
- PE_SRC_READY,
- PE_SRC_DISABLED,
- PE_SRC_CAPABILITY_RESPONSE,
- PE_SRC_HARD_RESET,
- PE_SRC_HARD_RESET_RECEIVED,
- PE_SRC_TRANSITION_TO_DEFAULT,
- PE_SNK_STARTUP,
- PE_SNK_DISCOVERY,
- PE_SNK_WAIT_FOR_CAPABILITIES,
- PE_SNK_EVALUATE_CAPABILITY,
- PE_SNK_SELECT_CAPABILITY,
- PE_SNK_READY,
- PE_SNK_HARD_RESET,
- PE_SNK_TRANSITION_TO_DEFAULT,
- PE_SNK_GIVE_SINK_CAP,
- PE_SNK_GET_SOURCE_CAP,
- PE_SNK_TRANSITION_SINK,
- PE_SEND_SOFT_RESET,
- PE_SOFT_RESET,
- PE_SEND_NOT_SUPPORTED,
- PE_SRC_PING,
- PE_GIVE_BATTERY_CAP,
- PE_GIVE_BATTERY_STATUS,
- PE_DRS_EVALUATE_SWAP,
- PE_DRS_CHANGE,
- PE_DRS_SEND_SWAP,
- PE_PRS_SRC_SNK_EVALUATE_SWAP,
- PE_PRS_SRC_SNK_TRANSITION_TO_OFF,
- PE_PRS_SRC_SNK_WAIT_SOURCE_ON,
- PE_PRS_SRC_SNK_SEND_SWAP,
- PE_PRS_SNK_SRC_EVALUATE_SWAP,
- PE_PRS_SNK_SRC_TRANSITION_TO_OFF,
- PE_PRS_SNK_SRC_ASSERT_RP,
- PE_PRS_SNK_SRC_SOURCE_ON,
- PE_PRS_SNK_SRC_SEND_SWAP,
- PE_FRS_SNK_SRC_START_AMS,
- PE_VCS_EVALUATE_SWAP,
- PE_VCS_SEND_SWAP,
- PE_VCS_WAIT_FOR_VCONN_SWAP,
- PE_VCS_TURN_ON_VCONN_SWAP,
- PE_VCS_TURN_OFF_VCONN_SWAP,
- PE_VCS_SEND_PS_RDY_SWAP,
- PE_DO_PORT_DISCOVERY,
- PE_VDM_REQUEST,
- PE_VDM_ACKED,
- PE_VDM_RESPONSE,
- PE_HANDLE_CUSTOM_VDM_REQUEST,
- PE_WAIT_FOR_ERROR_RECOVERY,
- PE_BIST,
- PE_DR_SNK_GET_SINK_CAP,
-
- /* Super States */
- PE_PRS_FRS_SHARED,
-};
-
-/* Forward declare the full list of states. This is indexed by usb_pe_state */
-static const struct usb_state pe_states[];
-
-#ifdef CONFIG_COMMON_RUNTIME
-/* List of human readable state names for console debugging */
-static const char * const pe_state_names[] = {
- [PE_SRC_STARTUP] = "PE_SRC_Startup",
- [PE_SRC_DISCOVERY] = "PE_SRC_Discovery",
- [PE_SRC_SEND_CAPABILITIES] = "PE_SRC_Send_Capabilities",
- [PE_SRC_NEGOTIATE_CAPABILITY] = "PE_SRC_Negotiate_Capability",
- [PE_SRC_TRANSITION_SUPPLY] = "PE_SRC_Transition_Supply",
- [PE_SRC_READY] = "PE_SRC_Ready",
- [PE_SRC_DISABLED] = "PE_SRC_Disabled",
- [PE_SRC_CAPABILITY_RESPONSE] = "PE_SRC_Capability_Response",
- [PE_SRC_HARD_RESET] = "PE_SRC_Hard_Reset",
- [PE_SRC_HARD_RESET_RECEIVED] = "PE_SRC_Hard_Reset_Received",
- [PE_SRC_TRANSITION_TO_DEFAULT] = "PE_SRC_Transition_to_default",
- [PE_SNK_STARTUP] = "PE_SNK_Startup",
- [PE_SNK_DISCOVERY] = "PE_SNK_Discovery",
- [PE_SNK_WAIT_FOR_CAPABILITIES] = "PE_SNK_Wait_for_Capabilities",
- [PE_SNK_EVALUATE_CAPABILITY] = "PE_SNK_Evaluate_Capability",
- [PE_SNK_SELECT_CAPABILITY] = "PE_SNK_Select_Capability",
- [PE_SNK_READY] = "PE_SNK_Ready",
- [PE_SNK_HARD_RESET] = "PE_SNK_Hard_Reset",
- [PE_SNK_TRANSITION_TO_DEFAULT] = "PE_SNK_Transition_to_default",
- [PE_SNK_GIVE_SINK_CAP] = "PE_SNK_Give_Sink_Cap",
- [PE_SNK_GET_SOURCE_CAP] = "PE_SNK_Get_Source_Cap",
- [PE_SNK_TRANSITION_SINK] = "PE_SNK_Transition_Sink",
- [PE_SEND_SOFT_RESET] = "PE_Send_Soft_Reset",
- [PE_SOFT_RESET] = "PE_Soft_Reset",
- [PE_SEND_NOT_SUPPORTED] = "PE_Send_Not_Supported",
- [PE_SRC_PING] = "PE_SRC_Ping",
- [PE_GIVE_BATTERY_CAP] = "PE_Give_Battery_Cap",
- [PE_GIVE_BATTERY_STATUS] = "PE_Give_Battery_Status",
- [PE_DRS_EVALUATE_SWAP] = "PE_DRS_Evaluate_Swap",
- [PE_DRS_CHANGE] = "PE_DRS_Change",
- [PE_DRS_SEND_SWAP] = "PE_DRS_Send_Swap",
- [PE_PRS_SRC_SNK_EVALUATE_SWAP] = "PE_PRS_SRC_SNK_Evaluate_Swap",
- [PE_PRS_SRC_SNK_TRANSITION_TO_OFF] = "PE_PRS_SRC_SNK_Transition_To_Off",
- [PE_PRS_SRC_SNK_WAIT_SOURCE_ON] = "PE_PRS_SRC_SNK_Wait_Source_On",
- [PE_PRS_SRC_SNK_SEND_SWAP] = "PE_PRS_SRC_SNK_Send_Swap",
- [PE_PRS_SNK_SRC_EVALUATE_SWAP] = "PE_PRS_SNK_SRC_Evaluate_Swap",
- [PE_PRS_SNK_SRC_TRANSITION_TO_OFF] = "PE_PRS_SNK_SRC_Transition_To_Off",
- [PE_PRS_SNK_SRC_ASSERT_RP] = "PE_PRS_SNK_SRC_Assert_Rp",
- [PE_PRS_SNK_SRC_SOURCE_ON] = "PE_PRS_SNK_SRC_Source_On",
- [PE_PRS_SNK_SRC_SEND_SWAP] = "PE_PRS_SNK_SRC_Send_Swap",
- [PE_FRS_SNK_SRC_START_AMS] = "PE_FRS_SNK_SRC_Start_Ams",
- [PE_VCS_EVALUATE_SWAP] = "PE_VCS_Evaluate_Swap",
- [PE_VCS_SEND_SWAP] = "PE_VCS_Send_Swap",
- [PE_VCS_WAIT_FOR_VCONN_SWAP] = "PE_VCS_Wait_For_Vconn_Swap",
- [PE_VCS_TURN_ON_VCONN_SWAP] = "PE_VCS_Turn_On_Vconn_Swap",
- [PE_VCS_TURN_OFF_VCONN_SWAP] = "PE_VCS_Turn_Off_Vconn_Swap",
- [PE_VCS_SEND_PS_RDY_SWAP] = "PE_VCS_Send_Ps_Rdy_Swap",
- [PE_DO_PORT_DISCOVERY] = "PE_Do_Port_Discovery",
- [PE_VDM_REQUEST] = "PE_VDM_Request",
- [PE_VDM_ACKED] = "PE_VDM_Acked",
- [PE_VDM_RESPONSE] = "PE_VDM_Response",
- [PE_HANDLE_CUSTOM_VDM_REQUEST] = "PE_Handle_Custom_Vdm_Request",
- [PE_WAIT_FOR_ERROR_RECOVERY] = "PE_Wait_For_Error_Recovery",
- [PE_BIST] = "PE_Bist",
- [PE_DR_SNK_GET_SINK_CAP] = "PE_DR_SNK_Get_Sink_Cap",
-};
-#endif
-
-/*
- * NOTE:
- * DO_PORT_DISCOVERY_START is not actually a vdm command. It is used
- * to start the port partner discovery proccess.
- */
-enum vdm_cmd {
- DO_PORT_DISCOVERY_START,
- DISCOVER_IDENTITY,
- DISCOVER_SVIDS,
- DISCOVER_MODES,
- ENTER_MODE,
- EXIT_MODE,
- ATTENTION,
-};
-
-enum port_partner {
- PORT,
- CABLE,
-};
-
-/*
- * This enum is used to implement a state machine consisting of at most
- * 3 states, inside a Policy Engine State.
- */
-enum sub_state {
- PE_SUB0,
- PE_SUB1,
- PE_SUB2
-};
-
-static enum sm_local_state local_state[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/*
- * Policy Engine State Machine Object
- */
-static struct policy_engine {
- /* state machine context */
- struct sm_ctx ctx;
- /* current port power role (SOURCE or SINK) */
- enum pd_power_role power_role;
- /* current port data role (DFP or UFP) */
- enum pd_data_role data_role;
- /* saved data and power roles while communicating with a cable plug */
- enum pd_data_role saved_data_role;
- enum pd_power_role saved_power_role;
- /* state machine flags */
- uint32_t flags;
- /* Device Policy Manager Request */
- uint32_t dpm_request;
- /* state timeout timer */
- uint64_t timeout;
- /* last requested voltage PDO index */
- int requested_idx;
-
- /* Current limit / voltage based on the last request message */
- uint32_t curr_limit;
- uint32_t supply_voltage;
-
- /* state specific state machine variable */
- enum sub_state sub;
-
- /* VDO */
-
- /* PD_VDO_INVALID is used when there is an invalid VDO */
- int32_t active_cable_vdo1;
- int32_t active_cable_vdo2;
- int32_t passive_cable_vdo;
- int32_t ama_vdo;
- int32_t vpd_vdo;
- /* alternate mode policy*/
- struct pd_policy am_policy;
-
- /* VDM */
- enum port_partner partner_type;
- uint32_t vdm_cmd;
- uint32_t vdm_cnt;
- uint32_t vdm_data[VDO_HDR_SIZE + VDO_MAX_SIZE];
-
- /* Timers */
-
- /*
- * The NoResponseTimer is used by the Policy Engine in a Source
- * to determine that its Port Partner is not responding after a
- * Hard Reset.
- */
- uint64_t no_response_timer;
-
- /*
- * Prior to a successful negotiation, a Source Shall use the
- * SourceCapabilityTimer to periodically send out a
- * Source_Capabilities Message.
- */
- uint64_t source_cap_timer;
-
- /*
- * This timer is started when a request for a new Capability has been
- * accepted and will timeout after PD_T_PS_TRANSITION if a PS_RDY
- * Message has not been received.
- */
- uint64_t ps_transition_timer;
-
- /*
- * This timer is used to ensure that a Message requesting a response
- * (e.g. Get_Source_Cap Message) is responded to within a bounded time
- * of PD_T_SENDER_RESPONSE.
- */
- uint64_t sender_response_timer;
-
- /*
- * This timer is used during an Explicit Contract when discovering
- * whether a Port Partner is PD Capable using SOP.
- */
- uint64_t discover_port_identity_timer;
-
- /*
- * This timer is used in a Source to ensure that the Sink has had
- * sufficient time to process Hard Reset Signaling before turning
- * off its power supply to VBUS.
- */
- uint64_t ps_hard_reset_timer;
-
- /*
- * This timer is used to ensure that the time before the next Sink
- * Request Message, after a Wait Message has been received from the
- * Source in response to a Sink Request Message.
- */
- uint64_t sink_request_timer;
-
- /*
- * This timer combines the PSSourceOffTimer and PSSourceOnTimer timers.
- * For PSSourceOffTimer, when this DRP device is currently acting as a
- * Sink, this timer times out on a PS_RDY Message during a Power Role
- * Swap sequence.
- *
- * For PSSourceOnTimer, when this DRP device is currently acting as a
- * Source that has just stopped sourcing power and is waiting to start
- * sinking power to timeout on a PS_RDY Message during a Power Role
- * Swap.
- */
- uint64_t ps_source_timer;
-
- /*
- * This timer is used by a UUT to ensure that a Continuous BIST Mode
- * (i.e. BIST Carrier Mode) is exited in a timely fashion.
- */
- uint64_t bist_cont_mode_timer;
-
- /*
- * This timer is used by the new Source, after a Power Role Swap or
- * Fast Role Swap, to ensure that it does not send Source_Capabilities
- * Message before the new Sink is ready to receive the
- * Source_Capabilities Message.
- */
- uint64_t swap_source_start_timer;
-
- /*
- * This timer is used by the Initiator’s Policy Engine to ensure that
- * a Structured VDM Command request needing a response (e.g. Discover
- * Identity Command request) is responded to within a bounded time of
- * tVDMSenderResponse.
- */
- uint64_t vdm_response_timer;
-
- /*
- * This timer is used during a VCONN Swap.
- */
- uint64_t vconn_on_timer;
-
- /* Counters */
-
- /*
- * This counter is used to retry the Hard Reset whenever there is no
- * response from the remote device.
- */
- uint32_t hard_reset_counter;
-
- /*
- * This counter is used to count the number of Source_Capabilities
- * Messages which have been sent by a Source at power up or after a
- * Hard Reset.
- */
- uint32_t caps_counter;
-
- /*
- * This counter maintains a count of Discover Identity Messages sent
- * to a port partner.
- */
- uint32_t discover_port_identity_counter;
- /*
- * For PD2.0, we need to be a DFP before sending a discovery identity
- * messaage to our port partner. This counter keeps track of how
- * many attempts to DR SWAP from UFP to DFP.
- */
- uint32_t dr_swap_attempt_counter;
-
- /* Last received source cap */
- uint32_t src_caps[PDO_MAX_OBJECTS];
- int src_cap_cnt;
-
-} pe[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/*
- * As a sink, this is the max voltage (in millivolts) we can request
- * before getting source caps
- */
-static unsigned int max_request_mv = PD_MAX_VOLTAGE_MV;
-
-/*
- * Private VDM utility functions
- */
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-static int validate_mode_request(struct svdm_amode_data *modep,
- uint16_t svid, int opos);
-static void dfp_consume_attention(int port, uint32_t *payload);
-static void dfp_consume_identity(int port, int cnt, uint32_t *payload);
-static void dfp_consume_svids(int port, int cnt, uint32_t *payload);
-static int dfp_discover_modes(int port, uint32_t *payload);
-static void dfp_consume_modes(int port, int cnt, uint32_t *payload);
-static int get_mode_idx(int port, uint16_t svid);
-static struct svdm_amode_data *get_modep(int port, uint16_t svid);
-#endif
-
-test_export_static enum usb_pe_state get_state_pe(const int port);
-test_export_static void set_state_pe(const int port,
- const enum usb_pe_state new_state);
-
-static void pe_init(int port)
-{
- pe[port].flags = 0;
- pe[port].dpm_request = 0;
- pe[port].source_cap_timer = TIMER_DISABLED;
- pe[port].no_response_timer = TIMER_DISABLED;
- pe[port].data_role = tc_get_data_role(port);
-
- tc_pd_connection(port, 0);
-
- if (tc_get_power_role(port) == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_STARTUP);
- else
- set_state_pe(port, PE_SNK_STARTUP);
-}
-
-int pe_is_running(int port)
-{
- return local_state[port] == SM_RUN;
-}
-
-void pe_run(int port, int evt, int en)
-{
- switch (local_state[port]) {
- case SM_PAUSED:
- if (!en)
- break;
- /* fall through */
- case SM_INIT:
- pe_init(port);
- local_state[port] = SM_RUN;
- /* fall through */
- case SM_RUN:
- if (!en) {
- local_state[port] = SM_PAUSED;
- /*
- * While we are paused, exit all states and wait until
- * initialized again.
- */
- set_state(port, &pe[port].ctx, NULL);
- break;
- }
-
- /*
- * Check for Fast Role Swap signal
- * This is not a typical pattern for adding state changes.
- * I added this here because FRS SIGNALED can happen at any
- * state once we are listening for the signal and we want to
- * make sure to handle it immediately.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_SIGNALED)) {
- PE_CLR_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_SIGNALED);
- set_state_pe(port, PE_FRS_SNK_SRC_START_AMS);
- }
-
- /* Run state machine */
- run_state(port, &pe[port].ctx);
- break;
- }
-}
-
-int pe_is_explicit_contract(int port)
-{
- return PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT);
-}
-
-void pe_message_received(int port)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- PE_SET_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-}
-
-void pe_hard_reset_sent(int port)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- PE_CLR_FLAG(port, PE_FLAGS_HARD_RESET_PENDING);
-}
-
-void pe_got_hard_reset(int port)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- /*
- * Transition from any state to the PE_SRC_Hard_Reset_Received or
- * PE_SNK_Transition_to_default state when:
- * 1) Hard Reset Signaling is detected.
- */
- pe[port].power_role = tc_get_power_role(port);
-
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_HARD_RESET_RECEIVED);
- else
- set_state_pe(port, PE_SNK_TRANSITION_TO_DEFAULT);
-}
-
-/*
- * pe_got_frs_signal
- *
- * Called by the handler that detects the FRS signal in order to
- * switch PE states to complete the FRS that the hardware has
- * started.
- */
-void pe_got_frs_signal(int port)
-{
- PE_SET_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_SIGNALED);
-}
-
-/*
- * PE_Set_FRS_Enable
- *
- * This function should be called every time an explicit contract
- * is disabled, to disable FRS.
- *
- * Enabling an explicit contract is not enough to enable FRS, it
- * also requires a Sink Capability power requirement from a Source
- * that supports FRS so we can determine if this is something we
- * can handle.
- */
-static void pe_set_frs_enable(int port, int enable)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- if (IS_ENABLED(CONFIG_USB_TYPEC_PD_FAST_ROLE_SWAP)) {
- int current = PE_CHK_FLAG(port,
- PE_FLAGS_FAST_ROLE_SWAP_ENABLED);
-
- /* Request an FRS change, only if the state has changed */
- if (!!current != !!enable) {
- tcpm_set_frs_enable(port, enable);
-
- if (enable)
- PE_SET_FLAG(port,
- PE_FLAGS_FAST_ROLE_SWAP_ENABLED);
- else
- PE_CLR_FLAG(port,
- PE_FLAGS_FAST_ROLE_SWAP_ENABLED);
- }
- }
-}
-
-static void pe_invalidate_explicit_contract(int port)
-{
- pe_set_frs_enable(port, 0);
- PE_CLR_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT);
-}
-
-void pe_report_error(int port, enum pe_error e)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- /*
- * Generate Hard Reset if Protocol Error occurred
- * while in PE_Send_Soft_Reset state.
- */
- if (get_state_pe(port) == PE_SEND_SOFT_RESET) {
- if (pe[port].power_role == PD_ROLE_SINK)
- set_state_pe(port, PE_SNK_HARD_RESET);
- else
- set_state_pe(port, PE_SRC_HARD_RESET);
- return;
- }
-
- if (get_state_pe(port) == PE_SRC_SEND_CAPABILITIES ||
- get_state_pe(port) == PE_SRC_TRANSITION_SUPPLY ||
- get_state_pe(port) == PE_PRS_SRC_SNK_WAIT_SOURCE_ON ||
- get_state_pe(port) == PE_SRC_DISABLED ||
- get_state_pe(port) == PE_SRC_DISCOVERY ||
- get_state_pe(port) == PE_VDM_REQUEST) {
- PE_SET_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
- return;
- }
-
- /*
- * See section 8.3.3.4.1.1 PE_SRC_Send_Soft_Reset State:
- *
- * The PE_Send_Soft_Reset state shall be entered from
- * any state when a Protocol Error is detected by
- * Protocol Layer during a Non-Interruptible AMS or when
- * Message has not been sent after retries. When an explicit
- * contract is not in effect. Otherwise go to PE_Snk/Src_Ready
- */
- if (!PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT) &&
- (!PE_CHK_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS)
- || (e == ERR_TCH_XMIT))) {
- set_state_pe(port, PE_SEND_SOFT_RESET);
- }
- /*
- * Transition to PE_Snk_Ready or PE_Src_Ready by a Protocol
- * Error during an Interruptible AMS.
- */
- else {
- PE_SET_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
- if (pe[port].power_role == PD_ROLE_SINK)
- set_state_pe(port, PE_SNK_READY);
- else
- set_state_pe(port, PE_SRC_READY);
- }
-}
-
-void pe_got_soft_reset(int port)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- /*
- * The PE_SRC_Soft_Reset state Shall be entered from any state when a
- * Soft_Reset Message is received from the Protocol Layer.
- */
- set_state_pe(port, PE_SOFT_RESET);
-}
-
-void pe_dpm_request(int port, enum pe_dpm_request req)
-{
- if (get_state_pe(port) == PE_SRC_READY ||
- get_state_pe(port) == PE_SNK_READY)
- PE_SET_DPM_REQUEST(port, req);
-}
-
-void pe_vconn_swap_complete(int port)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- PE_SET_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE);
-}
-
-void pe_ps_reset_complete(int port)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- PE_SET_FLAG(port, PE_FLAGS_PS_RESET_COMPLETE);
-}
-
-void pe_message_sent(int port)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- PE_SET_FLAG(port, PE_FLAGS_TX_COMPLETE);
-}
-
-void pe_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data,
- int count)
-{
- pe[port].partner_type = PORT;
-
- /* Copy VDM Header */
- pe[port].vdm_data[0] = VDO(vid, ((vid & USB_SID_PD) == USB_SID_PD) ?
- 1 : (PD_VDO_CMD(cmd) <= CMD_ATTENTION),
- VDO_SVDM_VERS(1) | cmd);
-
- /* Copy Data after VDM Header */
- memcpy((pe[port].vdm_data + 1), data, count);
-
- pe[port].vdm_cnt = count + 1;
-
- PE_SET_FLAG(port, PE_FLAGS_SEND_SVDM);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void pe_exit_dp_mode(int port)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
- int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
-
- if (opos <= 0)
- return;
-
- CPRINTS("C%d Exiting DP mode", port);
- if (!pd_dfp_exit_mode(port, USB_SID_DISPLAYPORT, opos))
- return;
-
- pe_send_vdm(port, USB_SID_DISPLAYPORT,
- CMD_EXIT_MODE | VDO_OPOS(opos), NULL, 0);
- }
-}
-
-/*
- * Private functions
- */
-
-/* Set the TypeC state machine to a new state. */
-test_export_static void set_state_pe(const int port,
- const enum usb_pe_state new_state)
-{
- set_state(port, &pe[port].ctx, &pe_states[new_state]);
-}
-
-/* Get the current TypeC state. */
-test_export_static enum usb_pe_state get_state_pe(const int port)
-{
- return pe[port].ctx.current - &pe_states[0];
-}
-
-/* Get the previous TypeC state. */
-static enum usb_pe_state get_last_state_pe(const int port)
-{
- return pe[port].ctx.previous - &pe_states[0];
-}
-
-static void print_current_state(const int port)
-{
- const char *mode = "";
-
- if (PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH))
- mode = " FRS-MODE";
-
- CPRINTS("C%d: %s%s", port, pe_state_names[get_state_pe(port)], mode);
-}
-
-static void send_source_cap(int port)
-{
-#if defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \
- defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT)
- const uint32_t *src_pdo;
- const int src_pdo_cnt = charge_manager_get_source_pdo(&src_pdo, port);
-#else
- const uint32_t *src_pdo = pd_src_pdo;
- const int src_pdo_cnt = pd_src_pdo_cnt;
-#endif
-
- if (src_pdo_cnt == 0) {
- /* No source capabilities defined, sink only */
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_REJECT);
- }
-
- emsg[port].len = src_pdo_cnt * 4;
- memcpy(emsg[port].buf, (uint8_t *)src_pdo, emsg[port].len);
-
- prl_send_data_msg(port, TCPC_TX_SOP, PD_DATA_SOURCE_CAP);
-}
-
-/*
- * Request desired charge voltage from source.
- */
-static void pe_send_request_msg(int port)
-{
- uint32_t rdo;
- uint32_t curr_limit;
- uint32_t supply_voltage;
- int charging;
- int max_request_allowed;
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER))
- charging = (charge_manager_get_active_charge_port() == port);
- else
- charging = 1;
-
- if (IS_ENABLED(CONFIG_USB_PD_CHECK_MAX_REQUEST_ALLOWED))
- max_request_allowed = pd_is_max_request_allowed();
- else
- max_request_allowed = 1;
-
- /* Build and send request RDO */
- /*
- * If this port is not actively charging or we are not allowed to
- * request the max voltage, then select vSafe5V
- */
- pd_build_request(pe[port].src_cap_cnt, pe[port].src_caps,
- pe[port].vpd_vdo, &rdo, &curr_limit,
- &supply_voltage, charging && max_request_allowed ?
- PD_REQUEST_MAX : PD_REQUEST_VSAFE5V, max_request_mv);
-
- CPRINTF("C%d Req [%d] %dmV %dmA", port, RDO_POS(rdo),
- supply_voltage, curr_limit);
- if (rdo & RDO_CAP_MISMATCH)
- CPRINTF(" Mismatch");
- CPRINTF("\n");
-
- pe[port].curr_limit = curr_limit;
- pe[port].supply_voltage = supply_voltage;
-
- emsg[port].len = 4;
-
- memcpy(emsg[port].buf, (uint8_t *)&rdo, emsg[port].len);
- prl_send_data_msg(port, TCPC_TX_SOP, PD_DATA_REQUEST);
-}
-
-static void pe_update_pdo_flags(int port, uint32_t pdo)
-{
-#ifdef CONFIG_CHARGE_MANAGER
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- int charge_allowlisted =
- (tc_get_power_role(port) == PD_ROLE_SINK &&
- pd_charge_from_device(pd_get_identity_vid(port),
- pd_get_identity_pid(port)));
-#else
- const int charge_allowlisted = 0;
-#endif
-#endif
-
- /* can only parse PDO flags if type is fixed */
- if ((pdo & PDO_TYPE_MASK) != PDO_TYPE_FIXED)
- return;
-
- if (pdo & PDO_FIXED_DUAL_ROLE)
- tc_partner_dr_power(port, 1);
- else
- tc_partner_dr_power(port, 0);
-
- if (pdo & PDO_FIXED_EXTERNAL)
- tc_partner_extpower(port, 1);
- else
- tc_partner_extpower(port, 0);
-
- if (pdo & PDO_FIXED_COMM_CAP)
- tc_partner_usb_comm(port, 1);
- else
- tc_partner_usb_comm(port, 0);
-
- if (pdo & PDO_FIXED_DATA_SWAP)
- tc_partner_dr_data(port, 1);
- else
- tc_partner_dr_data(port, 0);
-
-#ifdef CONFIG_CHARGE_MANAGER
- /*
- * Treat device as a dedicated charger (meaning we should charge
- * from it) if it does not support power swap, or if it is externally
- * powered, or if we are a sink and the device identity matches a
- * charging allowlist.
- */
- if (!(pdo & PDO_FIXED_DUAL_ROLE) || (pdo & PDO_FIXED_EXTERNAL) ||
- charge_allowlisted) {
- PE_CLR_FLAG(port, PE_FLAGS_PORT_PARTNER_IS_DUALROLE);
- charge_manager_update_dualrole(port, CAP_DEDICATED);
- } else {
- PE_SET_FLAG(port, PE_FLAGS_PORT_PARTNER_IS_DUALROLE);
- charge_manager_update_dualrole(port, CAP_DUALROLE);
- }
-#endif
-}
-
-int pd_is_port_partner_dualrole(int port)
-{
- return PE_CHK_FLAG(port, PE_FLAGS_PORT_PARTNER_IS_DUALROLE);
-}
-
-int pd_board_check_request(uint32_t rdo, int pdo_cnt)
-{
- int idx = RDO_POS(rdo);
-
- /* Check for invalid index */
- return (!idx || idx > pdo_cnt) ?
- EC_ERROR_INVAL : EC_SUCCESS;
-}
-
-static void pe_prl_execute_hard_reset(int port)
-{
- prl_execute_hard_reset(port);
-}
-
-/*
- * This function must only be called from the PE_SNK_READY entry and
- * PE_SRC_READY entry State.
- */
-static void pe_attempt_port_discovery(int port)
-{
- if (!PE_CHK_FLAG(port, PE_FLAGS_MODAL_OPERATION |
- PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE) &&
- pe[port].discover_port_identity_counter <=
- N_DISCOVER_IDENTITY_COUNT) {
- /*
- * If we are operating as PD2.0 version, make sure we are
- * DFP before sending Discover Identity message.
- */
- if (prl_get_rev(port, TCPC_TX_SOP) == PD_REV20 &&
- pe[port].data_role == PD_ROLE_UFP) {
- /*
- * If we are UFP and DR SWAP fails
- * N_DR_SWAP_ATTEMPT_COUNT number of times, give up
- * port discovery. Also give up if the Port Partner
- * rejected the DR_SWAP.
- */
- if ((pe[port].dr_swap_attempt_counter >=
- N_DR_SWAP_ATTEMPT_COUNT) ||
- (pe[port].dr_swap_attempt_counter > 0 &&
- !PE_CHK_FLAG(port, PE_FLAGS_WAITING_DR_SWAP))) {
- PE_SET_FLAG(port,
- PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE);
- pe[port].discover_port_identity_timer =
- TIMER_DISABLED;
- } else {
- PE_SET_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP);
- pe[port].discover_port_identity_timer =
- get_time().val + PD_T_DISCOVER_IDENTITY;
- }
- } else {
- pe[port].discover_port_identity_timer =
- get_time().val + PD_T_DISCOVER_IDENTITY;
- }
- } else {
- PE_SET_FLAG(port, PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE);
- pe[port].discover_port_identity_timer = TIMER_DISABLED;
- }
-
- /*
- * For PD2.0, add some jitter of up to 100ms before sending a message.
- * Some devices are chatty once we reach the SRC_READY state and we may
- * end up in a collision of messages if we try to immediately send our
- * interrogations.
- */
- if (prl_get_rev(port, TCPC_TX_SOP) == PD_REV20) {
- if (pe[port].discover_port_identity_timer != TIMER_DISABLED)
- pe[port].discover_port_identity_timer +=
- (get_time().le.lo % (100 * MSEC));
- }
-
- /* Clear the PE_FLAGS_WAITING_DR_SWAP flag if it was set. */
- PE_CLR_FLAG(port, PE_FLAGS_WAITING_DR_SWAP);
-}
-
-/*
- * This function must only be called from the PE_SNK_READY run and
- * PE_SRC_READY run State.
- */
-static void pe_start_port_discovery(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP)) {
- PE_CLR_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP);
- pe[port].dr_swap_attempt_counter++;
- set_state_pe(port, PE_DRS_SEND_SWAP);
- } else {
- pe[port].discover_port_identity_counter++;
- pe[port].vdm_cmd = DO_PORT_DISCOVERY_START;
- PE_CLR_FLAG(port, PE_FLAGS_VDM_REQUEST_NAKED |
- PE_FLAGS_VDM_REQUEST_BUSY);
- set_state_pe(port, PE_DO_PORT_DISCOVERY);
- }
-}
-
-/**
- * PE_SRC_Startup
- */
-static void pe_src_startup_entry(int port)
-{
- print_current_state(port);
-
- /* Initialize VDOs to default values */
- pe[port].active_cable_vdo1 = PD_VDO_INVALID;
- pe[port].active_cable_vdo2 = PD_VDO_INVALID;
- pe[port].passive_cable_vdo = PD_VDO_INVALID;
- pe[port].ama_vdo = PD_VDO_INVALID;
- pe[port].vpd_vdo = PD_VDO_INVALID;
-
- /* Reset CapsCounter */
- pe[port].caps_counter = 0;
-
- /* Reset the protocol layer */
- prl_reset(port);
-
- /* Set initial data role */
- pe[port].data_role = tc_get_data_role(port);
-
- /* Set initial power role */
- pe[port].power_role = PD_ROLE_SOURCE;
-
- /* Clear explicit contract. */
- pe_invalidate_explicit_contract(port);
-
- /* Clear port discovery flags */
- PE_CLR_FLAG(port, PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE);
- pe[port].discover_port_identity_counter = 0;
-
- /* Reset dr swap attempt counter */
- pe[port].dr_swap_attempt_counter = 0;
-
- if (PE_CHK_FLAG(port, PE_FLAGS_RUN_SOURCE_START_TIMER)) {
- PE_CLR_FLAG(port, PE_FLAGS_RUN_SOURCE_START_TIMER);
-
- /* Start SwapSourceStartTimer */
- pe[port].swap_source_start_timer = get_time().val +
- PD_T_SWAP_SOURCE_START;
- } else {
- /*
- * SwapSourceStartTimer delay is not needed, so trigger now.
- * We can't use set_state_pe here, since we need to ensure that
- * the protocol layer is running again (done in run function).
- */
- pe[port].swap_source_start_timer = get_time().val;
- }
-}
-
-static void pe_src_startup_run(int port)
-{
- /* Wait until protocol layer is running */
- if (!prl_is_running(port))
- return;
-
- if (get_time().val > pe[port].swap_source_start_timer)
- set_state_pe(port, PE_SRC_SEND_CAPABILITIES);
-}
-
-/**
- * PE_SRC_Discovery
- */
-static void pe_src_discovery_entry(int port)
-{
- print_current_state(port);
-
- /*
- * Initialize and run the SourceCapabilityTimer in order
- * to trigger sending a Source_Capabilities Message.
- *
- * The SourceCapabilityTimer Shall continue to run during
- * identity discover and Shall Not be initialized on re-entry
- * to PE_SRC_Discovery.
- */
- if (get_last_state_pe(port) != PE_VDM_REQUEST)
- pe[port].source_cap_timer =
- get_time().val + PD_T_SEND_SOURCE_CAP;
-}
-
-static void pe_src_discovery_run(int port)
-{
- /*
- * Transition to the PE_SRC_Send_Capabilities state when:
- * 1) The SourceCapabilityTimer times out and
- * CapsCounter ≤ nCapsCount.
- *
- * Transition to the PE_SRC_Disabled state when:
- * 1) The Port Partners are not presently PD Connected
- * 2) And the SourceCapabilityTimer times out
- * 3) And CapsCounter > nCapsCount.
- */
- if (get_time().val > pe[port].source_cap_timer) {
- if (pe[port].caps_counter <= N_CAPS_COUNT) {
- set_state_pe(port, PE_SRC_SEND_CAPABILITIES);
- return;
- } else if (!PE_CHK_FLAG(port, PE_FLAGS_PD_CONNECTION)) {
- set_state_pe(port, PE_SRC_DISABLED);
- return;
- }
- }
-
- /*
- * Transition to the PE_SRC_Disabled state when:
- * 1) The Port Partners have not been PD Connected.
- * 2) And the NoResponseTimer times out.
- * 3) And the HardResetCounter > nHardResetCount.
- */
- if (!PE_CHK_FLAG(port, PE_FLAGS_PD_CONNECTION) &&
- get_time().val > pe[port].no_response_timer &&
- pe[port].hard_reset_counter > N_HARD_RESET_COUNT) {
- set_state_pe(port, PE_SRC_DISABLED);
- return;
- }
-}
-
-/**
- * PE_SRC_Send_Capabilities
- */
-static void pe_src_send_capabilities_entry(int port)
-{
- print_current_state(port);
-
- /* Send PD Capabilities message */
- send_source_cap(port);
-
- /* Increment CapsCounter */
- pe[port].caps_counter++;
-
- /* Stop sender response timer */
- pe[port].sender_response_timer = TIMER_DISABLED;
-
- /*
- * Clear PE_FLAGS_INTERRUPTIBLE_AMS flag if it was set
- * in the src_discovery state
- */
- PE_CLR_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
-}
-
-static void pe_src_send_capabilities_run(int port)
-{
- /*
- * If a GoodCRC Message is received then the Policy Engine Shall:
- * 1) Stop the NoResponseTimer.
- * 2) Reset the HardResetCounter and CapsCounter to zero.
- * 3) Initialize and run the SenderResponseTimer.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE) &&
- pe[port].sender_response_timer == TIMER_DISABLED) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- /* Stop the NoResponseTimer */
- pe[port].no_response_timer = TIMER_DISABLED;
-
- /* Reset the HardResetCounter to zero */
- pe[port].hard_reset_counter = 0;
-
- /* Reset the CapsCounter to zero */
- pe[port].caps_counter = 0;
-
- /* Initialize and run the SenderResponseTimer */
- pe[port].sender_response_timer = get_time().val +
- PD_T_SENDER_RESPONSE;
- }
-
- /*
- * Transition to the PE_SRC_Negotiate_Capability state when:
- * 1) A Request Message is received from the Sink
- */
- if (pe[port].sender_response_timer != TIMER_DISABLED &&
- PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- /*
- * Request Message Received?
- */
- if (PD_HEADER_CNT(emsg[port].header) > 0 &&
- PD_HEADER_TYPE(emsg[port].header) == PD_DATA_REQUEST) {
-
- /*
- * Set to highest revision supported by both
- * ports.
- */
- prl_set_rev(port, TCPC_TX_SOP,
- (PD_HEADER_REV(emsg[port].header) > PD_REV30) ?
- PD_REV30 : PD_HEADER_REV(emsg[port].header));
-
- /* We are PD connected */
- PE_SET_FLAG(port, PE_FLAGS_PD_CONNECTION);
- tc_pd_connection(port, 1);
-
- /*
- * Handle the Sink Request in
- * PE_SRC_Negotiate_Capability state
- */
- set_state_pe(port, PE_SRC_NEGOTIATE_CAPABILITY);
- return;
- }
-
- /*
- * We have a Protocol Error.
- * PE_SNK/SRC_READY if explicit contract
- * PE_SEND_SOFT_RESET otherwise
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT))
- if (pe[port].power_role == PD_ROLE_SINK)
- set_state_pe(port, PE_SNK_READY);
- else
- set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SEND_SOFT_RESET);
- return;
- }
-
- /*
- * Transition to the PE_SRC_Discovery state when:
- * 1) The Protocol Layer indicates that the Message has not been sent
- * and we are presently not Connected
- *
- * NOTE: The PE_FLAGS_PROTOCOL_ERROR is set if a GoodCRC Message
- * is not received.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR) &&
- !PE_CHK_FLAG(port, PE_FLAGS_PD_CONNECTION)) {
- PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
-
- set_state_pe(port, PE_SRC_DISCOVERY);
- return;
- }
-
- /*
- * Transition to the PE_SRC_Disabled state when:
- * 1) The Port Partners have not been PD Connected
- * 2) The NoResponseTimer times out
- * 3) And the HardResetCounter > nHardResetCount.
- *
- * Transition to the Error Recovery state when:
- * 1) The Port Partners have previously been PD Connected
- * 2) The NoResponseTimer times out
- * 3) And the HardResetCounter > nHardResetCount.
- */
- if (get_time().val > pe[port].no_response_timer) {
- if (pe[port].hard_reset_counter <= N_HARD_RESET_COUNT)
- set_state_pe(port, PE_SRC_HARD_RESET);
- else if (PE_CHK_FLAG(port, PE_FLAGS_PD_CONNECTION))
- set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY);
- else
- set_state_pe(port, PE_SRC_DISABLED);
- return;
- }
-
- /*
- * Transition to the PE_SRC_Hard_Reset state when:
- * 1) The SenderResponseTimer times out.
- */
- if (get_time().val > pe[port].sender_response_timer) {
- set_state_pe(port, PE_SRC_HARD_RESET);
- return;
- }
-}
-
-/**
- * PE_SRC_Negotiate_Capability
- */
-static void pe_src_negotiate_capability_entry(int port)
-{
- uint32_t payload;
-
- print_current_state(port);
-
- /* Get message payload */
- payload = *(uint32_t *)(&emsg[port].buf);
-
- /*
- * Evaluate the Request from the Attached Sink
- */
-
- /*
- * Transition to the PE_SRC_Capability_Response state when:
- * 1) The Request cannot be met.
- * 2) Or the Request can be met later from the Power Reserve
- *
- * Transition to the PE_SRC_Transition_Supply state when:
- * 1) The Request can be met
- *
- */
- if (pd_check_requested_voltage(payload, port) != EC_SUCCESS) {
- set_state_pe(port, PE_SRC_CAPABILITY_RESPONSE);
- } else {
- PE_SET_FLAG(port, PE_FLAGS_ACCEPT);
- pe[port].requested_idx = RDO_POS(payload);
- set_state_pe(port, PE_SRC_TRANSITION_SUPPLY);
- }
-}
-
-/**
- * PE_SRC_Transition_Supply
- */
-static void pe_src_transition_supply_entry(int port)
-{
- print_current_state(port);
-
- /* Transition Power Supply */
- pd_transition_voltage(pe[port].requested_idx);
-
- /* Send a GotoMin Message or otherwise an Accept Message */
- if (PE_CHK_FLAG(port, PE_FLAGS_ACCEPT)) {
- PE_CLR_FLAG(port, PE_FLAGS_ACCEPT);
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_ACCEPT);
- } else {
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_GOTO_MIN);
- }
-
-}
-
-static void pe_src_transition_supply_run(int port)
-{
- /*
- * Transition to the PE_SRC_Ready state when:
- * 1) The power supply is ready.
- *
- * NOTE: This code block is executed twice:
- * First Pass)
- * When PE_FLAGS_TX_COMPLETE is set due to the
- * PD_CTRL_ACCEPT or PD_CTRL_GOTO_MIN messages
- * being sent.
- *
- * Second Pass)
- * When PE_FLAGS_TX_COMPLETE is set due to the
- * PD_CTRL_PS_RDY message being sent.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- /*
- * NOTE: If a message was received,
- * pe_src_ready state will handle it.
- */
-
- if (PE_CHK_FLAG(port, PE_FLAGS_PS_READY)) {
- PE_CLR_FLAG(port, PE_FLAGS_PS_READY);
- /* NOTE: Second pass through this code block */
- /* Explicit Contract is now in place */
- PE_SET_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT);
- set_state_pe(port, PE_SRC_READY);
- } else {
- /* NOTE: First pass through this code block */
- /* Send PS_RDY message */
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_PS_RDY);
- PE_SET_FLAG(port, PE_FLAGS_PS_READY);
- }
-
- return;
- }
-
- /*
- * Transition to the PE_SRC_Hard_Reset state when:
- * 1) A Protocol Error occurs.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
- PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
- set_state_pe(port, PE_SRC_HARD_RESET);
- }
-}
-
-/**
- * PE_SRC_Ready
- */
-static void pe_src_ready_entry(int port)
-{
- print_current_state(port);
-
- /*
- * If the transition into PE_SRC_Ready is the result of Protocol Error
- * that has not caused a Soft Reset (see Section 8.3.3.4.1) then the
- * notification to the Protocol Layer of the end of the AMS Shall Not
- * be sent since there is a Message to be processed.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
- PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
- } else {
- PE_CLR_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
- prl_end_ams(port);
- }
-
- /*
- * Do port partner discovery
- *
- * This function modifies state variables that are used in the run
- * part of this state. See pe_attempt_port_discovery for details.
- */
- pe_attempt_port_discovery(port);
-}
-
-static void pe_src_ready_run(int port)
-{
- uint32_t payload;
- uint8_t type;
- uint8_t cnt;
- uint8_t ext;
-
- /*
- * Start Port Discovery when:
- * 1) The DiscoverIdentityTimer times out.
- */
- if (get_time().val > pe[port].discover_port_identity_timer) {
- pe_start_port_discovery(port);
- return;
- }
-
- /*
- * Handle Device Policy Manager Requests
- */
-
- /*
- * Ignore sink specific request:
- * DPM_REQUEST_NEW_POWER_LEVEL
- * DPM_REQUEST_SOURCE_CAP
- */
-
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_NEW_POWER_LEVEL |
- DPM_REQUEST_SOURCE_CAP);
-
- if (pe[port].dpm_request) {
- if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_DR_SWAP)) {
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_DR_SWAP);
- if (PE_CHK_FLAG(port, PE_FLAGS_MODAL_OPERATION))
- set_state_pe(port, PE_SRC_HARD_RESET);
- else
- set_state_pe(port, PE_DRS_SEND_SWAP);
- } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_PR_SWAP)) {
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_PR_SWAP);
- set_state_pe(port, PE_PRS_SRC_SNK_SEND_SWAP);
- } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_VCONN_SWAP)) {
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_VCONN_SWAP);
- set_state_pe(port, PE_VCS_SEND_SWAP);
- } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_GOTO_MIN)) {
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_GOTO_MIN);
- set_state_pe(port, PE_SRC_TRANSITION_SUPPLY);
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_SRC_CAP_CHANGE)) {
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_SRC_CAP_CHANGE);
- set_state_pe(port, PE_SRC_SEND_CAPABILITIES);
- } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_SEND_PING)) {
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_SEND_PING);
- set_state_pe(port, PE_SRC_PING);
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_DISCOVER_IDENTITY)) {
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_DISCOVER_IDENTITY);
-
- pe[port].partner_type = CABLE;
- pe[port].vdm_cmd = DISCOVER_IDENTITY;
- pe[port].vdm_data[0] = VDO(
- USB_SID_PD,
- 1, /* structured */
- VDO_SVDM_VERS(1) | DISCOVER_IDENTITY);
- pe[port].vdm_cnt = 1;
- set_state_pe(port, PE_VDM_REQUEST);
- }
- return;
- }
-
- /*
- * Handle Source Requests
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(emsg[port].header);
- cnt = PD_HEADER_CNT(emsg[port].header);
- ext = PD_HEADER_EXT(emsg[port].header);
- payload = *(uint32_t *)emsg[port].buf;
-
- /* Extended Message Requests */
- if (ext > 0) {
- switch (type) {
-#ifdef CONFIG_BATTERY
- case PD_EXT_GET_BATTERY_CAP:
- set_state_pe(port, PE_GIVE_BATTERY_CAP);
- break;
- case PD_EXT_GET_BATTERY_STATUS:
- set_state_pe(port, PE_GIVE_BATTERY_STATUS);
- break;
-#endif
- default:
- set_state_pe(port, PE_SEND_NOT_SUPPORTED);
- }
- }
- /* Data Message Requests */
- else if (cnt > 0) {
- switch (type) {
- case PD_DATA_REQUEST:
- set_state_pe(port, PE_SRC_NEGOTIATE_CAPABILITY);
- break;
- case PD_DATA_SINK_CAP:
- break;
- case PD_DATA_VENDOR_DEF:
- if (PD_HEADER_TYPE(emsg[port].header) ==
- PD_DATA_VENDOR_DEF) {
- if (PD_VDO_SVDM(payload)) {
- set_state_pe(port,
- PE_VDM_RESPONSE);
- } else
- set_state_pe(port,
- PE_HANDLE_CUSTOM_VDM_REQUEST);
- }
- break;
- case PD_DATA_BIST:
- set_state_pe(port, PE_BIST);
- break;
- default:
- set_state_pe(port, PE_SEND_NOT_SUPPORTED);
- }
- }
- /* Control Message Requests */
- else {
- switch (type) {
- case PD_CTRL_GOOD_CRC:
- break;
- case PD_CTRL_NOT_SUPPORTED:
- break;
- case PD_CTRL_PING:
- break;
- case PD_CTRL_GET_SOURCE_CAP:
- set_state_pe(port, PE_SRC_SEND_CAPABILITIES);
- break;
- case PD_CTRL_GET_SINK_CAP:
- set_state_pe(port, PE_SNK_GIVE_SINK_CAP);
- break;
- case PD_CTRL_GOTO_MIN:
- break;
- case PD_CTRL_PR_SWAP:
- set_state_pe(port,
- PE_PRS_SRC_SNK_EVALUATE_SWAP);
- break;
- case PD_CTRL_DR_SWAP:
- if (PE_CHK_FLAG(port,
- PE_FLAGS_MODAL_OPERATION)) {
- set_state_pe(port, PE_SRC_HARD_RESET);
- return;
- }
-
- set_state_pe(port, PE_DRS_EVALUATE_SWAP);
- break;
- case PD_CTRL_VCONN_SWAP:
- set_state_pe(port, PE_VCS_EVALUATE_SWAP);
- break;
- default:
- set_state_pe(port, PE_SEND_NOT_SUPPORTED);
- }
- }
- }
-}
-
-static void pe_src_ready_exit(int port)
-{
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- /*
- * If the Source is initiating an AMS then the Policy Engine Shall
- * notify the Protocol Layer that the first Message in an AMS will
- * follow.
- */
- if (!PE_CHK_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS))
- prl_start_ams(port);
-}
-
-/**
- * PE_SRC_Disabled
- */
-static void pe_src_disabled_entry(int port)
-{
- print_current_state(port);
-
- if ((pe[port].vpd_vdo >= 0) && VPD_VDO_CTS(pe[port].vpd_vdo)) {
- /*
- * Inform the Device Policy Manager that a Charge-Through VCONN
- * Powered Device was detected.
- */
- tc_ctvpd_detected(port);
- }
-
- /*
- * Unresponsive to USB Power Delivery messaging, but not to Hard Reset
- * Signaling. See pe_got_hard_reset
- */
-}
-
-/**
- * PE_SRC_Capability_Response
- */
-static void pe_src_capability_response_entry(int port)
-{
- print_current_state(port);
-
- /* NOTE: Wait messaging should be implemented. */
-
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_REJECT);
-}
-
-static void pe_src_capability_response_run(int port)
-{
- /*
- * Transition to the PE_SRC_Ready state when:
- * 1) There is an Explicit Contract and
- * 2) A Reject Message has been sent and the present Contract is still
- * Valid or
- * 3) A Wait Message has been sent.
- *
- * Transition to the PE_SRC_Hard_Reset state when:
- * 1) There is an Explicit Contract and
- * 2) The Reject Message has been sent and the present
- * Contract is Invalid
- *
- * Transition to the PE_SRC_Wait_New_Capabilities state when:
- * 1) There is no Explicit Contract and
- * 2) A Reject Message has been sent or
- * 3) A Wait Message has been sent.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- if (PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT))
- /*
- * NOTE: The src capabilities listed in
- * board/xxx/usb_pd_policy.c will not
- * change so the present contract will
- * never be invalid.
- */
- set_state_pe(port, PE_SRC_READY);
- else
- /*
- * NOTE: The src capabilities listed in
- * board/xxx/usb_pd_policy.c will not
- * change, so no need to resending them
- * again. Transition to disabled state.
- */
- set_state_pe(port, PE_SRC_DISABLED);
- }
-}
-
-/**
- * PE_SRC_Hard_Reset
- */
-static void pe_src_hard_reset_entry(int port)
-{
- print_current_state(port);
-
- /* Generate Hard Reset Signal */
- prl_execute_hard_reset(port);
-
- /* Increment the HardResetCounter */
- pe[port].hard_reset_counter++;
-
- /* Start NoResponseTimer */
- pe[port].no_response_timer = get_time().val + PD_T_NO_RESPONSE;
-
- /* Start PSHardResetTimer */
- pe[port].ps_hard_reset_timer = get_time().val + PD_T_PS_HARD_RESET;
-}
-
-static void pe_src_hard_reset_run(int port)
-{
- /*
- * Transition to the PE_SRC_Transition_to_default state when:
- * 1) The PSHardResetTimer times out.
- */
- if (get_time().val > pe[port].ps_hard_reset_timer)
- set_state_pe(port, PE_SRC_TRANSITION_TO_DEFAULT);
-}
-
-/**
- * PE_SRC_Hard_Reset_Received
- */
-static void pe_src_hard_reset_received_entry(int port)
-{
- print_current_state(port);
-
- /* Start NoResponseTimer */
- pe[port].no_response_timer = get_time().val + PD_T_NO_RESPONSE;
-
- /* Start PSHardResetTimer */
- pe[port].ps_hard_reset_timer = get_time().val + PD_T_PS_HARD_RESET;
-}
-
-static void pe_src_hard_reset_received_run(int port)
-{
- /*
- * Transition to the PE_SRC_Transition_to_default state when:
- * 1) The PSHardResetTimer times out.
- */
- if (get_time().val > pe[port].ps_hard_reset_timer)
- set_state_pe(port, PE_SRC_TRANSITION_TO_DEFAULT);
-}
-
-/**
- * PE_SRC_Transition_To_Default
- */
-static void pe_src_transition_to_default_entry(int port)
-{
- print_current_state(port);
-
- /* Reset flags */
- pe[port].flags = 0;
-
- /* Reset DPM Request */
- pe[port].dpm_request = 0;
-
- /*
- * Request Device Policy Manager to request power
- * supply Hard Resets to vSafe5V via vSafe0V
- * Reset local HW
- * Request Device Policy Manager to set Port Data
- * Role to DFP and turn off VCONN
- */
- tc_hard_reset(port);
-}
-
-static void pe_src_transition_to_default_run(int port)
-{
- /*
- * Transition to the PE_SRC_Startup state when:
- * 1) The power supply has reached the default level.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_PS_RESET_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_PS_RESET_COMPLETE);
- /* Inform the Protocol Layer that the Hard Reset is complete */
- prl_hard_reset_complete(port);
- set_state_pe(port, PE_SRC_STARTUP);
- }
-}
-
-/**
- * PE_SNK_Startup State
- */
-static void pe_snk_startup_entry(int port)
-{
- print_current_state(port);
-
- /* Reset the protocol layer */
- prl_reset(port);
-
- /* Set initial data role */
- pe[port].data_role = tc_get_data_role(port);
-
- /* Set initial power role */
- pe[port].power_role = PD_ROLE_SINK;
-
- /* Clear explicit contract */
- pe_invalidate_explicit_contract(port);
-
- /* Clear port discovery flags */
- PE_CLR_FLAG(port, PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE);
- pe[port].discover_port_identity_counter = 0;
-
- /* Reset dr swap attempt counter */
- pe[port].dr_swap_attempt_counter = 0;
-}
-
-static void pe_snk_startup_run(int port)
-{
- /* Wait until protocol layer is running */
- if (!prl_is_running(port))
- return;
-
- /*
- * Once the reset process completes, the Policy Engine Shall
- * transition to the PE_SNK_Discovery state
- */
- set_state_pe(port, PE_SNK_DISCOVERY);
-}
-
-/**
- * PE_SNK_Discovery State
- */
-static void pe_snk_discovery_entry(int port)
-{
- print_current_state(port);
-}
-
-static void pe_snk_discovery_run(int port)
-{
- /*
- * Transition to the PE_SNK_Wait_for_Capabilities state when:
- * 1) VBUS has been detected
- */
- if (pd_is_vbus_present(port))
- set_state_pe(port, PE_SNK_WAIT_FOR_CAPABILITIES);
-}
-
-/**
- * PE_SNK_Wait_For_Capabilities State
- */
-static void pe_snk_wait_for_capabilities_entry(int port)
-{
- print_current_state(port);
-
- /* Initialize and start the SinkWaitCapTimer */
- pe[port].timeout = get_time().val + PD_T_SINK_WAIT_CAP;
-}
-
-static void pe_snk_wait_for_capabilities_run(int port)
-{
- uint8_t type;
- uint8_t cnt;
- uint8_t ext;
-
- /*
- * Transition to the PE_SNK_Evaluate_Capability state when:
- * 1) A Source_Capabilities Message is received.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(emsg[port].header);
- cnt = PD_HEADER_CNT(emsg[port].header);
- ext = PD_HEADER_EXT(emsg[port].header);
-
- if ((ext == 0) && (cnt > 0) && (type == PD_DATA_SOURCE_CAP)) {
- set_state_pe(port, PE_SNK_EVALUATE_CAPABILITY);
- return;
- }
- }
-
- /* When the SinkWaitCapTimer times out, perform a Hard Reset. */
- if (get_time().val > pe[port].timeout) {
- PE_SET_FLAG(port, PE_FLAGS_SNK_WAIT_CAP_TIMEOUT);
- set_state_pe(port, PE_SNK_HARD_RESET);
- }
-}
-
-/**
- * PE_SNK_Evaluate_Capability State
- */
-static void pe_snk_evaluate_capability_entry(int port)
-{
- uint32_t *pdo = (uint32_t *)emsg[port].buf;
- uint32_t header = emsg[port].header;
- uint32_t num = emsg[port].len >> 2;
- int i;
-
- print_current_state(port);
-
- /* Reset Hard Reset counter to zero */
- pe[port].hard_reset_counter = 0;
-
- /* Set to highest revision supported by both ports. */
- prl_set_rev(port, TCPC_TX_SOP, (PD_HEADER_REV(header) > PD_REV30) ?
- PD_REV30 : PD_HEADER_REV(header));
-
- pe[port].src_cap_cnt = num;
-
- for (i = 0; i < num; i++)
- pe[port].src_caps[i] = *pdo++;
-
- /* src cap 0 should be fixed PDO */
- pe_update_pdo_flags(port, pdo[0]);
-
- /* Evaluate the options based on supplied capabilities */
- pd_process_source_cap(port, pe[port].src_cap_cnt, pe[port].src_caps);
-
- /* We are PD Connected */
- PE_SET_FLAG(port, PE_FLAGS_PD_CONNECTION);
- tc_pd_connection(port, 1);
-
- /* Device Policy Response Received */
- set_state_pe(port, PE_SNK_SELECT_CAPABILITY);
-}
-
-/**
- * PE_SNK_Select_Capability State
- */
-static void pe_snk_select_capability_entry(int port)
-{
- print_current_state(port);
-
- pe[port].sender_response_timer = TIMER_DISABLED;
- /* Send Request */
- pe_send_request_msg(port);
-}
-
-static void pe_snk_select_capability_run(int port)
-{
- uint8_t type;
- uint8_t cnt;
-
- /* Wait until message is sent */
- if (pe[port].sender_response_timer == TIMER_DISABLED) {
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- /* Initialize and run SenderResponseTimer */
- pe[port].sender_response_timer =
- get_time().val + PD_T_SENDER_RESPONSE;
- } else {
- return;
- }
- }
-
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
- type = PD_HEADER_TYPE(emsg[port].header);
- cnt = PD_HEADER_CNT(emsg[port].header);
-
- /*
- * Transition to the PE_SNK_Transition_Sink state when:
- * 1) An Accept Message is received from the Source.
- *
- * Transition to the PE_SNK_Wait_for_Capabilities state when:
- * 1) There is no Explicit Contract in place and
- * 2) A Reject Message is received from the Source or
- * 3) A Wait Message is received from the Source.
- *
- * Transition to the PE_SNK_Ready state when:
- * 1) There is an Explicit Contract in place and
- * 2) A Reject Message is received from the Source or
- * 3) A Wait Message is received from the Source.
- *
- * Transition to the PE_SNK_Hard_Reset state when:
- * 1) A SenderResponseTimer timeout occurs.
- */
-
- /* Only look at control messages */
- if (cnt == 0) {
- /*
- * Accept Message Received
- */
- if (type == PD_CTRL_ACCEPT) {
- /* explicit contract is now in place */
- PE_SET_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT);
- set_state_pe(port, PE_SNK_TRANSITION_SINK);
-
- /*
- * Setup to get Device Policy Manager to
- * request Sink Capabilities for possible FRS
- */
- pe_dpm_request(port, DPM_REQUEST_GET_SNK_CAPS);
- return;
- }
- /*
- * Reject or Wait Message Received
- */
- else if (type == PD_CTRL_REJECT ||
- type == PD_CTRL_WAIT) {
- if (type == PD_CTRL_WAIT)
- PE_SET_FLAG(port, PE_FLAGS_WAIT);
-
- /*
- * We had a previous explicit contract, so
- * transition to PE_SNK_Ready
- */
- if (PE_CHK_FLAG(port,
- PE_FLAGS_EXPLICIT_CONTRACT))
- set_state_pe(port, PE_SNK_READY);
- /*
- * No previous explicit contract, so transition
- * to PE_SNK_Wait_For_Capabilities
- */
- else
- set_state_pe(port,
- PE_SNK_WAIT_FOR_CAPABILITIES);
- return;
- }
- /*
- * Unexpected Control Message Received
- */
- else {
- /* Send Soft Reset */
- set_state_pe(port, PE_SEND_SOFT_RESET);
- return;
- }
- }
- /*
- * Unexpected Data Message
- */
- else {
- /* Send Soft Reset */
- set_state_pe(port, PE_SEND_SOFT_RESET);
- return;
- }
- }
-
- /* SenderResponsetimer timeout */
- if (get_time().val > pe[port].sender_response_timer)
- set_state_pe(port, PE_SNK_HARD_RESET);
-}
-
-/**
- * PE_SNK_Transition_Sink State
- */
-static void pe_snk_transition_sink_entry(int port)
-{
- print_current_state(port);
-
- /* Initialize and run PSTransitionTimer */
- pe[port].ps_transition_timer = get_time().val + PD_T_PS_TRANSITION;
-}
-
-static void pe_snk_transition_sink_run(int port)
-{
- /*
- * Transition to the PE_SNK_Ready state when:
- * 1) A PS_RDY Message is received from the Source.
- *
- * Transition to the PE_SNK_Hard_Reset state when:
- * 1) A Protocol Error occurs.
- */
-
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- /*
- * PS_RDY message received
- */
- if ((PD_HEADER_CNT(emsg[port].header) == 0) &&
- (PD_HEADER_TYPE(emsg[port].header) ==
- PD_CTRL_PS_RDY)) {
- set_state_pe(port, PE_SNK_READY);
- return;
- }
-
- /*
- * Protocol Error
- */
- set_state_pe(port, PE_SNK_HARD_RESET);
- }
-
- /*
- * Timeout will lead to a Hard Reset
- */
- if (get_time().val > pe[port].ps_transition_timer &&
- pe[port].hard_reset_counter <= N_HARD_RESET_COUNT) {
- PE_SET_FLAG(port, PE_FLAGS_PS_TRANSITION_TIMEOUT);
-
- set_state_pe(port, PE_SNK_HARD_RESET);
- }
-}
-
-static void pe_snk_transition_sink_exit(int port)
-{
- /* Transition Sink's power supply to the new power level */
- pd_set_input_current_limit(port,
- pe[port].curr_limit, pe[port].supply_voltage);
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER))
- /* Set ceiling based on what's negotiated */
- charge_manager_set_ceil(port,
- CEIL_REQUESTOR_PD, pe[port].curr_limit);
-}
-
-
-/**
- * PE_SNK_Ready State
- */
-static void pe_snk_ready_entry(int port)
-{
- print_current_state(port);
-
- PE_CLR_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
- prl_end_ams(port);
-
- /*
- * On entry to the PE_SNK_Ready state as the result of a wait, then do
- * the following:
- * 1) Initialize and run the SinkRequestTimer
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_WAIT)) {
- PE_CLR_FLAG(port, PE_FLAGS_WAIT);
- pe[port].sink_request_timer =
- get_time().val + PD_T_SINK_REQUEST;
- } else {
- pe[port].sink_request_timer = TIMER_DISABLED;
- }
-
- /*
- * Do port partner discovery
- *
- * This function modifies state variables that are used in the run
- * part of this state. See pe_attempt_port_discovery for details.
- */
- pe_attempt_port_discovery(port);
-}
-
-static void pe_snk_ready_run(int port)
-{
- uint32_t payload;
- uint8_t type;
- uint8_t cnt;
- uint8_t ext;
-
- if (get_time().val > pe[port].sink_request_timer) {
- set_state_pe(port, PE_SNK_SELECT_CAPABILITY);
- return;
- }
-
- /*
- * Start Port Discovery when:
- * 1) The PortDiscoverIdentityTimer times out.
- */
- if (get_time().val > pe[port].discover_port_identity_timer) {
- pe_start_port_discovery(port);
- return;
- }
-
- /*
- * Handle Device Policy Manager Requests
- */
- /*
- * Ignore source specific requests:
- * DPM_REQUEST_GOTO_MIN
- * DPM_REQUEST_SRC_CAP_CHANGE,
- * DPM_REQUEST_SEND_PING
- */
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_GOTO_MIN |
- DPM_REQUEST_SRC_CAP_CHANGE |
- DPM_REQUEST_SEND_PING);
-
- if (pe[port].dpm_request) {
- if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_DR_SWAP)) {
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_DR_SWAP);
- if (PE_CHK_FLAG(port, PE_FLAGS_MODAL_OPERATION))
- set_state_pe(port, PE_SNK_HARD_RESET);
- else
- set_state_pe(port, PE_DRS_SEND_SWAP);
- } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_PR_SWAP)) {
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_PR_SWAP);
- set_state_pe(port, PE_PRS_SNK_SRC_SEND_SWAP);
- } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_VCONN_SWAP)) {
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_VCONN_SWAP);
- set_state_pe(port, PE_VCS_SEND_SWAP);
- } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_SOURCE_CAP)) {
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_SOURCE_CAP);
- set_state_pe(port, PE_SNK_GET_SOURCE_CAP);
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_NEW_POWER_LEVEL)) {
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_NEW_POWER_LEVEL);
- set_state_pe(port, PE_SNK_SELECT_CAPABILITY);
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_DISCOVER_IDENTITY)) {
- PE_CLR_DPM_REQUEST(port,
- DPM_REQUEST_DISCOVER_IDENTITY);
-
- pe[port].partner_type = CABLE;
- pe[port].vdm_cmd = DISCOVER_IDENTITY;
- pe[port].vdm_data[0] = VDO(
- USB_SID_PD,
- 1, /* structured */
- VDO_SVDM_VERS(1) | DISCOVER_IDENTITY);
- pe[port].vdm_cnt = 1;
-
- set_state_pe(port, PE_VDM_REQUEST);
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_GET_SNK_CAPS)) {
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_GET_SNK_CAPS);
- set_state_pe(port, PE_DR_SNK_GET_SINK_CAP);
- }
- return;
- }
-
- /*
- * Handle Source Requests
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(emsg[port].header);
- cnt = PD_HEADER_CNT(emsg[port].header);
- ext = PD_HEADER_EXT(emsg[port].header);
- payload = *(uint32_t *)emsg[port].buf;
-
- /* Extended Message Request */
- if (ext > 0) {
- switch (type) {
-#ifdef CONFIG_BATTERY
- case PD_EXT_GET_BATTERY_CAP:
- set_state_pe(port, PE_GIVE_BATTERY_CAP);
- break;
- case PD_EXT_GET_BATTERY_STATUS:
- set_state_pe(port, PE_GIVE_BATTERY_STATUS);
- break;
-#endif
- default:
- set_state_pe(port, PE_SEND_NOT_SUPPORTED);
- }
- }
- /* Data Messages */
- else if (cnt > 0) {
- switch (type) {
- case PD_DATA_SOURCE_CAP:
- set_state_pe(port,
- PE_SNK_EVALUATE_CAPABILITY);
- break;
- case PD_DATA_VENDOR_DEF:
- if (PD_HEADER_TYPE(emsg[port].header) ==
- PD_DATA_VENDOR_DEF) {
- if (PD_VDO_SVDM(payload))
- set_state_pe(port,
- PE_VDM_RESPONSE);
- else
- set_state_pe(port,
- PE_HANDLE_CUSTOM_VDM_REQUEST);
- }
- break;
- case PD_DATA_BIST:
- set_state_pe(port, PE_BIST);
- break;
- default:
- set_state_pe(port, PE_SEND_NOT_SUPPORTED);
- }
- }
- /* Control Messages */
- else {
- switch (type) {
- case PD_CTRL_GOOD_CRC:
- /* Do nothing */
- break;
- case PD_CTRL_PING:
- /* Do noghing */
- break;
- case PD_CTRL_GET_SOURCE_CAP:
- set_state_pe(port, PE_SNK_GET_SOURCE_CAP);
- break;
- case PD_CTRL_GET_SINK_CAP:
- set_state_pe(port, PE_SNK_GIVE_SINK_CAP);
- break;
- case PD_CTRL_GOTO_MIN:
- set_state_pe(port, PE_SNK_TRANSITION_SINK);
- break;
- case PD_CTRL_PR_SWAP:
- set_state_pe(port,
- PE_PRS_SNK_SRC_EVALUATE_SWAP);
- break;
- case PD_CTRL_DR_SWAP:
- if (PE_CHK_FLAG(port, PE_FLAGS_MODAL_OPERATION))
- set_state_pe(port, PE_SNK_HARD_RESET);
- else
- set_state_pe(port,
- PE_DRS_EVALUATE_SWAP);
- break;
- case PD_CTRL_VCONN_SWAP:
- set_state_pe(port, PE_VCS_EVALUATE_SWAP);
- break;
- case PD_CTRL_NOT_SUPPORTED:
- /* Do nothing */
- break;
- default:
- set_state_pe(port, PE_SEND_NOT_SUPPORTED);
- }
- }
- }
-}
-
-static void pe_snk_ready_exit(int port)
-{
- if (!PE_CHK_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS))
- prl_start_ams(port);
-}
-
-/**
- * PE_SNK_Hard_Reset
- */
-static void pe_snk_hard_reset_entry(int port)
-{
- print_current_state(port);
-
- /*
- * Note: If the SinkWaitCapTimer times out and the HardResetCounter is
- * greater than nHardResetCount the Sink Shall assume that the
- * Source is non-responsive.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_SNK_WAIT_CAP_TIMEOUT) &&
- pe[port].hard_reset_counter > N_HARD_RESET_COUNT) {
- set_state_pe(port, PE_SRC_DISABLED);
- }
-
- PE_CLR_FLAG(port, PE_FLAGS_SNK_WAIT_CAP_TIMEOUT);
-
- /* Request the generation of Hard Reset Signaling by the PHY Layer */
- pe_prl_execute_hard_reset(port);
-
- /* Increment the HardResetCounter */
- pe[port].hard_reset_counter++;
-
- /*
- * Transition the Sink’s power supply to the new power level if
- * PSTransistionTimer timeout occurred.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_PS_TRANSITION_TIMEOUT)) {
- PE_CLR_FLAG(port, PE_FLAGS_PS_TRANSITION_TIMEOUT);
-
- /* Transition Sink's power supply to the new power level */
- pd_set_input_current_limit(port, pe[port].curr_limit,
- pe[port].supply_voltage);
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER))
- /* Set ceiling based on what's negotiated */
- charge_manager_set_ceil(port, CEIL_REQUESTOR_PD,
- pe[port].curr_limit);
- }
-}
-
-static void pe_snk_hard_reset_run(int port)
-{
- /*
- * Transition to the PE_SNK_Transition_to_default state when:
- * 1) The Hard Reset is complete.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_HARD_RESET_PENDING))
- return;
-
- set_state_pe(port, PE_SNK_TRANSITION_TO_DEFAULT);
-}
-
-/**
- * PE_SNK_Transition_to_default
- */
-static void pe_snk_transition_to_default_entry(int port)
-{
- print_current_state(port);
-
- tc_hard_reset(port);
-}
-
-static void pe_snk_transition_to_default_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_PS_RESET_COMPLETE)) {
- /* PE_SNK_Startup clears all flags */
-
- /* Inform the Protocol Layer that the Hard Reset is complete */
- prl_hard_reset_complete(port);
- set_state_pe(port, PE_SNK_STARTUP);
- }
-}
-
-/**
- * PE_SNK_Get_Source_Cap
- */
-static void pe_snk_get_source_cap_entry(int port)
-{
- print_current_state(port);
-
- /* Send a Get_Source_Cap Message */
- emsg[port].len = 0;
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_GET_SOURCE_CAP);
-}
-
-static void pe_snk_get_source_cap_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- set_state_pe(port, PE_SNK_READY);
- }
-}
-
-/**
- * PE_SNK_Send_Soft_Reset and PE_SRC_Send_Soft_Reset
- */
-static void pe_send_soft_reset_entry(int port)
-{
- print_current_state(port);
-
- /* Reset Protocol Layer */
- prl_reset(port);
-
- pe[port].sender_response_timer = TIMER_DISABLED;
-}
-
-static void pe_send_soft_reset_run(int port)
-{
- int type;
- int cnt;
- int ext;
-
- /* Wait until protocol layer is running */
- if (!prl_is_running(port))
- return;
-
- if (pe[port].sender_response_timer == TIMER_DISABLED) {
- /* Send Soft Reset message */
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_SOFT_RESET);
-
- /* Initialize and run SenderResponseTimer */
- pe[port].sender_response_timer =
- get_time().val + PD_T_SENDER_RESPONSE;
- }
-
- /*
- * Transition to PE_SNK_Hard_Reset or PE_SRC_Hard_Reset on Sender
- * Response Timer Timeout or Protocol Layer or Protocol Error
- */
- if (get_time().val > pe[port].sender_response_timer ||
- PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
- PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
-
- if (pe[port].power_role == PD_ROLE_SINK)
- set_state_pe(port, PE_SRC_HARD_RESET);
- else
- set_state_pe(port, PE_SRC_HARD_RESET);
- return;
- }
-
- /*
- * Transition to the PE_SNK_Send_Capabilities or
- * PE_SRC_Send_Capabilities state when:
- * 1) An Accept Message has been received.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(emsg[port].header);
- cnt = PD_HEADER_CNT(emsg[port].header);
- ext = PD_HEADER_EXT(emsg[port].header);
-
- if ((ext == 0) && (cnt == 0) && (type == PD_CTRL_ACCEPT)) {
- if (pe[port].power_role == PD_ROLE_SINK)
- set_state_pe(port,
- PE_SNK_WAIT_FOR_CAPABILITIES);
- else
- set_state_pe(port,
- PE_SRC_SEND_CAPABILITIES);
- return;
- }
- }
-}
-
-static void pe_send_soft_reset_exit(int port)
-{
- /* Clear TX Complete Flag */
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-}
-
-/**
- * PE_SNK_Soft_Reset and PE_SNK_Soft_Reset
- */
-static void pe_soft_reset_entry(int port)
-{
- print_current_state(port);
-
- pe[port].sender_response_timer = TIMER_DISABLED;
-
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_ACCEPT);
-}
-
-static void pe_soft_reset_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- if (pe[port].power_role == PD_ROLE_SINK)
- set_state_pe(port, PE_SNK_WAIT_FOR_CAPABILITIES);
- else
- set_state_pe(port, PE_SRC_SEND_CAPABILITIES);
- } else if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
- PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
-
- if (pe[port].power_role == PD_ROLE_SINK)
- set_state_pe(port, PE_SNK_HARD_RESET);
- else
- set_state_pe(port, PE_SRC_HARD_RESET);
- }
-}
-
-/**
- * PE_SRC_Not_Supported and PE_SNK_Not_Supported
- */
-static void pe_send_not_supported_entry(int port)
-{
- print_current_state(port);
-
- /* Request the Protocol Layer to send a Not_Supported Message. */
- if (prl_get_rev(port, TCPC_TX_SOP) > PD_REV20)
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_NOT_SUPPORTED);
- else
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_REJECT);
-}
-
-static void pe_send_not_supported_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SNK_READY);
- }
-}
-
-/**
- * PE_SRC_Ping
- */
-static void pe_src_ping_entry(int port)
-{
- print_current_state(port);
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_PING);
-}
-
-static void pe_src_ping_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- set_state_pe(port, PE_SRC_READY);
- }
-}
-
-/**
- * PE_Give_Battery_Cap
- */
-static void pe_give_battery_cap_entry(int port)
-{
- uint32_t payload = *(uint32_t *)(&emsg[port].buf);
- uint16_t *msg = (uint16_t *)emsg[port].buf;
-
- if (!IS_ENABLED(CONFIG_BATTERY))
- return;
- print_current_state(port);
-
- /* msg[0] - extended header is set by Protocol Layer */
-
- /* Set VID */
- msg[1] = USB_VID_GOOGLE;
-
- /* Set PID */
- msg[2] = CONFIG_USB_PID;
-
- if (battery_is_present()) {
- /*
- * We only have one fixed battery,
- * so make sure batt cap ref is 0.
- */
- if (BATT_CAP_REF(payload) != 0) {
- /* Invalid battery reference */
- msg[3] = 0;
- msg[4] = 0;
- msg[5] = 1;
- } else {
- uint32_t v;
- uint32_t c;
-
- /*
- * The Battery Design Capacity field shall return the
- * Battery’s design capacity in tenths of Wh. If the
- * Battery is Hot Swappable and is not present, the
- * Battery Design Capacity field shall be set to 0. If
- * the Battery is unable to report its Design Capacity,
- * it shall return 0xFFFF
- */
- msg[3] = 0xffff;
-
- /*
- * The Battery Last Full Charge Capacity field shall
- * return the Battery’s last full charge capacity in
- * tenths of Wh. If the Battery is Hot Swappable and
- * is not present, the Battery Last Full Charge Capacity
- * field shall be set to 0. If the Battery is unable to
- * report its Design Capacity, the Battery Last Full
- * Charge Capacity field shall be set to 0xFFFF.
- */
- msg[4] = 0xffff;
-
- if (battery_design_voltage(&v) == 0) {
- if (battery_design_capacity(&c) == 0) {
- /*
- * Wh = (c * v) / 1000000
- * 10th of a Wh = Wh * 10
- */
- msg[3] = DIV_ROUND_NEAREST((c * v),
- 100000);
- }
-
- if (battery_full_charge_capacity(&c) == 0) {
- /*
- * Wh = (c * v) / 1000000
- * 10th of a Wh = Wh * 10
- */
- msg[4] = DIV_ROUND_NEAREST((c * v),
- 100000);
- }
- }
- }
- }
-
- /* Extended Battery Cap data is 9 bytes */
- emsg[port].len = 9;
-
- prl_send_ext_data_msg(port, TCPC_TX_SOP, PD_EXT_BATTERY_CAP);
-}
-
-static void pe_give_battery_cap_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SNK_READY);
- }
-}
-
-/**
- * PE_Give_Battery_Status
- */
-static void pe_give_battery_status_entry(int port)
-{
- uint32_t payload = *(uint32_t *)(&emsg[port].buf);
- uint32_t *msg = (uint32_t *)emsg[port].buf;
-
- if (!IS_ENABLED(CONFIG_BATTERY))
- return;
- print_current_state(port);
-
- if (battery_is_present()) {
- /*
- * We only have one fixed battery,
- * so make sure batt cap ref is 0.
- */
- if (BATT_CAP_REF(payload) != 0) {
- /* Invalid battery reference */
- *msg |= BSDO_INVALID;
- } else {
- uint32_t v;
- uint32_t c;
-
- if (battery_design_voltage(&v) != 0 ||
- battery_remaining_capacity(&c) != 0) {
- *msg |= BSDO_CAP(BSDO_CAP_UNKNOWN);
- } else {
- /*
- * Wh = (c * v) / 1000000
- * 10th of a Wh = Wh * 10
- */
- *msg |= BSDO_CAP(DIV_ROUND_NEAREST((c * v),
- 100000));
- }
-
- /* Battery is present */
- *msg |= BSDO_PRESENT;
-
- /*
- * For drivers that are not smart battery compliant,
- * battery_status() returns EC_ERROR_UNIMPLEMENTED and
- * the battery is assumed to be idle.
- */
- if (battery_status(&c) != 0) {
- *msg |= BSDO_IDLE; /* assume idle */
- } else {
- if (c & STATUS_FULLY_CHARGED)
- /* Fully charged */
- *msg |= BSDO_IDLE;
- else if (c & STATUS_DISCHARGING)
- /* Discharging */
- *msg |= BSDO_DISCHARGING;
- /* else battery is charging.*/
- }
- }
- } else {
- *msg = BSDO_CAP(BSDO_CAP_UNKNOWN);
- }
-
- /* Battery Status data is 4 bytes */
- emsg[port].len = 4;
-
- prl_send_data_msg(port, TCPC_TX_SOP, PD_DATA_BATTERY_STATUS);
-}
-
-static void pe_give_battery_status_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- set_state_pe(port, PE_SRC_READY);
- }
-}
-
-/**
- * PE_DRS_Evaluate_Swap
- */
-static void pe_drs_evaluate_swap_entry(int port)
-{
- print_current_state(port);
-
- /* Get evaluation of Data Role Swap request from DPM */
- if (pd_check_data_swap(port, pe[port].data_role)) {
- PE_SET_FLAG(port, PE_FLAGS_ACCEPT);
- /*
- * PE_DRS_UFP_DFP_Evaluate_Swap and
- * PE_DRS_DFP_UFP_Evaluate_Swap states embedded here.
- */
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_ACCEPT);
- } else {
- /*
- * PE_DRS_UFP_DFP_Reject_Swap and PE_DRS_DFP_UFP_Reject_Swap
- * states embedded here.
- */
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_REJECT);
- }
-}
-
-static void pe_drs_evaluate_swap_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- /* Accept Message sent. Transtion to PE_DRS_Change */
- if (PE_CHK_FLAG(port, PE_FLAGS_ACCEPT)) {
- PE_CLR_FLAG(port, PE_FLAGS_ACCEPT);
- set_state_pe(port, PE_DRS_CHANGE);
- } else {
- /*
- * Message sent. Transition back to PE_SRC_Ready or
- * PE_SNK_Ready.
- */
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SNK_READY);
- }
- }
-}
-
-/**
- * PE_DRS_Change
- */
-static void pe_drs_change_entry(int port)
-{
- print_current_state(port);
-
- /*
- * PE_DRS_UFP_DFP_Change_to_DFP and PE_DRS_DFP_UFP_Change_to_UFP
- * states embedded here.
- */
- /* Request DPM to change port data role */
- pd_request_data_swap(port);
-}
-
-static void pe_drs_change_run(int port)
-{
- /* Wait until the data role is changed */
- if (pe[port].data_role == tc_get_data_role(port))
- return;
-
- /* Update the data role */
- pe[port].data_role = tc_get_data_role(port);
-
- if (pe[port].data_role == PD_ROLE_DFP)
- PE_CLR_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP);
-
- /*
- * Port changed. Transition back to PE_SRC_Ready or
- * PE_SNK_Ready.
- */
- if (pe[port].power_role == PD_ROLE_SINK)
- set_state_pe(port, PE_SNK_READY);
- else
- set_state_pe(port, PE_SRC_READY);
-}
-
-/**
- * PE_DRS_Send_Swap
- */
-static void pe_drs_send_swap_entry(int port)
-{
- print_current_state(port);
-
- /*
- * PE_DRS_UFP_DFP_Send_Swap and PE_DRS_DFP_UFP_Send_Swap
- * states embedded here.
- */
- /* Request the Protocol Layer to send a DR_Swap Message */
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_DR_SWAP);
-
- pe[port].sender_response_timer = TIMER_DISABLED;
-}
-
-static void pe_drs_send_swap_run(int port)
-{
- int type;
- int cnt;
- int ext;
-
- /* Wait until message is sent */
- if (pe[port].sender_response_timer == TIMER_DISABLED) {
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- /* Initialize and run SenderResponseTimer */
- pe[port].sender_response_timer =
- get_time().val + PD_T_SENDER_RESPONSE;
- } else {
- return;
- }
- }
-
- /*
- * Transition to PE_SRC_Ready or PE_SNK_Ready state when:
- * 1) Or the SenderResponseTimer times out.
- */
- if (get_time().val > pe[port].sender_response_timer) {
- if (pe[port].power_role == PD_ROLE_SINK)
- set_state_pe(port, PE_SNK_READY);
- else
- set_state_pe(port, PE_SRC_READY);
- return;
- }
-
- /*
- * Transition to PE_DRS_Change when:
- * 1) An Accept Message is received.
- *
- * Transition to PE_SRC_Ready or PE_SNK_Ready state when:
- * 1) A Reject Message is received.
- * 2) Or a Wait Message is received.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(emsg[port].header);
- cnt = PD_HEADER_CNT(emsg[port].header);
- ext = PD_HEADER_EXT(emsg[port].header);
-
- if ((ext == 0) && (cnt == 0)) {
- if (type == PD_CTRL_ACCEPT) {
- set_state_pe(port, PE_DRS_CHANGE);
- return;
- } else if ((type == PD_CTRL_REJECT) ||
- (type == PD_CTRL_WAIT)) {
- if (type == PD_CTRL_WAIT)
- PE_SET_FLAG(port,
- PE_FLAGS_WAITING_DR_SWAP);
-
- if (pe[port].power_role == PD_ROLE_SINK)
- set_state_pe(port, PE_SNK_READY);
- else
- set_state_pe(port, PE_SRC_READY);
- return;
- }
- }
- }
-
- /*
- * Transition to PE_SRC_Ready or PE_SNK_Ready state when:
- * 1) the SenderResponseTimer times out.
- */
- if (get_time().val > pe[port].sender_response_timer) {
- if (pe[port].power_role == PD_ROLE_SINK)
- set_state_pe(port, PE_SNK_READY);
- else
- set_state_pe(port, PE_SRC_READY);
- return;
- }
-}
-
-/**
- * PE_PRS_SRC_SNK_Evaluate_Swap
- */
-static void pe_prs_src_snk_evaluate_swap_entry(int port)
-{
- print_current_state(port);
-
- if (!pd_check_power_swap(port)) {
- /* PE_PRS_SRC_SNK_Reject_PR_Swap state embedded here */
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_REJECT);
- } else {
- pd_request_power_swap(port);
- /* PE_PRS_SRC_SNK_Accept_Swap state embedded here */
- PE_SET_FLAG(port, PE_FLAGS_ACCEPT);
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_ACCEPT);
- }
-}
-
-static void pe_prs_src_snk_evaluate_swap_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- if (PE_CHK_FLAG(port, PE_FLAGS_ACCEPT)) {
- PE_CLR_FLAG(port, PE_FLAGS_ACCEPT);
-
- /*
- * Power Role Swap OK, transition to
- * PE_PRS_SRC_SNK_Transition_to_off
- */
- set_state_pe(port, PE_PRS_SRC_SNK_TRANSITION_TO_OFF);
- } else {
- /* Message sent, return to PE_SRC_Ready */
- set_state_pe(port, PE_SRC_READY);
- }
- }
-}
-
-/**
- * PE_PRS_SRC_SNK_Transition_To_Off
- */
-static void pe_prs_src_snk_transition_to_off_entry(int port)
-{
- print_current_state(port);
-
- /* Tell TypeC to swap from Attached.SRC to Attached.SNK */
- tc_prs_src_snk_assert_rd(port);
- pe[port].ps_source_timer =
- get_time().val + PD_POWER_SUPPLY_TURN_OFF_DELAY;
-}
-
-static void pe_prs_src_snk_transition_to_off_run(int port)
-{
- /* Give time for supply to power off */
- if (get_time().val < pe[port].ps_source_timer)
- return;
-
- /* Wait until Rd is asserted */
- if (tc_is_attached_snk(port)) {
- /* Contract is invalid */
- pe_invalidate_explicit_contract(port);
- set_state_pe(port, PE_PRS_SRC_SNK_WAIT_SOURCE_ON);
- }
-}
-
-/**
- * PE_PRS_SRC_SNK_Wait_Source_On
- */
-static void pe_prs_src_snk_wait_source_on_entry(int port)
-{
- print_current_state(port);
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_PS_RDY);
- pe[port].ps_source_timer = TIMER_DISABLED;
-}
-
-static void pe_prs_src_snk_wait_source_on_run(int port)
-{
- int type;
- int cnt;
- int ext;
-
- if (pe[port].ps_source_timer != TIMER_DISABLED &&
- PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- /* Update pe power role */
- pe[port].power_role = tc_get_power_role(port);
- pe[port].ps_source_timer = get_time().val + PD_T_PS_SOURCE_ON;
- }
-
- /*
- * Transition to PE_SNK_Startup when:
- * 1) An PS_RDY Message is received.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(emsg[port].header);
- cnt = PD_HEADER_CNT(emsg[port].header);
- ext = PD_HEADER_EXT(emsg[port].header);
-
- if ((ext == 0) && (cnt == 0) && (type == PD_CTRL_PS_RDY)) {
- tc_pr_swap_complete(port);
- pe[port].ps_source_timer = TIMER_DISABLED;
- set_state_pe(port, PE_SNK_STARTUP);
- return;
- }
- }
-
- /*
- * Transition to ErrorRecovery state when:
- * 1) The PSSourceOnTimer times out.
- * 2) PS_RDY not sent after retries.
- */
- if (get_time().val > pe[port].ps_source_timer ||
- PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
- PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
-
- set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY);
- return;
- }
-}
-
-/**
- * PE_PRS_SRC_SNK_Send_Swap
- */
-static void pe_prs_src_snk_send_swap_entry(int port)
-{
- print_current_state(port);
-
- /* Request the Protocol Layer to send a PR_Swap Message. */
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_PR_SWAP);
-
- /* Start the SenderResponseTimer */
- pe[port].sender_response_timer =
- get_time().val + PD_T_SENDER_RESPONSE;
-}
-
-static void pe_prs_src_snk_send_swap_run(int port)
-{
- int type;
- int cnt;
- int ext;
-
- /*
- * Transition to PE_SRC_Ready state when:
- * 1) Or the SenderResponseTimer times out.
- */
- if (get_time().val > pe[port].sender_response_timer) {
- set_state_pe(port, PE_SRC_READY);
- return;
- }
-
- /*
- * Transition to PE_PRS_SRC_SNK_Transition_To_Off when:
- * 1) An Accept Message is received.
- *
- * Transition to PE_SRC_Ready state when:
- * 1) A Reject Message is received.
- * 2) Or a Wait Message is received.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(emsg[port].header);
- cnt = PD_HEADER_CNT(emsg[port].header);
- ext = PD_HEADER_EXT(emsg[port].header);
-
- if ((ext == 0) && (cnt == 0)) {
- if (type == PD_CTRL_ACCEPT)
- set_state_pe(port,
- PE_PRS_SRC_SNK_TRANSITION_TO_OFF);
- else if ((type == PD_CTRL_REJECT) ||
- (type == PD_CTRL_WAIT))
- set_state_pe(port, PE_SRC_READY);
- }
- }
-}
-
-static void pe_prs_src_snk_send_swap_exit(int port)
-{
- /* Clear TX Complete Flag if set */
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-}
-
-/**
- * PE_PRS_SNK_SRC_Evaluate_Swap
- */
-static void pe_prs_snk_src_evaluate_swap_entry(int port)
-{
- print_current_state(port);
-
- if (!pd_check_power_swap(port)) {
- /* PE_PRS_SNK_SRC_Reject_Swap state embedded here */
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_REJECT);
- } else {
- pd_request_power_swap(port);
- /* PE_PRS_SNK_SRC_Accept_Swap state embedded here */
- PE_SET_FLAG(port, PE_FLAGS_ACCEPT);
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_ACCEPT);
- }
-}
-
-static void pe_prs_snk_src_evaluate_swap_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- if (PE_CHK_FLAG(port, PE_FLAGS_ACCEPT)) {
- PE_CLR_FLAG(port, PE_FLAGS_ACCEPT);
-
- /*
- * Accept message sent, transition to
- * PE_PRS_SNK_SRC_Transition_to_off
- */
- set_state_pe(port, PE_PRS_SNK_SRC_TRANSITION_TO_OFF);
- } else {
- /* Message sent, return to PE_SNK_Ready */
- set_state_pe(port, PE_SNK_READY);
- }
- }
-}
-
-/**
- * PE_PRS_SNK_SRC_Transition_To_Off
- * PE_FRS_SNK_SRC_Transition_To_Off
- *
- * NOTE: Shared action code used for Power Role Swap and Fast Role Swap
- */
-static void pe_prs_snk_src_transition_to_off_entry(int port)
-{
- print_current_state(port);
-
- if (!PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH))
- tc_snk_power_off(port);
-
- pe[port].ps_source_timer = get_time().val + PD_T_PS_SOURCE_OFF;
-}
-
-static void pe_prs_snk_src_transition_to_off_run(int port)
-{
- int type;
- int cnt;
- int ext;
-
- /*
- * Transition to ErrorRecovery state when:
- * 1) The PSSourceOffTimer times out.
- */
- if (get_time().val > pe[port].ps_source_timer)
- set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY);
-
- /*
- * Transition to PE_PRS_SNK_SRC_Assert_Rp when:
- * 1) An PS_RDY Message is received.
- */
- else if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(emsg[port].header);
- cnt = PD_HEADER_CNT(emsg[port].header);
- ext = PD_HEADER_EXT(emsg[port].header);
-
- if ((ext == 0) && (cnt == 0) && (type == PD_CTRL_PS_RDY)) {
- /*
- * FRS: We are always ready to drive vSafe5v, so just
- * skip PE_FRS_SNK_SRC_Vbus_Applied and go direct to
- * PE_FRS_SNK_SRC_Assert_Rp
- */
- set_state_pe(port, PE_PRS_SNK_SRC_ASSERT_RP);
- }
- }
-}
-
-/**
- * PE_PRS_SNK_SRC_Assert_Rp
- * PE_FRS_SNK_SRC_Assert_Rp
- *
- * NOTE: Shared action code used for Power Role Swap and Fast Role Swap
- */
-static void pe_prs_snk_src_assert_rp_entry(int port)
-{
- print_current_state(port);
-
- /*
- * Tell TypeC to Power/Fast Role Swap (PRS/FRS) from
- * Attached.SNK to Attached.SRC
- */
- tc_prs_snk_src_assert_rp(port);
-}
-
-static void pe_prs_snk_src_assert_rp_run(int port)
-{
- /* Wait until TypeC is in the Attached.SRC state */
- if (tc_is_attached_src(port)) {
- if (!PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH)) {
- /* Contract is invalid now */
- pe_invalidate_explicit_contract(port);
- }
-
- set_state_pe(port, PE_PRS_SNK_SRC_SOURCE_ON);
- }
-}
-
-/**
- * PE_PRS_SNK_SRC_Source_On
- * PE_FRS_SNK_SRC_Source_On
- *
- * NOTE: Shared action code used for Power Role Swap and Fast Role Swap
- */
-static void pe_prs_snk_src_source_on_entry(int port)
-{
- print_current_state(port);
-
- /*
- * VBUS was enabled when the TypeC state machine entered
- * Attached.SRC state
- */
- pe[port].ps_source_timer = get_time().val +
- PD_POWER_SUPPLY_TURN_ON_DELAY;
-}
-
-static void pe_prs_snk_src_source_on_run(int port)
-{
- /* Wait until power supply turns on */
- if (pe[port].ps_source_timer != TIMER_DISABLED) {
- if (get_time().val < pe[port].ps_source_timer)
- return;
-
- /* update pe power role */
- pe[port].power_role = tc_get_power_role(port);
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_PS_RDY);
- /* reset timer so PD_CTRL_PS_RDY isn't sent again */
- pe[port].ps_source_timer = TIMER_DISABLED;
- }
-
- /*
- * Transition to ErrorRecovery state when:
- * 1) On protocol error
- */
- else if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
- PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
- set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY);
- }
-
- else if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- /* Run swap source timer on entry to pe_src_startup */
- PE_SET_FLAG(port, PE_FLAGS_RUN_SOURCE_START_TIMER);
- tc_pr_swap_complete(port);
- set_state_pe(port, PE_SRC_STARTUP);
- }
-}
-
-/**
- * PE_PRS_SNK_SRC_Send_Swap
- * PE_FRS_SNK_SRC_Send_Swap
- *
- * NOTE: Shared action code used for Power Role Swap and Fast Role Swap
- */
-static void pe_prs_snk_src_send_swap_entry(int port)
-{
- print_current_state(port);
-
- /*
- * PRS_SNK_SRC_SEND_SWAP
- * Request the Protocol Layer to send a PR_Swap Message.
- *
- * FRS_SNK_SRC_SEND_SWAP
- * Hardware should have turned off sink power and started
- * bringing Vbus to vSafe5.
- * Request the Protocol Layer to send a FR_Swap Message.
- */
- prl_send_ctrl_msg(port,
- TCPC_TX_SOP,
- PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH)
- ? PD_CTRL_FR_SWAP
- : PD_CTRL_PR_SWAP);
-
- /* Start the SenderResponseTimer */
- pe[port].sender_response_timer =
- get_time().val + PD_T_SENDER_RESPONSE;
-}
-
-static void pe_prs_snk_src_send_swap_run(int port)
-{
- int type;
- int cnt;
- int ext;
-
- /*
- * PRS: Transition to PE_SNK_Ready state when:
- * FRS: Transition to ErrorRecovery state when:
- * 1) The SenderResponseTimer times out.
- */
- if (get_time().val > pe[port].sender_response_timer)
- set_state_pe(port,
- PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH)
- ? PE_WAIT_FOR_ERROR_RECOVERY
- : PE_SNK_READY);
-
- /*
- * Transition to PE_PRS_SNK_SRC_Transition_to_off when:
- * 1) An Accept Message is received.
- *
- * PRS: Transition to PE_SNK_Ready state when:
- * FRS: Transition to ErrorRecovery state when:
- * 1) A Reject Message is received.
- * 2) Or a Wait Message is received.
- */
- else if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(emsg[port].header);
- cnt = PD_HEADER_CNT(emsg[port].header);
- ext = PD_HEADER_EXT(emsg[port].header);
-
- if ((ext == 0) && (cnt == 0)) {
- if (type == PD_CTRL_ACCEPT)
- set_state_pe(port,
- PE_PRS_SNK_SRC_TRANSITION_TO_OFF);
- else if ((type == PD_CTRL_REJECT) ||
- (type == PD_CTRL_WAIT))
- set_state_pe(port,
- PE_CHK_FLAG(port,
- PE_FLAGS_FAST_ROLE_SWAP_PATH)
- ? PE_WAIT_FOR_ERROR_RECOVERY
- : PE_SNK_READY);
- }
- }
-}
-
-static void pe_prs_snk_src_send_swap_exit(int port)
-{
- /* Clear TX Complete Flag if set */
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-}
-
-/**
- * PE_FRS_SNK_SRC_Start_AMS
- */
-static void pe_frs_snk_src_start_ams_entry(int port)
-{
- print_current_state(port);
-
- /* Contract is invalid now */
- pe_invalidate_explicit_contract(port);
-
- /* Inform Protocol Layer this is start of AMS */
- prl_start_ams(port);
-
- /* Shared PRS/FRS code, indicate FRS path */
- PE_SET_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH);
- set_state_pe(port, PE_PRS_SNK_SRC_SEND_SWAP);
-}
-
-/**
- * PE_PRS_FRS_SHARED
- */
-static void pe_prs_frs_shared_entry(int port)
-{
- /*
- * Shared PRS/FRS code, assume PRS path
- *
- * This is the super state entry. It will be called before
- * the first entry state to get into the PRS/FRS path.
- * For FRS, PE_FRS_SNK_SRC_START_AMS entry will be called
- * after this and that will set for the FRS path.
- */
- PE_CLR_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH);
-}
-
-static void pe_prs_frs_shared_exit(int port)
-{
- /*
- * Shared PRS/FRS code, when not in shared path
- * indicate PRS path
- */
- PE_CLR_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH);
-}
-
-/**
- * BIST
- */
-static void pe_bist_entry(int port)
-{
- uint32_t *payload = (uint32_t *)emsg[port].buf;
- uint8_t mode = BIST_MODE(payload[0]);
-
- print_current_state(port);
-
- /*
- * See section 6.4.3.6 BIST Carrier Mode 2:
- * With a BIST Carrier Mode 2 BIST Data Object, the UUT Shall send out
- * a continuous string of alternating "1"s and “0”s.
- * The UUT Shall exit the Continuous BIST Mode within tBISTContMode of
- * this Continuous BIST Mode being enabled.
- */
- if (mode == BIST_CARRIER_MODE_2) {
- prl_send_ctrl_msg(port, TCPC_TX_BIST_MODE_2, 0);
- pe[port].bist_cont_mode_timer =
- get_time().val + PD_T_BIST_CONT_MODE;
- }
- /*
- * See section 6.4.3.9 BIST Test Data:
- * With a BIST Test Data BIST Data Object, the UUT Shall return a
- * GoodCRC Message and Shall enter a test mode in which it sends no
- * further Messages except for GoodCRC Messages in response to received
- * Messages.
- */
- else if (mode == BIST_TEST_DATA)
- pe[port].bist_cont_mode_timer = TIMER_DISABLED;
-}
-
-static void pe_bist_run(int port)
-{
- if (get_time().val > pe[port].bist_cont_mode_timer) {
-
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_TRANSITION_TO_DEFAULT);
- else
- set_state_pe(port, PE_SNK_TRANSITION_TO_DEFAULT);
- } else {
- /*
- * We are in test data mode and no further Messages except for
- * GoodCRC Messages in response to received Messages will
- * be sent.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED))
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
- }
-}
-
-/**
- * Give_Sink_Cap Message
- */
-static void pe_snk_give_sink_cap_entry(int port)
-{
- print_current_state(port);
-
- /* Send a Sink_Capabilities Message */
- emsg[port].len = pd_snk_pdo_cnt * 4;
- memcpy(emsg[port].buf, (uint8_t *)pd_snk_pdo, emsg[port].len);
- prl_send_data_msg(port, TCPC_TX_SOP, PD_DATA_SINK_CAP);
-}
-
-static void pe_snk_give_sink_cap_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SNK_READY);
- }
-}
-
-/**
- * Wait For Error Recovery
- */
-static void pe_wait_for_error_recovery_entry(int port)
-{
- print_current_state(port);
- tc_start_error_recovery(port);
-}
-
-static void pe_wait_for_error_recovery_run(int port)
-{
- /* Stay here until error recovery is complete */
-}
-
-/**
- * PE_Handle_Custom_Vdm_Request
- */
-static void pe_handle_custom_vdm_request_entry(int port)
-{
- /* Get the message */
- uint32_t *payload = (uint32_t *)emsg[port].buf;
- int cnt = PD_HEADER_CNT(emsg[port].header);
- int sop = PD_HEADER_GET_SOP(emsg[port].header);
- int rlen = 0;
- uint32_t *rdata;
-
- print_current_state(port);
-
- /* This is an Interruptible AMS */
- PE_SET_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
-
- rlen = pd_custom_vdm(port, cnt, payload, &rdata);
- if (rlen > 0) {
- emsg[port].len = rlen * 4;
- memcpy(emsg[port].buf, (uint8_t *)rdata, emsg[port].len);
- prl_send_data_msg(port, sop, PD_DATA_VENDOR_DEF);
- }
-}
-
-static void pe_handle_custom_vdm_request_run(int port)
-{
- /* Wait for ACCEPT, WAIT or Reject message to send. */
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- /*
- * Message sent. Transition back to
- * PE_SRC_Ready or PE_SINK_Ready
- */
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SNK_READY);
- }
-}
-
-/**
- * PE_DO_PORT_Discovery
- *
- * NOTE: Port Discovery Policy
- * To discover a port partner, Vendor Defined Messages (VDMs) are
- * sent to the port partner. The sequence of commands are
- * sent in the following order:
- * 1) CMD_DISCOVER_IDENT
- * 2) CMD_DISCOVER_SVID
- * 3) CMD_DISCOVER_MODES
- * 4) CMD_ENTER_MODE
- * 5) CMD_DP_STATUS
- * 6) CMD_DP_CONFIG
- *
- * If a the port partner replies with BUSY, the sequence is resent
- * N_DISCOVER_IDENTITY_COUNT times before giving up.
- */
-static void pe_do_port_discovery_entry(int port)
-{
- print_current_state(port);
-
- pe[port].partner_type = PORT;
- pe[port].vdm_cnt = 0;
-}
-
-static void pe_do_port_discovery_run(int port)
-{
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- uint32_t *payload = (uint32_t *)emsg[port].buf;
- struct svdm_amode_data *modep = get_modep(port, PD_VDO_VID(payload[0]));
- int ret = 0;
-
- if (!PE_CHK_FLAG(port,
- PE_FLAGS_VDM_REQUEST_NAKED | PE_FLAGS_VDM_REQUEST_BUSY)) {
- switch (pe[port].vdm_cmd) {
- case DO_PORT_DISCOVERY_START:
- pe[port].vdm_cmd = CMD_DISCOVER_IDENT;
- pe[port].vdm_data[0] = 0;
- ret = 1;
- break;
- case CMD_DISCOVER_IDENT:
- pe[port].vdm_cmd = CMD_DISCOVER_SVID;
- pe[port].vdm_data[0] = 0;
- ret = 1;
- break;
- case CMD_DISCOVER_SVID:
- pe[port].vdm_cmd = CMD_DISCOVER_MODES;
- ret = dfp_discover_modes(port, pe[port].vdm_data);
- break;
- case CMD_DISCOVER_MODES:
- pe[port].vdm_cmd = CMD_ENTER_MODE;
- pe[port].vdm_data[0] = pd_dfp_enter_mode(port, 0, 0);
- if (pe[port].vdm_data[0])
- ret = 1;
- break;
- case CMD_ENTER_MODE:
- pe[port].vdm_cmd = CMD_DP_STATUS;
- if (modep->opos) {
- ret = modep->fx->status(port,
- pe[port].vdm_data);
- pe[port].vdm_data[0] |=
- PD_VDO_OPOS(modep->opos);
- }
- break;
- case CMD_DP_STATUS:
- pe[port].vdm_cmd = CMD_DP_CONFIG;
-
- /*
- * DP status response & UFP's DP attention have same
- * payload
- */
- dfp_consume_attention(port, pe[port].vdm_data);
- if (modep && modep->opos)
- ret = modep->fx->config(port,
- pe[port].vdm_data);
- break;
- case CMD_DP_CONFIG:
- if (modep && modep->opos && modep->fx->post_config)
- modep->fx->post_config(port);
- PE_SET_FLAG(port, PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE);
- break;
- case CMD_EXIT_MODE:
- /* Do nothing */
- break;
- case CMD_ATTENTION:
- /* Do nothing */
- break;
- }
- }
-
- if (ret == 0) {
- if (PE_CHK_FLAG(port, PE_FLAGS_VDM_REQUEST_NAKED))
- PE_SET_FLAG(port, PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE);
-
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SNK_READY);
- } else {
- PE_CLR_FLAG(port, PE_FLAGS_VDM_REQUEST_BUSY);
-
- /*
- * Copy Vendor Defined Message (VDM) Header into
- * message buffer
- */
- if (pe[port].vdm_data[0] == 0)
- pe[port].vdm_data[0] = VDO(
- USB_SID_PD,
- 1, /* structured */
- VDO_SVDM_VERS(1) | pe[port].vdm_cmd);
-
- pe[port].vdm_data[0] |= VDO_CMDT(CMDT_INIT);
- pe[port].vdm_data[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port));
-
- pe[port].vdm_cnt = ret;
- set_state_pe(port, PE_VDM_REQUEST);
- }
-#endif
-}
-
-/**
- * PE_VDM_REQUEST
- */
-
-static void pe_vdm_request_entry(int port)
-{
- print_current_state(port);
-
- /* This is an Interruptible AMS */
- PE_SET_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
-
- /* Copy Vendor Data Objects (VDOs) into message buffer */
- if (pe[port].vdm_cnt > 0) {
- /* Copy data after header */
- memcpy(&emsg[port].buf,
- (uint8_t *)pe[port].vdm_data,
- pe[port].vdm_cnt * 4);
- /* Update len with the number of VDO bytes */
- emsg[port].len = pe[port].vdm_cnt * 4;
- }
-
- if (pe[port].partner_type) {
- /* Save power and data roles */
- pe[port].saved_power_role = tc_get_power_role(port);
- pe[port].saved_data_role = tc_get_data_role(port);
-
- prl_send_data_msg(port, TCPC_TX_SOP_PRIME, PD_DATA_VENDOR_DEF);
- } else {
- prl_send_data_msg(port, TCPC_TX_SOP, PD_DATA_VENDOR_DEF);
- }
-
- pe[port].vdm_response_timer = TIMER_DISABLED;
-}
-
-static void pe_vdm_request_run(int port)
-{
- if (pe[port].vdm_response_timer == TIMER_DISABLED &&
- PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- /* Message was sent */
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- /* Start no response timer */
- pe[port].vdm_response_timer =
- get_time().val + PD_T_VDM_SNDR_RSP;
- }
-
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- uint32_t *payload;
- int sop;
- uint8_t type;
- uint8_t cnt;
- uint8_t ext;
-
- /* Message received */
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- /* Get the message */
- payload = (uint32_t *)emsg[port].buf;
- sop = PD_HEADER_GET_SOP(emsg[port].header);
- type = PD_HEADER_TYPE(emsg[port].header);
- cnt = PD_HEADER_CNT(emsg[port].header);
- ext = PD_HEADER_EXT(emsg[port].header);
-
- if ((sop == TCPC_TX_SOP || sop == TCPC_TX_SOP_PRIME) &&
- type == PD_DATA_VENDOR_DEF && cnt > 0 &&
- ext == 0) {
- if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_ACK) {
- set_state_pe(port, PE_VDM_ACKED);
- return;
- } else if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_NAK ||
- PD_VDO_CMDT(payload[0]) == CMDT_RSP_BUSY) {
- if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_NAK)
- PE_SET_FLAG(port,
- PE_FLAGS_VDM_REQUEST_NAKED);
- else
- PE_SET_FLAG(port,
- PE_FLAGS_VDM_REQUEST_BUSY);
- }
- } else {
- /*
- * Unexpected Message Received.
- * Return to Src.Ready or Snk.Ready to
- * handle it.
- */
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SNK_READY);
- }
- }
-
- if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
- /* Message not sent and we received a protocol error */
- PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
-
- /* Fake busy response so we try to send command again */
- PE_SET_FLAG(port, PE_FLAGS_VDM_REQUEST_BUSY);
- } else if (get_time().val > pe[port].vdm_response_timer) {
- CPRINTF("VDM %s Response Timeout\n",
- pe[port].partner_type ? "Cable" : "Port");
-
- PE_SET_FLAG(port, PE_FLAGS_VDM_REQUEST_NAKED);
- }
-
- if (PE_CHK_FLAG(port, PE_FLAGS_VDM_REQUEST_NAKED |
- PE_FLAGS_VDM_REQUEST_BUSY)) {
- /* Return to previous state */
- if (get_last_state_pe(port) == PE_DO_PORT_DISCOVERY)
- set_state_pe(port, PE_DO_PORT_DISCOVERY);
- else if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SNK_READY);
- }
-}
-
-static void pe_vdm_request_exit(int port)
-{
- PE_CLR_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
-}
-
-enum idh_ptype get_usb_pd_mux_cable_type(int port)
-{
- if (pe[port].passive_cable_vdo != PD_VDO_INVALID)
- return IDH_PTYPE_PCABLE;
- else if (pe[port].active_cable_vdo1 != PD_VDO_INVALID)
- return IDH_PTYPE_ACABLE;
- else
- return IDH_PTYPE_UNDEF;
-}
-
-/**
- * PE_VDM_Acked
- */
-static void pe_vdm_acked_entry(int port)
-{
- uint32_t *payload;
- uint8_t vdo_cmd;
- int sop;
-
- print_current_state(port);
-
- /* Get the message */
- payload = (uint32_t *)emsg[port].buf;
- vdo_cmd = PD_VDO_CMD(payload[0]);
- sop = PD_HEADER_GET_SOP(emsg[port].header);
-
- if (sop == TCPC_TX_SOP) {
- /*
- * Handle Message From Port Partner
- */
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- int cnt = PD_HEADER_CNT(emsg[port].header);
- struct svdm_amode_data *modep;
-
- modep = get_modep(port, PD_VDO_VID(payload[0]));
-#endif
-
- switch (vdo_cmd) {
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- case CMD_DISCOVER_IDENT:
- dfp_consume_identity(port, cnt, payload);
-#ifdef CONFIG_CHARGE_MANAGER
- if (pd_charge_from_device(pd_get_identity_vid(port),
- pd_get_identity_pid(port))) {
- charge_manager_update_dualrole(port,
- CAP_DEDICATED);
- }
-#endif
- break;
- case CMD_DISCOVER_SVID:
- dfp_consume_svids(port, cnt, payload);
- break;
- case CMD_DISCOVER_MODES:
- dfp_consume_modes(port, cnt, payload);
- break;
- case CMD_ENTER_MODE:
- break;
- case CMD_DP_STATUS:
- /*
- * DP status response & UFP's DP attention have same
- * payload
- */
- dfp_consume_attention(port, payload);
- break;
- case CMD_DP_CONFIG:
- if (modep && modep->opos && modep->fx->post_config)
- modep->fx->post_config(port);
- break;
- case CMD_EXIT_MODE:
- /* Do nothing */
- break;
-#endif
- case CMD_ATTENTION:
- /* Do nothing */
- break;
- default:
- CPRINTF("ERR:CMD:%d\n", vdo_cmd);
- }
- }
-
- if (!PE_CHK_FLAG(port, PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE)) {
- set_state_pe(port, PE_DO_PORT_DISCOVERY);
- } else if (pe[port].power_role == PD_ROLE_SOURCE) {
- set_state_pe(port, PE_SRC_READY);
- } else {
- set_state_pe(port, PE_SNK_READY);
- }
-}
-
-/**
- * PE_VDM_Response
- */
-static void pe_vdm_response_entry(int port)
-{
- int ret = 0;
- uint32_t *payload;
- uint8_t vdo_cmd;
- int cmd_type;
- svdm_rsp_func func = NULL;
-
- print_current_state(port);
-
- /* Get the message */
- payload = (uint32_t *)emsg[port].buf;
- vdo_cmd = PD_VDO_CMD(payload[0]);
- cmd_type = PD_VDO_CMDT(payload[0]);
- payload[0] &= ~VDO_CMDT_MASK;
-
- if (cmd_type != CMDT_INIT) {
- CPRINTF("ERR:CMDT:%d\n", vdo_cmd);
-
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SNK_READY);
- return;
- }
-
- switch (vdo_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:
- func = svdm_rsp.amode->status;
- break;
- case CMD_DP_CONFIG:
- 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);
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SNK_READY);
- return;
-#endif
- default:
- CPRINTF("VDO ERR:CMD:%d\n", vdo_cmd);
- }
-
- if (func) {
- ret = func(port, payload);
- if (ret)
- /* ACK */
- payload[0] = VDO(
- USB_VID_GOOGLE,
- 1, /* Structured VDM */
- VDO_SVDM_VERS(pd_get_vdo_ver(port)) |
- VDO_CMDT(CMDT_RSP_ACK) |
- vdo_cmd);
- else if (!ret)
- /* NAK */
- payload[0] = VDO(
- USB_VID_GOOGLE,
- 1, /* Structured VDM */
- VDO_SVDM_VERS(pd_get_vdo_ver(port)) |
- VDO_CMDT(CMDT_RSP_NAK) |
- vdo_cmd);
- else
- /* BUSY */
- payload[0] = VDO(
- USB_VID_GOOGLE,
- 1, /* Structured VDM */
- VDO_SVDM_VERS(pd_get_vdo_ver(port)) |
- VDO_CMDT(CMDT_RSP_BUSY) |
- vdo_cmd);
-
- if (ret <= 0)
- ret = 4;
- } else {
- /* not supported : NACK it */
- payload[0] = VDO(
- USB_VID_GOOGLE,
- 1, /* Structured VDM */
- VDO_SVDM_VERS(pd_get_vdo_ver(port)) |
- VDO_CMDT(CMDT_RSP_NAK) |
- vdo_cmd);
- ret = 4;
- }
-
- /* Send ACK, NAK, or BUSY */
- emsg[port].len = ret;
- prl_send_data_msg(port, TCPC_TX_SOP, PD_DATA_VENDOR_DEF);
-}
-
-static void pe_vdm_response_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE) ||
- PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE |
- PE_FLAGS_PROTOCOL_ERROR);
-
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SNK_READY);
- }
-}
-
-/*
- * PE_VCS_Evaluate_Swap
- */
-static void pe_vcs_evaluate_swap_entry(int port)
-{
- print_current_state(port);
-
- /*
- * Request the DPM for an evaluation of the VCONN Swap request.
- * Note: Ports that are presently the VCONN Source must always
- * accept a VCONN
- */
-
- /*
- * Transition to the PE_VCS_Accept_Swap state when:
- * 1) The Device Policy Manager indicates that a VCONN Swap is ok.
- *
- * Transition to the PE_VCS_Reject_Swap state when:
- * 1) Port is not presently the VCONN Source and
- * 2) The DPM indicates that a VCONN Swap is not ok or
- * 3) The DPM indicates that a VCONN Swap cannot be done at this time.
- */
-
- /* DPM rejects a VCONN Swap and port is not a VCONN source*/
- if (!tc_check_vconn_swap(port) && tc_is_vconn_src(port) < 1) {
- /* NOTE: PE_VCS_Reject_Swap State embedded here */
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_REJECT);
- }
- /* Port is not ready to perform a VCONN swap */
- else if (tc_is_vconn_src(port) < 0) {
- /* NOTE: PE_VCS_Reject_Swap State embedded here */
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_WAIT);
- }
- /* Port is ready to perform a VCONN swap */
- else {
- /* NOTE: PE_VCS_Accept_Swap State embedded here */
- PE_SET_FLAG(port, PE_FLAGS_ACCEPT);
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_ACCEPT);
- }
-}
-
-static void pe_vcs_evaluate_swap_run(int port)
-{
- /* Wait for ACCEPT, WAIT or Reject message to send. */
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- if (PE_CHK_FLAG(port, PE_FLAGS_ACCEPT)) {
- PE_CLR_FLAG(port, PE_FLAGS_ACCEPT);
- /* Accept Message sent and Presently VCONN Source */
- if (tc_is_vconn_src(port))
- set_state_pe(port, PE_VCS_WAIT_FOR_VCONN_SWAP);
- /* Accept Message sent and Not presently VCONN Source */
- else
- set_state_pe(port, PE_VCS_TURN_ON_VCONN_SWAP);
- } else {
- /*
- * Message sent. Transition back to PE_SRC_Ready or
- * PE_SINK_Ready
- */
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SNK_READY);
-
- }
- }
-}
-
-/*
- * PE_VCS_Send_Swap
- */
-static void pe_vcs_send_swap_entry(int port)
-{
- print_current_state(port);
-
- /* Send a VCONN_Swap Message */
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_VCONN_SWAP);
-
- pe[port].sender_response_timer = TIMER_DISABLED;
-}
-
-static void pe_vcs_send_swap_run(int port)
-{
- uint8_t type;
- uint8_t cnt;
-
- /* Wait until message is sent */
- if (pe[port].sender_response_timer == TIMER_DISABLED &&
- PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- /* Start the SenderResponseTimer */
- pe[port].sender_response_timer = get_time().val +
- PD_T_SENDER_RESPONSE;
- }
-
- if (pe[port].sender_response_timer == TIMER_DISABLED)
- return;
-
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(emsg[port].header);
- cnt = PD_HEADER_CNT(emsg[port].header);
-
- /* Only look at control messages */
- if (cnt == 0) {
- /*
- * Transition to the PE_VCS_Wait_For_VCONN state when:
- * 1) Accept Message Received and
- * 2) The Port is presently the VCONN Source.
- *
- * Transition to the PE_VCS_Turn_On_VCONN state when:
- * 1) Accept Message Received and
- * 2) The Port is not presently the VCONN Source.
- */
- if (type == PD_CTRL_ACCEPT) {
- if (tc_is_vconn_src(port))
- set_state_pe(port,
- PE_VCS_WAIT_FOR_VCONN_SWAP);
- else
- set_state_pe(port,
- PE_VCS_TURN_ON_VCONN_SWAP);
- return;
- }
- /*
- * Transition back to either the PE_SRC_Ready or
- * PE_SNK_Ready state when:
- * 1) SenderResponseTimer Timeout or
- * 2) Reject message is received or
- * 3) Wait message Received.
- */
- if (get_time().val > pe[port].sender_response_timer ||
- type == PD_CTRL_REJECT ||
- type == PD_CTRL_WAIT) {
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SNK_READY);
- }
- }
- /*
- * Unexpected Data Message Received
- */
- else {
- /* Send Soft Reset */
- set_state_pe(port, PE_SEND_SOFT_RESET);
- return;
- }
- }
-}
-
-/*
- * PE_VCS_Wait_for_VCONN_Swap
- */
-static void pe_vcs_wait_for_vconn_swap_entry(int port)
-{
- print_current_state(port);
-
- /* Start the VCONNOnTimer */
- pe[port].vconn_on_timer = get_time().val + PD_T_VCONN_SOURCE_ON;
-}
-
-static void pe_vcs_wait_for_vconn_swap_run(int port)
-{
- /*
- * Transition to the PE_VCS_Turn_Off_VCONN state when:
- * 1) A PS_RDY Message is received.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
- /*
- * PS_RDY message received
- */
- if ((PD_HEADER_CNT(emsg[port].header) == 0) &&
- (PD_HEADER_TYPE(emsg[port].header) ==
- PD_CTRL_PS_RDY)) {
- set_state_pe(port, PE_VCS_TURN_OFF_VCONN_SWAP);
- return;
- }
- }
-
- /*
- * Transition to either the PE_SRC_Hard_Reset or
- * PE_SNK_Hard_Reset state when:
- * 1) The VCONNOnTimer times out.
- */
- if (get_time().val > pe[port].vconn_on_timer) {
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_HARD_RESET);
- else
- set_state_pe(port, PE_SNK_HARD_RESET);
- }
-}
-
-/*
- * PE_VCS_Turn_On_VCONN_Swap
- */
-static void pe_vcs_turn_on_vconn_swap_entry(int port)
-{
- print_current_state(port);
-
- /* Request DPM to turn on VCONN */
- pd_request_vconn_swap_on(port);
- pe[port].timeout = 0;
-}
-
-static void pe_vcs_turn_on_vconn_swap_run(int port)
-{
-
- /*
- * Transition to the PE_VCS_Send_Ps_Rdy state when:
- * 1) The Port’s VCONN is on.
- */
- if (pe[port].timeout == 0 &&
- PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE);
- pe[port].timeout = get_time().val + PD_VCONN_SWAP_DELAY;
- }
-
- if (pe[port].timeout > 0 && get_time().val > pe[port].timeout)
- set_state_pe(port, PE_VCS_SEND_PS_RDY_SWAP);
-}
-
-/*
- * PE_VCS_Turn_Off_VCONN_Swap
- */
-static void pe_vcs_turn_off_vconn_swap_entry(int port)
-{
- print_current_state(port);
-
- /* Request DPM to turn off VCONN */
- pd_request_vconn_swap_off(port);
- pe[port].timeout = 0;
-}
-
-static void pe_vcs_turn_off_vconn_swap_run(int port)
-{
- /* Wait for VCONN to turn off */
- if (pe[port].timeout == 0 &&
- PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE);
- pe[port].timeout = get_time().val + PD_VCONN_SWAP_DELAY;
- }
-
- if (pe[port].timeout > 0 && get_time().val > pe[port].timeout) {
- /*
- * A VCONN Swap Shall reset the DiscoverIdentityCounter
- * to zero
- */
- pe[port].discover_port_identity_counter = 0;
- pe[port].dr_swap_attempt_counter = 0;
-
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SNK_READY);
- }
-}
-
-/*
- * PE_VCS_Send_PS_Rdy_Swap
- */
-static void pe_vcs_send_ps_rdy_swap_entry(int port)
-{
- print_current_state(port);
-
- /* Send a PS_RDY Message */
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_PS_RDY);
-
- pe[port].sub = PE_SUB0;
-}
-
-static void pe_vcs_send_ps_rdy_swap_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- switch (pe[port].sub) {
- case PE_SUB0:
- /*
- * After a VCONN Swap the VCONN Source needs to reset
- * the Cable Plug’s Protocol Layer in order to ensure
- * MessageID synchronization.
- */
- prl_send_ctrl_msg(port, TCPC_TX_SOP_PRIME,
- PD_CTRL_SOFT_RESET);
- pe[port].sub = PE_SUB1;
- pe[port].timeout = get_time().val + 100*MSEC;
- break;
- case PE_SUB1:
- /* Got ACCEPT or REJECT from Cable Plug */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED) ||
- get_time().val > pe[port].timeout) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
- /*
- * A VCONN Swap Shall reset the
- * DiscoverIdentityCounter to zero
- */
- pe[port].discover_port_identity_counter = 0;
- pe[port].dr_swap_attempt_counter = 0;
-
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SNK_READY);
- }
- break;
- case PE_SUB2:
- /* Do nothing */
- break;
- }
- }
-}
-
-/*
- * PE_DR_SNK_Get_Sink_Cap
- */
-static void pe_dr_snk_get_sink_cap_entry(int port)
-{
- print_current_state(port);
-
- /* Send a Get Sink Cap Message */
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_GET_SINK_CAP);
-
- /* Don't start the timer until message sent */
- pe[port].sender_response_timer = 0;
-}
-
-static void pe_dr_snk_get_sink_cap_run(int port)
-{
- int type;
- int cnt;
- int ext;
- uint32_t payload;
-
- /* Wait until message is sent */
- if (pe[port].sender_response_timer == 0) {
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- /* start the SenderResponseTimer */
- pe[port].sender_response_timer =
- get_time().val + PD_T_SENDER_RESPONSE;
- } else {
- return;
- }
- }
-
- /*
- * Determine if FRS is possible based on the returned Sink Caps
- * and transition to PE_SNK_Ready when:
- * 1) An Accept Message is received.
- *
- * Transition to PE_SNK_Ready state when:
- * 1) A Reject Message is received.
- * 2) Or a Wait Message is received.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(emsg[port].header);
- cnt = PD_HEADER_CNT(emsg[port].header);
- ext = PD_HEADER_EXT(emsg[port].header);
- payload = *(uint32_t *)emsg[port].buf;
-
- if ((ext == 0) && (cnt == 0)) {
- if (type == PD_CTRL_ACCEPT) {
- /*
- * Check message to see if we can handle
- * FRS for this connection.
- *
- * TODO(b/14191267): Make sure we can handle
- * the required current before we enable FRS.
- */
- if (payload & PDO_FIXED_DUAL_ROLE) {
- switch (payload &
- PDO_FIXED_FRS_CURR_MASK) {
- case PDO_FIXED_FRS_CURR_NOT_SUPPORTED:
- break;
- case PDO_FIXED_FRS_CURR_DFLT_USB_POWER:
- case PDO_FIXED_FRS_CURR_1A5_AT_5V:
- case PDO_FIXED_FRS_CURR_3A0_AT_5V:
- pe_set_frs_enable(port, 1);
- return;
- }
- }
- set_state_pe(port, PE_SNK_READY);
- return;
- } else if ((type == PD_CTRL_REJECT) ||
- (type == PD_CTRL_WAIT)) {
- set_state_pe(port, PE_SNK_READY);
- return;
- }
- }
- }
-
- /*
- * Transition to PE_SNK_Ready state when:
- * 1) SenderResponseTimer times out.
- */
- if (get_time().val > pe[port].sender_response_timer)
- set_state_pe(port, PE_SNK_READY);
-}
-
-/* Policy Engine utility functions */
-int pd_check_requested_voltage(uint32_t rdo, const int port)
-{
- int max_ma = rdo & 0x3FF;
- int op_ma = (rdo >> 10) & 0x3FF;
- int idx = RDO_POS(rdo);
- uint32_t pdo;
- uint32_t pdo_ma;
-#if defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \
- defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT)
- const uint32_t *src_pdo;
- const int pdo_cnt = charge_manager_get_source_pdo(&src_pdo, port);
-#else
- const uint32_t *src_pdo = pd_src_pdo;
- const int pdo_cnt = pd_src_pdo_cnt;
-#endif
-
- /* Board specific check for this request */
- if (pd_board_check_request(rdo, pdo_cnt))
- return EC_ERROR_INVAL;
-
- /* check current ... */
- pdo = src_pdo[idx - 1];
- pdo_ma = (pdo & 0x3ff);
-
- if (op_ma > pdo_ma)
- return EC_ERROR_INVAL; /* too much op current */
-
- if (max_ma > pdo_ma && !(rdo & RDO_CAP_MISMATCH))
- return EC_ERROR_INVAL; /* too much max current */
-
- CPRINTF("Requested %d mV %d mA (for %d/%d mA)\n",
- ((pdo >> 10) & 0x3ff) * 50, (pdo & 0x3ff) * 10,
- op_ma * 10, max_ma * 10);
-
- /* Accept the requested voltage */
- return EC_SUCCESS;
-}
-
-void pd_process_source_cap(int port, int cnt, uint32_t *src_caps)
-{
-#ifdef CONFIG_CHARGE_MANAGER
- uint32_t ma, mv, pdo;
-#endif
- int i;
-
- pe[port].src_cap_cnt = cnt;
- for (i = 0; i < cnt; i++)
- pe[port].src_caps[i] = *src_caps++;
-
-#ifdef CONFIG_CHARGE_MANAGER
- /* Get max power info that we could request */
- pd_find_pdo_index(pe[port].src_cap_cnt, pe[port].src_caps,
- PD_MAX_VOLTAGE_MV, &pdo);
- pd_extract_pdo_power(pdo, &ma, &mv);
- /* Set max. limit, but apply 500mA ceiling */
- charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, PD_MIN_MA);
- pd_set_input_current_limit(port, ma, mv);
-#endif
-}
-
-void pd_set_max_voltage(unsigned int mv)
-{
- max_request_mv = mv;
-}
-
-unsigned int pd_get_max_voltage(void)
-{
- return max_request_mv;
-}
-
-int pd_charge_from_device(uint16_t vid, uint16_t pid)
-{
- /* TODO: rewrite into table if we get more of these */
- /*
- * Allow-list Apple charge-through accessory since it doesn't set
- * externally powered bit, but we still need to charge from it when
- * we are a sink.
- */
- return (vid == USB_VID_APPLE &&
- (pid == USB_PID1_APPLE || pid == USB_PID2_APPLE));
-}
-
-void pd_set_vbus_discharge(int port, int enable)
-{
- static struct mutex discharge_lock[CONFIG_USB_PD_PORT_MAX_COUNT];
-
- if (port >= board_get_usb_pd_port_count())
- return;
-
- mutex_lock(&discharge_lock[port]);
- enable &= !board_vbus_source_enabled(port);
-
- if (IS_ENABLED(CONFIG_USB_PD_DISCHARGE_GPIO)) {
- switch (port) {
-#if defined(CONFIG_USB_PD_DISCHARGE_GPIO) && CONFIG_USB_PD_PORT_MAX_COUNT >= 3
- case 2:
- gpio_set_level(GPIO_USB_C2_DISCHARGE, enable);
- break;
-#endif
-#if defined(CONFIG_USB_PD_DISCHARGE_GPIO) && CONFIG_USB_PD_PORT_MAX_COUNT >= 2
- case 1:
- gpio_set_level(GPIO_USB_C1_DISCHARGE, enable);
- break;
-#endif
-#if defined(CONFIG_USB_PD_DISCHARGE_GPIO) && CONFIG_USB_PD_PORT_MAX_COUNT >= 1
- case 0:
- gpio_set_level(GPIO_USB_C0_DISCHARGE, enable);
- break;
-#endif
- default:
- CPRINTF("Could not discharge port %d via GPIO", port);
- break;
- }
- } else if (IS_ENABLED(CONFIG_USB_PD_DISCHARGE_TCPC)) {
- tcpc_discharge_vbus(port, enable);
- } else if (IS_ENABLED(CONFIG_USB_PD_DISCHARGE_PPC)) {
- ppc_discharge_vbus(port, enable);
- }
-
- mutex_unlock(&discharge_lock[port]);
-}
-
-/* VDM utility functions */
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-static void pd_usb_billboard_deferred(void)
-{
-#if defined(CONFIG_USB_PD_ALT_MODE) && !defined(CONFIG_USB_PD_ALT_MODE_DFP) \
- && !defined(CONFIG_USB_PD_SIMPLE_DFP) && defined(CONFIG_USB_BOS)
-
- /*
- * TODO(tbroch)
- * 1. Will we have multiple type-C port UFPs
- * 2. Will there be other modes applicable to DFPs besides DP
- */
- if (!pd_alt_mode(0, USB_SID_DISPLAYPORT))
- usb_connect();
-
-#endif
-}
-DECLARE_DEFERRED(pd_usb_billboard_deferred);
-
-void pd_dfp_pe_init(int port)
-{
- memset(&pe[port].am_policy, 0, sizeof(struct pd_policy));
-}
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-static void dfp_consume_identity(int port, int cnt, uint32_t *payload)
-{
- int ptype = PD_IDH_PTYPE(payload[VDO_I(IDH)]);
- size_t identity_size = MIN(sizeof(pe[port].am_policy.identity),
- (cnt - 1) * sizeof(uint32_t));
-
- pd_dfp_pe_init(port);
- memcpy(&pe[port].am_policy.identity, payload + 1, identity_size);
-
- switch (ptype) {
- case IDH_PTYPE_AMA:
-/* Leave vbus ON if the following macro is false */
-#if defined(CONFIG_USB_PD_DUAL_ROLE) && defined(CONFIG_USBC_VCONN_SWAP)
- /* Adapter is requesting vconn, try to supply it */
- if (PD_VDO_AMA_VCONN_REQ(payload[VDO_I(AMA)]))
- tc_vconn_on(port);
-
- /* Only disable vbus if vconn was requested */
- if (PD_VDO_AMA_VCONN_REQ(payload[VDO_I(AMA)]) &&
- !PD_VDO_AMA_VBUS_REQ(payload[VDO_I(AMA)]))
- pd_power_supply_reset(port);
-#endif
- break;
- default:
- break;
- }
-}
-
-static void dfp_consume_svids(int port, int cnt, uint32_t *payload)
-{
- int i;
- uint32_t *ptr = payload + 1;
- int vdo = 1;
- uint16_t svid0, svid1;
-
- for (i = pe[port].am_policy.svid_cnt;
- i < pe[port].am_policy.svid_cnt + 12; i += 2) {
- if (i == SVID_DISCOVERY_MAX) {
- CPRINTF("ERR:SVIDCNT\n");
- break;
- }
- /*
- * Verify we're still within the valid packet (count will be one
- * for the VDM header + xVDOs)
- */
- if (vdo >= cnt)
- break;
-
- svid0 = PD_VDO_SVID_SVID0(*ptr);
- if (!svid0)
- break;
- pe[port].am_policy.svids[i].svid = svid0;
- pe[port].am_policy.svid_cnt++;
-
- svid1 = PD_VDO_SVID_SVID1(*ptr);
- if (!svid1)
- break;
- pe[port].am_policy.svids[i + 1].svid = svid1;
- pe[port].am_policy.svid_cnt++;
- ptr++;
- vdo++;
- }
-
- /* TODO(tbroch) need to re-issue discover svids if > 12 */
- if (i && ((i % 12) == 0))
- CPRINTF("ERR:SVID+12\n");
-}
-
-static int dfp_discover_modes(int port, uint32_t *payload)
-{
- uint16_t svid =
- pe[port].am_policy.svids[pe[port].am_policy.svid_idx].svid;
-
- if (pe[port].am_policy.svid_idx >= pe[port].am_policy.svid_cnt)
- return 0;
-
- payload[0] = VDO(svid, 1, CMD_DISCOVER_MODES);
-
- return 1;
-}
-
-static void dfp_consume_modes(int port, int cnt, uint32_t *payload)
-{
- int idx = pe[port].am_policy.svid_idx;
-
- pe[port].am_policy.svids[idx].mode_cnt = cnt - 1;
-
- if (pe[port].am_policy.svids[idx].mode_cnt < 0) {
- CPRINTF("ERR:NOMODE\n");
- } else {
- memcpy(
- pe[port].am_policy.svids[pe[port].am_policy.svid_idx].mode_vdo,
- &payload[1],
- sizeof(uint32_t) * pe[port].am_policy.svids[idx].mode_cnt);
- }
-
- pe[port].am_policy.svid_idx++;
-}
-
-static int get_mode_idx(int port, uint16_t svid)
-{
- int i;
-
- for (i = 0; i < PD_AMODE_COUNT; i++) {
- if (pe[port].am_policy.amodes[i].fx->svid == svid)
- return i;
- }
-
- return -1;
-}
-
-static struct svdm_amode_data *get_modep(int port, uint16_t svid)
-{
- int idx = get_mode_idx(port, svid);
-
- return (idx == -1) ? NULL : &pe[port].am_policy.amodes[idx];
-}
-
-int pd_alt_mode(int port, uint16_t svid)
-{
- struct svdm_amode_data *modep = get_modep(port, svid);
-
- return (modep) ? modep->opos : -1;
-}
-
-int allocate_mode(int port, uint16_t svid)
-{
- int i, j;
- struct svdm_amode_data *modep;
- int mode_idx = get_mode_idx(port, svid);
-
- if (mode_idx != -1)
- return mode_idx;
-
- /* There's no space to enter another mode */
- if (pe[port].am_policy.amode_idx == PD_AMODE_COUNT) {
- CPRINTF("ERR:NO AMODE SPACE\n");
- return -1;
- }
-
- /* Allocate ... if SVID == 0 enter default supported policy */
- for (i = 0; i < supported_modes_cnt; i++) {
- if (!&supported_modes[i])
- continue;
-
- for (j = 0; j < pe[port].am_policy.svid_cnt; j++) {
- struct svdm_svid_data *svidp =
- &pe[port].am_policy.svids[j];
-
- if ((svidp->svid != supported_modes[i].svid) ||
- (svid && (svidp->svid != svid)))
- continue;
-
- modep =
- &pe[port].am_policy.amodes[pe[port].am_policy.amode_idx];
- modep->fx = &supported_modes[i];
- modep->data = &pe[port].am_policy.svids[j];
- pe[port].am_policy.amode_idx++;
- return pe[port].am_policy.amode_idx - 1;
- }
- }
- return -1;
-}
-
-uint32_t pd_dfp_enter_mode(int port, uint16_t svid, int opos)
-{
- int mode_idx = allocate_mode(port, svid);
- struct svdm_amode_data *modep;
- uint32_t mode_caps;
-
- if (mode_idx == -1)
- return 0;
-
- modep = &pe[port].am_policy.amodes[mode_idx];
-
- if (!opos) {
- /* choose the lowest as default */
- modep->opos = 1;
- } else if (opos <= modep->data->mode_cnt) {
- modep->opos = opos;
- } else {
- CPRINTF("opos error\n");
- return 0;
- }
-
- mode_caps = modep->data->mode_vdo[modep->opos - 1];
- if (modep->fx->enter(port, mode_caps) == -1)
- return 0;
-
- PE_SET_FLAG(port, PE_FLAGS_MODAL_OPERATION);
-
- /* SVDM to send to UFP for mode entry */
- return VDO(modep->fx->svid, 1, CMD_ENTER_MODE | VDO_OPOS(modep->opos));
-}
-
-static int validate_mode_request(struct svdm_amode_data *modep,
- uint16_t svid, int opos)
-{
- if (!modep->fx)
- return 0;
-
- if (svid != modep->fx->svid) {
- CPRINTF("ERR:svid r:0x%04x != c:0x%04x\n",
- svid, modep->fx->svid);
- return 0;
- }
-
- if (opos != modep->opos) {
- CPRINTF("ERR:opos r:%d != c:%d\n",
- opos, modep->opos);
- return 0;
- }
-
- return 1;
-}
-
-static void dfp_consume_attention(int port, uint32_t *payload)
-{
- uint16_t svid = PD_VDO_VID(payload[0]);
- int opos = PD_VDO_OPOS(payload[0]);
- struct svdm_amode_data *modep = get_modep(port, svid);
-
- if (!modep || !validate_mode_request(modep, svid, opos))
- return;
-
- if (modep->fx->attention)
- modep->fx->attention(port, payload);
-}
-#endif
-/*
- * This algorithm defaults to choosing higher pin config over lower ones in
- * order to prefer multi-function if desired.
- *
- * NAME | SIGNALING | OUTPUT TYPE | MULTI-FUNCTION | PIN CONFIG
- * -------------------------------------------------------------
- * A | USB G2 | ? | no | 00_0001
- * B | USB G2 | ? | yes | 00_0010
- * C | DP | CONVERTED | no | 00_0100
- * D | PD | CONVERTED | yes | 00_1000
- * E | DP | DP | no | 01_0000
- * F | PD | DP | yes | 10_0000
- *
- * if UFP has NOT asserted multi-function preferred code masks away B/D/F
- * leaving only A/C/E. For single-output dongles that should leave only one
- * possible pin config depending on whether its a converter DP->(VGA|HDMI) or DP
- * output. If UFP is a USB-C receptacle it may assert C/D/E/F. The DFP USB-C
- * receptacle must always choose C/D in those cases.
- */
-int pd_dfp_dp_get_pin_mode(int port, uint32_t status)
-{
- struct svdm_amode_data *modep = get_modep(port, USB_SID_DISPLAYPORT);
- uint32_t mode_caps;
- uint32_t pin_caps;
-
- if (!modep)
- return 0;
-
- mode_caps = modep->data->mode_vdo[modep->opos - 1];
-
- /* TODO(crosbug.com/p/39656) revisit with DFP that can be a sink */
- pin_caps = PD_DP_PIN_CAPS(mode_caps);
-
- /* if don't want multi-function then ignore those pin configs */
- if (!PD_VDO_DPSTS_MF_PREF(status))
- pin_caps &= ~MODE_DP_PIN_MF_MASK;
-
- /* TODO(crosbug.com/p/39656) revisit if DFP drives USB Gen 2 signals */
- pin_caps &= ~MODE_DP_PIN_BR2_MASK;
-
- /* if C/D present they have precedence over E/F for USB-C->USB-C */
- if (pin_caps & (MODE_DP_PIN_C | MODE_DP_PIN_D))
- pin_caps &= ~(MODE_DP_PIN_E | MODE_DP_PIN_F);
-
- /* get_next_bit returns undefined for zero */
- if (!pin_caps)
- return 0;
-
- return 1 << get_next_bit(&pin_caps);
-}
-
-int pd_dfp_exit_mode(int port, uint16_t svid, int opos)
-{
- struct svdm_amode_data *modep;
- int idx;
-
-
- /*
- * Empty svid signals we should reset DFP VDM state by exiting all
- * entered modes then clearing state. This occurs when we've
- * disconnected or for hard reset.
- */
- if (!svid) {
- for (idx = 0; idx < PD_AMODE_COUNT; idx++)
- if (pe[port].am_policy.amodes[idx].fx)
- pe[port].am_policy.amodes[idx].fx->exit(port);
-
- pd_dfp_pe_init(port);
- return 0;
- }
-
- /*
- * TODO(crosbug.com/p/33946) : below needs revisited to allow multiple
- * mode exit. Additionally it should honor OPOS == 7 as DFP's request
- * to exit all modes. We currently don't have any UFPs that support
- * multiple modes on one SVID.
- */
- modep = get_modep(port, svid);
- if (!modep || !validate_mode_request(modep, svid, opos))
- return 0;
-
- /* call DFPs exit function */
- modep->fx->exit(port);
-
- PE_CLR_FLAG(port, PE_FLAGS_MODAL_OPERATION);
-
- /* exit the mode */
- modep->opos = 0;
-
- return 1;
-}
-
-uint16_t pd_get_identity_vid(int port)
-{
- return PD_IDH_VID(pe[port].am_policy.identity[0]);
-}
-
-uint16_t pd_get_identity_pid(int port)
-{
- return PD_PRODUCT_PID(pe[port].am_policy.identity[2]);
-}
-
-
-#ifdef CONFIG_CMD_USB_PD_PE
-static void dump_pe(int port)
-{
- const char * const idh_ptype_names[] = {
- "UNDEF", "Hub", "Periph", "PCable", "ACable", "AMA",
- "RSV6", "RSV7"};
-
- int i, j, idh_ptype;
- struct svdm_amode_data *modep;
- uint32_t mode_caps;
-
- if (pe[port].am_policy.identity[0] == 0) {
- ccprintf("No identity discovered yet.\n");
- return;
- }
- idh_ptype = PD_IDH_PTYPE(pe[port].am_policy.identity[0]);
- ccprintf("IDENT:\n");
- ccprintf("\t[ID Header] %08x :: %s, VID:%04x\n",
- pe[port].am_policy.identity[0],
- idh_ptype_names[idh_ptype],
- pd_get_identity_vid(port));
- ccprintf("\t[Cert Stat] %08x\n", pe[port].am_policy.identity[1]);
- for (i = 2; i < ARRAY_SIZE(pe[port].am_policy.identity); i++) {
- ccprintf("\t");
- if (pe[port].am_policy.identity[i])
- ccprintf("[%d] %08x ", i,
- pe[port].am_policy.identity[i]);
- }
- ccprintf("\n");
-
- if (pe[port].am_policy.svid_cnt < 1) {
- ccprintf("No SVIDS discovered yet.\n");
- return;
- }
-
- for (i = 0; i < pe[port].am_policy.svid_cnt; i++) {
- ccprintf("SVID[%d]: %04x MODES:", i,
- pe[port].am_policy.svids[i].svid);
- for (j = 0; j < pe[port].am_policy.svids[j].mode_cnt; j++)
- ccprintf(" [%d] %08x", j + 1,
- pe[port].am_policy.svids[i].mode_vdo[j]);
- ccprintf("\n");
- modep = get_modep(port, pe[port].am_policy.svids[i].svid);
- if (modep) {
- mode_caps = modep->data->mode_vdo[modep->opos - 1];
- ccprintf("MODE[%d]: svid:%04x caps:%08x\n", modep->opos,
- modep->fx->svid, mode_caps);
- }
- }
-}
-
-static int command_pe(int argc, char **argv)
-{
- int port;
- char *e;
-
- if (argc < 3)
- return EC_ERROR_PARAM_COUNT;
-
- /* command: pe <port> <subcmd> <args> */
- port = strtoi(argv[1], &e, 10);
- if (*e || port >= board_get_usb_pd_port_count())
- return EC_ERROR_PARAM2;
- if (!strncasecmp(argv[2], "dump", 4))
- dump_pe(port);
-
- return EC_SUCCESS;
-}
-
-DECLARE_CONSOLE_COMMAND(pe, command_pe,
- "<port> dump",
- "USB PE");
-#endif /* CONFIG_CMD_USB_PD_PE */
-
-static enum ec_status hc_remote_pd_discovery(struct host_cmd_handler_args *args)
-{
- const uint8_t *port = args->params;
- struct ec_params_usb_pd_discovery_entry *r = args->response;
-
- if (*port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- r->vid = pd_get_identity_vid(*port);
- r->ptype = PD_IDH_PTYPE(pe[*port].am_policy.identity[0]);
-
- /* pid only included if vid is assigned */
- if (r->vid)
- r->pid = PD_PRODUCT_PID(pe[*port].am_policy.identity[2]);
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_DISCOVERY,
- hc_remote_pd_discovery,
- EC_VER_MASK(0));
-
-static enum ec_status hc_remote_pd_get_amode(struct host_cmd_handler_args *args)
-{
- struct svdm_amode_data *modep;
- const struct ec_params_usb_pd_get_mode_request *p = args->params;
- struct ec_params_usb_pd_get_mode_response *r = args->response;
-
- if (p->port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- /* no more to send */
- if (p->svid_idx >= pe[p->port].am_policy.svid_cnt) {
- r->svid = 0;
- args->response_size = sizeof(r->svid);
- return EC_RES_SUCCESS;
- }
-
- r->svid = pe[p->port].am_policy.svids[p->svid_idx].svid;
- r->opos = 0;
- memcpy(r->vdo, pe[p->port].am_policy.svids[p->svid_idx].mode_vdo, 24);
- modep = get_modep(p->port, r->svid);
-
- if (modep)
- r->opos = pd_alt_mode(p->port, r->svid);
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_GET_AMODE,
- hc_remote_pd_get_amode,
- EC_VER_MASK(0));
-
-#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
-
-static const struct usb_state pe_states[] = {
- /* Super States */
- [PE_PRS_FRS_SHARED] = {
- .entry = pe_prs_frs_shared_entry,
- .exit = pe_prs_frs_shared_exit,
- },
-
- /* Normal States */
- [PE_SRC_STARTUP] = {
- .entry = pe_src_startup_entry,
- .run = pe_src_startup_run,
- },
- [PE_SRC_DISCOVERY] = {
- .entry = pe_src_discovery_entry,
- .run = pe_src_discovery_run,
- },
- [PE_SRC_SEND_CAPABILITIES] = {
- .entry = pe_src_send_capabilities_entry,
- .run = pe_src_send_capabilities_run,
- },
- [PE_SRC_NEGOTIATE_CAPABILITY] = {
- .entry = pe_src_negotiate_capability_entry,
- },
- [PE_SRC_TRANSITION_SUPPLY] = {
- .entry = pe_src_transition_supply_entry,
- .run = pe_src_transition_supply_run,
- },
- [PE_SRC_READY] = {
- .entry = pe_src_ready_entry,
- .run = pe_src_ready_run,
- .exit = pe_src_ready_exit,
- },
- [PE_SRC_DISABLED] = {
- .entry = pe_src_disabled_entry,
- },
- [PE_SRC_CAPABILITY_RESPONSE] = {
- .entry = pe_src_capability_response_entry,
- .run = pe_src_capability_response_run,
- },
- [PE_SRC_HARD_RESET] = {
- .entry = pe_src_hard_reset_entry,
- .run = pe_src_hard_reset_run,
- },
- [PE_SRC_HARD_RESET_RECEIVED] = {
- .entry = pe_src_hard_reset_received_entry,
- .run = pe_src_hard_reset_received_run,
- },
- [PE_SRC_TRANSITION_TO_DEFAULT] = {
- .entry = pe_src_transition_to_default_entry,
- .run = pe_src_transition_to_default_run,
- },
- [PE_SNK_STARTUP] = {
- .entry = pe_snk_startup_entry,
- .run = pe_snk_startup_run,
- },
- [PE_SNK_DISCOVERY] = {
- .entry = pe_snk_discovery_entry,
- .run = pe_snk_discovery_run,
- },
- [PE_SNK_WAIT_FOR_CAPABILITIES] = {
- .entry = pe_snk_wait_for_capabilities_entry,
- .run = pe_snk_wait_for_capabilities_run,
- },
- [PE_SNK_EVALUATE_CAPABILITY] = {
- .entry = pe_snk_evaluate_capability_entry,
- },
- [PE_SNK_SELECT_CAPABILITY] = {
- .entry = pe_snk_select_capability_entry,
- .run = pe_snk_select_capability_run,
- },
- [PE_SNK_READY] = {
- .entry = pe_snk_ready_entry,
- .run = pe_snk_ready_run,
- .exit = pe_snk_ready_exit,
- },
- [PE_SNK_HARD_RESET] = {
- .entry = pe_snk_hard_reset_entry,
- .run = pe_snk_hard_reset_run,
- },
- [PE_SNK_TRANSITION_TO_DEFAULT] = {
- .entry = pe_snk_transition_to_default_entry,
- .run = pe_snk_transition_to_default_run,
- },
- [PE_SNK_GIVE_SINK_CAP] = {
- .entry = pe_snk_give_sink_cap_entry,
- .run = pe_snk_give_sink_cap_run,
- },
- [PE_SNK_GET_SOURCE_CAP] = {
- .entry = pe_snk_get_source_cap_entry,
- .run = pe_snk_get_source_cap_run,
- },
- [PE_SNK_TRANSITION_SINK] = {
- .entry = pe_snk_transition_sink_entry,
- .run = pe_snk_transition_sink_run,
- .exit = pe_snk_transition_sink_exit,
- },
- [PE_SEND_SOFT_RESET] = {
- .entry = pe_send_soft_reset_entry,
- .run = pe_send_soft_reset_run,
- .exit = pe_send_soft_reset_exit,
- },
- [PE_SOFT_RESET] = {
- .entry = pe_soft_reset_entry,
- .run = pe_soft_reset_run,
- },
- [PE_SEND_NOT_SUPPORTED] = {
- .entry = pe_send_not_supported_entry,
- .run = pe_send_not_supported_run,
- },
- [PE_SRC_PING] = {
- .entry = pe_src_ping_entry,
- .run = pe_src_ping_run,
- },
- [PE_GIVE_BATTERY_CAP] = {
- .entry = pe_give_battery_cap_entry,
- .run = pe_give_battery_cap_run,
- },
- [PE_GIVE_BATTERY_STATUS] = {
- .entry = pe_give_battery_status_entry,
- .run = pe_give_battery_status_run,
- },
- [PE_DRS_EVALUATE_SWAP] = {
- .entry = pe_drs_evaluate_swap_entry,
- .run = pe_drs_evaluate_swap_run,
- },
- [PE_DRS_CHANGE] = {
- .entry = pe_drs_change_entry,
- .run = pe_drs_change_run,
- },
- [PE_DRS_SEND_SWAP] = {
- .entry = pe_drs_send_swap_entry,
- .run = pe_drs_send_swap_run,
- },
- [PE_PRS_SRC_SNK_EVALUATE_SWAP] = {
- .entry = pe_prs_src_snk_evaluate_swap_entry,
- .run = pe_prs_src_snk_evaluate_swap_run,
- },
- [PE_PRS_SRC_SNK_TRANSITION_TO_OFF] = {
- .entry = pe_prs_src_snk_transition_to_off_entry,
- .run = pe_prs_src_snk_transition_to_off_run,
- },
- [PE_PRS_SRC_SNK_WAIT_SOURCE_ON] = {
- .entry = pe_prs_src_snk_wait_source_on_entry,
- .run = pe_prs_src_snk_wait_source_on_run,
- },
- [PE_PRS_SRC_SNK_SEND_SWAP] = {
- .entry = pe_prs_src_snk_send_swap_entry,
- .run = pe_prs_src_snk_send_swap_run,
- .exit = pe_prs_src_snk_send_swap_exit,
- },
- [PE_PRS_SNK_SRC_EVALUATE_SWAP] = {
- .entry = pe_prs_snk_src_evaluate_swap_entry,
- .run = pe_prs_snk_src_evaluate_swap_run,
- },
- /*
- * Some of the Power Role Swap actions are shared with the very
- * similar actions of Fast Role Swap.
- */
- /* State actions are shared with PE_FRS_SNK_SRC_TRANSITION_TO_OFF */
- [PE_PRS_SNK_SRC_TRANSITION_TO_OFF] = {
- .entry = pe_prs_snk_src_transition_to_off_entry,
- .run = pe_prs_snk_src_transition_to_off_run,
- .parent = &pe_states[PE_PRS_FRS_SHARED],
- },
- /* State actions are shared with PE_FRS_SNK_SRC_ASSERT_RP */
- [PE_PRS_SNK_SRC_ASSERT_RP] = {
- .entry = pe_prs_snk_src_assert_rp_entry,
- .run = pe_prs_snk_src_assert_rp_run,
- .parent = &pe_states[PE_PRS_FRS_SHARED],
- },
- /* State actions are shared with PE_FRS_SNK_SRC_SOURCE_ON */
- [PE_PRS_SNK_SRC_SOURCE_ON] = {
- .entry = pe_prs_snk_src_source_on_entry,
- .run = pe_prs_snk_src_source_on_run,
- .parent = &pe_states[PE_PRS_FRS_SHARED],
- },
- /* State actions are shared with PE_FRS_SNK_SRC_SEND_SWAP */
- [PE_PRS_SNK_SRC_SEND_SWAP] = {
- .entry = pe_prs_snk_src_send_swap_entry,
- .run = pe_prs_snk_src_send_swap_run,
- .exit = pe_prs_snk_src_send_swap_exit,
- .parent = &pe_states[PE_PRS_FRS_SHARED],
- },
- [PE_FRS_SNK_SRC_START_AMS] = {
- .entry = pe_frs_snk_src_start_ams_entry,
- .parent = &pe_states[PE_PRS_FRS_SHARED],
- },
- [PE_VCS_EVALUATE_SWAP] = {
- .entry = pe_vcs_evaluate_swap_entry,
- .run = pe_vcs_evaluate_swap_run,
- },
- [PE_VCS_SEND_SWAP] = {
- .entry = pe_vcs_send_swap_entry,
- .run = pe_vcs_send_swap_run,
- },
- [PE_VCS_WAIT_FOR_VCONN_SWAP] = {
- .entry = pe_vcs_wait_for_vconn_swap_entry,
- .run = pe_vcs_wait_for_vconn_swap_run,
- },
- [PE_VCS_TURN_ON_VCONN_SWAP] = {
- .entry = pe_vcs_turn_on_vconn_swap_entry,
- .run = pe_vcs_turn_on_vconn_swap_run,
- },
- [PE_VCS_TURN_OFF_VCONN_SWAP] = {
- .entry = pe_vcs_turn_off_vconn_swap_entry,
- .run = pe_vcs_turn_off_vconn_swap_run,
- },
- [PE_VCS_SEND_PS_RDY_SWAP] = {
- .entry = pe_vcs_send_ps_rdy_swap_entry,
- .run = pe_vcs_send_ps_rdy_swap_run,
- },
- [PE_DO_PORT_DISCOVERY] = {
- .entry = pe_do_port_discovery_entry,
- .run = pe_do_port_discovery_run,
- },
- [PE_VDM_REQUEST] = {
- .entry = pe_vdm_request_entry,
- .run = pe_vdm_request_run,
- .exit = pe_vdm_request_exit,
- },
- [PE_VDM_ACKED] = {
- .entry = pe_vdm_acked_entry,
- },
- [PE_VDM_RESPONSE] = {
- .entry = pe_vdm_response_entry,
- .run = pe_vdm_response_run,
- },
- [PE_HANDLE_CUSTOM_VDM_REQUEST] = {
- .entry = pe_handle_custom_vdm_request_entry,
- .run = pe_handle_custom_vdm_request_run
- },
- [PE_WAIT_FOR_ERROR_RECOVERY] = {
- .entry = pe_wait_for_error_recovery_entry,
- .run = pe_wait_for_error_recovery_run,
- },
- [PE_BIST] = {
- .entry = pe_bist_entry,
- .run = pe_bist_run,
- },
- [PE_DR_SNK_GET_SINK_CAP] = {
- .entry = pe_dr_snk_get_sink_cap_entry,
- .run = pe_dr_snk_get_sink_cap_run,
- },
-};
-
-#ifdef TEST_BUILD
-const struct test_sm_data test_pe_sm_data[] = {
- {
- .base = pe_states,
- .size = ARRAY_SIZE(pe_states),
- .names = pe_state_names,
- .names_size = ARRAY_SIZE(pe_state_names),
- },
-};
-const int test_pe_sm_data_size = ARRAY_SIZE(test_pe_sm_data);
-
-void pe_set_flag(int port, int flag)
-{
- PE_SET_FLAG(port, flag);
-}
-void pe_clr_flag(int port, int flag)
-{
- PE_CLR_FLAG(port, flag);
-}
-int pe_chk_flag(int port, int flag)
-{
- return PE_CHK_FLAG(port, flag);
-}
-int pe_get_all_flags(int port)
-{
- return pe[port].flags;
-}
-void pe_set_all_flags(int port, int flags)
-{
- pe[port].flags = flags;
-}
-#endif
diff --git a/common/usbc/usb_prl_sm.c b/common/usbc/usb_prl_sm.c
deleted file mode 100644
index 9a78b59474..0000000000
--- a/common/usbc/usb_prl_sm.c
+++ /dev/null
@@ -1,1762 +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 "ec_commands.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "registers.h"
-#include "system.h"
-#include "task.h"
-#include "timer.h"
-#include "tcpm.h"
-#include "util.h"
-#include "usb_charge.h"
-#include "usb_mux.h"
-#include "usb_pd.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"
-#include "version.h"
-
-#define RCH_SET_FLAG(port, flag) atomic_or(&rch[port].flags, (flag))
-#define RCH_CLR_FLAG(port, flag) atomic_clear(&rch[port].flags, (flag))
-#define RCH_CHK_FLAG(port, flag) (rch[port].flags & (flag))
-
-#define TCH_SET_FLAG(port, flag) atomic_or(&tch[port].flags, (flag))
-#define TCH_CLR_FLAG(port, flag) atomic_clear(&tch[port].flags, (flag))
-#define TCH_CHK_FLAG(port, flag) (tch[port].flags & (flag))
-
-#define PRL_TX_SET_FLAG(port, flag) atomic_or(&prl_tx[port].flags, (flag))
-#define PRL_TX_CLR_FLAG(port, flag) atomic_clear(&prl_tx[port].flags, (flag))
-#define PRL_TX_CHK_FLAG(port, flag) (prl_tx[port].flags & (flag))
-
-#define PRL_HR_SET_FLAG(port, flag) atomic_or(&prl_hr[port].flags, (flag))
-#define PRL_HR_CLR_FLAG(port, flag) atomic_clear(&prl_hr[port].flags, (flag))
-#define PRL_HR_CHK_FLAG(port, flag) (prl_hr[port].flags & (flag))
-
-#define PDMSG_SET_FLAG(port, flag) atomic_or(&pdmsg[port].flags, (flag))
-#define PDMSG_CLR_FLAG(port, flag) atomic_clear(&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 an AMS is being started by PE */
-#define PRL_FLAGS_START_AMS BIT(1)
-/* Flag to note an AMS is being stopped by PE */
-#define PRL_FLAGS_END_AMS 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 */
-#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)
-
-/* PD counter definitions */
-#define PD_MESSAGE_ID_COUNT 7
-
-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,
-};
-
-/* 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[];
-static const struct usb_state rch_states[];
-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;
- /* protocol timer */
- uint64_t chunk_sender_response_timer;
-} 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;
- /* protocol timer */
- uint64_t chunk_sender_request_timer;
- /* 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 {
- /* 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;
- /* protocol timer */
- uint64_t sink_tx_timer;
- /* tcpc transmit timeout */
- uint64_t tcpc_tx_timeout;
- /* last message type we transmitted */
- enum tcpm_transmit_type last_xmit_type;
- /* message id counters for all 6 port partners */
- uint32_t msg_id_counter[NUM_SOP_STAR_TYPES];
- /* message retry counter */
- uint32_t retry_counter;
- /* 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;
- /* protocol timer */
- uint64_t hard_reset_complete_timer;
-} prl_hr[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Chunking Message Object */
-static struct pd_message {
- /* message status flags */
- uint32_t flags;
- /* SOP* */
- enum tcpm_transmit_type xmit_type;
- /* type of message */
- uint8_t msg_type;
- /* extended message */
- uint8_t ext;
- /* 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 chk_buf[7];
- uint32_t chunk_number_expected;
- uint32_t num_bytes_received;
- uint32_t chunk_number_to_send;
- uint32_t send_offset;
-} pdmsg[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-struct extended_msg 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);
-
-/* 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];
-}
-
-/* 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]);
-}
-
-#ifdef TEST_BUILD
-/* 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];
-}
-#endif
-
-/* Set the chunked Rx statemachine to a new state. */
-static void set_state_rch(const int port, const enum usb_rch_state new_state)
-{
- set_state(port, &rch[port].ctx, &rch_states[new_state]);
-}
-
-/* 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];
-}
-
-/* Set the chunked Tx statemachine to a new state. */
-static void set_state_tch(const int port, const enum usb_tch_state new_state)
-{
- 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)
-{
- return tch[port].ctx.current - &tch_states[0];
-}
-
-void pd_transmit_complete(int port, int status)
-{
- 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_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SM, 0);
-}
-
-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_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SM, 0);
-}
-
-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 = {};
-
- prl_tx[port].flags = 0;
- prl_tx[port].last_xmit_type = TCPC_TX_SOP;
- prl_tx[port].xmit_status = TCPC_TX_UNSET;
-
- tch[port].flags = 0;
- rch[port].flags = 0;
-
- /*
- * 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[TCPC_TX_SOP] = PD_REV30;
- pdmsg[port].rev[TCPC_TX_SOP_PRIME] = PD_REV30;
- pdmsg[port].rev[TCPC_TX_SOP_PRIME_PRIME] = PD_REV30;
- pdmsg[port].rev[TCPC_TX_SOP_DEBUG_PRIME] = PD_REV30;
- pdmsg[port].rev[TCPC_TX_SOP_DEBUG_PRIME_PRIME] = PD_REV30;
- 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;
- }
-
- /* Clear state machines and set initial states */
- prl_tx[port].ctx = cleared;
- set_state_prl_tx(port, PRL_TX_PHY_LAYER_RESET);
-
- 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);
-}
-
-void prl_start_ams(int port)
-{
- PRL_TX_SET_FLAG(port, PRL_FLAGS_START_AMS);
-}
-
-void prl_end_ams(int port)
-{
- PRL_TX_SET_FLAG(port, PRL_FLAGS_END_AMS);
-}
-
-void prl_hard_reset_complete(int port)
-{
- PRL_HR_SET_FLAG(port, PRL_FLAGS_HARD_RESET_COMPLETE);
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SM, 0);
-}
-
-void prl_send_ctrl_msg(int port,
- enum tcpm_transmit_type type,
- enum pd_ctrl_msg_type msg)
-{
- pdmsg[port].xmit_type = type;
- pdmsg[port].msg_type = msg;
- pdmsg[port].ext = 0;
- emsg[port].len = 0;
-
- TCH_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SM, 0);
-}
-
-void prl_send_data_msg(int port,
- enum tcpm_transmit_type type,
- enum pd_data_msg_type msg)
-{
- pdmsg[port].xmit_type = type;
- pdmsg[port].msg_type = msg;
- pdmsg[port].ext = 0;
-
- TCH_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SM, 0);
-}
-
-void prl_send_ext_data_msg(int port,
- enum tcpm_transmit_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_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SM, 0);
-}
-
-void prl_reset(int port)
-{
- local_state[port] = SM_INIT;
-}
-
-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 disabling, wait until message is sent. */
- if (!en && tch_get_state(port) ==
- TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE) {
-
- /* Disable RX */
- if (IS_ENABLED(CONFIG_USB_TYPEC_CTVPD) ||
- IS_ENABLED(CONFIG_USB_TYPEC_VPD))
- vpd_rx_enable(0);
- else
- tcpm_set_rx_enable(port, 0);
-
- local_state[port] = SM_PAUSED;
- break;
- }
-
- /* Run Protocol Layer Message Reception */
- prl_rx_wait_for_phy_message(port, evt);
-
- /* Run RX Chunked state machine */
- run_state(port, &rch[port].ctx);
-
- /* Run TX Chunked state machine */
- run_state(port, &tch[port].ctx);
-
- /* Run Protocol Layer Message Transmission state machine */
- run_state(port, &prl_tx[port].ctx);
-
- /* Run Protocol Layer Hard Reset state machine */
- run_state(port, &prl_hr[port].ctx);
- break;
- }
-}
-
-void prl_set_rev(int port, enum tcpm_transmit_type type,
- enum pd_rev_type rev)
-{
- pdmsg[port].rev[type] = rev;
-}
-enum pd_rev_type prl_get_rev(int port, enum tcpm_transmit_type type)
-{
- return pdmsg[port].rev[type];
-}
-
-/* Common Protocol Layer Message Transmission */
-static void prl_tx_phy_layer_reset_entry(const int port)
-{
- if (IS_ENABLED(CONFIG_USB_TYPEC_CTVPD)
- || IS_ENABLED(CONFIG_USB_TYPEC_VPD)) {
- vpd_rx_enable(1);
- } else {
- tcpm_init(port);
- tcpm_clear_pending_messages(port);
- tcpm_set_rx_enable(port, 1);
- }
-}
-
-static void prl_tx_phy_layer_reset_run(const int port)
-{
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_MESSAGE_REQUEST);
-}
-
-static void prl_tx_wait_for_message_request_entry(const int port)
-{
- /* Reset RetryCounter */
- prl_tx[port].retry_counter = 0;
-}
-
-static void prl_tx_wait_for_message_request_run(const int port)
-{
- if ((prl_get_rev(port, pdmsg[port].xmit_type) == PD_REV30) &&
- PRL_TX_CHK_FLAG(port,
- (PRL_FLAGS_START_AMS | PRL_FLAGS_END_AMS))) {
- if (tc_get_power_role(port) == PD_ROLE_SOURCE) {
- /*
- * Start of AMS notification received from
- * Policy Engine
- */
- if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_START_AMS)) {
- PRL_TX_CLR_FLAG(port, PRL_FLAGS_START_AMS);
- set_state_prl_tx(port, PRL_TX_SRC_SOURCE_TX);
- return;
- }
- /*
- * End of AMS notification received from
- * Policy Engine
- */
- else if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_END_AMS)) {
- PRL_TX_CLR_FLAG(port, PRL_FLAGS_END_AMS);
- /* Set Rp = SinkTxOk */
- tcpm_select_rp_value(port, SINK_TX_OK);
- tcpm_set_cc(port, TYPEC_CC_RP);
- prl_tx[port].retry_counter = 0;
- prl_tx[port].flags = 0;
- }
- } else {
- if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_START_AMS)) {
- PRL_TX_CLR_FLAG(port, PRL_FLAGS_START_AMS);
- /*
- * First Message in AMS notification
- * received from Policy Engine.
- */
- set_state_prl_tx(port, PRL_TX_SNK_START_AMS);
- return;
- }
- }
- } else 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) &&
- (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)
-{
- /* Increment msgidCounter */
- increment_msgid_counter(port);
- set_state_prl_tx(port, PRL_TX_PHY_LAYER_RESET);
-}
-
-/*
- * PrlTxSrcSourceTx
- */
-static void prl_tx_src_source_tx_entry(const int port)
-{
- /* Set Rp = SinkTxNG */
- tcpm_select_rp_value(port, SINK_TX_NG);
- tcpm_set_cc(port, TYPEC_CC_RP);
-}
-
-static void prl_tx_src_source_tx_run(const int port)
-{
- if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) {
- PRL_TX_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT);
-
- set_state_prl_tx(port, PRL_TX_SRC_PENDING);
- }
-}
-
-/*
- * PrlTxSnkStartAms
- */
-static void prl_tx_snk_start_ams_run(const int port)
-{
- if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) {
- PRL_TX_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT);
-
- set_state_prl_tx(port, PRL_TX_SNK_PENDING);
- }
-}
-
-/*
- * PrlTxLayerResetForTransmit
- */
-static void prl_tx_layer_reset_for_transmit_entry(const int port)
-{
- int i;
-
- /* Reset MessageIdCounters */
- for (i = 0; i < NUM_SOP_STAR_TYPES; i++)
- prl_tx[port].msg_id_counter[i] = 0;
-}
-
-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 == TCPC_TX_SOP;
-
- /* SOP vs SOP'/SOP" headers are different. Replace fields as needed */
- return PD_HEADER(
- pdmsg[port].msg_type,
- is_sop_packet ?
- tc_get_power_role(port) : tc_get_cable_plug(port),
- is_sop_packet ?
- tc_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],
- pdmsg[port].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;
-
- /*
- * 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].chk_buf);
-}
-
-/*
- * PrlTxWaitForPhyResponse
- */
-static void prl_tx_wait_for_phy_response_entry(const int port)
-{
- prl_tx[port].tcpc_tx_timeout = get_time().val + 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 satifies the PRL_Tx_Match_MessageID state
- * requirement.
- */
-
- if (get_time().val > prl_tx[port].tcpc_tx_timeout ||
- prl_tx[port].xmit_status == TCPC_TX_COMPLETE_FAILED ||
- prl_tx[port].xmit_status == TCPC_TX_COMPLETE_DISCARDED) {
-
- /* NOTE: PRL_Tx_Check_RetryCounter State embedded here. */
-
- /* Increment check RetryCounter */
- prl_tx[port].retry_counter++;
-
- /*
- * (RetryCounter > nRetryCount) | Large Extended Message
- */
- if (prl_tx[port].retry_counter > N_RETRY_COUNT ||
- (pdmsg[port].ext &&
- PD_EXT_HEADER_DATA_SIZE(GET_EXT_HEADER(
- pdmsg[port].chk_buf[0]) > 26))) {
-
- /*
- * NOTE: PRL_Tx_Transmission_Error State embedded
- * here.
- */
-
- /*
- * State tch_wait_for_transmission_complete will
- * inform policy engine of error
- */
- PDMSG_SET_FLAG(port, PRL_FLAGS_TX_ERROR);
-
- /* Increment message id counter */
- increment_msgid_counter(port);
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_MESSAGE_REQUEST);
- } else {
- /*
- * NOTE: PRL_TX_Construct_Message State embedded
- * here.
- */
- /* Try to resend the message. */
- prl_tx_construct_message(port);
- }
- } else 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 */
- PDMSG_SET_FLAG(port, PRL_FLAGS_TX_COMPLETE);
- /*
- * This event reduces the time of informing the policy engine of
- * the transmission by one state machine cycle
- */
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SM, 0);
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_MESSAGE_REQUEST);
- }
-}
-
-static void prl_tx_wait_for_phy_response_exit(const int port)
-{
- prl_tx[port].xmit_status = TCPC_TX_UNSET;
-}
-
-/* Source Protocol Layer Message Transmission */
-/*
- * PrlTxSrcPending
- */
-static void prl_tx_src_pending_entry(const int port)
-{
- /* Start SinkTxTimer */
- prl_tx[port].sink_tx_timer = get_time().val + PD_T_SINK_TX;
-}
-
-static void prl_tx_src_pending_run(const int port)
-{
-
- if (get_time().val > prl_tx[port].sink_tx_timer) {
- /*
- * Soft Reset Message pending &
- * SinkTxTimer timeout
- */
- if ((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;
- }
-}
-
-/*
- * PrlTxSnkPending
- */
-static void prl_tx_snk_pending_run(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
-
- tcpm_get_cc(port, &cc1, &cc2);
- if (cc1 == TYPEC_CC_VOLT_RP_3_0 || cc2 == TYPEC_CC_VOLT_RP_3_0) {
- /*
- * Soft Reset Message Message pending &
- * Rp = SinkTxOk
- */
- if ((pdmsg[port].msg_type == PD_CTRL_SOFT_RESET) &&
- (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 */
-
-static void prl_hr_wait_for_request_entry(const int 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;
-
- /* reset messageIDCounters */
- for (i = 0; i < NUM_SOP_STAR_TYPES; i++)
- prl_tx[port].msg_id_counter[i] = 0;
- /*
- * Protocol Layer message transmission transitions to
- * PRL_Tx_Wait_For_Message_Request state.
- */
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_MESSAGE_REQUEST);
-
- tch[port].flags = 0;
- rch[port].flags = 0;
- pdmsg[port].flags = 0;
-
- /* Reset message ids */
- 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_TYPEC_CTVPD) ||
- IS_ENABLED(CONFIG_USB_TYPEC_VPD))
- vpd_rx_enable(0);
- else
- tcpm_set_rx_enable(port, 0);
-
- 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 */
- prl_send_ctrl_msg(port, TCPC_TX_HARD_RESET, 0);
- 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)
-{
- /* Start HardResetCompleteTimer */
- prl_hr[port].hard_reset_complete_timer =
- get_time().val + 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) ||
- (get_time().val > prl_hr[port].hard_reset_complete_timer)) {
- /* 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;
- }
-}
-
-/*
- * PrlHrWaitForPeHardResetComplete
- */
-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);
- 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(emsg[port].header) * 4);
-
- /* Copy chunk into extended message */
- memcpy((uint8_t *)emsg[port].buf, (uint8_t *)pdmsg[port].chk_buf,
- pdmsg[port].num_bytes_received);
-
- /* Set extended message length */
- emsg[port].len = pdmsg[port].num_bytes_received;
-}
-
-/*
- * Chunked Rx State Machine
- */
-/*
- * RchWaitForMessageFromProtocolLayer
- */
-static void rch_wait_for_message_from_protocol_layer_entry(const int 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 (prl_get_rev(port, pdmsg[port].xmit_type) == PD_REV30 &&
- PD_HEADER_EXT(emsg[port].header)) {
- uint16_t exhdr = GET_EXT_HEADER(*pdmsg[port].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(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 {
- set_state_rch(port, RCH_REPORT_ERROR);
- }
- }
- /*
- * Received Non-Extended Message
- */
- else if (!PD_HEADER_EXT(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 {
- set_state_rch(port, RCH_REPORT_ERROR);
- }
- }
-}
-
-/*
- * RchPassUpMessage
- */
-static void rch_pass_up_message_entry(const int 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_run(const int port)
-{
- uint16_t exhdr = GET_EXT_HEADER(pdmsg[port].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 > 25)
- byte_num = 26;
-
- /* Make sure extended message buffer does not overflow */
- if (pdmsg[port].num_bytes_received +
- byte_num > EXTENDED_BUFFER_SIZE) {
- set_state_rch(port, RCH_REPORT_ERROR);
- return;
- }
-
- /* Append data */
- /* Add 2 to chk_buf to skip over extended message header */
- memcpy(((uint8_t *)emsg[port].buf +
- pdmsg[port].num_bytes_received),
- (uint8_t *)pdmsg[port].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) {
- 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
- set_state_rch(port, RCH_REPORT_ERROR);
-}
-
-/*
- * RchRequestingChunk
- */
-static void rch_requesting_chunk_entry(const int port)
-{
- /*
- * Send Chunk Request to Protocol Layer
- * with chunk number = Chunk_Number_Expected
- */
- pdmsg[port].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;
- PRL_TX_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TX, 0);
-}
-
-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);
- }
- /*
- * Transmission Error from Protocol Layer or
- * Message Received From Protocol Layer
- */
- else if (RCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED) ||
- PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_ERROR)) {
- /*
- * Leave PRL_FLAGS_MSG_RECEIVED flag set. It'll be
- * cleared in rch_report_error state
- */
- set_state_rch(port, RCH_REPORT_ERROR);
- }
-}
-
-/*
- * RchWaitingChunk
- */
-static void rch_waiting_chunk_entry(const int port)
-{
- /*
- * Start ChunkSenderResponseTimer
- */
- rch[port].chunk_sender_response_timer =
- get_time().val + PD_T_CHUNK_SENDER_RESPONSE;
-}
-
-static void rch_waiting_chunk_run(const int port)
-{
- if (RCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- /*
- * 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(emsg[port].header)) {
- uint16_t exhdr = GET_EXT_HEADER(pdmsg[port].chk_buf[0]);
- /*
- * Other Message Received from Protocol Layer
- */
- if (PD_EXT_HEADER_REQ_CHUNK(exhdr) ||
- !PD_EXT_HEADER_CHUNKED(exhdr)) {
- set_state_rch(port, RCH_REPORT_ERROR);
- }
- /*
- * Chunk response Received from Protocol Layer
- */
- else {
- /*
- * No error wad 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 (get_time().val > rch[port].chunk_sender_response_timer) {
- set_state_rch(port, RCH_REPORT_ERROR);
- }
-}
-
-/*
- * RchReportError
- */
-static void rch_report_error_entry(const int 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);
- } else {
- /* Report error */
- pe_report_error(port, ERR_RCH_CHUNKED);
- }
-}
-
-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)
-{
- /* 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 (prl_get_rev(port, pdmsg[port].xmit_type) == PD_REV30
- && 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
- */
- {
- /* Make sure buffer doesn't overflow */
- if (emsg[port].len > BUFFER_SIZE) {
- tch[port].error = ERR_TCH_XMIT;
- set_state_tch(port, TCH_REPORT_ERROR);
- return;
- }
-
- /* NOTE: TCH_Pass_Down_Message embedded here */
- /* Copy message to chunked buffer */
- memset((uint8_t *)pdmsg[port].chk_buf,
- 0, BUFFER_SIZE);
- memcpy((uint8_t *)pdmsg[port].chk_buf,
- (uint8_t *)emsg[port].buf,
- emsg[port].len);
- /*
- * Pad length to 4-byte boundery 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 =
- (emsg[port].len + 3) >> 2;
- /* 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_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);
- }
- /*
- * 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);
- }
-}
-
-/*
- * TchConstructChunkedMessage
- */
-static void tch_construct_chunked_message_entry(const int port)
-{
- uint16_t *ext_hdr;
- uint8_t *data;
- uint16_t num;
-
- /*
- * 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].chk_buf;
- data = ((uint8_t *)pdmsg[port].chk_buf + 2);
- num = emsg[port].len - pdmsg[port].send_offset;
-
- if (num > 26)
- num = 26;
-
- /* Set the chunks extended header */
- *ext_hdr = PD_EXT_HEADER(pdmsg[port].chunk_number_to_send,
- 0, /* Chunk Request */
- emsg[port].len);
-
- /* Copy the message chunk into chk_buf */
- memset(data, 0, 28);
- memcpy(data, 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_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 (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)
-{
- /* Increment Chunk Number to Send */
- pdmsg[port].chunk_number_to_send++;
- /* Start Chunk Sender Request Timer */
- tch[port].chunk_sender_request_timer =
- get_time().val + 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(emsg[port].header)) {
- uint16_t exthdr;
-
- exthdr = GET_EXT_HEADER(pdmsg[port].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 (get_time().val >=
- tch[port].chunk_sender_request_timer) {
- set_state_tch(port, TCH_MESSAGE_SENT);
- }
-}
-
-/*
- * TchMessageReceived
- */
-static void tch_message_received_entry(const int port)
-{
- /* Pass message to chunked Rx */
- RCH_SET_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
-}
-
-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)
-{
- /* Tell PE message was sent */
- pe_message_sent(port);
- set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
-}
-
-/*
- * TchReportError
- */
-static void tch_report_error_entry(const int port)
-{
- /* Report Error To Policy Engine */
- pe_report_error(port, tch[port].error);
- set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
-}
-
-/*
- * 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;
- uint8_t sop;
- int8_t msid;
-
- /* If we don't have any message, just stop processing now. */
- if (!tcpm_has_pending_message(port) ||
- tcpm_dequeue_message(port, pdmsg[port].chk_buf, &header))
- return;
-
- emsg[port].header = header;
- type = PD_HEADER_TYPE(header);
- cnt = PD_HEADER_CNT(header);
- msid = PD_HEADER_ID(header);
- sop = PD_HEADER_GET_SOP(header);
-
- /*
- * Ignore messages sent to the cable from our
- * port partner if we aren't Vconn powered device.
- */
- if (!IS_ENABLED(CONFIG_USB_TYPEC_CTVPD) &&
- !IS_ENABLED(CONFIG_USB_TYPEC_VPD) &&
- PD_HEADER_GET_SOP(header) != PD_MSG_SOP &&
- PD_HEADER_PROLE(header) == PD_PLUG_FROM_DFP_UFP)
- return;
-
- if (cnt == 0 && type == PD_CTRL_SOFT_RESET) {
- int i;
-
- for (i = 0; i < NUM_SOP_STAR_TYPES; i++) {
- /* Clear MessageIdCounter */
- prl_tx[port].msg_id_counter[i] = 0;
- /* Clear stored MessageID value */
- prl_rx[port].msg_id[i] = -1;
- }
-
- /* Inform Policy Engine of Soft Reset */
- pe_got_soft_reset(port);
-
- /* Soft Reset occurred */
- set_state_prl_tx(port, PRL_TX_PHY_LAYER_RESET);
- set_state_rch(port, RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER);
- set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
- }
-
- /*
- * Ignore if this is a duplicate message. Stop processing.
- */
- if (prl_rx[port].msg_id[sop] == msid)
- return;
-
- /*
- * Discard any pending tx message if this is
- * not a ping message
- */
- if (prl_get_rev(port, pdmsg[port].xmit_type) == PD_REV30 &&
- (cnt == 0) && type != PD_CTRL_PING) {
- if (prl_tx_get_state(port) == PRL_TX_SRC_PENDING ||
- prl_tx_get_state(port) == PRL_TX_SNK_PENDING)
- set_state_prl_tx(port, PRL_TX_DISCARD_MESSAGE);
- }
-
- /* Store Message Id */
- prl_rx[port].msg_id[sop] = msid;
-
- /* RTR Chunked Message Router States. */
- /*
- * Received Ping from Protocol Layer
- */
- if (cnt == 0 && type == PD_CTRL_PING) {
- /* NOTE: RTR_PING State embedded here. */
- emsg[port].len = 0;
- pe_message_received(port);
- return;
- }
- /*
- * Message (not Ping) Received from
- * Protocol Layer & Doing Tx Chunks
- */
- else if (tch_get_state(port) != TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE &&
- tch_get_state(port) != TCH_WAIT_FOR_TRANSMISSION_COMPLETE) {
- /* 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);
- }
-
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SM, 0);
-}
-
-/* All necessary Protocol Transmit States (Section 6.11.2.2) */
-static const struct usb_state prl_tx_states[] = {
- [PRL_TX_PHY_LAYER_RESET] = {
- .entry = prl_tx_phy_layer_reset_entry,
- .run = prl_tx_phy_layer_reset_run,
- },
- [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,
- },
- [PRL_TX_SRC_SOURCE_TX] = {
- .entry = prl_tx_src_source_tx_entry,
- .run = prl_tx_src_source_tx_run,
- },
- [PRL_TX_SNK_START_AMS] = {
- .run = prl_tx_snk_start_ams_run,
- },
- [PRL_TX_SRC_PENDING] = {
- .entry = prl_tx_src_pending_entry,
- .run = prl_tx_src_pending_run,
- },
- [PRL_TX_SNK_PENDING] = {
- .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 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,
- },
- [PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE] = {
- .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) */
-static const struct usb_state rch_states[] = {
- [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] = {
- .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,
- },
- [RCH_REPORT_ERROR] = {
- .entry = rch_report_error_entry,
- .run = rch_report_error_run,
- },
-};
-
-/* All necessary Chunked Tx states (Section 6.11.2.1.3) */
-static const struct usb_state tch_states[] = {
- [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] = {
- .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] = {
- .run = tch_sending_chunked_message_run,
- },
- [TCH_WAIT_CHUNK_REQUEST] = {
- .entry = tch_wait_chunk_request_entry,
- .run = tch_wait_chunk_request_run,
- },
- [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,
- },
-};
-
-#ifdef TEST_BUILD
-const struct test_sm_data test_prl_sm_data[] = {
- {
- .base = prl_tx_states,
- .size = ARRAY_SIZE(prl_tx_states),
- },
- {
- .base = prl_hr_states,
- .size = ARRAY_SIZE(prl_hr_states),
- },
- {
- .base = rch_states,
- .size = ARRAY_SIZE(rch_states),
- },
- {
- .base = tch_states,
- .size = ARRAY_SIZE(tch_states),
- },
-};
-const int test_prl_sm_data_size = ARRAY_SIZE(test_prl_sm_data);
-#endif
-
diff --git a/common/usbc/usb_sm.c b/common/usbc/usb_sm.c
deleted file mode 100644
index ba155281be..0000000000
--- a/common/usbc/usb_sm.c
+++ /dev/null
@@ -1,193 +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 "common.h"
-#include "console.h"
-#include "usb_pd.h"
-#include "usb_sm.h"
-#include "util.h"
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USB, format, ## args)
-#else /* CONFIG_COMMON_RUNTIME */
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif
-
-/* Private structure (to this file) used to track state machine context */
-struct internal_ctx {
- usb_state_ptr last_entered;
- uint32_t running : 1;
- uint32_t enter : 1;
- uint32_t exit : 1;
-};
-BUILD_ASSERT(sizeof(struct internal_ctx) ==
- member_size(struct sm_ctx, internal));
-
-/* Gets the first shared parent state between a and b (inclusive) */
-static usb_state_ptr shared_parent_state(usb_state_ptr a, usb_state_ptr b)
-{
- const usb_state_ptr orig_b = b;
-
- /* There are no common ancestors */
- if (b == NULL)
- return NULL;
-
- /* This assumes that both A and B are NULL terminated without cycles */
- while (a != NULL) {
- /* We found a match return */
- if (a == b)
- return a;
-
- /*
- * Otherwise, increment b down the list for comparison until we
- * run out, then increment a and start over on b for comparison
- */
- if (b->parent == NULL) {
- a = a->parent;
- b = orig_b;
- } else {
- b = b->parent;
- }
- }
-
- return NULL;
-}
-
-/*
- * Call all entry functions of parents before children. If set_state is called
- * during one of the entry functions, then do not call any remaining entry
- * functions.
- */
-static void call_entry_functions(const int port,
- struct internal_ctx *const internal,
- const usb_state_ptr stop,
- const usb_state_ptr current)
-{
- if (current == stop)
- return;
-
- call_entry_functions(port, internal, stop, current->parent);
-
- /*
- * If the previous entry function called set_state, then don't enter
- * remaining states.
- */
- if (!internal->enter)
- return;
-
- /* Track the latest state that was entered, so we can exit properly. */
- internal->last_entered = current;
- if (current->entry)
- current->entry(port);
-}
-
-/*
- * Call all exit functions of children before parents. Note set_state is ignored
- * during an exit function.
- */
-static void call_exit_functions(const int port, const usb_state_ptr stop,
- const usb_state_ptr current)
-{
- if (current == stop)
- return;
-
- if (current->exit)
- current->exit(port);
-
- call_exit_functions(port, stop, current->parent);
-}
-
-void set_state(const int port, struct sm_ctx *const ctx,
- const usb_state_ptr new_state)
-{
- struct internal_ctx * const internal = (void *) ctx->internal;
- usb_state_ptr last_state;
- usb_state_ptr shared_parent;
-
- /*
- * It does not make sense to call set_state in an exit phase of a state
- * since we are already in a transition; we would always ignore the
- * intended state to transition into.
- */
- if (internal->exit) {
- CPRINTF("C%d: Ignoring set state to 0x%pP within 0x%pP",
- port, new_state, ctx->current);
- return;
- }
-
- /*
- * Determine the last state that was entered. Normally it is current,
- * but we could have called set_state within an entry phase, so we
- * shouldn't exit any states that weren't fully entered.
- */
- last_state = internal->enter ? internal->last_entered : ctx->current;
-
- /* We don't exit and re-enter shared parent states */
- shared_parent = shared_parent_state(last_state, new_state);
-
- /*
- * Exit all of the non-common states from the last state.
- */
- internal->exit = true;
- call_exit_functions(port, shared_parent, last_state);
- internal->exit = false;
-
- ctx->previous = ctx->current;
- ctx->current = new_state;
-
- /*
- * Enter all new non-common states. last_entered will contain the last
- * state that successfully entered before another set_state was called.
- */
- internal->last_entered = NULL;
- internal->enter = true;
- call_entry_functions(port, internal, shared_parent, ctx->current);
- /*
- * Setting enter to false ensures that all pending entry calls will be
- * skipped (in the case of a parent state calling set_state, which means
- * we should not enter any child states)
- */
- internal->enter = false;
-
- /*
- * If we set_state while we are running a child state, then stop running
- * any remaining parent states.
- */
- internal->running = false;
-}
-
-/*
- * Call all run functions of children before parents. If set_state is called
- * during one of the entry functions, then do not call any remaining entry
- * functions.
- */
-static void call_run_functions(const int port,
- const struct internal_ctx *const internal,
- const usb_state_ptr current)
-{
- if (!current)
- return;
-
- /* If set_state is called during run, don't call remain functions. */
- if (!internal->running)
- return;
-
- if (current->run)
- current->run(port);
-
- call_run_functions(port, internal, current->parent);
-}
-
-void run_state(const int port, struct sm_ctx *const ctx)
-{
- struct internal_ctx * const internal = (void *) ctx->internal;
-
- internal->running = true;
- call_run_functions(port, internal, ctx->current);
- internal->running = false;
-}
-
diff --git a/common/usbc/usb_tc_ctvpd_sm.c b/common/usbc/usb_tc_ctvpd_sm.c
deleted file mode 100644
index 1747a8c0ab..0000000000
--- a/common/usbc/usb_tc_ctvpd_sm.c
+++ /dev/null
@@ -1,1673 +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 "common.h"
-#include "console.h"
-#include "system.h"
-#include "task.h"
-#include "tcpm.h"
-#include "usb_pd.h"
-#include "usb_tc_sm.h"
-#include "vpd_api.h"
-
-/* USB Type-C CTVPD module */
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_HOOK, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_HOOK, format, ## args)
-#else /* CONFIG_COMMON_RUNTIME */
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif
-
-/* Type-C Layer Flags */
-#define TC_FLAGS_VCONN_ON BIT(0)
-
-#define SUPPORT_TIMER_RESET_INIT 0
-#define SUPPORT_TIMER_RESET_REQUEST 1
-#define SUPPORT_TIMER_RESET_COMPLETE 2
-
-/**
- * This is the Type-C Port object that contains information needed to
- * implement a Charge Through VCONN Powered Device.
- */
-static struct type_c {
- /* state machine context */
- struct sm_ctx ctx;
- /* Higher-level power deliver state machines are enabled if true. */
- uint8_t pd_enable;
- /* port flags, see TC_FLAGS_* */
- uint32_t flags;
- /*
- * Time a charge-through port shall wait before it can determine it
- * is attached
- */
- uint64_t cc_debounce;
- /* Time a host port shall wait before it can determine it is attached */
- uint64_t host_cc_debounce;
- /* Time a Sink port shall wait before it can determine it is detached
- * due to the potential for USB PD signaling on CC as described in
- * the state definitions.
- */
- uint64_t pd_debounce;
- /* Maintains state of billboard device */
- int billboard_presented;
- /*
- * Time a port shall wait before it can determine it is
- * re-attached during the try-wait process.
- */
- uint64_t try_wait_debounce;
- /* charge-through support timer */
- uint64_t support_timer;
- /* reset the charge-through support timer */
- uint8_t support_timer_reset;
- /* VPD host port cc state */
- enum pd_cc_states host_cc_state;
- uint8_t ct_cc;
- /* The cc state */
- enum pd_cc_states cc_state;
- uint64_t next_role_swap;
-} tc[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* List of all TypeC-level states */
-enum usb_tc_state {
- /* Normal States */
- TC_DISABLED,
- TC_UNATTACHED_SNK,
- TC_ATTACH_WAIT_SNK,
- TC_ATTACHED_SNK,
- TC_ERROR_RECOVERY,
- TC_TRY_SNK,
- TC_UNATTACHED_SRC,
- TC_ATTACH_WAIT_SRC,
- TC_TRY_WAIT_SRC,
- TC_ATTACHED_SRC,
- TC_CT_TRY_SNK,
- TC_CT_ATTACH_WAIT_UNSUPPORTED,
- TC_CT_ATTACHED_UNSUPPORTED,
- TC_CT_UNATTACHED_UNSUPPORTED,
- TC_CT_UNATTACHED_VPD,
- TC_CT_DISABLED_VPD,
- TC_CT_ATTACHED_VPD,
- TC_CT_ATTACH_WAIT_VPD,
- /* Super States */
- TC_VBUS_CC_ISO,
- TC_HOST_RARD_CT_RD,
- TC_HOST_OPEN_CT_OPEN,
- TC_HOST_RP3_CT_RD,
- TC_HOST_RP3_CT_RPU,
- TC_HOST_RPU_CT_RD,
-};
-
-/* Forward declare the full list of states. This is indexed by usb_tc_state */
-static const struct usb_state tc_states[];
-
-
-#ifdef CONFIG_COMMON_RUNTIME
-/* List of human readable state names for console debugging */
-const char * const tc_state_names[] = {
- [TC_DISABLED] = "Disabled",
- [TC_UNATTACHED_SNK] = "Unattached.SNK",
- [TC_ATTACH_WAIT_SNK] = "AttachWait.SNK",
- [TC_ATTACHED_SNK] = "Attached.SNK",
- [TC_ERROR_RECOVERY] = "ErrorRecovery",
- [TC_TRY_SNK] = "Try.SNK",
- [TC_UNATTACHED_SRC] = "Unattached.SRC",
- [TC_ATTACH_WAIT_SRC] = "AttachWait.SRC",
- [TC_TRY_WAIT_SRC] = "TryWait.SRC",
- [TC_ATTACHED_SRC] = "Attached.SRC",
- [TC_CT_TRY_SNK] = "CTTry.SNK",
- [TC_CT_ATTACH_WAIT_UNSUPPORTED] = "CTAttachWait.Unsupported",
- [TC_CT_ATTACHED_UNSUPPORTED] = "CTAttached.Unsupported",
- [TC_CT_UNATTACHED_UNSUPPORTED] = "CTUnattached.Unsupported",
- [TC_CT_UNATTACHED_VPD] = "CTUnattached.VPD",
- [TC_CT_DISABLED_VPD] = "CTDisabled.VPD",
- [TC_CT_ATTACHED_VPD] = "CTAttached.VPD",
- [TC_CT_ATTACH_WAIT_VPD] = "CTAttachWait.VPD",
-};
-#endif
-
-/* Forward declare private, common functions */
-static void set_state_tc(const int port, enum usb_tc_state new_state);
-
-/* Public TypeC functions */
-
-enum pd_power_role tc_get_power_role(int port)
-{
- /* Vconn power device is always the sink */
- return PD_ROLE_SINK;
-}
-
-enum pd_cable_plug tc_get_cable_plug(int port)
-{
- /* Vconn power device is always the cable */
- return PD_PLUG_FROM_CABLE;
-}
-
-enum pd_data_role tc_get_data_role(int port)
-{
- /* Vconn power device doesn't have a data role, but UFP matches SNK */
- return PD_ROLE_UFP;
-}
-
-/* Note tc_set_power_role and tc_set_data_role are unimplemented */
-
-uint8_t tc_get_polarity(int port)
-{
- /* Does not track polarity */
- return 0;
-}
-
-uint8_t tc_get_pd_enabled(int port)
-{
- return tc[port].pd_enable;
-}
-
-void tc_reset_support_timer(int port)
-{
- tc[port].support_timer_reset |= SUPPORT_TIMER_RESET_REQUEST;
-}
-
-void tc_state_init(int port)
-{
- int res = 0;
-
- res = tc_restart_tcpc(port);
-
- CPRINTS("TCPC p%d init %s", port, res ? "failed" : "ready");
-
- /* Disable if restart failed, otherwise start in default state. */
- set_state_tc(port, res ? TC_DISABLED : TC_UNATTACHED_SNK);
-
- /* Disable pd state machines */
- tc[port].pd_enable = 0;
- tc[port].billboard_presented = 0;
- tc[port].flags = 0;
-}
-
-void tc_event_check(int port, int evt)
-{
- /* Do Nothing */
-}
-
-void tc_run(const int port)
-{
- run_state(port, &tc[port].ctx);
-}
-
-/* Internal Functions */
-
-/* Set the TypeC state machine to a new state. */
-static void set_state_tc(const int port, enum usb_tc_state new_state)
-{
- set_state(port, &tc[port].ctx, &tc_states[new_state]);
-}
-
-/* Get the current TypeC state. */
-test_export_static enum usb_tc_state get_state_tc(const int port)
-{
- return tc[port].ctx.current - &tc_states[0];
-}
-
-/* Get the previous TypeC state. */
-static enum usb_tc_state get_last_state_tc(const int port)
-{
- return tc[port].ctx.previous - &tc_states[0];
-}
-
-test_mockable_static void print_current_state(const int port)
-{
- CPRINTS("C%d: %s", port, tc_state_names[get_state_tc(port)]);
-}
-
-/**
- * Disabled
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Remove the terminations from Host
- * Remove the terminations from Charge-Through
- */
-static void tc_disabled_entry(const int port)
-{
- print_current_state(port);
-}
-
-static void tc_disabled_run(const int port)
-{
- task_wait_event(-1);
-}
-
-static void tc_disabled_exit(const int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_TCPC)) {
- if (tc_restart_tcpc(port) != 0) {
- CPRINTS("TCPC p%d restart failed!", port);
- return;
- }
- }
-
- CPRINTS("TCPC p%d resumed!", port);
-}
-
-/**
- * ErrorRecovery
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Remove the terminations from Host
- * Remove the terminations from Charge-Through
- */
-static void tc_error_recovery_entry(const int port)
-{
- print_current_state(port);
- /* Use cc_debounce state variable for error recovery timeout */
- tc[port].cc_debounce = get_time().val + PD_T_ERROR_RECOVERY;
-}
-
-static void tc_error_recovery_run(const int port)
-{
- if (get_time().val > tc[port].cc_debounce)
- set_state_tc(port, TC_UNATTACHED_SNK);
-}
-
-/**
- * Unattached.SNK
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place Ra on VCONN and Rd on Host CC
- * Place Rd on Charge-Through CCs
- */
-static void tc_unattached_snk_entry(const int port)
-{
- if (get_last_state_tc(port) != TC_UNATTACHED_SRC)
- print_current_state(port);
-
- tc[port].flags &= ~TC_FLAGS_VCONN_ON;
- tc[port].cc_state = PD_CC_UNSET;
-}
-
-static void tc_unattached_snk_run(const int port)
-{
- int host_cc;
- int new_cc_state;
- int cc1;
- int cc2;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- /*
- * Transition to AttachWait.SNK when a Source connection is
- * detected, as indicated by the SNK.Rp state on its Host-side
- * port’s CC pin.
- */
- if (cc_is_rp(host_cc)) {
- set_state_tc(port, TC_ATTACH_WAIT_SNK);
- return;
- }
-
- /* Check Charge-Through CCs for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (cc_is_rp(cc1) != cc_is_rp(cc2))
- new_cc_state = PD_CC_DFP_ATTACHED;
- else
- new_cc_state = PD_CC_NONE;
-
- /* Debounce Charge-Through CC state */
- if (tc[port].cc_state != new_cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE;
- }
-
- /* If we are here, Host CC must be open */
-
- /* Wait for Charge-Through CC debounce */
- if (get_time().val < tc[port].cc_debounce)
- return;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Unattached.SRC when the state of the Host-side port’s CC pin is
- * SNK.Open for tDRP − dcSRC.DRP ∙ tDRP and both of the following
- * is detected on the Charge-Through port.
- * 1) SNK.Rp state is detected on exactly one of the CC1 or CC2
- * pins for at least tCCDebounce
- * 2) VBUS is detected
- */
- if (vpd_is_ct_vbus_present() &&
- tc[port].cc_state == PD_CC_DFP_ATTACHED) {
- set_state_tc(port, TC_UNATTACHED_SRC);
- return;
- }
-}
-
-/**
- * AttachWait.SNK
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place Ra on VCONN and Rd on Host CC
- * Place Rd on Charge-Through CCs
- */
-static void tc_attach_wait_snk_entry(const int port)
-{
- print_current_state(port);
- tc[port].host_cc_state = PD_CC_UNSET;
-}
-
-static void tc_attach_wait_snk_run(const int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (cc_is_rp(host_cc))
- host_new_cc_state = PD_CC_DFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- if (host_new_cc_state == PD_CC_DFP_ATTACHED)
- tc[port].host_cc_debounce = get_time().val +
- PD_T_CC_DEBOUNCE;
- else
- tc[port].host_cc_debounce = get_time().val +
- PD_T_PD_DEBOUNCE;
- return;
- }
-
- /* Wait for Host CC debounce */
- if (get_time().val < tc[port].host_cc_debounce)
- return;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Attached.SNK after the state of the Host-side port’s CC pin is
- * SNK.Rp for at least tCCDebounce and either host-side VCONN or
- * VBUS is detected.
- *
- * Transition to Unattached.SNK when the state of both the CC1 and
- * CC2 pins is SNK.Open for at least tPDDebounce.
- */
- if (tc[port].host_cc_state == PD_CC_DFP_ATTACHED &&
- (vpd_is_vconn_present() || vpd_is_host_vbus_present()))
- set_state_tc(port, TC_ATTACHED_SNK);
- else if (tc[port].host_cc_state == PD_CC_NONE)
- set_state_tc(port, TC_UNATTACHED_SNK);
-}
-
-/**
- * Attached.SNK
- */
-static void tc_attached_snk_entry(const int port)
-{
- print_current_state(port);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- set_polarity(port, 0);
-
- /*
- * This state can only be entered from states AttachWait.SNK
- * and Try.SNK. So the Host port is isolated from the
- * Charge-Through port. We only need to High-Z the
- * Charge-Through ports CC1 and CC2 pins.
- */
- vpd_ct_set_pull(TYPEC_CC_OPEN, 0);
-
- tc[port].host_cc_state = PD_CC_UNSET;
-
- /* Start Charge-Through support timer */
- tc[port].support_timer_reset = SUPPORT_TIMER_RESET_INIT;
- tc[port].support_timer = get_time().val + PD_T_AME;
-}
-
-static void tc_attached_snk_run(const int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /* Has host vbus and vconn been removed */
- if (!vpd_is_host_vbus_present() && !vpd_is_vconn_present()) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /*
- * Reset the Charge-Through Support Timer when it first
- * receives any USB PD Structured VDM Command it supports,
- * which is the Discover Identity command. And this is only
- * done one time.
- */
- if (tc[port].support_timer_reset == SUPPORT_TIMER_RESET_REQUEST) {
- tc[port].support_timer_reset |= SUPPORT_TIMER_RESET_COMPLETE;
- tc[port].support_timer = get_time().val + PD_T_AME;
- }
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (cc_is_rp(host_cc))
- host_new_cc_state = PD_CC_DFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- tc[port].host_cc_debounce = get_time().val + PD_T_VPDCTDD;
- return;
- }
-
- /* Wait for Host CC debounce */
- if (get_time().val < tc[port].host_cc_debounce)
- return;
-
- if (vpd_is_vconn_present()) {
- if (!(tc[port].flags & TC_FLAGS_VCONN_ON)) {
- /* VCONN detected. Remove RA */
- vpd_host_set_pull(TYPEC_CC_RD, 0);
- tc[port].flags |= TC_FLAGS_VCONN_ON;
- }
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to CTUnattached.VPD if VCONN is present and the state of
- * its Host-side port’s CC pin is SNK.Open for tVPDCTDD.
- */
- if (tc[port].host_cc_state == PD_CC_NONE) {
- set_state_tc(port, TC_CT_UNATTACHED_VPD);
- return;
- }
- }
-
- /* Check the Support Timer */
- if (get_time().val > tc[port].support_timer &&
- !tc[port].billboard_presented) {
- /*
- * Present USB Billboard Device Class interface
- * indicating that Charge-Through is not supported
- */
- tc[port].billboard_presented = 1;
- vpd_present_billboard(BB_SNK);
- }
-}
-
-static void tc_attached_snk_exit(const int port)
-{
- tc[port].billboard_presented = 0;
- vpd_present_billboard(BB_NONE);
-}
-
-/**
- * Super State HOST_RA_CT_RD
- */
-static void tc_host_rard_ct_rd_entry(const int port)
-{
- /* Place Ra on VCONN and Rd on Host CC */
- vpd_host_set_pull(TYPEC_CC_RA_RD, 0);
-
- /* Place Rd on Charge-Through CCs */
- vpd_ct_set_pull(TYPEC_CC_RD, 0);
-}
-
-/**
- * Super State HOST_OPEN_CT_OPEN
- */
-static void tc_host_open_ct_open_entry(const int port)
-{
- /* Remove the terminations from Host */
- vpd_host_set_pull(TYPEC_CC_OPEN, 0);
-
- /* Remove the terminations from Charge-Through */
- vpd_ct_set_pull(TYPEC_CC_OPEN, 0);
-}
-
-/**
- * Super State VBUS_CC_ISO
- */
-static void tc_vbus_cc_iso_entry(const int port)
-{
- /* Isolate the Host-side port from the Charge-Through port */
- vpd_vbus_pass_en(0);
-
- /* Remove Charge-Through side port CCs */
- vpd_ct_cc_sel(CT_OPEN);
-
- /* Enable mcu communication and cc */
- vpd_mcu_cc_en(1);
-}
-
-/**
- * Unattached.SRC
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RpUSB on Host CC
- * Place Rd on Charge-Through CCs
- */
-static void tc_unattached_src_entry(const int port)
-{
- if (get_last_state_tc(port) != TC_UNATTACHED_SNK)
- print_current_state(port);
-
- /* Get power from VBUS */
- vpd_vconn_pwr_sel_odl(PWR_VBUS);
-
- /* Make sure it's the Charge-Through Port's VBUS */
- if (!vpd_is_ct_vbus_present()) {
- set_state_tc(port, TC_ERROR_RECOVERY);
- return;
- }
-
- tc[port].next_role_swap = get_time().val + PD_T_DRP_SRC;
-}
-
-static void tc_unattached_src_run(const int port)
-{
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- /*
- * Transition to AttachWait.SRC when host-side VBUS is
- * vSafe0V and SRC.Rd state is detected on the Host-side
- * port’s CC pin.
- */
- if (!vpd_is_host_vbus_present() && host_cc == TYPEC_CC_VOLT_RD) {
- set_state_tc(port, TC_ATTACH_WAIT_SRC);
- return;
- }
-
- /*
- * Transition to Unattached.SNK within tDRPTransition or
- * if Charge-Through VBUS is removed.
- */
- if (!vpd_is_ct_vbus_present() ||
- get_time().val > tc[port].next_role_swap) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-}
-
-/**
- * AttachWait.SRC
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RpUSB on Host CC
- * Place Rd on Charge-Through CCs
- */
-static void tc_attach_wait_src_entry(const int port)
-{
- print_current_state(port);
-
- tc[port].host_cc_state = PD_CC_UNSET;
-}
-
-static void tc_attach_wait_src_run(const int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (host_cc == TYPEC_CC_VOLT_RD)
- host_new_cc_state = PD_CC_UFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to Unattached.SNK when the SRC.Open state is detected on the
- * Host-side port’s CC or if Charge-Through VBUS falls below
- * vSinkDisconnect. The Charge-Through VCONN-Powered USB Device
- * shall detect the SRC.Open state within tSRCDisconnect, but
- * should detect it as quickly as possible.
- */
- if (host_new_cc_state == PD_CC_NONE || !vpd_is_ct_vbus_present()) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE;
- return;
- }
-
- /* Wait for Host CC debounce */
- if (get_time().val < tc[port].cc_debounce)
- return;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Try.SNK when the host-side VBUS is at vSafe0V and the SRC.Rd
- * state is on the Host-side port’s CC pin for at least tCCDebounce.
- */
- if (tc[port].host_cc_state == PD_CC_UFP_ATTACHED &&
- !vpd_is_host_vbus_present()) {
- set_state_tc(port, TC_TRY_SNK);
- return;
- }
-}
-
-/**
- * Attached.SRC
- */
-static void tc_attached_src_entry(const int port)
-{
- print_current_state(port);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- set_polarity(port, 0);
-
- /* Connect Charge-Through VBUS to Host VBUS */
- vpd_vbus_pass_en(1);
-
- /*
- * Get power from VBUS. No need to test because
- * the Host VBUS is connected to the Charge-Through
- * VBUS
- */
- vpd_vconn_pwr_sel_odl(PWR_VBUS);
-}
-
-static void tc_attached_src_run(const int port)
-{
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Unattached.SNK when VBUS falls below vSinkDisconnect or the
- * Host-side port’s CC pin is SRC.Open. The Charge-Through
- * VCONNPowered USB Device shall detect the SRC.Open state within
- * tSRCDisconnect, but should detect it as quickly as possible.
- */
- if (!vpd_is_ct_vbus_present() || host_cc == TYPEC_CC_VOLT_OPEN)
- set_state_tc(port, TC_UNATTACHED_SNK);
-}
-
-/**
- * Super State HOST_RPU_CT_RD
- */
-static void tc_host_rpu_ct_rd_entry(const int port)
-{
- /* Place RpUSB on Host CC */
- vpd_host_set_pull(TYPEC_CC_RP, TYPEC_RP_USB);
-
- /* Place Rd on Charge-Through CCs */
- vpd_ct_set_pull(TYPEC_CC_RD, 0);
-}
-
-/**
- * Try.SNK
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place Ra on VCONN and Rd on Host CC
- * Place Rd on Charge-Through CCs
- */
-static void tc_try_snk_entry(const int port)
-{
- print_current_state(port);
-
- /* Get power from VBUS */
- vpd_vconn_pwr_sel_odl(PWR_VBUS);
-
- /* Make sure it's the Charge-Through Port's VBUS */
- if (!vpd_is_ct_vbus_present()) {
- set_state_tc(port, TC_ERROR_RECOVERY);
- return;
- }
-
- tc[port].host_cc_state = PD_CC_UNSET;
-
- /* Using next_role_swap timer as try_src timer */
- tc[port].next_role_swap = get_time().val + PD_T_DRP_TRY;
-}
-
-static void tc_try_snk_run(const int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /*
- * Wait for tDRPTry before monitoring the Charge-Through
- * port’s CC pins for the SNK.Rp
- */
- if (get_time().val < tc[port].next_role_swap)
- return;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (cc_is_rp(host_cc))
- host_new_cc_state = PD_CC_DFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_DEBOUNCE;
- return;
- }
-
- /* Wait for Host CC debounce */
- if (get_time().val < tc[port].cc_debounce)
- return;
-
- /*
- * The Charge-Through VCONN-Powered USB Device shall then transition to
- * Attached.SNK when the SNK.Rp state is detected on the Host-side
- * port’s CC pin for at least tTryCCDebounce and VBUS or VCONN is
- * detected on Host-side port.
- *
- * Alternatively, the Charge-Through VCONN-Powered USB Device shall
- * transition to TryWait.SRC if Host-side SNK.Rp state is not detected
- * for tTryCCDebounce.
- */
- if (tc[port].host_cc_state == PD_CC_DFP_ATTACHED &&
- (vpd_is_host_vbus_present() || vpd_is_vconn_present()))
- set_state_tc(port, TC_ATTACHED_SNK);
- else if (tc[port].host_cc_state == PD_CC_NONE)
- set_state_tc(port, TC_TRY_WAIT_SRC);
-}
-
-/**
- * TryWait.SRC
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RpUSB on Host CC
- * Place Rd on Charge-Through CCs
- */
-static void tc_try_wait_src_entry(const int port)
-{
- print_current_state(port);
-
- tc[port].host_cc_state = PD_CC_UNSET;
- tc[port].next_role_swap = get_time().val + PD_T_DRP_TRY;
-}
-
-static void tc_try_wait_src_run(const int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (host_cc == TYPEC_CC_VOLT_RD)
- host_new_cc_state = PD_CC_UFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- tc[port].host_cc_debounce =
- get_time().val + PD_T_TRY_CC_DEBOUNCE;
- return;
- }
-
- if (get_time().val > tc[port].host_cc_debounce) {
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to Attached.SRC when host-side VBUS is at vSafe0V and the
- * SRC.Rd state is detected on the Host-side port’s CC pin for
- * at least tTryCCDebounce.
- */
- if (tc[port].host_cc_state == PD_CC_UFP_ATTACHED &&
- !vpd_is_host_vbus_present()) {
- set_state_tc(port, TC_ATTACHED_SRC);
- return;
- }
- }
-
- if (get_time().val > tc[port].next_role_swap) {
- /*
- * The Charge-Through VCONN-Powered USB Device shall transition
- * to Unattached.SNK after tDRPTry if the Host-side port’s CC
- * pin is not in the SRC.Rd state.
- */
- if (tc[port].host_cc_state == PD_CC_NONE) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
- }
-}
-
-/**
- * CTTry.SNK
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Connect Charge-Through Rd
- * Get power from VCONN
- */
-static void tc_ct_try_snk_entry(const int port)
-{
- print_current_state(port);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- set_polarity(port, 0);
-
- tc[port].cc_state = PD_CC_UNSET;
- tc[port].next_role_swap = get_time().val + PD_T_DRP_TRY;
-}
-
-static void tc_ct_try_snk_run(const int port)
-{
- int new_cc_state;
- int cc1;
- int cc2;
-
- /*
- * Wait for tDRPTry before monitoring the Charge-Through
- * port’s CC pins for the SNK.Rp
- */
- if (get_time().val < tc[port].next_role_swap)
- return;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (cc_is_rp(cc1) || cc_is_rp(cc2))
- new_cc_state = PD_CC_DFP_ATTACHED;
- else
- new_cc_state = PD_CC_NONE;
-
- /*
- * The Charge-Through VCONN-Powered USB Device shall transition
- * to Unattached.SNK if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /* Debounce the CT CC state */
- if (tc[port].cc_state != new_cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_DEBOUNCE;
- tc[port].try_wait_debounce = get_time().val + PD_T_TRY_WAIT;
-
- return;
- }
-
- if (get_time().val > tc[port].cc_debounce) {
- /*
- * The Charge-Through VCONN-Powered USB Device shall then
- * transition to CTAttached.VPD when the SNK.Rp state is
- * detected on the Charge-Through port’s CC pins for at
- * least tTryCCDebounce and VBUS is detected on
- * Charge-Through port.
- */
- if (tc[port].cc_state == PD_CC_DFP_ATTACHED &&
- vpd_is_ct_vbus_present()) {
- set_state_tc(port, TC_CT_ATTACHED_VPD);
- return;
- }
- }
-
- if (get_time().val > tc[port].try_wait_debounce) {
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to CTAttached.Unsupported if SNK.Rp state is not detected
- * for tDRPTryWait.
- */
- if (tc[port].cc_state == PD_CC_NONE) {
- set_state_tc(port,
- TC_CT_ATTACHED_UNSUPPORTED);
- return;
- }
- }
-}
-
-static void tc_ct_try_snk_exit(const int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
-}
-
-/**
- * CTAttachWait.Unsupported
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Place RPUSB on Charge-Through CC
- * Get power from VCONN
- */
-static void tc_ct_attach_wait_unsupported_entry(const int port)
-{
- print_current_state(port);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- set_polarity(port, 0);
-
- tc[port].cc_state = PD_CC_UNSET;
-}
-
-static void tc_ct_attach_wait_unsupported_run(const int port)
-{
- int new_cc_state;
- int cc1;
- int cc2;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (cc_is_at_least_one_rd(cc1, cc2))
- new_cc_state = PD_CC_UFP_ATTACHED;
- else if (cc_is_audio_acc(cc1, cc2))
- new_cc_state = PD_CC_UFP_AUDIO_ACC;
- else /* (cc1 == TYPEC_CC_VOLT_OPEN or cc2 == TYPEC_CC_VOLT_OPEN */
- new_cc_state = PD_CC_NONE;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Unattached.SNK if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /* Debounce the cc state */
- if (tc[port].cc_state != new_cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE;
- return;
- }
-
- /* Wait for CC debounce */
- if (get_time().val < tc[port].cc_debounce)
- return;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTUnattached.VPD when the state of either the Charge-Through
- * Port’s CC1 or CC2 pin is SRC.Open for at least tCCDebounce.
- *
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTTry.SNK if the state of at least one of the Charge-Through
- * port’s CC pins is SRC.Rd, or if the state of both the CC1 and CC2
- * pins is SRC.Ra. for at least tCCDebounce.
- */
- if (new_cc_state == PD_CC_NONE)
- set_state_tc(port, TC_CT_UNATTACHED_VPD);
- else /* PD_CC_UFP_ATTACHED or PD_CC_UFP_AUDIO_ACC */
- set_state_tc(port, TC_CT_TRY_SNK);
-}
-
-static void tc_ct_attach_wait_unsupported_exit(const int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
-}
-
-/**
- * CTAttached.Unsupported
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Place RPUSB on Charge-Through CC
- * Get power from VCONN
- */
-static void tc_ct_attached_unsupported_entry(const int port)
-{
- print_current_state(port);
-
- /* Present Billboard device */
- vpd_present_billboard(BB_SNK);
-}
-
-static void tc_ct_attached_unsupported_run(const int port)
-{
- int cc1;
- int cc2;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (!vpd_is_vconn_present()) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /*
- * The Charge-Through VCONN-Powered USB Device shall transition to
- * CTUnattached.VPD when SRC.Open state is detected on both the
- * Charge-Through port’s CC pins or the SRC.Open state is detected
- * on one CC pin and SRC.Ra is detected on the other CC pin.
- */
- if ((cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_OPEN) ||
- (cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_RA) ||
- (cc1 == TYPEC_CC_VOLT_RA && cc2 == TYPEC_CC_VOLT_OPEN)) {
- set_state_tc(port, TC_CT_UNATTACHED_VPD);
- return;
- }
-}
-
-static void tc_ct_attached_unsupported_exit(const int port)
-{
- vpd_present_billboard(BB_NONE);
-}
-
-/**
- * CTUnattached.Unsupported
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Place RPUSB on Charge-Through CC
- * Get power from VCONN
- */
-static void tc_ct_unattached_unsupported_entry(const int port)
-{
- if (get_last_state_tc(port) != TC_CT_UNATTACHED_VPD)
- print_current_state(port);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- set_polarity(port, 0);
-
- tc[port].next_role_swap = get_time().val + PD_T_DRP_SRC;
-}
-
-static void tc_ct_unattached_unsupported_run(const int port)
-{
- int cc1;
- int cc2;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTAttachWait.Unsupported when a Sink connection is detected on
- * the Charge-Through port, as indicated by the SRC.Rd state on at
- * least one of the Charge-Through port’s CC pins or SRC.Ra state
- * on both the CC1 and CC2 pins.
- */
- if (cc_is_at_least_one_rd(cc1, cc2) || cc_is_audio_acc(cc1, cc2)) {
- set_state_tc(port,
- TC_CT_ATTACH_WAIT_UNSUPPORTED);
- return;
- }
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Unattached.SNK if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTUnattached.VPD within tDRPTransition after dcSRC.DRP ∙ tDRP.
- */
- if (get_time().val > tc[port].next_role_swap) {
- set_state_tc(port, TC_CT_UNATTACHED_VPD);
- return;
- }
-}
-
-static void tc_ct_unattached_unsupported_exit(const int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
-}
-
-/**
- * CTUnattached.VPD
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Connect Charge-Through Rd
- * Get power from VCONN
- */
-static void tc_ct_unattached_vpd_entry(const int port)
-{
- if (get_last_state_tc(port) != TC_CT_UNATTACHED_UNSUPPORTED)
- print_current_state(port);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- set_polarity(port, 0);
-
- tc[port].cc_state = PD_CC_UNSET;
-}
-
-static void tc_ct_unattached_vpd_run(const int port)
-{
- int new_cc_state;
- int cc1;
- int cc2;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (cc_is_rp(cc1) != cc_is_rp(cc2))
- new_cc_state = PD_CC_DFP_ATTACHED;
- else if (!cc_is_rp(cc1) && !cc_is_rp(cc2))
- new_cc_state = PD_CC_NONE;
- else
- new_cc_state = PD_CC_UNSET;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTAttachWait.VPD when a Source connection is detected on the
- * Charge-Through port, as indicated by the SNK.Rp state on
- * exactly one of the Charge-Through port’s CC pins.
- */
- if (new_cc_state == PD_CC_DFP_ATTACHED) {
- set_state_tc(port, TC_CT_ATTACH_WAIT_VPD);
- return;
- }
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Unattached.SNK if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_DRP_SRC;
- return;
- }
-
- if (get_time().val < tc[port].cc_debounce)
- return;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTUnattached.Unsupported within tDRPTransition after the state
- * of both the Charge-Through port’s CC1 and CC2 pins is SNK.Open
- * for tDRP-dcSRC.DRP ∙ tDRP, or if directed.
- */
- if (tc[port].cc_state == PD_CC_NONE) {
- set_state_tc(port, TC_CT_UNATTACHED_UNSUPPORTED);
- return;
- }
-}
-
-static void tc_ct_unattached_vpd_exit(const int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
-}
-
-/**
- * CTDisabled.VPD
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Remove the terminations from Host
- * Remove the terminations from Charge-Through
- */
-static void tc_ct_disabled_vpd_entry(const int port)
-{
- print_current_state(port);
-
- /* Get power from VBUS */
- vpd_vconn_pwr_sel_odl(PWR_VBUS);
-
- tc[port].next_role_swap = get_time().val + PD_T_VPDDISABLE;
-}
-
-static void tc_ct_disabled_vpd_run(const int port)
-{
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to Unattached.SNK after tVPDDisable.
- */
- if (get_time().val > tc[port].next_role_swap)
- set_state_tc(port, TC_UNATTACHED_SNK);
-}
-
-/**
- * CTAttached.VPD
- */
-static void tc_ct_attached_vpd_entry(const int port)
-{
- int cc1;
- int cc2;
- print_current_state(port);
-
- /* Get power from VCONN */
- vpd_vconn_pwr_sel_odl(PWR_VCONN);
-
- /*
- * Detect which of the Charge-Through port’s CC1 or CC2
- * pins is connected through the cable
- */
- vpd_ct_get_cc(&cc1, &cc2);
- tc[port].ct_cc = cc_is_rp(cc2) ? CT_CC2 : CT_CC1;
-
- /*
- * 1. Remove or reduce any additional capacitance on the
- * Host-side CC port
- */
- vpd_mcu_cc_en(0);
-
- /*
- * 2. Disable the Rp termination advertising 3.0 A on the
- * host port’s CC pin
- */
- vpd_host_set_pull(TYPEC_CC_OPEN, 0);
-
- /*
- * 3. Passively multiplex the detected Charge-Through port’s
- * CC pin through to the host port’s CC
- */
- vpd_ct_cc_sel(tc[port].ct_cc);
-
- /*
- * 4. Disable the Rd on the Charge-Through port’s CC1 and CC2
- * pins
- */
- vpd_ct_set_pull(TYPEC_CC_OPEN, 0);
-
- /*
- * 5. Connect the Charge-Through port’s VBUS through to the
- * host port’s VBUS
- */
- vpd_vbus_pass_en(1);
-
- tc[port].cc_state = PD_CC_UNSET;
-}
-
-static void tc_ct_attached_vpd_run(const int port)
-{
- int new_cc_state;
- int cc1;
- int cc2;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTDisabled.VPD if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state_tc(port, TC_CT_DISABLED_VPD);
- return;
- }
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
- if ((tc[port].ct_cc ? cc2 : cc1) == TYPEC_CC_VOLT_OPEN)
- new_cc_state = PD_CC_NONE;
- else
- new_cc_state = PD_CC_DFP_ATTACHED;
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_VPDCTDD;
- return;
- }
-
- if (get_time().val < tc[port].pd_debounce)
- return;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTUnattached.VPD when VBUS falls below vSinkDisconnect and the
- * state of the passed-through CC pin is SNK.Open for tVPDCTDD.
- */
- if (tc[port].cc_state == PD_CC_NONE && !vpd_is_ct_vbus_present())
- set_state_tc(port, TC_CT_UNATTACHED_VPD);
-}
-
-/**
- * CTAttachWait.VPD
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Connect Charge-Through Rd
- * Get power from VCONN
- */
-static void tc_ct_attach_wait_vpd_entry(const int port)
-{
- print_current_state(port);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- set_polarity(port, 0);
-
- tc[port].cc_state = PD_CC_UNSET;
-}
-
-static void tc_ct_attach_wait_vpd_run(const int port)
-{
- int new_cc_state;
- int cc1;
- int cc2;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (cc_is_rp(cc1) != cc_is_rp(cc2))
- new_cc_state = PD_CC_DFP_ATTACHED;
- else if (!cc_is_rp(cc1) && !cc_is_rp(cc2))
- new_cc_state = PD_CC_NONE;
- else
- new_cc_state = PD_CC_UNSET;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTDisabled.VPD if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state_tc(port, TC_CT_DISABLED_VPD);
- return;
- }
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val +
- PD_T_CC_DEBOUNCE;
- tc[port].pd_debounce = get_time().val +
- PD_T_PD_DEBOUNCE;
- return;
- }
-
- if (get_time().val > tc[port].pd_debounce) {
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to CTUnattached.VPD when the state of both the Charge-Through
- * port’s CC1 and CC2 pins are SNK.Open for at least
- * tPDDebounce.
- */
- if (tc[port].cc_state == PD_CC_NONE) {
- set_state_tc(port, TC_CT_UNATTACHED_VPD);
- return;
- }
- }
-
- if (get_time().val > tc[port].cc_debounce) {
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTAttached.VPD after the state of only one of the
- * Charge-Through port’s CC1 or CC2 pins is SNK.Rp for at
- * least tCCDebounce and VBUS on the Charge-Through port is
- * detected.
- */
- if (tc[port].cc_state == PD_CC_DFP_ATTACHED &&
- vpd_is_ct_vbus_present()) {
- set_state_tc(port, TC_CT_ATTACHED_VPD);
- return;
- }
- }
-}
-
-static void tc_ct_attach_wait_vpd_exit(const int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
-}
-
-/**
- * Super State HOST_RP3_CT_RD
- */
-static void tc_host_rp3_ct_rd_entry(const int port)
-{
- /* Place RP3A0 on Host CC */
- vpd_host_set_pull(TYPEC_CC_RP, TYPEC_RP_3A0);
-
- /* Connect Charge-Through Rd */
- vpd_ct_set_pull(TYPEC_CC_RD, 0);
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall
- * ensure that it is powered by VCONN
- */
-
- /* Make sure vconn is on */
- if (!vpd_is_vconn_present())
- set_state_tc(port, TC_ERROR_RECOVERY);
-
- /* Get power from VCONN */
- vpd_vconn_pwr_sel_odl(PWR_VCONN);
-}
-
-/**
- * Super State HOST_RP3_CT_RPU
- */
-static void tc_host_rp3_ct_rpu_entry(const int port)
-{
- /* Place RP3A0 on Host CC */
- vpd_host_set_pull(TYPEC_CC_RP, TYPEC_RP_3A0);
-
- /* Place RPUSB on Charge-Through CC */
- vpd_ct_set_pull(TYPEC_CC_RP, TYPEC_RP_USB);
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall
- * ensure that it is powered by VCONN
- */
-
- /* Make sure vconn is on */
- if (!vpd_is_vconn_present())
- set_state_tc(port, TC_ERROR_RECOVERY);
-
- /* Get power from VCONN */
- vpd_vconn_pwr_sel_odl(PWR_VCONN);
-}
-
-/* All necessary Type-C states */
-
-/*
- * Type-C State Hierarchy (Sub-States are listed inside the boxes)
- *
- * | TC_VBUS_CC_ISO ------------------------------------------------------|
- * | |
- * | | TC_HOST_RARD_CT_RD -----------| | TC_HOST_OPEN_CT_OPEN ---------| |
- * | | | | | |
- * | | TC_UNATTACHED_SNK | | TC_DISABLED | |
- * | | TC_ATTACH_WAIT_SNK | | TC_ERROR_RECOVERY | |
- * | | TC_TRY_SNK | |-------------------------------| |
- * | |-------------------------------| |
- * | |
- * | | TC_HOST_RP3_CT_RD ------------| | TC_HOST_RPU_CT_RD ------------| |
- * | | | | | |
- * | | TC_CT_TRY_SNK | | TC_UNATTACHED_SRC | |
- * | | TC_CT_UNATTACHED_VPD | | TC_ATTACH_WAIT_SRC | |
- * | | TC_CT_ATTACH_WAIT_VPD | | TC_TRY_WAIT_SR | |
- * | |-------------------------------| |-------------------------------| |
- * | |
- * | | TC_HOST_RP3_CT_RPU -----------| |
- * | | | |
- * | | TC_CT_ATTACH_WAIT_UNSUPPORTED | |
- * | | TC_CT_ATTACHED_UNSUPPORTED | |
- * | | TC_CT_UNATTACHED_UNSUPPORTED | |
- * | |-------------------------------| |
- * |----------------------------------------------------------------------|
- *
- * TC_ATTACHED_SNK
- * TC_ATTACHED_SRC
- * TC_CT_ATTACHED_VPD
- *
- */
-static const struct usb_state tc_states[] = {
- /* Super States */
- [TC_VBUS_CC_ISO] = {
- .entry = tc_vbus_cc_iso_entry,
- },
- [TC_HOST_RARD_CT_RD] = {
- .entry = tc_host_rard_ct_rd_entry,
- .parent = &tc_states[TC_VBUS_CC_ISO],
- },
- [TC_HOST_OPEN_CT_OPEN] = {
- .entry = tc_host_open_ct_open_entry,
- .parent = &tc_states[TC_VBUS_CC_ISO],
- },
- [TC_HOST_RP3_CT_RD] = {
- .entry = tc_host_rp3_ct_rd_entry,
- .parent = &tc_states[TC_VBUS_CC_ISO],
- },
- [TC_HOST_RP3_CT_RPU] = {
- .entry = tc_host_rp3_ct_rpu_entry,
- .parent = &tc_states[TC_VBUS_CC_ISO],
- },
- [TC_HOST_RPU_CT_RD] = {
- .entry = tc_host_rpu_ct_rd_entry,
- .parent = &tc_states[TC_VBUS_CC_ISO],
- },
- /* Normal States */
- [TC_DISABLED] = {
- .entry = tc_disabled_entry,
- .run = tc_disabled_run,
- .exit = tc_disabled_exit,
- .parent = &tc_states[TC_HOST_OPEN_CT_OPEN],
- },
- [TC_UNATTACHED_SNK] = {
- .entry = tc_unattached_snk_entry,
- .run = tc_unattached_snk_run,
- .parent = &tc_states[TC_HOST_RARD_CT_RD],
- },
- [TC_ATTACH_WAIT_SNK] = {
- .entry = tc_attach_wait_snk_entry,
- .run = tc_attach_wait_snk_run,
- .parent = &tc_states[TC_HOST_RARD_CT_RD],
- },
- [TC_ATTACHED_SNK] = {
- .entry = tc_attached_snk_entry,
- .run = tc_attached_snk_run,
- .exit = tc_attached_snk_exit,
- },
- [TC_ERROR_RECOVERY] = {
- .entry = tc_error_recovery_entry,
- .run = tc_error_recovery_run,
- .parent = &tc_states[TC_HOST_OPEN_CT_OPEN],
- },
- [TC_TRY_SNK] = {
- .entry = tc_try_snk_entry,
- .run = tc_try_snk_run,
- .parent = &tc_states[TC_HOST_RARD_CT_RD],
- },
- [TC_UNATTACHED_SRC] = {
- .entry = tc_unattached_src_entry,
- .run = tc_unattached_src_run,
- .parent = &tc_states[TC_HOST_RPU_CT_RD],
- },
- [TC_ATTACH_WAIT_SRC] = {
- .entry = tc_attach_wait_src_entry,
- .run = tc_attach_wait_src_run,
- .parent = &tc_states[TC_HOST_RPU_CT_RD],
- },
- [TC_TRY_WAIT_SRC] = {
- .entry = tc_try_wait_src_entry,
- .run = tc_try_wait_src_run,
- .parent = &tc_states[TC_HOST_RPU_CT_RD],
- },
- [TC_ATTACHED_SRC] = {
- .entry = tc_attached_src_entry,
- .run = tc_attached_src_run,
- },
- [TC_CT_TRY_SNK] = {
- .entry = tc_ct_try_snk_entry,
- .run = tc_ct_try_snk_run,
- .exit = tc_ct_try_snk_exit,
- .parent = &tc_states[TC_HOST_RP3_CT_RD],
- },
- [TC_CT_ATTACH_WAIT_UNSUPPORTED] = {
- .entry = tc_ct_attach_wait_unsupported_entry,
- .run = tc_ct_attach_wait_unsupported_run,
- .exit = tc_ct_attach_wait_unsupported_exit,
- .parent = &tc_states[TC_HOST_RP3_CT_RPU],
- },
- [TC_CT_ATTACHED_UNSUPPORTED] = {
- .entry = tc_ct_attached_unsupported_entry,
- .run = tc_ct_attached_unsupported_run,
- .exit = tc_ct_attached_unsupported_exit,
- .parent = &tc_states[TC_HOST_RP3_CT_RPU],
- },
- [TC_CT_UNATTACHED_UNSUPPORTED] = {
- .entry = tc_ct_unattached_unsupported_entry,
- .run = tc_ct_unattached_unsupported_run,
- .exit = tc_ct_unattached_unsupported_exit,
- .parent = &tc_states[TC_HOST_RP3_CT_RPU],
- },
- [TC_CT_UNATTACHED_VPD] = {
- .entry = tc_ct_unattached_vpd_entry,
- .run = tc_ct_unattached_vpd_run,
- .exit = tc_ct_unattached_vpd_exit,
- .parent = &tc_states[TC_HOST_RP3_CT_RD],
- },
- [TC_CT_DISABLED_VPD] = {
- .entry = tc_ct_disabled_vpd_entry,
- .run = tc_ct_disabled_vpd_run,
- .parent = &tc_states[TC_HOST_OPEN_CT_OPEN],
- },
- [TC_CT_ATTACHED_VPD] = {
- .entry = tc_ct_attached_vpd_entry,
- .run = tc_ct_attached_vpd_run,
- },
- [TC_CT_ATTACH_WAIT_VPD] = {
- .entry = tc_ct_attach_wait_vpd_entry,
- .run = tc_ct_attach_wait_vpd_run,
- .exit = tc_ct_attach_wait_vpd_exit,
- .parent = &tc_states[TC_HOST_RP3_CT_RD],
- },
-};
-
-#ifdef TEST_BUILD
-const struct test_sm_data test_tc_sm_data[] = {
- {
- .base = tc_states,
- .size = ARRAY_SIZE(tc_states),
- .names = tc_state_names,
- .names_size = ARRAY_SIZE(tc_state_names),
- },
-};
-const int test_tc_sm_data_size = ARRAY_SIZE(test_tc_sm_data);
-#endif
diff --git a/common/usbc/usb_tc_drp_acc_trysrc_sm.c b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
deleted file mode 100644
index 6aa39b520b..0000000000
--- a/common/usbc/usb_tc_drp_acc_trysrc_sm.c
+++ /dev/null
@@ -1,3547 +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 "charge_manager.h"
-#include "charge_state.h"
-#include "common.h"
-#include "console.h"
-#include "hooks.h"
-#include "system.h"
-#include "task.h"
-#include "tcpm.h"
-#include "usb_common.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "usb_pe_sm.h"
-#include "usb_prl_sm.h"
-#include "usb_sm.h"
-#include "usb_tc_sm.h"
-#include "usbc_ppc.h"
-
-/*
- * USB Type-C DRP with Accessory and Try.SRC module
- * See Figure 4-16 in Release 1.4 of USB Type-C Spec.
- */
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_HOOK, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_HOOK, format, ## args)
-#else /* CONFIG_COMMON_RUNTIME */
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif
-
-/* Type-C Layer Flags */
-/* Flag to note we are sourcing VCONN */
-#define TC_FLAGS_VCONN_ON BIT(0)
-/* Flag to note port partner has Rp/Rp or Rd/Rd */
-#define TC_FLAGS_TS_DTS_PARTNER BIT(1)
-/* Flag to note VBus input has never been low */
-#define TC_FLAGS_VBUS_NEVER_LOW BIT(2)
-/* Flag to note Low Power Mode transition is currently happening */
-#define TC_FLAGS_LPM_TRANSITION BIT(3)
-/* Flag to note Low Power Mode is currently on */
-#define TC_FLAGS_LPM_ENGAGED BIT(4)
-/* Flag to note Low Power Mode is requested. Not currently used */
-#define TC_FLAGS_LPM_REQUESTED BIT(5)
-/* Flag to note CVTPD has been detected */
-#define TC_FLAGS_CTVPD_DETECTED BIT(6)
-/* Flag to note request to swap to VCONN on */
-#define TC_FLAGS_REQUEST_VC_SWAP_ON BIT(7)
-/* Flag to note request to swap to VCONN off */
-#define TC_FLAGS_REQUEST_VC_SWAP_OFF BIT(8)
-/* Flag to note request to swap VCONN is being rejected */
-#define TC_FLAGS_REJECT_VCONN_SWAP BIT(9)
-/* Flag to note request to power role swap */
-#define TC_FLAGS_REQUEST_PR_SWAP BIT(10)
-/* Flag to note request to data role swap */
-#define TC_FLAGS_REQUEST_DR_SWAP BIT(11)
-/* Flag to note request to power off sink */
-#define TC_FLAGS_POWER_OFF_SNK BIT(12)
-/* Flag to note port partner has external power */
-#define TC_FLAGS_PARTNER_EXTPOWER BIT(13)
-/* Flag to note port partner is Dual Role Data */
-#define TC_FLAGS_PARTNER_DR_DATA BIT(14)
-/* Flag to note port partner is Dual Role Power */
-#define TC_FLAGS_PARTNER_DR_POWER BIT(15)
-/* Flag to note port partner is Power Delivery capable */
-#define TC_FLAGS_PARTNER_PD_CAPABLE BIT(16)
-/* Flag to note hard reset has been triggered */
-#define TC_FLAGS_HARD_RESET BIT(17)
-/* Flag to note port partner is USB comms capable */
-#define TC_FLAGS_PARTNER_USB_COMM BIT(18)
-/* Flag to note we are currently performing PR Swap */
-#define TC_FLAGS_PR_SWAP_IN_PROGRESS BIT(19)
-/* Flag to note we need to perform PR Swap */
-#define TC_FLAGS_DO_PR_SWAP BIT(20)
-/* Flag to note we are performing Discover Identity */
-#define TC_FLAGS_DISC_IDENT_IN_PROGRESS BIT(21)
-/* Flag to note we should wake from LPM */
-#define TC_FLAGS_WAKE_FROM_LPM BIT(22)
-/* Flag to note a chipset power state has changed */
-#define TC_FLAGS_POWER_STATE_CHANGE BIT(23)
-/* Flag to note the TCPM supports auto toggle */
-#define TC_FLAGS_AUTO_TOGGLE_SUPPORTED BIT(24)
-
-/*
- * Clear all flags except TC_FLAGS_AUTO_TOGGLE_SUPPORTED,
- * TC_FLAGS_LPM_REQUESTED, and TC_FLAGS_LPM_ENGAGED if
- * they are set.
- */
-#define CLR_ALL_BUT_LPM_FLAGS(port) (tc[port].flags &= \
- (TC_FLAGS_AUTO_TOGGLE_SUPPORTED | \
- TC_FLAGS_LPM_REQUESTED | \
- TC_FLAGS_LPM_ENGAGED))
-
-/* 100 ms is enough time for any TCPC transaction to complete. */
-#define PD_LPM_DEBOUNCE_US (100 * MSEC)
-
-enum ps_reset_sequence {
- PS_STATE0,
- PS_STATE1,
- PS_STATE2,
- PS_STATE3
-};
-
-/* List of all TypeC-level states */
-enum usb_tc_state {
- /* Normal States */
- TC_DISABLED,
- TC_ERROR_RECOVERY,
- TC_UNATTACHED_SNK,
- TC_ATTACH_WAIT_SNK,
- TC_ATTACHED_SNK,
- TC_UNORIENTED_DBG_ACC_SRC,
- TC_DBG_ACC_SNK,
- TC_UNATTACHED_SRC,
- TC_ATTACH_WAIT_SRC,
- TC_ATTACHED_SRC,
- TC_TRY_SRC,
- TC_TRY_WAIT_SNK,
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- TC_DRP_AUTO_TOGGLE,
-#endif
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- TC_LOW_POWER_MODE,
-#endif
-#ifdef CONFIG_USB_PE_SM
- TC_CT_UNATTACHED_SNK,
- TC_CT_ATTACHED_SNK,
-#endif
- /* Super States */
- TC_CC_OPEN,
- TC_CC_RD,
- TC_CC_RP,
- TC_UNATTACHED,
-};
-/* Forward declare the full list of states. This is indexed by usb_tc_state */
-static const struct usb_state tc_states[];
-
-#ifdef CONFIG_COMMON_RUNTIME
-/* List of human readable state names for console debugging */
-static const char * const tc_state_names[] = {
- [TC_DISABLED] = "Disabled",
- [TC_ERROR_RECOVERY] = "ErrorRecovery",
- [TC_UNATTACHED_SNK] = "Unattached.SNK",
- [TC_ATTACH_WAIT_SNK] = "AttachWait.SNK",
- [TC_ATTACHED_SNK] = "Attached.SNK",
- [TC_UNORIENTED_DBG_ACC_SRC] = "UnorientedDebugAccessory.SRC",
- [TC_DBG_ACC_SNK] = "DebugAccessory.SNK",
- [TC_UNATTACHED_SRC] = "Unattached.SRC",
- [TC_ATTACH_WAIT_SRC] = "AttachWait.SRC",
- [TC_ATTACHED_SRC] = "Attached.SRC",
- [TC_TRY_SRC] = "Try.SRC",
- [TC_TRY_WAIT_SNK] = "TryWait.SNK",
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- [TC_DRP_AUTO_TOGGLE] = "DRPAutoToggle",
-#endif
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- [TC_LOW_POWER_MODE] = "LowPowerMode",
-#endif
-#ifdef CONFIG_USB_PE_SM
- [TC_CT_UNATTACHED_SNK] = "CTUnattached.SNK",
- [TC_CT_ATTACHED_SNK] = "CTAttached.SNK",
-#endif
-
-};
-#endif
-
-/* Generate a compiler error if invalid states are referenced */
-#ifndef CONFIG_USB_PD_TRY_SRC
-#define TC_TRY_SRC TC_TRY_SRC_UNDEFINED
-#define TC_TRY_WAIT_SNK TC_TRY_WAIT_SNK_UNDEFINED
-#endif
-
-static struct type_c {
- /* state machine context */
- struct sm_ctx ctx;
- /* current port power role (SOURCE or SINK) */
- enum pd_power_role power_role;
- /* current port data role (DFP or UFP) */
- enum pd_data_role data_role;
- /* Higher-level power deliver state machines are enabled if true. */
- uint8_t pd_enable;
- /*
- * Timer for handling TOGGLE_OFF/FORCE_SINK mode when auto-toggle
- * enabled. See drp_auto_toggle_next_state() for details.
- */
- uint64_t drp_sink_time;
-#ifdef CONFIG_USB_PE_SM
- /* Power supply reset sequence during a hard reset */
- enum ps_reset_sequence ps_reset_state;
-#endif
- /* Port polarity : 0 => CC1 is CC line, 1 => CC2 is CC line */
- uint8_t polarity;
- /* port flags, see TC_FLAGS_* */
- uint32_t flags;
- /* event timeout */
- uint64_t evt_timeout;
- /* Time a port shall wait before it can determine it is attached */
- uint64_t cc_debounce;
- /*
- * Time a Sink port shall wait before it can determine it is detached
- * due to the potential for USB PD signaling on CC as described in
- * the state definitions.
- */
- uint64_t pd_debounce;
-#ifdef CONFIG_USB_PD_TRY_SRC
- /*
- * Time a port shall wait before it can determine it is
- * re-attached during the try-wait process.
- */
- uint64_t try_wait_debounce;
-#endif
- /* The cc state */
- enum pd_cc_states cc_state;
- /* Role toggle timer */
- uint64_t next_role_swap;
- /* Generic timer */
- uint64_t timeout;
- /* Time to enter low power mode */
- uint64_t low_power_time;
- /* Tasks to notify after TCPC has been reset */
- int tasks_waiting_on_reset;
- /* Tasks preventing TCPC from entering low power mode */
- int tasks_preventing_lpm;
- /* Voltage on CC pin */
- enum tcpc_cc_voltage_status cc_voltage;
- /* Type-C current */
- typec_current_t typec_curr;
- /* Type-C current change */
- typec_current_t typec_curr_change;
- /* Attached ChromeOS device id, RW hash, and current RO / RW image */
- uint16_t dev_id;
- uint32_t dev_rw_hash[PD_RW_HASH_SIZE/4];
- enum ec_current_image current_image;
-} tc[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Port dual-role state */
-static volatile __maybe_unused
-enum pd_dual_role_states drp_state[CONFIG_USB_PD_PORT_MAX_COUNT] = {
- [0 ... (CONFIG_USB_PD_PORT_MAX_COUNT - 1)] =
- CONFIG_USB_PD_INITIAL_DRP_STATE};
-
-#ifdef CONFIG_USBC_VCONN
-static void set_vconn(int port, int enable);
-#endif
-
-#ifdef CONFIG_USB_PE_SM
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-/* Tracker for which task is waiting on sysjump prep to finish */
-static volatile task_id_t sysjump_task_waiting = TASK_ID_INVALID;
-#endif
-
-/*
- * 4 entry rw_hash table of type-C devices that AP has firmware updates for.
- */
-#ifdef CONFIG_COMMON_RUNTIME
-#define RW_HASH_ENTRIES 4
-static struct ec_params_usb_pd_rw_hash_entry rw_hash_table[RW_HASH_ENTRIES];
-#endif
-
-/* Forward declare common, private functions */
-static __maybe_unused int reset_device_and_notify(int port);
-
-#ifdef CONFIG_POWER_COMMON
-static void handle_new_power_state(int port);
-#endif /* CONFIG_POWER_COMMON */
-
-static void pd_update_dual_role_config(int port);
-#endif /* CONFIG_USB_PE_SM */
-
-/* Forward declare common, private functions */
-static void set_state_tc(const int port, const enum usb_tc_state new_state);
-test_export_static enum usb_tc_state get_state_tc(const int port);
-
-#ifdef CONFIG_USB_PD_TRY_SRC
-/* Enable variable for Try.SRC states */
-static uint8_t pd_try_src_enable;
-static void pd_update_try_source(void);
-#endif
-
-static void sink_stop_drawing_current(int port);
-
-/*
- * Public Functions
- *
- * NOTE: Functions prefixed with pd_ are defined in usb_pd.h
- * Functions prefixed with tc_ are defined int usb_tc_sm.h
- */
-
-#ifndef CONFIG_USB_PRL_SM
-
-/*
- * These pd_ functions are implemented in common/usb_prl_sm.c
- */
-
-void pd_transmit_complete(int port, int status)
-{
- /* DO NOTHING */
-}
-
-void pd_execute_hard_reset(int port)
-{
- /* DO NOTHING */
-}
-
-void pd_set_vbus_discharge(int port, int enable)
-{
- /* DO NOTHING */
-}
-
-uint16_t pd_get_identity_vid(int port)
-{
- /* DO NOTHING */
- return 0;
-}
-
-#endif /* !CONFIG_USB_PRL_SM */
-
-void pd_update_contract(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- /* Must be in Attached.SRC when this function is called */
- if (get_state_tc(port) == TC_ATTACHED_SRC)
- pe_dpm_request(port, DPM_REQUEST_SRC_CAP_CHANGE);
- }
-}
-
-void pd_request_source_voltage(int port, int mv)
-{
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- pd_set_max_voltage(mv);
-
- /* Must be in Attached.SNK when this function is called */
- if (get_state_tc(port) == TC_ATTACHED_SNK)
- pe_dpm_request(port, DPM_REQUEST_NEW_POWER_LEVEL);
- else
- TC_SET_FLAG(port, TC_FLAGS_REQUEST_PR_SWAP);
-
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-void pd_set_external_voltage_limit(int port, int mv)
-{
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- pd_set_max_voltage(mv);
-
- /* Must be in Attached.SNK when this function is called */
- if (get_state_tc(port) == TC_ATTACHED_SNK)
- pe_dpm_request(port, DPM_REQUEST_NEW_POWER_LEVEL);
-
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-void pd_set_new_power_request(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- /* Must be in Attached.SNK when this function is called */
- if (get_state_tc(port) == TC_ATTACHED_SNK)
- pe_dpm_request(port, DPM_REQUEST_NEW_POWER_LEVEL);
- }
-}
-
-void pd_request_power_swap(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- /*
- * Must be in Attached.SRC, Attached.SNK, UnorientedDbgAcc.SRC,
- * or DbgAcc.SNK, when this function is called.
- */
- if (get_state_tc(port) == TC_ATTACHED_SRC ||
- get_state_tc(port) == TC_ATTACHED_SNK ||
- get_state_tc(port) == TC_DBG_ACC_SNK ||
- get_state_tc(port) ==
- TC_UNORIENTED_DBG_ACC_SRC) {
- TC_SET_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS);
- }
- }
-}
-
-static inline void pd_set_dual_role_no_wakeup(int port,
- enum pd_dual_role_states state)
-{
- drp_state[port] = state;
-
- if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC))
- pd_update_try_source();
-}
-
-void pd_set_dual_role(int port, enum pd_dual_role_states state)
-{
- pd_set_dual_role_no_wakeup(port, state);
-
- /* Wake task up to process change */
- task_set_event(PD_PORT_TO_TASK_ID(port),
- PD_EVENT_UPDATE_DUAL_ROLE, 0);
-}
-
-#ifdef CONFIG_USB_PE_SM
-int pd_get_partner_data_swap_capable(int port)
-{
- /* return data swap capable status of port partner */
- return TC_CHK_FLAG(port, TC_FLAGS_PARTNER_DR_DATA);
-}
-
-int pd_comm_is_enabled(int port)
-{
- return tc[port].pd_enable;
-}
-
-void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data,
- int count)
-{
- pe_send_vdm(port, vid, cmd, data, count);
-}
-
-void pd_request_data_swap(int port)
-{
- /*
- * Must be in Attached.SRC or Attached.SNK when this function
- * is called
- */
- if (get_state_tc(port) == TC_ATTACHED_SRC ||
- get_state_tc(port) == TC_ATTACHED_SNK) {
- TC_SET_FLAG(port, TC_FLAGS_REQUEST_DR_SWAP);
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SM, 0);
- }
-}
-
-/*
- * Return true if partner port is a DTS or TS capable of entering debug
- * mode (eg. is presenting Rp/Rp or Rd/Rd).
- */
-int pd_ts_dts_plugged(int port)
-{
- return TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER);
-}
-
-/* Return true if partner port is known to be PD capable. */
-int pd_capable(int port)
-{
- return TC_CHK_FLAG(port, TC_FLAGS_PARTNER_PD_CAPABLE);
-}
-
-/*
- * Return true if partner port is capable of communication over USB data
- * lines.
- */
-int pd_get_partner_usb_comm_capable(int port)
-{
- return TC_CHK_FLAG(port, TC_FLAGS_PARTNER_USB_COMM);
-}
-
-enum pd_dual_role_states pd_get_dual_role(int port)
-{
- return drp_state[port];
-}
-
-int pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash,
- uint32_t current_image)
-{
- int i;
-
- tc[port].dev_id = dev_id;
- memcpy(tc[port].dev_rw_hash, rw_hash, PD_RW_HASH_SIZE);
-#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO
- if (debug_level >= 2)
- pd_dev_dump_info(dev_id, (uint8_t *)rw_hash);
-#endif
- tc[port].current_image = current_image;
-
- /* Search table for matching device / hash */
- for (i = 0; i < RW_HASH_ENTRIES; i++)
- if (dev_id == rw_hash_table[i].dev_id)
- return !memcmp(rw_hash,
- rw_hash_table[i].dev_rw_hash,
- PD_RW_HASH_SIZE);
- return 0;
-}
-
-void pd_got_frs_signal(int port)
-{
- pe_got_frs_signal(port);
-}
-
-int tc_is_attached_src(int port)
-{
- return get_state_tc(port) == TC_ATTACHED_SRC;
-}
-
-int tc_is_attached_snk(int port)
-{
- return get_state_tc(port) == TC_ATTACHED_SNK;
-}
-
-void tc_partner_dr_power(int port, int en)
-{
- if (en)
- TC_SET_FLAG(port, TC_FLAGS_PARTNER_DR_POWER);
- else
- TC_CLR_FLAG(port, TC_FLAGS_PARTNER_DR_POWER);
-}
-
-void tc_partner_extpower(int port, int en)
-{
- if (en)
- TC_SET_FLAG(port, TC_FLAGS_PARTNER_EXTPOWER);
- else
- TC_CLR_FLAG(port, TC_FLAGS_PARTNER_EXTPOWER);
-}
-
-void tc_partner_usb_comm(int port, int en)
-{
- if (en)
- TC_SET_FLAG(port, TC_FLAGS_PARTNER_USB_COMM);
- else
- TC_CLR_FLAG(port, TC_FLAGS_PARTNER_USB_COMM);
-}
-
-void tc_partner_dr_data(int port, int en)
-{
- if (en)
- TC_SET_FLAG(port, TC_FLAGS_PARTNER_DR_DATA);
- else
- TC_CLR_FLAG(port, TC_FLAGS_PARTNER_DR_DATA);
-}
-
-void tc_pd_connection(int port, int en)
-{
- if (en)
- TC_SET_FLAG(port, TC_FLAGS_PARTNER_PD_CAPABLE);
- else
- TC_CLR_FLAG(port, TC_FLAGS_PARTNER_PD_CAPABLE);
-}
-
-void tc_ctvpd_detected(int port)
-{
- TC_SET_FLAG(port, TC_FLAGS_CTVPD_DETECTED);
-}
-
-void tc_vconn_on(int port)
-{
- set_vconn(port, 1);
-}
-
-int tc_check_vconn_swap(int port)
-{
-#ifdef CONFIG_USBC_VCONN
- if (TC_CHK_FLAG(port, TC_FLAGS_REJECT_VCONN_SWAP))
- return 0;
-
- return pd_check_vconn_swap(port);
-#else
- return 0;
-#endif
-}
-
-void tc_pr_swap_complete(int port)
-{
- TC_CLR_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS);
-}
-
-void tc_prs_src_snk_assert_rd(int port)
-{
- /* Must be in Attached.SRC when this function is called */
- if (get_state_tc(port) == TC_ATTACHED_SRC) {
- /* Transition to Attached.SNK to assert Rd */
- TC_SET_FLAG(port, TC_FLAGS_DO_PR_SWAP);
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SM, 0);
- }
-}
-
-void tc_prs_snk_src_assert_rp(int port)
-{
- /* Must be in Attached.SNK when this function is called */
- if (get_state_tc(port) == TC_ATTACHED_SNK) {
- /* Transition to Attached.SRC to assert Rp */
- TC_SET_FLAG(port, TC_FLAGS_DO_PR_SWAP);
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SM, 0);
- }
-}
-
-void tc_hard_reset(int port)
-{
- TC_SET_FLAG(port, TC_FLAGS_HARD_RESET);
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SM, 0);
-}
-
-void tc_disc_ident_in_progress(int port)
-{
- TC_SET_FLAG(port, TC_FLAGS_DISC_IDENT_IN_PROGRESS);
-}
-
-void tc_disc_ident_complete(int port)
-{
- TC_CLR_FLAG(port, TC_FLAGS_DISC_IDENT_IN_PROGRESS);
-}
-#endif /* CONFIG_USB_PE_SM */
-
-void tc_snk_power_off(int port)
-{
- if (get_state_tc(port) == TC_ATTACHED_SNK ||
- get_state_tc(port) == TC_DBG_ACC_SNK) {
- TC_SET_FLAG(port, TC_FLAGS_POWER_OFF_SNK);
- sink_stop_drawing_current(port);
- }
-}
-
-int tc_src_power_on(int port)
-{
- if (get_state_tc(port) == TC_ATTACHED_SRC)
- return pd_set_power_supply_ready(port);
-
- return 0;
-}
-
-void tc_src_power_off(int port)
-{
- if (get_state_tc(port) == TC_ATTACHED_SRC ||
- get_state_tc(port) == TC_UNORIENTED_DBG_ACC_SRC) {
- /* Remove VBUS */
- pd_power_supply_reset(port);
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER))
- charge_manager_set_ceil(port, CEIL_REQUESTOR_PD,
- CHARGE_CEIL_NONE);
- }
-}
-
-void pd_set_suspend(int port, int enable)
-{
- if (pd_is_port_enabled(port) == !enable)
- return;
-
- set_state_tc(port,
- enable ? TC_DISABLED : TC_UNATTACHED_SNK);
-}
-
-int pd_is_port_enabled(int port)
-{
- return get_state_tc(port) != TC_DISABLED;
-}
-
-int pd_fetch_acc_log_entry(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PE_SM))
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_GET_LOG, NULL, 0);
-
- return EC_RES_SUCCESS;
-}
-
-int pd_get_polarity(int port)
-{
- return tc[port].polarity;
-}
-
-int pd_get_role(int port)
-{
- return tc[port].data_role;
-}
-
-int pd_is_vbus_present(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_VBUS_DETECT_TCPC))
- return tcpm_get_vbus_level(port);
- else
- return pd_snk_is_vbus_provided(port);
-}
-
-void pd_vbus_low(int port)
-{
- TC_CLR_FLAG(port, TC_FLAGS_VBUS_NEVER_LOW);
-}
-
-int pd_is_connected(int port)
-{
- return (get_state_tc(port) == TC_ATTACHED_SNK) ||
- (get_state_tc(port) == TC_ATTACHED_SRC);
-}
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-/*
- * TODO(b/137493121): Move this function to a separate file that's shared
- * between the this and the original stack.
- */
-void pd_prepare_sysjump(void)
-{
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- int i;
-
- /*
- * Exit modes before sysjump so we can cleanly enter again
- * later
- */
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- /*
- * We can't be in an alternate mode if PD comm is
- * disabled, so no need to send the event
- */
- if (!pd_comm_is_enabled(i))
- continue;
-
- sysjump_task_waiting = task_get_current();
- task_set_event(PD_PORT_TO_TASK_ID(i),
- PD_EVENT_SYSJUMP, 0);
- task_wait_event_mask(TASK_EVENT_SYSJUMP_READY, -1);
- sysjump_task_waiting = TASK_ID_INVALID;
- }
- }
-}
-#endif
-
-#ifdef CONFIG_USB_PE_SM
-static void tc_perform_src_hard_reset(int port)
-{
- switch (tc[port].ps_reset_state) {
- case PS_STATE0:
- /* Remove VBUS */
- tc_src_power_off(port);
-
- /* Turn off VCONN */
- set_vconn(port, 0);
-
- /* Set role to DFP */
- tc_set_data_role(port, PD_ROLE_DFP);
-
- tc[port].ps_reset_state = PS_STATE1;
- tc[port].timeout = get_time().val + PD_T_SRC_RECOVER;
- return;
- case PS_STATE1:
- /* Enable VBUS */
- pd_set_power_supply_ready(port);
-
- /* Turn off VCONN */
- set_vconn(port, 1);
-
- tc[port].ps_reset_state = PS_STATE3;
- tc[port].timeout = get_time().val +
- PD_POWER_SUPPLY_TURN_ON_DELAY;
- return;
- case PS_STATE2:
- case PS_STATE3:
- /* Tell Policy Engine Hard Reset is complete */
- pe_ps_reset_complete(port);
-
- TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET);
- tc[port].ps_reset_state = PS_STATE0;
- return;
- }
-}
-#endif
-
-static void tc_perform_snk_hard_reset(int port)
-{
- tc_set_data_role(port, PD_ROLE_UFP);
-
- /* Clear the input current limit */
- sink_stop_drawing_current(port);
-
- /*
- * When VCONN is supported, the Hard Reset Shall cause
- * the Port with the Rd resistor asserted to turn off
- * VCONN.
- */
-#ifdef CONFIG_USBC_VCONN
- if (TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON))
- set_vconn(port, 0);
-#endif
-
- /*
- * Inform policy engine that power supply
- * reset is complete
- */
- pe_ps_reset_complete(port);
-}
-
-void tc_start_error_recovery(int port)
-{
- /*
- * Async. function call:
- * The port should transition to the ErrorRecovery state
- * from any other state when directed.
- */
- set_state_tc(port, TC_ERROR_RECOVERY);
-}
-
-static void restart_tc_sm(int port, enum usb_tc_state start_state)
-{
- int res = 0;
-
- res = tc_restart_tcpc(port);
-
- CPRINTS("TCPC p%d init %s", port, res ? "failed" : "ready");
-
- /* Disable if restart failed, otherwise start in default state. */
- set_state_tc(port, res ? TC_DISABLED : start_state);
-
- if (IS_ENABLED(CONFIG_USBC_SS_MUX))
- /* Initialize USB mux to its default state */
- usb_mux_init(port);
-
- tcpm_select_rp_value(port, CONFIG_USB_PD_PULLUP);
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) {
- /* Initialize PD and type-C supplier current limits to 0 */
- pd_set_input_current_limit(port, 0, 0);
- typec_set_input_current_limit(port, 0, 0);
- charge_manager_update_dualrole(port, CAP_UNKNOWN);
- }
-
- tc[port].flags = 0;
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- /*
- * Some TCPCs may not support DRP Auto Toggle, so query the
- * query the TCPC for DRP Auto toggle support.
- */
- if (tcpm_auto_toggle_supported(port))
- TC_SET_FLAG(port, TC_FLAGS_AUTO_TOGGLE_SUPPORTED);
-#endif
-
-#ifdef CONFIG_USB_PE_SM
- tc[port].pd_enable = 0;
- tc[port].ps_reset_state = PS_STATE0;
-#endif
-}
-
-void tc_state_init(int port)
-{
- /* Unattached.SNK is the default starting state. */
- restart_tc_sm(port, TC_UNATTACHED_SNK);
-
- /*
- * If the TCPC isn't accessed, it will enter low power mode
- * after PD_LPM_DEBOUNCE_US.
- */
- tc[port].low_power_time = get_time().val + PD_LPM_DEBOUNCE_US;
-}
-
-enum pd_power_role tc_get_power_role(int port)
-{
- return tc[port].power_role;
-}
-
-enum pd_data_role tc_get_data_role(int port)
-{
- return tc[port].data_role;
-}
-
-enum pd_cable_plug tc_get_cable_plug(int port)
-{
- /*
- * Messages sent by this state machine are always from a DFP/UFP,
- * i.e. the chromebook.
- */
- return PD_PLUG_FROM_DFP_UFP;
-}
-
-uint8_t tc_get_polarity(int port)
-{
- return tc[port].polarity;
-}
-
-uint8_t tc_get_pd_enabled(int port)
-{
- return tc[port].pd_enable;
-}
-
-void tc_set_power_role(int port, enum pd_power_role role)
-{
- tc[port].power_role = role;
-}
-
-/*
- * Private Functions
- */
-
-/* Set the TypeC state machine to a new state. */
-static void set_state_tc(const int port, const enum usb_tc_state new_state)
-{
- set_state(port, &tc[port].ctx, &tc_states[new_state]);
-}
-
-/* Get the current TypeC state. */
-test_export_static enum usb_tc_state get_state_tc(const int port)
-{
- return tc[port].ctx.current - &tc_states[0];
-}
-
-/* Get the previous TypeC state. */
-static enum usb_tc_state get_last_state_tc(const int port)
-{
- return tc[port].ctx.previous - &tc_states[0];
-}
-
-static void print_current_state(const int port)
-{
- CPRINTS("C%d: %s", port, tc_state_names[get_state_tc(port)]);
-}
-
-#ifdef CONFIG_USB_PE_SM
-static void handle_device_access(int port)
-{
- tc[port].low_power_time = get_time().val + PD_LPM_DEBOUNCE_US;
-}
-#endif
-
-void tc_event_check(int port, int evt)
-{
-#ifdef CONFIG_USB_PE_SM
- if (IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER)) {
- if (evt & PD_EXIT_LOW_POWER_EVENT_MASK)
- TC_SET_FLAG(port, TC_FLAGS_WAKE_FROM_LPM);
- if (evt & PD_EVENT_DEVICE_ACCESSED)
- handle_device_access(port);
- }
-
- /* if TCPC has reset, then need to initialize it again */
- if (evt & PD_EVENT_TCPC_RESET)
- reset_device_and_notify(port);
-
-#ifdef CONFIG_POWER_COMMON
- if (IS_ENABLED(CONFIG_POWER_COMMON)) {
- if (evt & PD_EVENT_POWER_STATE_CHANGE) {
- TC_SET_FLAG(port, TC_FLAGS_POWER_STATE_CHANGE);
- handle_new_power_state(port);
- }
- }
-#endif /* CONFIG_POWER_COMMON */
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
- if (evt & PD_EVENT_SYSJUMP) {
- pe_exit_dp_mode(port);
- notify_sysjump_ready(&sysjump_task_waiting);
- }
- }
-#endif
-
- if (evt & PD_EVENT_UPDATE_DUAL_ROLE)
- pd_update_dual_role_config(port);
-#endif
-}
-
-/*
- * CC values for regular sources and Debug sources (aka DTS)
- *
- * Source type Mode of Operation CC1 CC2
- * ---------------------------------------------
- * Regular Default USB Power RpUSB Open
- * Regular USB-C @ 1.5 A Rp1A5 Open
- * Regular USB-C @ 3 A Rp3A0 Open
- * DTS Default USB Power Rp3A0 Rp1A5
- * DTS USB-C @ 1.5 A Rp1A5 RpUSB
- * DTS USB-C @ 3 A Rp3A0 RpUSB
- */
-
-void tc_set_data_role(int port, enum pd_data_role role)
-{
- tc[port].data_role = role;
-
- if (IS_ENABLED(CONFIG_USBC_SS_MUX))
- set_usb_mux_with_current_data_role(port);
-
- /*
- * Run any board-specific code for role swap (e.g. setting OTG signals
- * to SoC).
- */
- pd_execute_data_swap(port, role);
-
- /* Notify TCPC of role update */
- tcpm_set_msg_header(port, tc[port].power_role, tc[port].data_role);
-}
-
-static void sink_stop_drawing_current(int port)
-{
- pd_set_input_current_limit(port, 0, 0);
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) {
- typec_set_input_current_limit(port, 0, 0);
- charge_manager_set_ceil(port,
- CEIL_REQUESTOR_PD, CHARGE_CEIL_NONE);
- }
-}
-
-#ifdef CONFIG_USB_PD_TRY_SRC
-static void pd_update_try_source(void)
-{
- int i;
- int try_src = 0;
- static struct mutex pd_try_src_enable_lock;
-
- int batt_soc = usb_get_battery_soc();
-
- try_src = 0;
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- try_src |= drp_state[i] == PD_DRP_TOGGLE_ON;
-
- /*
- * This function is called from this PD task and the hooks tasks.
- * A lock is added here to serialize access to the
- * pd_try_source_enable variable.
- */
- mutex_lock(&pd_try_src_enable_lock);
-
- /*
- * Enable try source when dual-role toggling AND battery is present
- * and at some minimum percentage.
- */
- pd_try_src_enable = try_src &&
- batt_soc >= CONFIG_USB_PD_TRY_SRC_MIN_BATT_SOC;
-
-#ifdef CONFIG_BATTERY_REVIVE_DISCONNECT
- /*
- * Don't attempt Try.Src if the battery is in the disconnect state. The
- * discharge FET may not be enabled and so attempting Try.Src may cut
- * off our only power source at the time.
- */
- pd_try_src_enable &= (battery_get_disconnect_state() ==
- BATTERY_NOT_DISCONNECTED);
-#elif defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \
- defined(CONFIG_BATTERY_PRESENT_GPIO)
- /*
- * When battery is cutoff in ship mode it may not be reliable to
- * check if battery is present with its state of charge.
- * Also check if battery is initialized and ready to provide power.
- */
- pd_try_src_enable &= (battery_is_present() == BP_YES);
-#endif /* CONFIG_BATTERY_PRESENT_[CUSTOM|GPIO] */
-
- mutex_unlock(&pd_try_src_enable_lock);
-}
-DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, pd_update_try_source, HOOK_PRIO_DEFAULT);
-#endif /* CONFIG_USB_PD_TRY_SRC */
-
-#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO
-static inline void pd_dev_dump_info(uint16_t dev_id, uint8_t *hash)
-{
- int j;
-
- ccprintf("DevId:%d.%d Hash:", HW_DEV_ID_MAJ(dev_id),
- HW_DEV_ID_MIN(dev_id));
- for (j = 0; j < PD_RW_HASH_SIZE; j += 4) {
- ccprintf(" 0x%02x%02x%02x%02x", hash[j + 3], hash[j + 2],
- hash[j + 1], hash[j]);
- }
- ccprintf("\n");
-}
-#endif /* CONFIG_CMD_PD_DEV_DUMP_INFO */
-
-static void set_vconn(int port, int enable)
-{
- if (enable == TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON))
- return;
-
- if (enable)
- TC_SET_FLAG(port, TC_FLAGS_VCONN_ON);
- else
- TC_CLR_FLAG(port, TC_FLAGS_VCONN_ON);
-
- /*
- * We always need to tell the TCPC to enable Vconn first, otherwise some
- * TCPCs get confused and think the CC line is in over voltage mode and
- * immediately disconnects. If there is a PPC, both devices will
- * potentially source Vconn, but that should be okay since Vconn has
- * "make before break" electrical requirements when swapping anyway.
- */
- tcpm_set_vconn(port, enable);
-
- if (IS_ENABLED(CONFIG_USBC_PPC_VCONN))
- ppc_set_vconn(port, enable);
-}
-
-#ifdef CONFIG_USB_PD_TCPM_TCPCI
-static uint32_t pd_ports_to_resume;
-static void resume_pd_port(void)
-{
- uint32_t port;
- uint32_t suspended_ports = atomic_read_clear(&pd_ports_to_resume);
-
- while (suspended_ports) {
- port = __builtin_ctz(suspended_ports);
- suspended_ports &= ~(1 << port);
- pd_set_suspend(port, 0);
- }
-}
-DECLARE_DEFERRED(resume_pd_port);
-
-void pd_deferred_resume(int port)
-{
- atomic_or(&pd_ports_to_resume, 1 << port);
- hook_call_deferred(&resume_pd_port_data, SECOND);
-}
-#endif /* CONFIG_USB_PD_DEFERRED_RESUME */
-
-#ifdef CONFIG_USB_PE_SM
-/* This must only be called from the PD task */
-static void pd_update_dual_role_config(int port)
-{
- /*
- * Change to sink if port is currently a source AND (new DRP
- * state is force sink OR new DRP state is either toggle off
- * or debug accessory toggle only and we are in the source
- * disconnected state).
- */
- if (!IS_ENABLED(CONFIG_USB_PE_SM))
- return;
-
- if (tc[port].power_role == PD_ROLE_SOURCE &&
- ((drp_state[port] == PD_DRP_FORCE_SINK &&
- !pd_ts_dts_plugged(port)) ||
- (drp_state[port] == PD_DRP_TOGGLE_OFF &&
- get_state_tc(port) == TC_UNATTACHED_SRC))) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- } else if (tc[port].power_role == PD_ROLE_SINK &&
- drp_state[port] == PD_DRP_FORCE_SOURCE) {
- /*
- * Change to source if port is currently a sink and the
- * new DRP state is force source.
- */
- set_state_tc(port, TC_UNATTACHED_SRC);
- }
-}
-
-#ifdef CONFIG_POWER_COMMON
-static void handle_new_power_state(int port)
-{
- if (IS_ENABLED(CONFIG_POWER_COMMON) &&
- IS_ENABLED(CONFIG_USB_PE_SM)) {
- if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF))
- /*
- * The SoC will negotiated DP mode again when it
- * boots up
- */
- pe_exit_dp_mode(port);
-
- /* Ensure mux is set properly after chipset transition */
- set_usb_mux_with_current_data_role(port);
- }
-}
-#endif /* CONFIG_POWER_COMMON */
-
-/*
- * HOST COMMANDS
- */
-#ifdef HAS_TASK_HOSTCMD
-static enum ec_status hc_pd_ports(struct host_cmd_handler_args *args)
-{
- struct ec_response_usb_pd_ports *r = args->response;
-
- r->num_ports = board_get_usb_pd_port_count();
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_PORTS,
- hc_pd_ports,
- EC_VER_MASK(0));
-static const enum pd_dual_role_states dual_role_map[USB_PD_CTRL_ROLE_COUNT] = {
- [USB_PD_CTRL_ROLE_TOGGLE_ON] = PD_DRP_TOGGLE_ON,
- [USB_PD_CTRL_ROLE_TOGGLE_OFF] = PD_DRP_TOGGLE_OFF,
- [USB_PD_CTRL_ROLE_FORCE_SINK] = PD_DRP_FORCE_SINK,
- [USB_PD_CTRL_ROLE_FORCE_SOURCE] = PD_DRP_FORCE_SOURCE,
- [USB_PD_CTRL_ROLE_FREEZE] = PD_DRP_FREEZE,
-};
-
-#ifdef CONFIG_USBC_SS_MUX
-static const enum typec_mux typec_mux_map[USB_PD_CTRL_MUX_COUNT] = {
- [USB_PD_CTRL_MUX_NONE] = TYPEC_MUX_NONE,
- [USB_PD_CTRL_MUX_USB] = TYPEC_MUX_USB,
- [USB_PD_CTRL_MUX_AUTO] = TYPEC_MUX_DP,
- [USB_PD_CTRL_MUX_DP] = TYPEC_MUX_DP,
- [USB_PD_CTRL_MUX_DOCK] = TYPEC_MUX_DOCK,
-};
-#endif
-
-__overridable uint8_t board_get_dp_pin_mode(int port)
-{
- return 0;
-}
-
-/*
- * TODO(b/142911453): Move this function to a common/usb_common.c to avoid
- * duplicate code
- */
-static enum ec_status hc_usb_pd_control(struct host_cmd_handler_args *args)
-{
- const struct ec_params_usb_pd_control *p = args->params;
- struct ec_response_usb_pd_control_v2 *r_v2 = args->response;
- struct ec_response_usb_pd_control *r = args->response;
-
- if (p->port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- if (p->role >= USB_PD_CTRL_ROLE_COUNT ||
- p->mux >= USB_PD_CTRL_MUX_COUNT)
- return EC_RES_INVALID_PARAM;
-
- if (p->role != USB_PD_CTRL_ROLE_NO_CHANGE)
- pd_set_dual_role(p->port, dual_role_map[p->role]);
-
-#ifdef CONFIG_USBC_SS_MUX
- if (p->mux != USB_PD_CTRL_MUX_NO_CHANGE)
- usb_mux_set(p->port, typec_mux_map[p->mux],
- typec_mux_map[p->mux] == TYPEC_MUX_NONE ?
- USB_SWITCH_DISCONNECT :
- USB_SWITCH_CONNECT,
- pd_get_polarity(p->port));
-#endif /* CONFIG_USBC_SS_MUX */
-
- if (p->swap == USB_PD_CTRL_SWAP_DATA)
- pd_request_data_swap(p->port);
- else if (p->swap == USB_PD_CTRL_SWAP_POWER)
- pd_request_power_swap(p->port);
-#ifdef CONFIG_USBC_VCONN_SWAP
- else if (p->swap == USB_PD_CTRL_SWAP_VCONN)
- pe_dpm_request(p->port, DPM_REQUEST_VCONN_SWAP);
-#endif
-
- switch (args->version) {
- case 0:
- r->enabled = pd_comm_is_enabled(p->port);
- r->role = tc[p->port].power_role;
- r->polarity = tc[p->port].polarity;
- r->state = get_state_tc(p->port);
- args->response_size = sizeof(*r);
- break;
- case 1:
- case 2:
- if (sizeof(*r_v2) > args->response_max)
- return EC_RES_INVALID_PARAM;
-
- r_v2->enabled =
- (pd_comm_is_enabled(p->port) ?
- PD_CTRL_RESP_ENABLED_COMMS : 0) |
- (pd_is_connected(p->port) ?
- PD_CTRL_RESP_ENABLED_CONNECTED : 0) |
- (TC_CHK_FLAG(p->port, TC_FLAGS_PARTNER_PD_CAPABLE) ?
- PD_CTRL_RESP_ENABLED_PD_CAPABLE : 0);
- r_v2->role =
- (tc[p->port].power_role ? PD_CTRL_RESP_ROLE_POWER : 0) |
- (tc[p->port].data_role ? PD_CTRL_RESP_ROLE_DATA : 0) |
- (TC_CHK_FLAG(p->port, TC_FLAGS_VCONN_ON) ?
- PD_CTRL_RESP_ROLE_VCONN : 0) |
- (TC_CHK_FLAG(p->port, TC_FLAGS_PARTNER_DR_POWER) ?
- PD_CTRL_RESP_ROLE_DR_POWER : 0) |
- (TC_CHK_FLAG(p->port, TC_FLAGS_PARTNER_DR_DATA) ?
- PD_CTRL_RESP_ROLE_DR_DATA : 0) |
- (TC_CHK_FLAG(p->port, TC_FLAGS_PARTNER_USB_COMM) ?
- PD_CTRL_RESP_ROLE_USB_COMM : 0) |
- (TC_CHK_FLAG(p->port, TC_FLAGS_PARTNER_EXTPOWER) ?
- PD_CTRL_RESP_ROLE_EXT_POWERED : 0);
- r_v2->polarity = tc[p->port].polarity;
- r_v2->cc_state = tc[p->port].cc_state;
- r_v2->dp_mode = board_get_dp_pin_mode(p->port);
- r_v2->cable_type = get_usb_pd_mux_cable_type(p->port);
-
- strzcpy(r_v2->state, tc_state_names[get_state_tc(p->port)],
- sizeof(r_v2->state));
- if (args->version == 1) {
- /*
- * ec_response_usb_pd_control_v2 (r_v2) is a
- * strict superset of ec_response_usb_pd_control_v1
- */
- args->response_size =
- sizeof(struct ec_response_usb_pd_control_v1);
- } else
- args->response_size = sizeof(*r_v2);
- break;
- default:
- return EC_RES_INVALID_PARAM;
- }
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_CONTROL,
- hc_usb_pd_control,
- EC_VER_MASK(0) | EC_VER_MASK(1) | EC_VER_MASK(2));
-
-static enum ec_status hc_remote_flash(struct host_cmd_handler_args *args)
-{
- const struct ec_params_usb_pd_fw_update *p = args->params;
- int port = p->port;
- int rv = EC_RES_SUCCESS;
- const uint32_t *data = &(p->size) + 1;
- int i, size;
-
- if (port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- if (p->size + sizeof(*p) > args->params_size)
- return EC_RES_INVALID_PARAM;
-
-#if defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \
-defined(CONFIG_BATTERY_PRESENT_GPIO)
- /*
- * Do not allow PD firmware update if no battery and this port
- * is sinking power, because we will lose power.
- */
- if (battery_is_present() != BP_YES &&
- charge_manager_get_active_charge_port() == port)
- return EC_RES_UNAVAILABLE;
-#endif
-
- switch (p->cmd) {
- case USB_PD_FW_REBOOT:
- pe_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_REBOOT, NULL, 0);
- /*
- * Return immediately to free pending i2c bus. Host needs to
- * manage this delay.
- */
- return EC_RES_SUCCESS;
-
- case USB_PD_FW_FLASH_ERASE:
- pe_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_ERASE, NULL, 0);
- /*
- * Return immediately. Host needs to manage delays here which
- * can be as long as 1.2 seconds on 64KB RW flash.
- */
- return EC_RES_SUCCESS;
-
- case USB_PD_FW_ERASE_SIG:
- pe_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_ERASE_SIG, NULL, 0);
- break;
-
- case USB_PD_FW_FLASH_WRITE:
- /* Data size must be a multiple of 4 */
- if (!p->size || p->size % 4)
- return EC_RES_INVALID_PARAM;
-
- size = p->size / 4;
- for (i = 0; i < size; i += VDO_MAX_SIZE - 1) {
- pe_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_WRITE,
- data + i, MIN(size - i, VDO_MAX_SIZE - 1));
- }
- return EC_RES_SUCCESS;
-
- default:
- return EC_RES_INVALID_PARAM;
- }
-
- return rv;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_FW_UPDATE,
- hc_remote_flash,
- EC_VER_MASK(0));
-
-static enum ec_status
-hc_remote_rw_hash_entry(struct host_cmd_handler_args *args)
-{
- int i, idx = 0, found = 0;
- const struct ec_params_usb_pd_rw_hash_entry *p = args->params;
- static int rw_hash_next_idx;
-
- if (!p->dev_id)
- return EC_RES_INVALID_PARAM;
-
- for (i = 0; i < RW_HASH_ENTRIES; i++) {
- if (p->dev_id == rw_hash_table[i].dev_id) {
- idx = i;
- found = 1;
- break;
- }
- }
-
- if (!found) {
- idx = rw_hash_next_idx;
- rw_hash_next_idx = rw_hash_next_idx + 1;
- if (rw_hash_next_idx == RW_HASH_ENTRIES)
- rw_hash_next_idx = 0;
- }
- memcpy(&rw_hash_table[idx], p, sizeof(*p));
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_RW_HASH_ENTRY,
- hc_remote_rw_hash_entry,
- EC_VER_MASK(0));
-
-static enum ec_status hc_remote_pd_dev_info(struct host_cmd_handler_args *args)
-{
- const uint8_t *port = args->params;
- struct ec_params_usb_pd_rw_hash_entry *r = args->response;
-
- if (*port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- r->dev_id = tc[*port].dev_id;
-
- if (r->dev_id)
- memcpy(r->dev_rw_hash, tc[*port].dev_rw_hash, PD_RW_HASH_SIZE);
-
- r->current_image = tc[*port].current_image;
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_DEV_INFO,
- hc_remote_pd_dev_info,
- EC_VER_MASK(0));
-
-#ifndef CONFIG_USB_PD_TCPC
-#ifdef CONFIG_EC_CMD_PD_CHIP_INFO
-static enum ec_status hc_remote_pd_chip_info(struct host_cmd_handler_args *args)
-{
- const struct ec_params_pd_chip_info *p = args->params;
- struct ec_response_pd_chip_info_v1 *info;
-
- if (p->port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- if (tcpm_get_chip_info(p->port, p->live, &info))
- return EC_RES_ERROR;
-
- /*
- * Take advantage of the fact that v0 and v1 structs have the
- * same layout for v0 data. (v1 just appends data)
- */
- args->response_size =
- args->version ? sizeof(struct ec_response_pd_chip_info_v1)
- : sizeof(struct ec_response_pd_chip_info);
-
- memcpy(args->response, info, args->response_size);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PD_CHIP_INFO,
- hc_remote_pd_chip_info,
- EC_VER_MASK(0) | EC_VER_MASK(1));
-#endif /* CONFIG_EC_CMD_PD_CHIP_INFO */
-#endif /* !CONFIG_USB_PD_TCPC */
-
-#ifdef CONFIG_HOSTCMD_EVENTS
-void pd_notify_dp_alt_mode_entry(void)
-{
- /*
- * Note: EC_HOST_EVENT_PD_MCU may be a more appropriate host event to
- * send, but we do not send that here because there are other cases
- * where we send EC_HOST_EVENT_PD_MCU such as charger insertion or
- * removal. Currently, those do not wake the system up, but
- * EC_HOST_EVENT_MODE_CHANGE does. If we made the system wake up on
- * EC_HOST_EVENT_PD_MCU, we would be turning the internal display on on
- * every charger insertion/removal, which is not desired.
- */
- CPRINTS("Notifying AP of DP Alt Mode Entry...");
- host_set_single_event(EC_HOST_EVENT_MODE_CHANGE);
-}
-#endif /* CONFIG_HOSTCMD_EVENTS */
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-static enum ec_status hc_remote_pd_set_amode(struct host_cmd_handler_args *args)
-{
- const struct ec_params_usb_pd_set_mode_request *p = args->params;
-
- if ((p->port >= board_get_usb_pd_port_count()) ||
- (!p->svid) || (!p->opos))
- return EC_RES_INVALID_PARAM;
-
- switch (p->cmd) {
- case PD_EXIT_MODE:
- if (pd_dfp_exit_mode(p->port, p->svid, p->opos))
- pd_send_vdm(p->port, p->svid,
- CMD_EXIT_MODE | VDO_OPOS(p->opos), NULL, 0);
- else {
- CPRINTF("Failed exit mode\n");
- return EC_RES_ERROR;
- }
- break;
- case PD_ENTER_MODE:
- if (pd_dfp_enter_mode(p->port, p->svid, p->opos))
- pd_send_vdm(p->port, p->svid, CMD_ENTER_MODE |
- VDO_OPOS(p->opos), NULL, 0);
- break;
- default:
- return EC_RES_INVALID_PARAM;
- }
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_SET_AMODE,
- hc_remote_pd_set_amode,
- EC_VER_MASK(0));
-#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
-#endif /* HAS_TASK_HOSTCMD */
-
-#if defined(CONFIG_USB_PD_ALT_MODE) && !defined(CONFIG_USB_PD_ALT_MODE_DFP)
-void pd_send_hpd(int port, enum hpd_event hpd)
-{
- uint32_t data[1];
- int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
-
- if (!opos)
- return;
-
- data[0] =
- VDO_DP_STATUS((hpd == hpd_irq), /* IRQ_HPD */
- (hpd != hpd_low), /* HPD_HI|LOW */
- 0, /* request exit DP */
- 0, /* request exit USB */
- 0, /* MF pref */
- 1, /* enabled */
- 0, /* power low */
- 0x2);
- pd_send_vdm(port, USB_SID_DISPLAYPORT,
- VDO_OPOS(opos) | CMD_ATTENTION, data, 1);
-}
-#endif
-#endif /* CONFIG_USB_PE_SM */
-
-#ifdef CONFIG_USBC_VCONN_SWAP
-void pd_request_vconn_swap_off(int port)
-{
- if (get_state_tc(port) == TC_ATTACHED_SRC ||
- get_state_tc(port) == TC_ATTACHED_SNK) {
- TC_SET_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_OFF);
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-void pd_request_vconn_swap_on(int port)
-{
- if (get_state_tc(port) == TC_ATTACHED_SRC ||
- get_state_tc(port) == TC_ATTACHED_SNK) {
- TC_SET_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_ON);
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-#endif
-
-#ifdef CONFIG_USBC_VCONN
-int tc_is_vconn_src(int port)
-{
- if (get_state_tc(port) == TC_ATTACHED_SRC ||
- get_state_tc(port) == TC_ATTACHED_SNK)
- return TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON);
- else
- return -1;
-}
-#endif
-
-#ifdef CONFIG_USBC_PPC
-static void pd_send_hard_reset(int port)
-{
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SEND_HARD_RESET, 0);
-}
-
-static uint32_t port_oc_reset_req;
-
-static void re_enable_ports(void)
-{
- uint32_t ports = atomic_read_clear(&port_oc_reset_req);
-
- while (ports) {
- int port = __fls(ports);
-
- ports &= ~BIT(port);
-
- /*
- * Let the board know that the overcurrent is
- * over since we're going to attempt re-enabling
- * the port.
- */
- board_overcurrent_event(port, 0);
-
- pd_send_hard_reset(port);
- /*
- * TODO(b/117854867): PD3.0 to send an alert message
- * indicating OCP after explicit contract.
- */
- }
-}
-DECLARE_DEFERRED(re_enable_ports);
-
-void pd_handle_overcurrent(int port)
-{
- /* Keep track of the overcurrent events. */
- CPRINTS("C%d: overcurrent!", port);
-
- if (IS_ENABLED(CONFIG_USB_PD_LOGGING))
- pd_log_event(PD_EVENT_PS_FAULT, PD_LOG_PORT_SIZE(port, 0),
- PS_FAULT_OCP, NULL);
-
- ppc_add_oc_event(port);
- /* Let the board specific code know about the OC event. */
- board_overcurrent_event(port, 1);
-
- /* Wait 1s before trying to re-enable the port. */
- atomic_or(&port_oc_reset_req, BIT(port));
- hook_call_deferred(&re_enable_ports_data, SECOND);
-}
-#endif /* defined(CONFIG_USBC_PPC) */
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
-static int reset_device_and_notify(int port)
-{
- int rv;
- int task, waiting_tasks;
-
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- rv = tc_restart_tcpc(port);
-
- if (rv == EC_SUCCESS)
- CPRINTS("TCPC p%d init ready", port);
- else
- CPRINTS("TCPC p%d init failed!", port);
-
- /*
- * Before getting the other tasks that are waiting, clear the reset
- * event from this PD task to prevent multiple reset/init events
- * occurring.
- *
- * The double reset event happens when the higher priority PD interrupt
- * task gets an interrupt during the above tcpm_init function. When that
- * occurs, the higher priority task waits correctly for us to finish
- * waking the TCPC, but it has also set PD_EVENT_TCPC_RESET again, which
- * would result in a second, unnecessary init.
- */
- atomic_clear(task_get_event_bitmap(task_get_current()),
- PD_EVENT_TCPC_RESET);
-
- waiting_tasks = atomic_read_clear(&tc[port].tasks_waiting_on_reset);
-
- /* Wake up all waiting tasks. */
- while (waiting_tasks) {
- task = __fls(waiting_tasks);
- waiting_tasks &= ~BIT(task);
- task_set_event(task, TASK_EVENT_PD_AWAKE, 0);
- }
-
- return rv;
-}
-
-void pd_wait_exit_low_power(int port)
-{
- if (TC_CHK_FLAG(port, TC_FLAGS_LPM_ENGAGED)) {
- TC_SET_FLAG(port, TC_FLAGS_WAKE_FROM_LPM);
-
- if (port != TASK_ID_TO_PD_PORT(task_get_current())) {
- /*
- * Otherwise, we need to wait for the TCPC reset to
- * complete
- */
- atomic_or(&tc[port].tasks_waiting_on_reset,
- 1 << task_get_current());
- /*
- * NOTE: We could be sending the PD task the reset
- * event while it is already processing the reset event.
- * If that occurs, then we will reset the TCPC multiple
- * times, which is undesirable but most likely benign.
- * Empirically, this doesn't happen much, but it if
- * starts occurring, we can add a guard to
- * prevent/reduce it.
- */
- task_set_event(PD_PORT_TO_TASK_ID(port),
- PD_EVENT_TCPC_RESET, 0);
- task_wait_event_mask(TASK_EVENT_PD_AWAKE, -1);
- }
- }
-}
-
-/*
- * This can be called from any task. If we are in the PD task, we can handle
- * immediately. Otherwise, we need to notify the PD task via event.
- */
-void pd_device_accessed(int port)
-{
- if (port == TASK_ID_TO_PD_PORT(task_get_current()))
- handle_device_access(port);
- else
- task_set_event(PD_PORT_TO_TASK_ID(port),
- PD_EVENT_DEVICE_ACCESSED, 0);
-}
-
-/*
- * TODO(b/137493121): Move this function to a separate file that's shared
- * between the this and the original stack.
- */
-void pd_prevent_low_power_mode(int port, int prevent)
-{
- const int current_task_mask = (1 << task_get_current());
-
- if (!IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER))
- return;
-
- if (prevent)
- atomic_or(&tc[port].tasks_preventing_lpm, current_task_mask);
- else
- atomic_clear(&tc[port].tasks_preventing_lpm, current_task_mask);
-}
-#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */
-
-static void sink_power_sub_states(int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2, cc;
- enum tcpc_cc_voltage_status new_cc_voltage;
-
- tcpm_get_cc(port, &cc1, &cc2);
-
- cc = tc[port].polarity ? cc2 : cc1;
-
- if (cc == TYPEC_CC_VOLT_RP_DEF)
- new_cc_voltage = TYPEC_CC_VOLT_RP_DEF;
- else if (cc == TYPEC_CC_VOLT_RP_1_5)
- new_cc_voltage = TYPEC_CC_VOLT_RP_1_5;
- else if (cc == TYPEC_CC_VOLT_RP_3_0)
- new_cc_voltage = TYPEC_CC_VOLT_RP_3_0;
- else
- new_cc_voltage = TYPEC_CC_VOLT_OPEN;
-
- /* Debounce the cc state */
- if (new_cc_voltage != tc[port].cc_voltage) {
- tc[port].cc_voltage = new_cc_voltage;
- tc[port].cc_debounce =
- get_time().val + PD_T_RP_VALUE_CHANGE;
- return;
- }
-
- if (tc[port].cc_debounce == 0 ||
- get_time().val < tc[port].cc_debounce)
- return;
-
- tc[port].cc_debounce = 0;
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) {
- tc[port].typec_curr = usb_get_typec_current_limit(
- tc[port].polarity, cc1, cc2);
-
- typec_set_input_current_limit(port,
- tc[port].typec_curr, TYPE_C_VOLTAGE);
- charge_manager_update_dualrole(port, CAP_DEDICATED);
- }
-}
-
-
-/*
- * TYPE-C State Implementations
- */
-
-/**
- * Disabled
- *
- * Super State Entry Actions:
- * Remove the terminations from CC
- * Set's VBUS and VCONN off
- */
-static void tc_disabled_entry(const int port)
-{
- print_current_state(port);
-}
-
-static void tc_disabled_run(const int port)
-{
- task_wait_event(-1);
-}
-
-static void tc_disabled_exit(const int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_TCPC)) {
- if (tc_restart_tcpc(port) != 0) {
- CPRINTS("TCPC p%d restart failed!", port);
- return;
- }
- }
-
- CPRINTS("TCPC p%d resumed!", port);
-}
-
-/**
- * ErrorRecovery
- *
- * Super State Entry Actions:
- * Remove the terminations from CC
- * Set's VBUS and VCONN off
- */
-static void tc_error_recovery_entry(const int port)
-{
- print_current_state(port);
-
- tc[port].timeout = get_time().val + PD_T_ERROR_RECOVERY;
-}
-
-static void tc_error_recovery_run(const int port)
-{
- if (tc[port].timeout > 0 && get_time().val > tc[port].timeout) {
- tc[port].timeout = 0;
- restart_tc_sm(port, TC_UNATTACHED_SRC);
- }
-}
-
-/**
- * Unattached.SNK
- *
- * Super State is Unattached state
- */
-static void tc_unattached_snk_entry(const int port)
-{
- if (get_last_state_tc(port) != TC_UNATTACHED_SRC)
- print_current_state(port);
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER))
- charge_manager_update_dualrole(port, CAP_UNKNOWN);
-
- /*
- * Indicate that the port is disconnected so the board
- * can restore state from any previous data swap.
- */
- pd_execute_data_swap(port, PD_ROLE_DISCONNECTED);
- tc[port].next_role_swap = get_time().val + PD_T_DRP_SNK;
-
- if (IS_ENABLED(CONFIG_USBC_SS_MUX))
- usb_mux_set(port, TYPEC_MUX_NONE,
- USB_SWITCH_DISCONNECT, tc[port].polarity);
-
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- CLR_ALL_BUT_LPM_FLAGS(port);
- tc[port].pd_enable = 0;
- }
-}
-
-static void tc_unattached_snk_run(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
-
- /*
- * TODO(b/137498392): Add wait before sampling the CC
- * status after role changes
- */
-
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET)) {
- TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET);
- tc_set_data_role(port, PD_ROLE_UFP);
- /* Inform Policy Engine that hard reset is complete */
- pe_ps_reset_complete(port);
- }
- }
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- /*
- * Attempt TCPC auto DRP toggle if it is
- * not already auto toggling.
- */
- if (drp_state[port] == PD_DRP_TOGGLE_ON &&
- TC_CHK_FLAG(port, TC_FLAGS_AUTO_TOGGLE_SUPPORTED) &&
- cc_is_open(cc1, cc2)) {
- set_state_tc(port, TC_DRP_AUTO_TOGGLE);
- return;
- }
-#endif
-
- /*
- * The port shall transition to AttachWait.SNK when a Source
- * connection is detected, as indicated by the SNK.Rp state
- * on at least one of its CC pins.
- *
- * A DRP shall transition to Unattached.SRC within tDRPTransition
- * after the state of both CC pins is SNK.Open for
- * tDRP − dcSRC.DRP ∙ tDRP.
- */
- if (cc_is_rp(cc1) || cc_is_rp(cc2)) {
- /* Connection Detected */
- set_state_tc(port, TC_ATTACH_WAIT_SNK);
- } else if (get_time().val > tc[port].next_role_swap &&
- drp_state[port] == PD_DRP_TOGGLE_ON) {
- /* DRP Toggle */
- set_state_tc(port, TC_UNATTACHED_SRC);
- }
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- else if (drp_state[port] == PD_DRP_FORCE_SINK ||
- drp_state[port] == PD_DRP_TOGGLE_OFF) {
- set_state_tc(port, TC_LOW_POWER_MODE);
- }
-#endif
-}
-
-/**
- * AttachWait.SNK
- *
- * Super State Entry Actions:
- * Vconn Off
- * Place Rd on CC
- * Set power role to SINK
- */
-static void tc_attach_wait_snk_entry(const int port)
-{
- print_current_state(port);
-
- tc[port].cc_state = PD_CC_UNSET;
-}
-
-static void tc_attach_wait_snk_run(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
- enum pd_cc_states new_cc_state;
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- if (cc_is_rp(cc1) && cc_is_rp(cc2))
- new_cc_state = PD_CC_DFP_DEBUG_ACC;
- else if (cc_is_rp(cc1) || cc_is_rp(cc2))
- new_cc_state = PD_CC_DFP_ATTACHED;
- else
- new_cc_state = PD_CC_NONE;
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE;
- tc[port].pd_debounce = get_time().val + PD_T_PD_DEBOUNCE;
- tc[port].cc_state = new_cc_state;
- return;
- }
-
- /*
- * A DRP shall transition to Unattached.SNK when the state of both
- * the CC1 and CC2 pins is SNK.Open for at least tPDDebounce.
- */
- if (new_cc_state == PD_CC_NONE &&
- get_time().val > tc[port].pd_debounce) {
- if (IS_ENABLED(CONFIG_USB_PE_SM) &&
- IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
- pd_dfp_exit_mode(port, 0, 0);
- }
-
- /* We are detached */
- set_state_tc(port, TC_UNATTACHED_SRC);
- return;
- }
-
- /* Wait for CC debounce */
- if (get_time().val < tc[port].cc_debounce)
- return;
-
- /*
- * The port shall transition to Attached.SNK after the state of only
- * one of the CC1 or CC2 pins is SNK.Rp for at least tCCDebounce and
- * VBUS is detected.
- *
- * A DRP that strongly prefers the Source role may optionally
- * transition to Try.SRC instead of Attached.SNK when the state of only
- * one CC pin has been SNK.Rp for at least tCCDebounce and VBUS is
- * detected.
- *
- * If the port supports Debug Accessory Mode, the port shall transition
- * to DebugAccessory.SNK if the state of both the CC1 and CC2 pins is
- * SNK.Rp for at least tCCDebounce and VBUS is detected.
- */
- if (pd_is_vbus_present(port)) {
- if (new_cc_state == PD_CC_DFP_ATTACHED) {
-#ifdef CONFIG_USB_PD_TRY_SRC
- if (pd_try_src_enable)
- set_state_tc(port, TC_TRY_SRC);
- else
-#endif
- set_state_tc(port, TC_ATTACHED_SNK);
- } else {
- /* new_cc_state is PD_CC_DFP_DEBUG_ACC */
- TC_SET_FLAG(port, TC_FLAGS_TS_DTS_PARTNER);
- set_state_tc(port, TC_DBG_ACC_SNK);
- }
-
- if (IS_ENABLED(CONFIG_USB_PE_SM) &&
- IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
- hook_call_deferred(&pd_usb_billboard_deferred_data,
- PD_T_AME);
- }
- }
-}
-
-/**
- * Attached.SNK
- */
-static void tc_attached_snk_entry(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
-
- print_current_state(port);
-
- /* Clear Low Power Mode Request */
- TC_CLR_FLAG(port, TC_FLAGS_LPM_REQUESTED);
-
-#ifdef CONFIG_USB_PE_SM
- if (TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
- /*
- * Both CC1 and CC2 pins shall be independently terminated to
- * ground through Rd.
- */
- tcpm_set_cc(port, TYPEC_CC_RD);
-
- /* Change role to sink */
- tc_set_power_role(port, PD_ROLE_SINK);
- tcpm_set_msg_header(port, tc[port].power_role,
- tc[port].data_role);
-
- /*
- * Maintain VCONN supply state, whether ON or OFF, and its
- * data role / usb mux connections.
- */
- } else
-#endif
- {
- /* Get connector orientation */
- tcpm_get_cc(port, &cc1, &cc2);
- tc[port].polarity = get_snk_polarity(cc1, cc2);
- set_polarity(port, tc[port].polarity);
-
- /*
- * Initial data role for sink is UFP
- * This also sets the usb mux
- */
- tc_set_data_role(port, PD_ROLE_UFP);
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) {
- tc[port].typec_curr =
- usb_get_typec_current_limit(tc[port].polarity,
- cc1, cc2);
- typec_set_input_current_limit(port,
- tc[port].typec_curr, TYPE_C_VOLTAGE);
- charge_manager_update_dualrole(port,
- pd_is_port_partner_dualrole(port) ?
- CAP_DUALROLE : CAP_DEDICATED);
- }
- }
-
- /* Apply Rd */
- tcpm_set_cc(port, TYPEC_CC_RD);
-
- tc[port].cc_debounce = 0;
-
- /* Enable PD */
- if (IS_ENABLED(CONFIG_USB_PE_SM))
- tc[port].pd_enable = 1;
-}
-
-static void tc_attached_snk_run(const int port)
-{
-#ifdef CONFIG_USB_PE_SM
- /*
- * Perform Hard Reset
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET)) {
- TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET);
- tc_perform_snk_hard_reset(port);
- }
-
- /*
- * The sink will be powered off during a power role swap but we don't
- * want to trigger a disconnect
- */
- if (!TC_CHK_FLAG(port, TC_FLAGS_POWER_OFF_SNK) &&
- !TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
- /* Detach detection */
- if (!pd_is_vbus_present(port)) {
- if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- pd_dfp_exit_mode(port, 0, 0);
-
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- if (!pe_is_explicit_contract(port))
- sink_power_sub_states(port);
- }
-
- /*
- * PD swap commands
- */
- if (tc[port].pd_enable && prl_is_running(port)) {
- /*
- * Power Role Swap
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_DO_PR_SWAP)) {
- /* Clear PR_SWAP flag in exit */
- set_state_tc(port, TC_ATTACHED_SRC);
- return;
- }
-
- /*
- * Data Role Swap
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_REQUEST_DR_SWAP)) {
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_DR_SWAP);
-
- /* Perform Data Role Swap */
- tc_set_data_role(port,
- tc[port].data_role == PD_ROLE_UFP ?
- PD_ROLE_DFP : PD_ROLE_UFP);
- }
-
-#ifdef CONFIG_USBC_VCONN
- /*
- * VCONN Swap
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_ON)) {
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_ON);
-
- set_vconn(port, 1);
- /* Inform policy engine that vconn swap is complete */
- pe_vconn_swap_complete(port);
- } else if (TC_CHK_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_OFF)) {
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_OFF);
-
- set_vconn(port, 0);
- /* Inform policy engine that vconn swap is complete */
- pe_vconn_swap_complete(port);
- }
-#endif
- /*
- * If the port supports Charge-Through VCONN-Powered USB
- * devices, and an explicit PD contract has failed to be
- * negotiated, the port shall query the identity of the
- * cable via USB PD on SOP’
- */
- if (!pe_is_explicit_contract(port) &&
- TC_CHK_FLAG(port, TC_FLAGS_CTVPD_DETECTED)) {
- /*
- * A port that via SOP’ has detected an attached
- * Charge-Through VCONN-Powered USB device shall
- * transition to Unattached.SRC if an explicit PD
- * contract has failed to be negotiated.
- */
- /* CTVPD detected */
- set_state_tc(port, TC_UNATTACHED_SRC);
- }
- }
-
-#else /* CONFIG_USB_PE_SM */
-
- /* Detach detection */
- if (!pd_is_vbus_present(port)) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /* Run Sink Power Sub-State */
- sink_power_sub_states(port);
-#endif /* CONFIG_USB_PE_SM */
-}
-
-static void tc_attached_snk_exit(const int port)
-{
- /*
- * If supplying VCONN, the port shall cease to supply
- * it within tVCONNOFF of exiting Attached.SNK if not PR swapping.
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON) &&
- !TC_CHK_FLAG(port, TC_FLAGS_DO_PR_SWAP))
- set_vconn(port, 0);
-
- /* Clear flags after checking Vconn status */
- TC_CLR_FLAG(port, TC_FLAGS_DO_PR_SWAP | TC_FLAGS_POWER_OFF_SNK);
-
- /* Stop drawing power */
- sink_stop_drawing_current(port);
-}
-
-/**
- * UnorientedDebugAccessory.SRC
- *
- * Super State Entry Actions:
- * Place Rp on CC
- * Set power role to SOURCE
- */
-static void tc_unoriented_dbg_acc_src_entry(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
-
- print_current_state(port);
-
- /* Run function relies on timeout being 0 or meaningful */
- tc[port].timeout = 0;
-
- /* Clear Low Power Mode Request */
- TC_CLR_FLAG(port, TC_FLAGS_LPM_REQUESTED);
-
- if (TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
- /* Enable VBUS */
- pd_set_power_supply_ready(port);
-
- /*
- * Maintain VCONN supply state, whether ON or OFF, and its
- * data role / usb mux connections.
- */
- } else {
- /* Get connector orientation */
- tcpm_get_cc(port, &cc1, &cc2);
- tc[port].polarity = (cc1 != TYPEC_CC_VOLT_RD);
- set_polarity(port, tc[port].polarity);
-
- /*
- * Initial data role for sink is DFP
- * This also sets the usb mux
- */
- tc_set_data_role(port, PD_ROLE_DFP);
-
- /* Enable VBUS */
- if (pd_set_power_supply_ready(port)) {
- if (IS_ENABLED(CONFIG_USBC_SS_MUX))
- usb_mux_set(port, TYPEC_MUX_NONE,
- USB_SWITCH_DISCONNECT, tc[port].polarity);
- }
-
-#ifdef CONFIG_USB_PE_SM
- tc[port].pd_enable = 0;
- tc[port].timeout = get_time().val +
- PD_POWER_SUPPLY_TURN_ON_DELAY;
-#endif
- }
-
- /* Inform PPC that a sink is connected. */
- if (IS_ENABLED(CONFIG_USBC_PPC))
- ppc_sink_is_connected(port, 1);
-}
-
-static void tc_unoriented_dbg_acc_src_run(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
- enum pd_cc_states new_cc_state;
-
-#ifdef CONFIG_USB_PE_SM
- /* Enable PD communications after power supply has fully turned on */
- if (tc[port].pd_enable == 0 &&
- get_time().val > tc[port].timeout) {
-
- tc[port].pd_enable = 1;
- tc[port].timeout = 0;
- }
-
- if (tc[port].pd_enable == 0)
- return;
-
- /*
- * Handle Hard Reset from Policy Engine
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET)) {
- if (get_time().val < tc[port].timeout)
- return;
-
- /*
- * This function clears TC_FLAGS_HARD_RESET
- * when the hard reset is complete.
- */
- tc_perform_src_hard_reset(port);
- }
-#endif
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- if (tc[port].polarity)
- cc1 = cc2;
-
- if (cc1 == TYPEC_CC_VOLT_OPEN)
- new_cc_state = PD_CC_NONE;
- else
- new_cc_state = PD_CC_UFP_ATTACHED;
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_SRC_DISCONNECT;
- }
-
- if (get_time().val < tc[port].cc_debounce)
- return;
-
- if (tc[port].cc_state == PD_CC_NONE &&
- !TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS) &&
- !TC_CHK_FLAG(port, TC_FLAGS_DISC_IDENT_IN_PROGRESS)) {
-
- tc[port].pd_enable = 0;
- set_state_tc(port, TC_UNATTACHED_SNK);
- }
-
-#ifdef CONFIG_USB_PE_SM
- /*
- * PD swap commands
- */
- if (tc[port].pd_enable) {
- /*
- * Power Role Swap Request
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_DO_PR_SWAP)) {
- /* Clear TC_FLAGS_DO_PR_SWAP on exit */
- return set_state_tc(port, TC_DBG_ACC_SNK);
- }
-
- /*
- * Data Role Swap Request
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_REQUEST_DR_SWAP)) {
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_DR_SWAP);
-
- /* Perform Data Role Swap */
- tc_set_data_role(port,
- tc[port].data_role == PD_ROLE_DFP ?
- PD_ROLE_UFP : PD_ROLE_DFP);
- }
- }
-#endif
-}
-
-static void tc_unoriented_dbg_acc_src_exit(const int port)
-{
- /*
- * A port shall cease to supply VBUS within tVBUSOFF of exiting
- * UnorientedDbg.SRC.
- */
- tc_src_power_off(port);
-
- /* Clear PR swap flag */
- TC_CLR_FLAG(port, TC_FLAGS_DO_PR_SWAP);
-}
-
-/**
- * Debug Accessory.SNK
- *
- * Super State Entry Actions:
- * Vconn Off
- * Place Rd on CC
- * Set power role to SINK
- */
-static void tc_dbg_acc_snk_entry(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
-
- print_current_state(port);
-
- if (TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
- /*
- * Both CC1 and CC2 pins shall be independently terminated to
- * ground through Rd.
- */
- tcpm_set_cc(port, TYPEC_CC_RD);
-
- /* Change role to sink */
- tc_set_power_role(port, PD_ROLE_SINK);
- tcpm_set_msg_header(port, tc[port].power_role,
- tc[port].data_role);
-
- /*
- * Maintain VCONN supply state, whether ON or OFF, and its
- * data role / usb mux connections.
- */
- } else {
- /* Get connector orientation */
- tcpm_get_cc(port, &cc1, &cc2);
- tc[port].polarity = get_snk_polarity(cc1, cc2);
- set_polarity(port, tc[port].polarity);
-
- /*
- * Initial data role for sink is UFP
- * This also sets the usb mux
- */
- tc_set_data_role(port, PD_ROLE_UFP);
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) {
- tc[port].typec_curr =
- usb_get_typec_current_limit(tc[port].polarity,
- cc1, cc2);
- typec_set_input_current_limit(port,
- tc[port].typec_curr, TYPE_C_VOLTAGE);
- charge_manager_update_dualrole(port,
- pd_is_port_partner_dualrole(port) ?
- CAP_DUALROLE : CAP_DEDICATED);
- }
- }
-
- /* Enable PD */
- tc[port].pd_enable = 1;
-}
-
-static void tc_dbg_acc_snk_run(const int port)
-{
-
- if (!IS_ENABLED(CONFIG_USB_PE_SM)) {
- /* Detach detection */
- if (!pd_is_vbus_present(port)) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /* Run Sink Power Sub-State */
- sink_power_sub_states(port);
-
- return;
- }
-
- /*
- * Perform Hard Reset
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET)) {
- TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET);
- tc_perform_snk_hard_reset(port);
- }
-
- /*
- * The sink will be powered off during a power role swap but we
- * don't want to trigger a disconnect
- */
- if (!TC_CHK_FLAG(port, TC_FLAGS_POWER_OFF_SNK) &&
- !TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
- /* Detach detection */
- if (!pd_is_vbus_present(port)) {
- if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- pd_dfp_exit_mode(port, 0, 0);
-
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- if (!pe_is_explicit_contract(port))
- sink_power_sub_states(port);
- }
-
- /* PD swap commands */
-
- /*
- * Power Role Swap
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_DO_PR_SWAP)) {
- /* Clear PR_SWAP flag in exit */
- set_state_tc(port, TC_UNORIENTED_DBG_ACC_SRC);
- return;
- }
-
- /*
- * Data Role Swap
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_REQUEST_DR_SWAP)) {
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_DR_SWAP);
-
- /* Perform Data Role Swap */
- tc_set_data_role(port, tc[port].data_role == PD_ROLE_UFP ?
- PD_ROLE_DFP : PD_ROLE_UFP);
- }
-}
-
-static void tc_dbg_acc_snk_exit(const int port)
-{
- TC_CLR_FLAG(port, TC_FLAGS_DO_PR_SWAP | TC_FLAGS_POWER_OFF_SNK);
-
- /* Stop drawing power */
- sink_stop_drawing_current(port);
-}
-
-/**
- * Unattached.SRC
- *
- * Super State is Unattached state
- */
-static void tc_unattached_src_entry(const int port)
-{
- if (get_last_state_tc(port) != TC_UNATTACHED_SNK)
- print_current_state(port);
-
- if (IS_ENABLED(CONFIG_USBC_PPC)) {
- /* There is no sink connected. */
- ppc_sink_is_connected(port, 0);
-
- /*
- * Clear the overcurrent event counter
- * since we've detected a disconnect.
- */
- ppc_clear_oc_event_counter(port);
- }
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER))
- charge_manager_update_dualrole(port, CAP_UNKNOWN);
-
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- CLR_ALL_BUT_LPM_FLAGS(port);
- tc[port].pd_enable = 0;
- }
-
- tc[port].next_role_swap = get_time().val + PD_T_DRP_SRC;
-}
-
-static void tc_unattached_src_run(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
-
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET)) {
- TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET);
- tc_set_data_role(port, PD_ROLE_DFP);
- /* Inform Policy Engine that hard reset is complete */
- pe_ps_reset_complete(port);
- }
- }
-
- if (IS_ENABLED(CONFIG_USBC_PPC)) {
- /*
- * If the port is latched off, just continue to
- * monitor for a detach.
- */
- if (ppc_is_port_latched_off(port))
- return;
- }
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- /*
- * Transition to AttachWait.SRC when VBUS is vSafe0V and:
- * 1) The SRC.Rd state is detected on either CC1 or CC2 pin or
- * 2) The SRC.Ra state is detected on both the CC1 and CC2 pins.
- *
- * A DRP shall transition to Unattached.SNK within tDRPTransition
- * after dcSRC.DRP ∙ tDRP
- */
- if (cc_is_at_least_one_rd(cc1, cc2) || cc_is_audio_acc(cc1, cc2))
- set_state_tc(port, TC_ATTACH_WAIT_SRC);
- else if (get_time().val > tc[port].next_role_swap &&
- drp_state[port] != PD_DRP_FORCE_SOURCE &&
- drp_state[port] != PD_DRP_FREEZE)
- set_state_tc(port, TC_UNATTACHED_SNK);
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- /*
- * Attempt TCPC auto DRP toggle
- */
- else if (drp_state[port] == PD_DRP_TOGGLE_ON &&
- TC_CHK_FLAG(port, TC_FLAGS_AUTO_TOGGLE_SUPPORTED) &&
- cc_is_open(cc1, cc2)) {
- set_state_tc(port, TC_DRP_AUTO_TOGGLE);
- }
-#endif
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- else if (drp_state[port] == PD_DRP_FORCE_SOURCE ||
- drp_state[port] == PD_DRP_TOGGLE_OFF) {
- set_state_tc(port, TC_LOW_POWER_MODE);
- }
-#endif
-}
-
-/**
- * AttachWait.SRC
- *
- * Super State Entry Actions:
- * Vconn Off
- * Place Rp on CC
- * Set power role to SOURCE
- */
-static void tc_attach_wait_src_entry(const int port)
-{
- print_current_state(port);
-
- tc[port].cc_state = PD_CC_UNSET;
-}
-
-static void tc_attach_wait_src_run(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
- enum pd_cc_states new_cc_state;
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- /* Debug accessory */
- if (cc_is_snk_dbg_acc(cc1, cc2)) {
- /* Debug accessory */
- new_cc_state = PD_CC_UFP_DEBUG_ACC;
- } else if (cc_is_at_least_one_rd(cc1, cc2)) {
- /* UFP attached */
- new_cc_state = PD_CC_UFP_ATTACHED;
- } else if (cc_is_audio_acc(cc1, cc2)) {
- /* AUDIO Accessory not supported. Just ignore */
- new_cc_state = PD_CC_UFP_AUDIO_ACC;
- } else {
- /* No UFP */
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE;
- tc[port].cc_state = new_cc_state;
- return;
- }
-
- /* Wait for CC debounce */
- if (get_time().val < tc[port].cc_debounce)
- return;
-
- /*
- * The port shall transition to Attached.SRC when VBUS is at vSafe0V
- * and the SRC.Rd state is detected on exactly one of the CC1 or CC2
- * pins for at least tCCDebounce.
- *
- * If the port supports Debug Accessory Mode, it shall transition to
- * UnorientedDebugAccessory.SRC when VBUS is at vSafe0V and the SRC.Rd
- * state is detected on both the CC1 and CC2 pins for at least
- * tCCDebounce.
- */
- if (!pd_is_vbus_present(port)) {
- if (new_cc_state == PD_CC_UFP_ATTACHED) {
- set_state_tc(port, TC_ATTACHED_SRC);
- return;
- } else if (new_cc_state == PD_CC_UFP_DEBUG_ACC) {
- set_state_tc(port, TC_UNORIENTED_DBG_ACC_SRC);
- return;
- }
- }
-}
-
-/**
- * Attached.SRC
- */
-static void tc_attached_src_entry(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
-
- print_current_state(port);
-
- /* Run function relies on timeout being 0 or meaningful */
- tc[port].timeout = 0;
-
- /* Clear Low Power Mode Request */
- TC_CLR_FLAG(port, TC_FLAGS_LPM_REQUESTED);
-
-#if defined(CONFIG_USB_PE_SM)
- if (TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
- /* Change role to source */
- tc_set_power_role(port, PD_ROLE_SOURCE);
- tcpm_set_msg_header(port,
- tc[port].power_role, tc[port].data_role);
- /*
- * Both CC1 and CC2 pins shall be independently terminated to
- * ground through Rp.
- */
- tcpm_select_rp_value(port, CONFIG_USB_PD_PULLUP);
-
- /* Enable VBUS */
- pd_set_power_supply_ready(port);
-
- /*
- * Maintain VCONN supply state, whether ON or OFF, and its
- * data role / usb mux connections.
- */
- } else {
- /* Get connector orientation */
- tcpm_get_cc(port, &cc1, &cc2);
- tc[port].polarity = (cc1 != TYPEC_CC_VOLT_RD);
- set_polarity(port, tc[port].polarity);
-
- /*
- * Initial data role for sink is DFP
- * This also sets the usb mux
- */
- tc_set_data_role(port, PD_ROLE_DFP);
-
- /*
- * Start sourcing Vconn before Vbus to ensure
- * we are within USB Type-C Spec 1.4 tVconnON
- */
- if (IS_ENABLED(CONFIG_USBC_VCONN))
- set_vconn(port, 1);
-
- /* Enable VBUS */
- if (pd_set_power_supply_ready(port)) {
- /* Stop sourcing Vconn if Vbus failed */
- if (IS_ENABLED(CONFIG_USBC_VCONN))
- set_vconn(port, 0);
-
- if (IS_ENABLED(CONFIG_USBC_SS_MUX))
- usb_mux_set(port, TYPEC_MUX_NONE,
- USB_SWITCH_DISCONNECT, tc[port].polarity);
- }
-
- tc[port].pd_enable = 0;
- tc[port].timeout = get_time().val +
- MAX(PD_POWER_SUPPLY_TURN_ON_DELAY, PD_T_VCONN_STABLE);
- }
-#else
- /* Get connector orientation */
- tcpm_get_cc(port, &cc1, &cc2);
- tc[port].polarity = (cc1 != TYPEC_CC_VOLT_RD);
- set_polarity(port, tc[port].polarity);
-
- /*
- * Initial data role for sink is DFP
- * This also sets the usb mux
- */
- tc_set_data_role(port, PD_ROLE_DFP);
-
- /*
- * Start sourcing Vconn before Vbus to ensure
- * we are within USB Type-C Spec 1.4 tVconnON
- */
- if (IS_ENABLED(CONFIG_USBC_VCONN))
- set_vconn(port, 1);
-
- /* Enable VBUS */
- if (pd_set_power_supply_ready(port)) {
- /* Stop sourcing Vconn if Vbus failed */
- if (IS_ENABLED(CONFIG_USBC_VCONN))
- set_vconn(port, 0);
-
- if (IS_ENABLED(CONFIG_USBC_SS_MUX))
- usb_mux_set(port, TYPEC_MUX_NONE,
- USB_SWITCH_DISCONNECT, tc[port].polarity);
- }
-#endif /* CONFIG_USB_PE_SM */
-
- /* Inform PPC that a sink is connected. */
- if (IS_ENABLED(CONFIG_USBC_PPC))
- ppc_sink_is_connected(port, 1);
-}
-
-static void tc_attached_src_run(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
- enum pd_cc_states new_cc_state;
-
-#ifdef CONFIG_USB_PE_SM
- /* Enable PD communications after power supply has fully turned on */
- if (tc[port].pd_enable == 0 &&
- get_time().val > tc[port].timeout) {
-
- tc[port].pd_enable = 1;
- tc[port].timeout = 0;
- }
-
- if (tc[port].pd_enable == 0)
- return;
-
- /*
- * Handle Hard Reset from Policy Engine
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET)) {
- if (get_time().val < tc[port].timeout)
- return;
- /*
- * This function clears TC_FLAGS_HARD_RESET
- * when the hard reset is complete.
- */
- tc_perform_src_hard_reset(port);
- }
-#endif
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- if (tc[port].polarity)
- cc1 = cc2;
-
- if (cc1 == TYPEC_CC_VOLT_OPEN)
- new_cc_state = PD_CC_NONE;
- else
- new_cc_state = PD_CC_UFP_ATTACHED;
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_SRC_DISCONNECT;
- }
-
- if (get_time().val < tc[port].cc_debounce)
- return;
-
- /*
- * When the SRC.Open state is detected on the monitored CC pin, a DRP
- * shall transition to Unattached.SNK unless it strongly prefers the
- * Source role. In that case, it shall transition to TryWait.SNK.
- * This transition to TryWait.SNK is needed so that two devices that
- * both prefer the Source role do not loop endlessly between Source
- * and Sink. In other words, a DRP that would enter Try.SRC from
- * AttachWait.SNK shall enter TryWait.SNK for a Sink detach from
- * Attached.SRC.
- */
- if (tc[port].cc_state == PD_CC_NONE &&
- !TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS) &&
- !TC_CHK_FLAG(port, TC_FLAGS_DISC_IDENT_IN_PROGRESS)) {
-
- if (IS_ENABLED(CONFIG_USB_PE_SM))
- if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- pd_dfp_exit_mode(port, 0, 0);
-
- tc[port].pd_enable = 0;
- set_state_tc(port, IS_ENABLED(CONFIG_USB_PD_TRY_SRC) ?
- TC_TRY_WAIT_SNK : TC_UNATTACHED_SNK);
- }
-
-#ifdef CONFIG_USB_PE_SM
- /*
- * PD swap commands
- */
- if (tc[port].pd_enable && prl_is_running(port)) {
- /*
- * Power Role Swap Request
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_DO_PR_SWAP)) {
- TC_CLR_FLAG(port, TC_FLAGS_DO_PR_SWAP);
- return set_state_tc(port, TC_ATTACHED_SNK);
- }
-
- /*
- * Data Role Swap Request
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_REQUEST_DR_SWAP)) {
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_DR_SWAP);
-
- /* Perform Data Role Swap */
- tc_set_data_role(port,
- tc[port].data_role == PD_ROLE_DFP ?
- PD_ROLE_UFP : PD_ROLE_DFP);
- }
-
- if (IS_ENABLED(CONFIG_USBC_VCONN)) {
- /*
- * VCONN Swap Request
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_ON)) {
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_ON);
- set_vconn(port, 1);
- pe_vconn_swap_complete(port);
- } else if (TC_CHK_FLAG(port,
- TC_FLAGS_REQUEST_VC_SWAP_OFF)) {
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_OFF);
- set_vconn(port, 0);
- pe_vconn_swap_complete(port);
- }
- }
-
- /*
- * A DRP that supports Charge-Through VCONN-Powered USB Devices
- * shall transition to CTUnattached.SNK if the connected device
- * identifies itself as a Charge-Through VCONN-Powered USB
- * Device in its Discover Identity Command response.
- */
-
- /*
- * A DRP that supports Charge-Through VCONN-Powered USB Devices
- * shall transition to CTUnattached.SNK if the connected device
- * identifies itself as a Charge-Through VCONN-Powered USB
- * Device in its Discover Identity Command response.
- *
- * If it detects that it is connected to a VCONN-Powered USB
- * Device, the port may remove VBUS and discharge it to
- * vSafe0V, while continuing to remain in this state with VCONN
- * applied.
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_CTVPD_DETECTED)) {
- TC_CLR_FLAG(port, TC_FLAGS_CTVPD_DETECTED);
-
- /* Clear TC_FLAGS_DISC_IDENT_IN_PROGRESS */
- TC_CLR_FLAG(port, TC_FLAGS_DISC_IDENT_IN_PROGRESS);
-
- set_state_tc(port, TC_CT_UNATTACHED_SNK);
- }
- }
-#endif
-}
-
-static void tc_attached_src_exit(const int port)
-{
- /*
- * A port shall cease to supply VBUS within tVBUSOFF of exiting
- * Attached.SRC.
- */
- tc_src_power_off(port);
-
- /* Disable VCONN if not power role swapping */
- if (TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON) &&
- !TC_CHK_FLAG(port, TC_FLAGS_DO_PR_SWAP))
- set_vconn(port, 0);
-
- /* Clear PR swap flag after checking for Vconn */
- TC_CLR_FLAG(port, TC_FLAGS_DO_PR_SWAP);
-}
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
-/**
- * DrpAutoToggle
- */
-static void tc_drp_auto_toggle_entry(const int port)
-{
- print_current_state(port);
-
- /*
- * The PD_EXIT_LOW_POWER_EVENT_MASK flag may have been set
- * due to a CC event. Clear it now since we haven't engaged
- * low power mode.
- */
- atomic_clear(task_get_event_bitmap(task_get_current()),
- PD_EXIT_LOW_POWER_EVENT_MASK);
-
- if (drp_state[port] == PD_DRP_TOGGLE_ON)
- tcpm_enable_drp_toggle(port);
-}
-
-static void tc_drp_auto_toggle_run(const int port)
-{
- enum pd_drp_next_states next_state;
- enum tcpc_cc_voltage_status cc1, cc2;
-
- /*
- * If SW decided we should be in a low power state and
- * the CC lines did not change, then don't talk with the
- * TCPC otherwise we might wake it up.
- */
- if (IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER)) {
- if (TC_CHK_FLAG(port, TC_FLAGS_LPM_REQUESTED) &&
- !TC_CHK_FLAG(port, TC_FLAGS_WAKE_FROM_LPM)) {
- if (get_time().val > tc[port].low_power_time)
- set_state_tc(port, TC_LOW_POWER_MODE);
- return;
- }
- }
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- tc[port].drp_sink_time = get_time().val;
- next_state = drp_auto_toggle_next_state(&tc[port].drp_sink_time,
- tc[port].power_role, drp_state[port], cc1, cc2);
-
- /*
- * The next state is not determined just by what is
- * attached, but also depends on DRP_STATE. Regardless
- * of next state, if nothing is attached, then always
- * request low power mode.
- */
- if (IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER)) {
- if (cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_OPEN &&
- !tc[port].tasks_preventing_lpm) {
- TC_SET_FLAG(port, TC_FLAGS_LPM_REQUESTED);
- TC_CLR_FLAG(port, TC_FLAGS_WAKE_FROM_LPM);
- }
- }
-
- switch (next_state) {
- case DRP_TC_DEFAULT:
- set_state_tc(port, PD_DEFAULT_STATE(port));
- break;
- case DRP_TC_UNATTACHED_SNK:
- set_state_tc(port, TC_UNATTACHED_SNK);
- break;
- case DRP_TC_UNATTACHED_SRC:
- set_state_tc(port, TC_UNATTACHED_SRC);
- break;
- case DRP_TC_DRP_AUTO_TOGGLE:
- /*
- * We are staying in PD_STATE_DRP_AUTO_TOGGLE
- */
- break;
- }
-}
-#endif /* CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE */
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
-static void tc_low_power_mode_entry(const int port)
-{
- print_current_state(port);
- CPRINTS("TCPC p%d Enter Low Power Mode", port);
- tcpm_enter_low_power_mode(port);
- TC_SET_FLAG(port, TC_FLAGS_LPM_ENGAGED);
-}
-
-static void tc_low_power_mode_run(const int port)
-{
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- if (TC_CHK_FLAG(port, TC_FLAGS_WAKE_FROM_LPM |
- TC_FLAGS_POWER_STATE_CHANGE)) {
- set_state_tc(port, TC_DRP_AUTO_TOGGLE);
- return;
- }
-#endif
- tc_pause_event_loop(port);
-}
-
-static void tc_low_power_mode_exit(const int port)
-{
- CPRINTS("TCPC p%d Exit Low Power Mode", port);
- TC_CLR_FLAG(port, TC_FLAGS_LPM_REQUESTED | TC_FLAGS_LPM_ENGAGED |
- TC_FLAGS_WAKE_FROM_LPM | TC_FLAGS_POWER_STATE_CHANGE);
- reset_device_and_notify(port);
- tc_start_event_loop(port);
-}
-#endif
-
-
-/**
- * Try.SRC
- *
- * Super State Entry Actions:
- * Vconn Off
- * Place Rp on CC
- * Set power role to SOURCE
- */
-#ifdef CONFIG_USB_PD_TRY_SRC
-static void tc_try_src_entry(const int port)
-{
- print_current_state(port);
-
- tc[port].cc_state = PD_CC_UNSET;
- tc[port].try_wait_debounce = get_time().val + PD_T_DRP_TRY;
- tc[port].timeout = get_time().val + PD_T_TRY_TIMEOUT;
-}
-
-static void tc_try_src_run(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
- enum pd_cc_states new_cc_state;
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- if ((cc1 == TYPEC_CC_VOLT_RD && cc2 != TYPEC_CC_VOLT_RD) ||
- (cc1 != TYPEC_CC_VOLT_RD && cc2 == TYPEC_CC_VOLT_RD))
- new_cc_state = PD_CC_UFP_ATTACHED;
- else
- new_cc_state = PD_CC_NONE;
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE;
- }
-
- /*
- * The port shall transition to Attached.SRC when the SRC.Rd state is
- * detected on exactly one of the CC1 or CC2 pins for at least
- * tTryCCDebounce.
- */
- if (get_time().val > tc[port].cc_debounce) {
- if (new_cc_state == PD_CC_UFP_ATTACHED)
- set_state_tc(port, TC_ATTACHED_SRC);
- }
-
- /*
- * The port shall transition to TryWait.SNK after tDRPTry and the
- * SRC.Rd state has not been detected and VBUS is within vSafe0V,
- * or after tTryTimeout and the SRC.Rd state has not been detected.
- */
- if (new_cc_state == PD_CC_NONE) {
- if ((get_time().val > tc[port].try_wait_debounce &&
- !pd_is_vbus_present(port)) ||
- get_time().val > tc[port].timeout) {
- set_state_tc(port, TC_TRY_WAIT_SNK);
- }
- }
-}
-
-/**
- * TryWait.SNK
- *
- * Super State Entry Actions:
- * Vconn Off
- * Place Rd on CC
- * Set power role to SINK
- */
-static void tc_try_wait_snk_entry(const int port)
-{
- print_current_state(port);
-
- tc[port].cc_state = PD_CC_UNSET;
- tc[port].try_wait_debounce = get_time().val + PD_T_CC_DEBOUNCE;
-}
-
-static void tc_try_wait_snk_run(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
- enum pd_cc_states new_cc_state;
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- /* We only care about CCs being open */
- if (cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_OPEN)
- new_cc_state = PD_CC_NONE;
- else
- new_cc_state = PD_CC_UNSET;
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].pd_debounce = get_time().val + PD_T_PD_DEBOUNCE;
- }
-
- /*
- * The port shall transition to Unattached.SNK when the state of both
- * of the CC1 and CC2 pins is SNK.Open for at least tPDDebounce.
- */
- if ((get_time().val > tc[port].pd_debounce) &&
- (new_cc_state == PD_CC_NONE)) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /*
- * The port shall transition to Attached.SNK after tCCDebounce if or
- * when VBUS is detected.
- */
- if (get_time().val > tc[port].try_wait_debounce &&
- pd_is_vbus_present(port))
- set_state_tc(port, TC_ATTACHED_SNK);
-}
-
-#endif
-
-#if defined(CONFIG_USB_PE_SM)
-/*
- * CTUnattached.SNK
- */
-static void tc_ct_unattached_snk_entry(int port)
-{
- print_current_state(port);
-
- /*
- * Both CC1 and CC2 pins shall be independently terminated to
- * ground through Rd.
- */
- tcpm_select_rp_value(port, CONFIG_USB_PD_PULLUP);
- tcpm_set_cc(port, TYPEC_CC_RD);
- tc[port].cc_state = PD_CC_UNSET;
-
- /* Set power role to sink */
- tc_set_power_role(port, PD_ROLE_SINK);
- tcpm_set_msg_header(port, tc[port].power_role, tc[port].data_role);
-
- /*
- * The policy engine is in the disabled state. Disable PD and
- * re-enable it
- */
- tc[port].pd_enable = 0;
-
- tc[port].timeout = get_time().val + PD_POWER_SUPPLY_TURN_ON_DELAY;
-}
-
-static void tc_ct_unattached_snk_run(int port)
-{
- enum tcpc_cc_voltage_status cc1;
- enum tcpc_cc_voltage_status cc2;
- enum pd_cc_states new_cc_state;
-
- if (tc[port].timeout > 0 && get_time().val > tc[port].timeout) {
- tc[port].pd_enable = 1;
- tc[port].timeout = 0;
- }
-
- if (tc[port].timeout > 0)
- return;
-
- /* Wait until Protocol Layer is ready */
- if (!prl_is_running(port))
- return;
-
- /*
- * Hard Reset is sent when the PE layer is disabled due to a
- * CTVPD connection.
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET)) {
- TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET);
- /* Nothing to do. Just signal hard reset completion */
- pe_ps_reset_complete(port);
- }
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- /* We only care about CCs being open */
- if (cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_OPEN)
- new_cc_state = PD_CC_NONE;
- else
- new_cc_state = PD_CC_UNSET;
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_VPDDETACH;
- }
-
- /*
- * The port shall transition to Unattached.SNK if the state of
- * the CC pin is SNK.Open for tVPDDetach after VBUS is vSafe0V.
- */
- if (get_time().val > tc[port].cc_debounce) {
- if (new_cc_state == PD_CC_NONE && !pd_is_vbus_present(port)) {
- if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- pd_dfp_exit_mode(port, 0, 0);
-
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
- }
-
- /*
- * The port shall transition to CTAttached.SNK when VBUS is detected.
- */
- if (pd_is_vbus_present(port))
- set_state_tc(port, TC_CT_ATTACHED_SNK);
-}
-
-/**
- * CTAttached.SNK
- */
-static void tc_ct_attached_snk_entry(int port)
-{
- print_current_state(port);
-
- /* The port shall reject a VCONN swap request. */
- TC_SET_FLAG(port, TC_FLAGS_REJECT_VCONN_SWAP);
-}
-
-static void tc_ct_attached_snk_run(int port)
-{
- /*
- * Hard Reset is sent when the PE layer is disabled due to a
- * CTVPD connection.
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET)) {
- TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET);
- /* Nothing to do. Just signal hard reset completion */
- pe_ps_reset_complete(port);
- }
-
- /*
- * A port that is not in the process of a USB PD Hard Reset shall
- * transition to CTUnattached.SNK within tSinkDisconnect when VBUS
- * falls below vSinkDisconnect
- */
- if (!pd_is_vbus_present(port)) {
- set_state_tc(port, TC_CT_UNATTACHED_SNK);
- return;
- }
-
- /*
- * The port shall operate in one of the Sink Power Sub-States
- * and remain within the Sink Power Sub-States, until either VBUS is
- * removed or a USB PD contract is established with the source.
- */
- if (!pe_is_explicit_contract(port))
- sink_power_sub_states(port);
-}
-
-static void tc_ct_attached_snk_exit(int port)
-{
- /* Stop drawing power */
- sink_stop_drawing_current(port);
-
- TC_CLR_FLAG(port, TC_FLAGS_REJECT_VCONN_SWAP);
-}
-#endif /* CONFIG_USB_PE_SM */
-
-/**
- * Super State CC_RD
- */
-static void tc_cc_rd_entry(const int port)
-{
- /* Disable VCONN */
- if (IS_ENABLED(CONFIG_USBC_VCONN))
- set_vconn(port, 0);
-
- /* Set power role to sink */
- tc_set_power_role(port, PD_ROLE_SINK);
- tcpm_set_msg_header(port, tc[port].power_role, tc[port].data_role);
-
- /*
- * Both CC1 and CC2 pins shall be independently terminated to
- * ground through Rd.
- */
- tcpm_set_cc(port, TYPEC_CC_RD);
-}
-
-
-/**
- * Super State CC_RP
- */
-static void tc_cc_rp_entry(const int port)
-{
- /* Disable VCONN */
- if (IS_ENABLED(CONFIG_USBC_VCONN))
- set_vconn(port, 0);
-
- /* Set power role to source */
- tc_set_power_role(port, PD_ROLE_SOURCE);
- tcpm_set_msg_header(port, tc[port].power_role, tc[port].data_role);
-
- /*
- * Both CC1 and CC2 pins shall be independently pulled
- * up through Rp.
- */
- tcpm_select_rp_value(port, CONFIG_USB_PD_PULLUP);
- tcpm_set_cc(port, TYPEC_CC_RP);
-}
-
-/**
- * Super State CC_OPEN
- */
-static void tc_cc_open_entry(const int port)
-{
- /* Disable VBUS */
- pd_power_supply_reset(port);
-
- /* Disable VCONN */
- if (TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON))
- set_vconn(port, 0);
-
- /* Remove terminations from CC */
- tcpm_set_cc(port, TYPEC_CC_OPEN);
-
- if (IS_ENABLED(CONFIG_USBC_PPC)) {
- /* There is no sink connected. */
- ppc_sink_is_connected(port, 0);
-
- /*
- * Clear the overcurrent event counter
- * since we've detected a disconnect.
- */
- ppc_clear_oc_event_counter(port);
- }
-}
-
-void tc_run(const int port)
-{
- run_state(port, &tc[port].ctx);
-}
-
-/**
- * This function checks the current CC status of the port partner
- * and returns true if the attached partner is UFP.
- */
-int pd_partner_is_ufp(int port)
-{
- return tc[port].cc_state == PD_CC_UFP_ATTACHED ||
- tc[port].cc_state == PD_CC_UFP_DEBUG_ACC ||
- tc[port].cc_state == PD_CC_UFP_AUDIO_ACC;
-}
-
-int pd_is_debug_acc(int port)
-{
- return tc[port].cc_state == PD_CC_UFP_DEBUG_ACC ||
- tc[port].cc_state == PD_CC_DFP_DEBUG_ACC;
-}
-
-static void pd_chipset_resume(void)
-{
- int i;
-
- for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) {
- pd_set_dual_role(i, PD_DRP_TOGGLE_ON);
- task_set_event(PD_PORT_TO_TASK_ID(i),
- PD_EVENT_POWER_STATE_CHANGE, 0);
- }
-
- CPRINTS("PD:S3->S0");
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, pd_chipset_resume, HOOK_PRIO_DEFAULT);
-
-static void pd_chipset_suspend(void)
-{
- int i;
-
- for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) {
- pd_set_dual_role(i, PD_DRP_TOGGLE_OFF);
- task_set_event(PD_PORT_TO_TASK_ID(i),
- PD_EVENT_POWER_STATE_CHANGE, 0);
- }
-
- CPRINTS("PD:S0->S3");
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, pd_chipset_suspend, HOOK_PRIO_DEFAULT);
-
-static void pd_chipset_startup(void)
-{
- int i;
-
- for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) {
- pd_set_dual_role_no_wakeup(i, PD_DRP_TOGGLE_OFF);
- task_set_event(PD_PORT_TO_TASK_ID(i),
- PD_EVENT_POWER_STATE_CHANGE |
- PD_EVENT_UPDATE_DUAL_ROLE,
- 0);
- }
-
- CPRINTS("PD:S5->S3");
-}
-DECLARE_HOOK(HOOK_CHIPSET_STARTUP, pd_chipset_startup, HOOK_PRIO_DEFAULT);
-
-static void pd_chipset_shutdown(void)
-{
- int i;
-
- for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) {
- pd_set_dual_role_no_wakeup(i, PD_DRP_FORCE_SINK);
- task_set_event(PD_PORT_TO_TASK_ID(i),
- PD_EVENT_POWER_STATE_CHANGE |
- PD_EVENT_UPDATE_DUAL_ROLE,
- 0);
- }
-
- CPRINTS("PD:S3->S5");
-}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pd_chipset_shutdown, HOOK_PRIO_DEFAULT);
-
-
-/*
- * Type-C State Hierarchy (Sub-States are listed inside the boxes)
- *
- * |TC_UNATTACHED ---------|
- * | |
- * | TC_UNATTACHED_SNK |
- * | TC_UNATTACHED_SRC |
- * |-----------------------|
- *
- * |TC_CC_RD --------------| |TC_CC_RP ------------------------|
- * | | | |
- * | TC_ATTACH_WAIT_SNK | | TC_ATTACH_WAIT_SRC |
- * | TC_TRY_WAIT_SNK | | TC_TRY_SRC |
- * | TC_DBG_ACC_SNK | | TC_UNORIENTED_DBG_ACC_SRC |
- * |-----------------------| |---------------------------------|
- *
- * |TC_CC_OPEN -----------|
- * | |
- * | TC_DISABLED |
- * | TC_ERROR_RECOVERY |
- * |----------------------|
- *
- * TC_ATTACHED_SNK TC_ATTACHED_SRC TC_DRP_AUTO_TOGGLE TC_LOW_POWER_MODE
- *
- */
-static const struct usb_state tc_states[] = {
- /* Super States */
- [TC_CC_OPEN] = {
- .entry = tc_cc_open_entry,
- },
- [TC_CC_RD] = {
- .entry = tc_cc_rd_entry,
- },
- [TC_CC_RP] = {
- .entry = tc_cc_rp_entry,
- },
- /* Normal States */
- [TC_DISABLED] = {
- .entry = tc_disabled_entry,
- .run = tc_disabled_run,
- .exit = tc_disabled_exit,
- .parent = &tc_states[TC_CC_OPEN],
- },
- [TC_ERROR_RECOVERY] = {
- .entry = tc_error_recovery_entry,
- .run = tc_error_recovery_run,
- .parent = &tc_states[TC_CC_OPEN],
- },
- [TC_UNATTACHED_SNK] = {
- .entry = tc_unattached_snk_entry,
- .run = tc_unattached_snk_run,
- .parent = &tc_states[TC_CC_RD],
- },
- [TC_ATTACH_WAIT_SNK] = {
- .entry = tc_attach_wait_snk_entry,
- .run = tc_attach_wait_snk_run,
- .parent = &tc_states[TC_CC_RD],
- },
- [TC_ATTACHED_SNK] = {
- .entry = tc_attached_snk_entry,
- .run = tc_attached_snk_run,
- .exit = tc_attached_snk_exit,
- },
- [TC_UNORIENTED_DBG_ACC_SRC] = {
- .entry = tc_unoriented_dbg_acc_src_entry,
- .run = tc_unoriented_dbg_acc_src_run,
- .exit = tc_unoriented_dbg_acc_src_exit,
- .parent = &tc_states[TC_CC_RP],
- },
- [TC_DBG_ACC_SNK] = {
- .entry = tc_dbg_acc_snk_entry,
- .run = tc_dbg_acc_snk_run,
- .exit = tc_dbg_acc_snk_exit,
- .parent = &tc_states[TC_CC_RD],
- },
- [TC_UNATTACHED_SRC] = {
- .entry = tc_unattached_src_entry,
- .run = tc_unattached_src_run,
- .parent = &tc_states[TC_CC_RP],
- },
- [TC_ATTACH_WAIT_SRC] = {
- .entry = tc_attach_wait_src_entry,
- .run = tc_attach_wait_src_run,
- .parent = &tc_states[TC_CC_RP],
- },
- [TC_ATTACHED_SRC] = {
- .entry = tc_attached_src_entry,
- .run = tc_attached_src_run,
- .exit = tc_attached_src_exit,
- },
-#ifdef CONFIG_USB_PD_TRY_SRC
- [TC_TRY_SRC] = {
- .entry = tc_try_src_entry,
- .run = tc_try_src_run,
- .parent = &tc_states[TC_CC_RP],
- },
- [TC_TRY_WAIT_SNK] = {
- .entry = tc_try_wait_snk_entry,
- .run = tc_try_wait_snk_run,
- .parent = &tc_states[TC_CC_RD],
- },
-#endif /* CONFIG_USB_PD_TRY_SRC */
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- [TC_DRP_AUTO_TOGGLE] = {
- .entry = tc_drp_auto_toggle_entry,
- .run = tc_drp_auto_toggle_run,
- },
-#endif /* CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE */
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- [TC_LOW_POWER_MODE] = {
- .entry = tc_low_power_mode_entry,
- .run = tc_low_power_mode_run,
- .exit = tc_low_power_mode_exit,
- },
-#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */
-#ifdef CONFIG_USB_PE_SM
- [TC_CT_UNATTACHED_SNK] = {
- .entry = tc_ct_unattached_snk_entry,
- .run = tc_ct_unattached_snk_run,
- },
- [TC_CT_ATTACHED_SNK] = {
- .entry = tc_ct_attached_snk_entry,
- .run = tc_ct_attached_snk_run,
- .exit = tc_ct_attached_snk_exit,
- },
-#endif
-};
-
-#ifdef TEST_BUILD
-const struct test_sm_data test_tc_sm_data[] = {
- {
- .base = tc_states,
- .size = ARRAY_SIZE(tc_states),
- .names = tc_state_names,
- .names_size = ARRAY_SIZE(tc_state_names),
- },
-};
-const int test_tc_sm_data_size = ARRAY_SIZE(test_tc_sm_data);
-#endif
diff --git a/common/usbc/usb_tc_vpd_sm.c b/common/usbc/usb_tc_vpd_sm.c
deleted file mode 100644
index 8dfed4226b..0000000000
--- a/common/usbc/usb_tc_vpd_sm.c
+++ /dev/null
@@ -1,399 +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 "common.h"
-#include "console.h"
-#include "system.h"
-#include "task.h"
-#include "tcpm.h"
-#include "usb_pd.h"
-#include "usb_tc_sm.h"
-#include "usb_sm.h"
-#include "vpd_api.h"
-
-/* USB Type-C VCONN Powered Device module */
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USB, format, ## args)
-#else /* CONFIG_COMMON_RUNTIME */
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif
-
-/* Type-C Layer Flags */
-#define TC_FLAGS_VCONN_ON BIT(0)
-
-/**
- * This is the Type-C Port object that contains information needed to
- * implement a VCONN Powered Device.
- */
-static struct type_c {
- /* state machine context */
- struct sm_ctx ctx;
- /* Higher-level power deliver state machines are enabled if true. */
- uint8_t pd_enable;
- /* port flags, see TC_FLAGS_* */
- uint32_t flags;
- /* Time a port shall wait before it can determine it is attached */
- uint64_t cc_debounce;
- /* VPD host port cc state */
- enum pd_cc_states host_cc_state;
- uint8_t ct_cc;
-} tc[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* List of all TypeC-level states */
-enum usb_tc_state {
- /* Normal States */
- TC_DISABLED,
- TC_UNATTACHED_SNK,
- TC_ATTACH_WAIT_SNK,
- TC_ATTACHED_SNK,
- /* Super States */
- TC_VBUS_CC_ISO,
- TC_HOST_RARD,
- TC_HOST_OPEN,
-};
-/* Forward declare the full list of states. This is indexed by usb_tc_state */
-static const struct usb_state tc_states[];
-
-#ifdef CONFIG_COMMON_RUNTIME
-/* List of human readable state names for console debugging */
-static const char * const tc_state_names[] = {
- [TC_DISABLED] = "Disabled",
- [TC_UNATTACHED_SNK] = "Unattached.SNK",
- [TC_ATTACH_WAIT_SNK] = "AttachWait.SNK",
- [TC_ATTACHED_SNK] = "Attached.SNK",
-};
-#endif
-
-/* Forward declare private, common functions */
-static void set_state_tc(const int port, enum usb_tc_state new_state);
-
-/* Public TypeC functions */
-
-void tc_state_init(int port)
-{
- int res = 0;
-
- res = tc_restart_tcpc(port);
-
- CPRINTS("TCPC p%d init %s", port, res ? "failed" : "ready");
-
- /* Disable TCPC RX until connection is established */
- tcpm_set_rx_enable(port, 0);
-
- set_state_tc(port, res ? TC_DISABLED : TC_UNATTACHED_SNK);
-
- /* Disable pd state machines */
- tc[port].pd_enable = 0;
- tc[port].flags = 0;
-}
-
-enum pd_power_role tc_get_power_role(int port)
-{
- /* Vconn power device is always the sink */
- return PD_ROLE_SINK;
-}
-
-enum pd_cable_plug tc_get_cable_plug(int port)
-{
- /* Vconn power device is always the cable */
- return PD_PLUG_FROM_CABLE;
-}
-
-enum pd_data_role tc_get_data_role(int port)
-{
- /* Vconn power device doesn't have a data role, but UFP match SNK */
- return PD_ROLE_UFP;
-}
-
-/* Note tc_set_power_role and tc_set_data_role are unimplemented */
-
-uint8_t tc_get_polarity(int port)
-{
- /* Does not track polarity yet */
- return 0;
-}
-
-uint8_t tc_get_pd_enabled(int port)
-{
- return tc[port].pd_enable;
-}
-
-void tc_event_check(int port, int evt)
-{
- /* Do Nothing */
-}
-
-/*
- * Private Functions
- */
-
-/* Set the TypeC state machine to a new state. */
-static void set_state_tc(const int port, const enum usb_tc_state new_state)
-{
- set_state(port, &tc[port].ctx, &tc_states[new_state]);
-}
-
-/* Get the current TypeC state. */
-test_export_static enum usb_tc_state get_state_tc(const int port)
-{
- return tc[port].ctx.current - &tc_states[0];
-}
-
-test_mockable_static void print_current_state(const int port)
-{
- CPRINTS("C%d: %s", port, tc_state_names[get_state_tc(port)]);
-}
-
-/**
- * Disabled
- *
- * Super State Entries:
- * Enable mcu communication
- * Remove the terminations from Host CC
- */
-static void tc_disabled_entry(const int port)
-{
- print_current_state(port);
-}
-
-static void tc_disabled_run(const int port)
-{
- task_wait_event(-1);
-}
-
-static void tc_disabled_exit(const int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_TCPC)) {
- if (tc_restart_tcpc(port) != 0) {
- CPRINTS("TCPC p%d restart failed!", port);
- return;
- }
- }
-
- CPRINTS("TCPC p%d resumed!", port);
-}
-
-/**
- * Unattached.SNK
- *
- * Super State Entry:
- * Enable mcu communication
- * Place Ra on VCONN and Rd on Host CC
- */
-static void tc_unattached_snk_entry(const int port)
-{
- print_current_state(port);
-}
-
-static void tc_unattached_snk_run(const int port)
-{
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- /*
- * Transition to AttachWait.SNK when a Source connection is
- * detected, as indicated by the SNK.Rp state on its Host-side
- * port’s CC pin.
- */
- if (cc_is_rp(host_cc))
- set_state_tc(port, TC_ATTACH_WAIT_SNK);
-}
-
-/**
- * AttachedWait.SNK
- *
- * Super State Entry:
- * Enable mcu communication
- * Place Ra on VCONN and Rd on Host CC
- */
-static void tc_attach_wait_snk_entry(const int port)
-{
- print_current_state(port);
-
- /* Forces an initial debounce in run function */
- tc[port].host_cc_state = -1;
-}
-
-static void tc_attach_wait_snk_run(const int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (cc_is_rp(host_cc))
- host_new_cc_state = PD_CC_DFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- if (host_new_cc_state == PD_CC_DFP_ATTACHED)
- tc[port].cc_debounce = get_time().val +
- PD_T_CC_DEBOUNCE;
- else
- tc[port].cc_debounce = get_time().val +
- PD_T_PD_DEBOUNCE;
-
- return;
- }
-
- /* Wait for Host CC debounce */
- if (get_time().val < tc[port].cc_debounce)
- return;
-
- /*
- * A VCONN-Powered USB Device shall transition to
- * Attached.SNK after the state of the Host-side port’s CC pin is
- * SNK.Rp for at least tCCDebounce and either host-side VCONN or
- * VBUS is detected.
- *
- * Transition to Unattached.SNK when the state of both the CC1 and
- * CC2 pins is SNK.Open for at least tPDDebounce.
- */
- if (tc[port].host_cc_state == PD_CC_DFP_ATTACHED &&
- (vpd_is_vconn_present() || vpd_is_host_vbus_present()))
- set_state_tc(port, TC_ATTACHED_SNK);
- else if (tc[port].host_cc_state == PD_CC_NONE)
- set_state_tc(port, TC_UNATTACHED_SNK);
-}
-
-/**
- * Attached.SNK
- */
-static void tc_attached_snk_entry(const int port)
-{
- print_current_state(port);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- set_polarity(port, 0);
-}
-
-static void tc_attached_snk_run(const int port)
-{
- /* Has host vbus and vconn been removed */
- if (!vpd_is_host_vbus_present() && !vpd_is_vconn_present()) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- if (vpd_is_vconn_present()) {
- if (!(tc[port].flags & TC_FLAGS_VCONN_ON)) {
- /* VCONN detected. Remove RA */
- vpd_host_set_pull(TYPEC_CC_RD, 0);
- tc[port].flags |= TC_FLAGS_VCONN_ON;
- }
- }
-}
-
-static void tc_attached_snk_exit(const int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
- tc[port].flags &= ~TC_FLAGS_VCONN_ON;
-}
-
-/**
- * Super State HOST_RARD
- */
-static void tc_host_rard_entry(const int port)
-{
- /* Place Ra on VCONN and Rd on Host CC */
- vpd_host_set_pull(TYPEC_CC_RA_RD, 0);
-}
-
-/**
- * Super State HOST_OPEN
- */
-static void tc_host_open_entry(const int port)
-{
- /* Remove the terminations from Host CC */
- vpd_host_set_pull(TYPEC_CC_OPEN, 0);
-}
-
-/**
- * Super State VBUS_CC_ISO
- */
-static void tc_vbus_cc_iso_entry(const int port)
-{
- /* Enable mcu communication and cc */
- vpd_mcu_cc_en(1);
-}
-
-void tc_run(const int port)
-{
- run_state(port, &tc[port].ctx);
-}
-
-/*
- * Type-C State Hierarchy (Sub-States are listed inside the boxes)
- *
- * | TC_VBUS_CC_ISO ----------------------------------------|
- * | |
- * | | TC_HOST_RARD -----------| | TC_HOST_OPEN ---------| |
- * | | | | | |
- * | | TC_UNATTACHED_SNK | | TC_DISABLED | |
- * | | TC_ATTACH_WAIT_SNK | |-----------------------| |
- * | |-------------------------| |
- * |--------------------------------------------------------|
- *
- * TC_ATTACHED_SNK
- */
-static const struct usb_state tc_states[] = {
- /* Super States */
- [TC_VBUS_CC_ISO] = {
- .entry = tc_vbus_cc_iso_entry,
- },
- [TC_HOST_RARD] = {
- .entry = tc_host_rard_entry,
- .parent = &tc_states[TC_VBUS_CC_ISO],
- },
- [TC_HOST_OPEN] = {
- .entry = tc_host_open_entry,
- .parent = &tc_states[TC_VBUS_CC_ISO],
- },
- /* Normal States */
- [TC_DISABLED] = {
- .entry = tc_disabled_entry,
- .run = tc_disabled_run,
- .exit = tc_disabled_exit,
- .parent = &tc_states[TC_HOST_OPEN],
- },
- [TC_UNATTACHED_SNK] = {
- .entry = tc_unattached_snk_entry,
- .run = tc_unattached_snk_run,
- .parent = &tc_states[TC_HOST_RARD],
- },
- [TC_ATTACH_WAIT_SNK] = {
- .entry = tc_attach_wait_snk_entry,
- .run = tc_attach_wait_snk_run,
- .parent = &tc_states[TC_HOST_RARD],
- },
- [TC_ATTACHED_SNK] = {
- .entry = tc_attached_snk_entry,
- .run = tc_attached_snk_run,
- .exit = tc_attached_snk_exit,
- },
-};
-
-#ifdef TEST_BUILD
-const struct test_sm_data test_tc_sm_data[] = {
- {
- .base = tc_states,
- .size = ARRAY_SIZE(tc_states),
- .names = tc_state_names,
- .names_size = ARRAY_SIZE(tc_state_names),
- },
-};
-const int test_tc_sm_data_size = ARRAY_SIZE(test_tc_sm_data);
-#endif
diff --git a/common/usbc/usbc_task.c b/common/usbc/usbc_task.c
deleted file mode 100644
index 219cf73b9a..0000000000
--- a/common/usbc/usbc_task.c
+++ /dev/null
@@ -1,204 +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 "ec_commands.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "registers.h"
-#include "system.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-#include "usb_charge.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "usb_prl_sm.h"
-#include "tcpm.h"
-#include "usb_pe_sm.h"
-#include "usb_prl_sm.h"
-#include "usb_sm.h"
-#include "usb_tc_sm.h"
-#include "usbc_ppc.h"
-#include "version.h"
-
-#define USBC_EVENT_TIMEOUT (5 * MSEC)
-
-static uint8_t paused;
-
-int tc_restart_tcpc(int port)
-{
- return tcpm_init(port);
-}
-
-void tc_pause_event_loop(int port)
-{
- paused = 1;
-}
-
-void tc_start_event_loop(int port)
-{
- paused = 0;
- task_set_event(PD_PORT_TO_TASK_ID(port), TASK_EVENT_WAKE, 0);
-}
-
-void set_polarity(int port, int polarity)
-{
- tcpm_set_polarity(port, polarity);
-
- if (IS_ENABLED(CONFIG_USBC_PPC_POLARITY))
- ppc_set_polarity(port, polarity);
-}
-
-void set_usb_mux_with_current_data_role(int port)
-{
-#ifdef CONFIG_USBC_SS_MUX
- /*
- * If the SoC is down, then we disconnect the MUX to save power since
- * no one cares about the data lines.
- */
-#ifdef CONFIG_POWER_COMMON
- if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) {
- usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT,
- tc_get_polarity(port));
- return;
- }
-#endif /* CONFIG_POWER_COMMON */
-
- /*
- * When PD stack is disconnected, then mux should be disconnected, which
- * is also what happens in the set_state disconnection code. Once the
- * PD state machine progresses out of disconnect, the MUX state will
- * be set correctly again.
- */
- if (!pd_is_connected(port))
- usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT,
- tc_get_polarity(port));
- /*
- * If new data role isn't DFP and we only support DFP, also disconnect.
- */
- else if (IS_ENABLED(CONFIG_USBC_SS_MUX_DFP_ONLY) &&
- tc_get_data_role(port) != PD_ROLE_DFP)
- usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT,
- tc_get_polarity(port));
- /*
- * Otherwise connect mux since we are in S3+
- */
- else
- usb_mux_set(port, TYPEC_MUX_USB, USB_SWITCH_CONNECT,
- tc_get_polarity(port));
-#endif /* CONFIG_USBC_SS_MUX */
-}
-
-/* High-priority interrupt tasks implementations */
-#if defined(HAS_TASK_PD_INT_C0) || defined(HAS_TASK_PD_INT_C1) || \
- defined(HAS_TASK_PD_INT_C2)
-
-/* Used to conditionally compile code in main pd task. */
-#define HAS_DEFFERED_INTERRUPT_HANDLER
-
-/* Events for pd_interrupt_handler_task */
-#define PD_PROCESS_INTERRUPT (1<<0)
-
-static uint8_t pd_int_task_id[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-void schedule_deferred_pd_interrupt(const int port)
-{
- task_set_event(pd_int_task_id[port], PD_PROCESS_INTERRUPT, 0);
-}
-
-/*
- * Main task entry point that handles PD interrupts for a single port
- *
- * @param p The PD port number for which to handle interrupts (pointer is
- * reinterpreted as an integer directly).
- */
-void pd_interrupt_handler_task(void *p)
-{
- const int port = (int) p;
- const int port_mask = (PD_STATUS_TCPC_ALERT_0 << port);
-
- ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT);
-
- pd_int_task_id[port] = task_get_current();
-
- while (1) {
- const int evt = task_wait_event(-1);
-
- if (evt & PD_PROCESS_INTERRUPT) {
- /*
- * While the interrupt signal is asserted; we have more
- * work to do. This effectively makes the interrupt a
- * level-interrupt instead of an edge-interrupt without
- * having to enable/disable a real level-interrupt in
- * multiple locations.
- *
- * Also, if the port is disabled do not process
- * interrupts. Upon existing suspend, we schedule a
- * PD_PROCESS_INTERRUPT to check if we missed anything.
- */
- while ((tcpc_get_alert_status() & port_mask) &&
- pd_is_port_enabled(port))
- tcpc_alert(port);
- }
- }
-}
-#endif /* HAS_TASK_PD_INT_C0 || HAS_TASK_PD_INT_C1 || HAS_TASK_PD_INT_C2 */
-
-void pd_task(void *u)
-{
- int port = TASK_ID_TO_PD_PORT(task_get_current());
-
- tc_state_init(port);
-
- if (IS_ENABLED(CONFIG_USBC_PPC))
- ppc_init(port);
-
- /*
- * Since most boards configure the TCPC interrupt as edge
- * and it is possible that the interrupt line was asserted between init
- * and calling set_state, we need to process any pending interrupts now.
- * Otherwise future interrupts will never fire because another edge
- * never happens. Note this needs to happen after set_state() is called.
- */
- if (IS_ENABLED(HAS_DEFFERED_INTERRUPT_HANDLER))
- schedule_deferred_pd_interrupt(port);
-
-
- while (1) {
- /* wait for next event/packet or timeout expiration */
- const uint32_t evt =
- task_wait_event(paused ? -1 : USBC_EVENT_TIMEOUT);
-
- /* handle events that affect the state machine as a whole */
- tc_event_check(port, evt);
-
- /*
- * run port controller task to check CC and/or read incoming
- * messages
- */
- if (IS_ENABLED(CONFIG_USB_PD_TCPC))
- tcpc_run(port, evt);
-
- if (IS_ENABLED(CONFIG_USB_PE_SM))
- /* Run policy engine state machine */
- pe_run(port, evt, tc_get_pd_enabled(port));
-
- if (IS_ENABLED(CONFIG_USB_PRL_SM))
- /* Run protocol state machine */
- prl_run(port, evt, tc_get_pd_enabled(port));
-
- /* Run TypeC state machine */
- tc_run(port);
- }
-}
diff --git a/common/usbc_ppc.c b/common/usbc_ppc.c
deleted file mode 100644
index 816c53d06e..0000000000
--- a/common/usbc_ppc.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/* Copyright 2017 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.
- */
-
-/* USB-C Power Path Controller Common Code */
-
-#include "atomic.h"
-#include "common.h"
-#include "console.h"
-#include "hooks.h"
-#include "timer.h"
-#include "usbc_ppc.h"
-#include "util.h"
-
-#ifndef TEST_BUILD
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#else
-#define CPRINTF(args...)
-#define CPRINTS(args...)
-#endif
-
-/*
- * A per-port table that indicates how many VBUS overcurrent events have
- * occurred. This table is cleared after detecting a physical disconnect of the
- * sink.
- */
-static uint8_t oc_event_cnt_tbl[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-static uint32_t connected_ports;
-
-/* Simple wrappers to dispatch to the drivers. */
-
-int ppc_init(int port)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->init) {
- rv = ppc->drv->init(port);
- if (rv)
- CPRINTS("p%d: PPC init failed! (%d)", port, rv);
- else
- CPRINTS("p%d: PPC init'd.", port);
- }
-
- return rv;
-}
-
-int ppc_add_oc_event(int port)
-{
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- oc_event_cnt_tbl[port]++;
-
- /* The port overcurrented, so don't clear it's OC events. */
- atomic_clear(&connected_ports, 1 << port);
-
- if (oc_event_cnt_tbl[port] >= PPC_OC_CNT_THRESH)
- CPRINTS("C%d: OC event limit reached! "
- "Source path disabled until physical disconnect.",
- port);
- return EC_SUCCESS;
-}
-
-static void clear_oc_tbl(void)
-{
- int port;
-
- for (port = 0; port < ppc_cnt; port++)
- /*
- * Only clear the table if the port partner is no longer
- * attached after debouncing.
- */
- if ((!(BIT(port) & connected_ports)) &&
- oc_event_cnt_tbl[port]) {
- oc_event_cnt_tbl[port] = 0;
- CPRINTS("C%d: OC events cleared", port);
- }
-}
-DECLARE_DEFERRED(clear_oc_tbl);
-
-int ppc_clear_oc_event_counter(int port)
-{
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- /*
- * If we are clearing our event table in quick succession, we may be in
- * an overcurrent loop where we are also detecting a disconnect on the
- * CC pins. Therefore, let's not clear it just yet and the let the
- * limit be reached. This way, we won't send the hard reset and
- * actually detect the physical disconnect.
- */
- if (oc_event_cnt_tbl[port]) {
- hook_call_deferred(&clear_oc_tbl_data,
- PPC_OC_COOLDOWN_DELAY_US);
- }
- return EC_SUCCESS;
-}
-
-int ppc_is_sourcing_vbus(int port)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->is_sourcing_vbus)
- rv = ppc->drv->is_sourcing_vbus(port);
-
- return rv;
-}
-
-#ifdef CONFIG_USBC_PPC_POLARITY
-int ppc_set_polarity(int port, int polarity)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->set_polarity)
- rv = ppc->drv->set_polarity(port, polarity);
-
- return rv;
-}
-#endif
-
-int ppc_set_vbus_source_current_limit(int port, enum tcpc_rp_value rp)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->set_vbus_source_current_limit)
- rv = ppc->drv->set_vbus_source_current_limit(port, rp);
-
- return rv;
-}
-
-int ppc_discharge_vbus(int port, int enable)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->discharge_vbus)
- rv = ppc->drv->discharge_vbus(port, enable);
-
- return rv;
-}
-
-int ppc_is_port_latched_off(int port)
-{
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- return oc_event_cnt_tbl[port] >= PPC_OC_CNT_THRESH;
-}
-
-#ifdef CONFIG_USBC_PPC_SBU
-int ppc_set_sbu(int port, int enable)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->set_sbu)
- rv = ppc->drv->set_sbu(port, enable);
-
- return rv;
-}
-#endif /* defined(CONFIG_USBC_PPC_SBU) */
-
-#ifdef CONFIG_USBC_PPC_VCONN
-int ppc_set_vconn(int port, int enable)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- /*
- * Check our OC event counter. If we've exceeded our threshold, then
- * let's latch our source path off to prevent continuous cycling. When
- * the PD state machine detects a disconnection on the CC lines, we will
- * reset our OC event counter.
- */
- if (enable && ppc_is_port_latched_off(port))
- return EC_ERROR_ACCESS_DENIED;
-
- ppc = &ppc_chips[port];
- if (ppc->drv->set_vconn)
- rv = ppc->drv->set_vconn(port, enable);
-
- return rv;
-}
-#endif
-
-void ppc_sink_is_connected(int port, int is_connected)
-{
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return;
- }
-
- if (is_connected)
- atomic_or(&connected_ports, 1 << port);
- else
- atomic_clear(&connected_ports, 1 << port);
-}
-
-int ppc_vbus_sink_enable(int port, int enable)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->vbus_sink_enable)
- rv = ppc->drv->vbus_sink_enable(port, enable);
-
- return rv;
-}
-
-int ppc_enter_low_power_mode(int port)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->enter_low_power_mode)
- rv = ppc->drv->enter_low_power_mode(port);
-
- return rv;
-}
-
-int ppc_vbus_source_enable(int port, int enable)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- /*
- * Check our OC event counter. If we've exceeded our threshold, then
- * let's latch our source path off to prevent continuous cycling. When
- * the PD state machine detects a disconnection on the CC lines, we will
- * reset our OC event counter.
- */
- if (enable && ppc_is_port_latched_off(port))
- return EC_ERROR_ACCESS_DENIED;
-
- ppc = &ppc_chips[port];
- if (ppc->drv->vbus_source_enable)
- rv = ppc->drv->vbus_source_enable(port, enable);
-
- return rv;
-}
-
-#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC
-int ppc_is_vbus_present(int port)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
-
- if (ppc->drv->is_vbus_present)
- rv = ppc->drv->is_vbus_present(port);
-
- return rv;
-}
-#endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */
-
-#ifdef CONFIG_CMD_PPC_DUMP
-static int command_ppc_dump(int argc, char **argv)
-{
- int port;
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- port = atoi(argv[1]);
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->reg_dump)
- rv = ppc->drv->reg_dump(port);
-
- return rv;
-}
-DECLARE_CONSOLE_COMMAND(ppc_dump, command_ppc_dump, "<Type-C port>",
- "dump the PPC regs");
-#endif /* defined(CONFIG_CMD_PPC_DUMP) */
diff --git a/driver/build.mk b/driver/build.mk
index 020ee211a7..db6949f8ca 100644
--- a/driver/build.mk
+++ b/driver/build.mk
@@ -125,20 +125,6 @@ driver-$(CONFIG_TOUCHPAD_ST)+=touchpad_st.o
driver-$(CONFIG_THERMISTOR)+=temp_sensor/thermistor.o
driver-$(CONFIG_THERMISTOR_NCP15WB)+=temp_sensor/thermistor_ncp15wb.o
-# Type-C port controller (TCPC) drivers
-driver-$(CONFIG_USB_PD_TCPM_STUB)+=tcpm/stub.o
-driver-$(CONFIG_USB_PD_TCPM_TCPCI)+=tcpm/tcpci.o
-driver-$(CONFIG_USB_PD_TCPM_FUSB302)+=tcpm/fusb302.o
-driver-$(CONFIG_USB_PD_TCPM_MT6370)+=tcpm/mt6370.o
-driver-$(CONFIG_USB_PD_TCPM_ITE83XX)+=tcpm/it83xx.o
-driver-$(CONFIG_USB_PD_TCPM_ANX74XX)+=tcpm/anx74xx.o
-driver-$(CONFIG_USB_PD_TCPM_ANX7688)+=tcpm/anx7688.o
-driver-$(CONFIG_USB_PD_TCPM_ANX7447)+=tcpm/anx7447.o
-driver-$(CONFIG_USB_PD_TCPM_PS8751)+=tcpm/ps8xxx.o
-driver-$(CONFIG_USB_PD_TCPM_PS8805)+=tcpm/ps8xxx.o
-driver-$(CONFIG_USB_PD_TCPM_TUSB422)+=tcpm/tusb422.o
-driver-$(CONFIG_USB_PD_TCPM_NCT38XX)+=tcpm/nct38xx.o
-
# Type-C Retimer drivers
driver-$(CONFIG_USBC_RETIMER_INTEL_BB)+=retimer/bb_retimer.o
driver-$(CONFIG_USBC_RETIMER_PI3DPX1207)+=retimer/pi3dpx1207.o
diff --git a/driver/tcpm/anx7447.c b/driver/tcpm/anx7447.c
deleted file mode 100644
index 0af495251c..0000000000
--- a/driver/tcpm/anx7447.c
+++ /dev/null
@@ -1,680 +0,0 @@
-/* Copyright 2018 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.
- */
-
-/* ANX7447 port manager */
-
-#include "common.h"
-#include "anx7447.h"
-#include "console.h"
-#include "hooks.h"
-#include "tcpci.h"
-#include "tcpm.h"
-#include "timer.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args)
-
-#define ANX7447_VENDOR_ALERT BIT(15)
-
-#define ANX7447_REG_STATUS 0x82
-#define ANX7447_REG_STATUS_LINK BIT(0)
-
-#define ANX7447_REG_HPD 0x83
-#define ANX7447_REG_HPD_HIGH BIT(0)
-#define ANX7447_REG_HPD_IRQ BIT(1)
-#define ANX7447_REG_HPD_ENABLE BIT(2)
-
-#define vsafe5v_min (3800/25)
-#define vsafe0v_max (800/25)
-/*
- * These interface are workable while ADC is enabled, before
- * calling them should make sure ec driver finished chip initilization.
- */
-#define is_equal_greater_safe5v(port) \
- (((anx7447_get_vbus_voltage(port))) > vsafe5v_min)
-#define is_equal_greater_safe0v(port) \
- (((anx7447_get_vbus_voltage(port))) > vsafe0v_max)
-
-struct anx_state {
- uint16_t i2c_slave_addr_flags;
-};
-
-struct anx_usb_mux {
- int state;
-};
-
-static int anx7447_mux_set(int port, mux_state_t mux_state);
-
-static struct anx_state anx[CONFIG_USB_PD_PORT_MAX_COUNT];
-static struct anx_usb_mux mux[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/*
- * ANX7447 has two co-existence I2C slave addresses, TCPC slave address and
- * SPI slave address. The registers of TCPC slave address are partly compliant
- * with standard USB TCPC specification, and the registers in SPI slave
- * address controls the other functions (ex, hpd_level, mux_switch, and
- * so on). It can't use tcpc_read() and tcpc_write() to access SPI slave
- * address because its slave address has been set as TCPC in the structure
- * tcpc_config_t.
- * anx7447_reg_write() and anx7447_reg_read() are implemented here to access
- * ANX7447 SPI slave address.
- */
-const struct anx7447_i2c_addr anx7447_i2c_addrs_flags[] = {
- {AN7447_TCPC0_I2C_ADDR_FLAGS, AN7447_SPI0_I2C_ADDR_FLAGS},
- {AN7447_TCPC1_I2C_ADDR_FLAGS, AN7447_SPI1_I2C_ADDR_FLAGS},
- {AN7447_TCPC2_I2C_ADDR_FLAGS, AN7447_SPI2_I2C_ADDR_FLAGS},
- {AN7447_TCPC3_I2C_ADDR_FLAGS, AN7447_SPI3_I2C_ADDR_FLAGS}
-};
-
-static inline int anx7447_reg_write(int port, int reg, int val)
-{
- int rv = i2c_write8(tcpc_config[port].i2c_info.port,
- anx[port].i2c_slave_addr_flags,
- reg, val);
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- pd_device_accessed(port);
-#endif
- return rv;
-}
-
-static inline int anx7447_reg_read(int port, int reg, int *val)
-{
- int rv = i2c_read8(tcpc_config[port].i2c_info.port,
- anx[port].i2c_slave_addr_flags,
- reg, val);
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- pd_device_accessed(port);
-#endif
- return rv;
-}
-
-void anx7447_hpd_mode_en(int port)
-{
- int reg, rv;
-
- rv = anx7447_reg_read(port, ANX7447_REG_HPD_CTRL_0, &reg);
- if (rv)
- return;
-
- reg |= ANX7447_REG_HPD_MODE;
- anx7447_reg_write(port, ANX7447_REG_HPD_CTRL_0, reg);
-}
-
-void anx7447_hpd_output_en(int port)
-{
- int reg, rv;
-
- rv = anx7447_reg_read(port, ANX7447_REG_HPD_DEGLITCH_H, &reg);
- if (rv)
- return;
-
- reg |= ANX7447_REG_HPD_OEN;
- anx7447_reg_write(port, ANX7447_REG_HPD_DEGLITCH_H, reg);
-}
-
-void anx7447_set_hpd_level(int port, int hpd_lvl)
-{
- int reg, rv;
-
- rv = anx7447_reg_read(port, ANX7447_REG_HPD_CTRL_0, &reg);
- if (rv)
- return;
-
- if (hpd_lvl)
- reg |= ANX7447_REG_HPD_OUT;
- else
- reg &= ~ANX7447_REG_HPD_OUT;
- anx7447_reg_write(port, ANX7447_REG_HPD_CTRL_0, reg);
-}
-
-#ifdef CONFIG_USB_PD_TCPM_ANX7447_OCM_ERASE_COMMAND
-static inline void anx7447_reg_write_and(int port, int reg, int v_and)
-{
- int val;
-
- if (!anx7447_reg_read(port, reg, &val))
- anx7447_reg_write(port, reg, (val & v_and));
-}
-
-static inline void anx7447_reg_write_or(int port, int reg, int v_or)
-{
- int val;
-
- if (!anx7447_reg_read(port, reg, &val))
- anx7447_reg_write(port, reg, (val | v_or));
-}
-
-#define ANX7447_FLASH_DONE_TIMEOUT_US (100 * MSEC)
-
-static int anx7447_wait_for_flash_done(int port)
-{
- timestamp_t deadline;
- int rv;
- int r;
-
- deadline.val = get_time().val + ANX7447_FLASH_DONE_TIMEOUT_US;
- do {
- if (timestamp_expired(deadline, NULL))
- return EC_ERROR_TIMEOUT;
- rv = anx7447_reg_read(port, ANX7447_REG_R_RAM_CTRL, &r);
- if (rv)
- return rv;
- } while (!(r & ANX7447_R_RAM_CTRL_FLASH_DONE));
-
- return EC_SUCCESS;
-}
-
-static int anx7447_flash_write_en(int port)
-{
- anx7447_reg_write(port, ANX7447_REG_FLASH_INST_TYPE,
- ANX7447_FLASH_INST_TYPE_WRITEENABLE);
- anx7447_reg_write_or(port, ANX7447_REG_R_FLASH_RW_CTRL,
- ANX7447_R_FLASH_RW_CTRL_GENERAL_INST_EN);
- return anx7447_wait_for_flash_done(port);
-}
-
-static int anx7447_flash_op_init(int port)
-{
- int rv;
-
- anx7447_reg_write_or(port, ANX7447_REG_OCM_CTRL_0,
- ANX7447_OCM_CTRL_OCM_RESET);
- anx7447_reg_write_or(port, ANX7447_REG_ADDR_GPIO_CTRL_0,
- ANX7447_ADDR_GPIO_CTRL_0_SPI_WP);
-
- rv = anx7447_flash_write_en(port);
- if (rv)
- return rv;
-
- anx7447_reg_write_and(port, ANX7447_REG_R_FLASH_STATUS_0,
- ANX7447_FLASH_STATUS_SPI_STATUS_0);
- anx7447_reg_write_or(port, ANX7447_REG_R_FLASH_RW_CTRL,
- ANX7447_R_FLASH_RW_CTRL_WRITE_STATUS_EN);
-
- return anx7447_wait_for_flash_done(port);
-}
-
-static int anx7447_flash_is_empty(int port)
-{
- int r;
-
- anx7447_reg_read(port, ANX7447_REG_OCM_VERSION, &r);
-
- return ((r == 0) ? 1 : 0);
-}
-
-static int anx7447_flash_erase_internal(int port, int write_console_if_empty)
-{
- int rv;
- int r;
-
- tcpc_read(port, TCPC_REG_COMMAND, &r);
- usleep(ANX7447_DELAY_IN_US);
-
- if (anx7447_flash_is_empty(port) == 1) {
- if (write_console_if_empty)
- CPRINTS("C%d: Nothing to erase!", port);
- return EC_SUCCESS;
- }
- CPRINTS("C%d: Erasing OCM flash...", port);
-
- rv = anx7447_flash_op_init(port);
- if (rv)
- return rv;
-
- usleep(ANX7447_DELAY_IN_US);
-
- rv = anx7447_flash_write_en(port);
- if (rv)
- return rv;
-
- anx7447_reg_write(port, ANX7447_REG_FLASH_ERASE_TYPE,
- ANX7447_FLASH_ERASE_TYPE_CHIPERASE);
- anx7447_reg_write_or(port, ANX7447_REG_R_FLASH_RW_CTRL,
- ANX7447_R_FLASH_RW_CTRL_FLASH_ERASE_EN);
-
- return anx7447_wait_for_flash_done(port);
-}
-
-int anx7447_flash_erase(int port)
-{
- return anx7447_flash_erase_internal(port,
- 0 /* suppress console if empty */);
-}
-
-/* Add console command to erase OCM flash if needed. */
-static int command_anx_ocm(int argc, char **argv)
-{
- char *e = NULL;
- int port;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- /* Get port number from first parameter */
- port = strtoi(argv[1], &e, 0);
- if (*e)
- return EC_ERROR_PARAM1;
-
- if (argc > 2) {
- int rv;
- if (strcasecmp(argv[2], "erase"))
- return EC_ERROR_PARAM2;
- rv = anx7447_flash_erase_internal(
- port, 1 /* write to console if empty */);
- if (rv)
- ccprintf("C%d: Failed to erase OCM flash (%d)\n",
- port, rv);
- }
-
- ccprintf("C%d: OCM flash is %sempty.\n",
- port, anx7447_flash_is_empty(port) ? "" : "not ");
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(anx_ocm, command_anx_ocm,
- "port [erase]",
- "Print OCM status or erases OCM for a given port.");
-#endif
-
-static int anx7447_init(int port)
-{
- int rv, reg, i;
-
- ASSERT(port < CONFIG_USB_PD_PORT_MAX_COUNT);
-
- memset(&anx[port], 0, sizeof(struct anx_state));
-
- /*
- * find corresponding anx7447 SPI slave address according to
- * specified TCPC slave address
- */
- for (i = 0; i < ARRAY_SIZE(anx7447_i2c_addrs_flags); i++) {
- if (I2C_GET_ADDR(tcpc_config[port].i2c_info.addr_flags) ==
- I2C_GET_ADDR(
- anx7447_i2c_addrs_flags[i].tcpc_slave_addr_flags)) {
- anx[port].i2c_slave_addr_flags =
- anx7447_i2c_addrs_flags[i].spi_slave_addr_flags;
- break;
- }
- }
- if (!I2C_GET_ADDR(anx[port].i2c_slave_addr_flags)) {
- ccprintf("TCPC I2C slave addr 0x%x is invalid for ANX7447\n",
- I2C_GET_ADDR(tcpc_config[port]
- .i2c_info.addr_flags));
- return EC_ERROR_UNKNOWN;
- }
-
-
- rv = tcpci_tcpm_init(port);
- if (rv)
- return rv;
-
-#ifdef CONFIG_USB_PD_TCPM_ANX7447_OCM_ERASE_COMMAND
- /* Check and print OCM status to console. */
- CPRINTS("C%d: OCM flash is %sempty",
- port, anx7447_flash_is_empty(port) ? "" : "not ");
-#endif
-
- /*
- * 7447 has a physical pin to detect the presence of VBUS, VBUS_SENSE
- * , and 7447 has a VBUS current protection mechanism through another
- * pin input VBUS_OCP. To enable VBUS OCP, OVP protection, driver needs
- * to set the threshold to the registers VBUS_VOLTAGE_ALARM_HI_CFG
- * (0x76 & 0x77) and VBUS_OCP_HI_THRESHOLD (0xDD &0xDE). These values
- * could be customized based on different platform design.
- * Disable VBUS protection here since the default values of
- * VBUS_VOLTAGE_ALARM_HI_CFG and VBUS_OCP_HI_THRESHOLD are zero.
- */
- rv = tcpc_read(port, ANX7447_REG_TCPC_CTRL_2, &reg);
- if (rv)
- return rv;
- reg &= ~ANX7447_REG_ENABLE_VBUS_PROTECT;
- rv = tcpc_write(port, ANX7447_REG_TCPC_CTRL_2, reg);
- if (rv)
- return rv;
-
- /* ADC enable, use to monitor VBUS voltage */
- rv = tcpc_read(port, ANX7447_REG_ADC_CTRL_1, &reg);
- if (rv)
- return rv;
- reg |= ANX7447_REG_ADCFSM_EN;
- rv = tcpc_write(port, ANX7447_REG_ADC_CTRL_1, reg);
- if (rv)
- return rv;
-
- /* Set VCONN OCP(Over Current Protection) threshold */
- rv = tcpc_read(port, ANX7447_REG_ANALOG_CTRL_8, &reg);
- if (rv)
- return rv;
- reg &= ~ANX7447_REG_VCONN_OCP_MASK;
- reg |= ANX7447_REG_VCONN_OCP_440mA;
- rv = tcpc_write(port, ANX7447_REG_ANALOG_CTRL_8, reg);
-
- /* Vconn SW protection time of inrush current */
- rv = tcpc_read(port, ANX7447_REG_ANALOG_CTRL_10, &reg);
- if (rv)
- return rv;
- reg &= ~ANX7447_REG_R_VCONN_PWR_PRT_INRUSH_TIME_MASK;
- reg |= ANX7447_REG_R_VCONN_PWR_PRT_INRUSH_TIME_2430US;
- rv = tcpc_write(port, ANX7447_REG_ANALOG_CTRL_10, reg);
-
-#ifdef CONFIG_USB_PD_TCPM_MUX
- /*
- * Run mux_set() here for considering CCD(Case-Closed Debugging) case
- * If this TCPC is not also the MUX then don't initialize to NONE
- */
- if (!(usb_muxes[port].flags & USB_MUX_FLAG_NOT_TCPC))
- rv |= anx7447_mux_set(port, TYPEC_MUX_NONE);
-#endif /* CONFIG_USB_PD_TCPM_MUX */
-
- return rv;
-}
-
-static int anx7447_release(int port)
-{
- return EC_SUCCESS;
-}
-
-static void anx7447_update_hpd_enable(int port)
-{
- int status, reg, rv;
-
- rv = tcpc_read(port, ANX7447_REG_STATUS, &status);
- rv |= tcpc_read(port, ANX7447_REG_HPD, &reg);
- if (rv)
- return;
-
- if (!(reg & ANX7447_REG_HPD_ENABLE) ||
- !(status & ANX7447_REG_STATUS_LINK)) {
- reg &= ~ANX7447_REG_HPD_IRQ;
- tcpc_write(port, ANX7447_REG_HPD,
- (status & ANX7447_REG_STATUS_LINK)
- ? reg | ANX7447_REG_HPD_ENABLE
- : reg & ~ANX7447_REG_HPD_ENABLE);
- }
-}
-
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
-static int anx7447_get_vbus_voltage(int port)
-{
- int vbus_volt = 0;
-
- tcpc_read16(port, TCPC_REG_VBUS_VOLTAGE, &vbus_volt);
-
- return vbus_volt;
-}
-
-int anx7447_set_power_supply_ready(int port)
-{
- int count = 0;
-
- while (is_equal_greater_safe0v(port)) {
- if (count >= 10)
- break;
- msleep(100);
- count++;
- }
-
- return tcpc_write(port, TCPC_REG_COMMAND, 0x77);
-}
-#endif /* CONFIG_USB_PD_VBUS_DETECT_TCPC */
-
-int anx7447_power_supply_reset(int port)
-{
- return tcpc_write(port, TCPC_REG_COMMAND, 0x66);
-}
-
-int anx7447_board_charging_enable(int port, int enable)
-{
- return tcpc_write(port, TCPC_REG_COMMAND, enable ? 0x55 : 0x44);
-}
-
-static void anx7447_tcpc_alert(int port)
-{
- int alert, rv;
-
- rv = tcpc_read16(port, TCPC_REG_ALERT, &alert);
- /* process and clear alert status */
- tcpci_tcpc_alert(port);
-
- if (!rv && (alert & ANX7447_VENDOR_ALERT))
- anx7447_update_hpd_enable(port);
-}
-
-/*
- * timestamp of the next possible toggle to ensure the 2-ms spacing
- * between IRQ_HPD.
- */
-static uint64_t hpd_deadline[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-void anx7447_tcpc_update_hpd_status(int port, int hpd_lvl, int hpd_irq)
-{
- int reg = 0;
-
- /*
- * All calls within this method need to update to a mux_read/write calls
- * that use the secondary address. This is a non-trival change and no
- * one is using the anx7447 as a mux only (and probably never will since
- * it doesn't have a re-driver). If that changes, we need to update this
- * code.
- */
- ASSERT(!(usb_muxes[port].flags & USB_MUX_FLAG_NOT_TCPC));
-
- anx7447_set_hpd_level(port, hpd_lvl);
-
- if (hpd_irq) {
- uint64_t now = get_time().val;
- /* wait for the minimum spacing between IRQ_HPD if needed */
- if (now < hpd_deadline[port])
- usleep(hpd_deadline[port] - now);
-
- anx7447_reg_read(port, ANX7447_REG_HPD_CTRL_0, &reg);
- reg &= ~ANX7447_REG_HPD_OUT;
- anx7447_reg_write(port, ANX7447_REG_HPD_CTRL_0, reg);
- usleep(HPD_DSTREAM_DEBOUNCE_IRQ);
- reg |= ANX7447_REG_HPD_OUT;
- anx7447_reg_write(port, ANX7447_REG_HPD_CTRL_0, reg);
- }
- /* enforce 2-ms delay between HPD pulses */
- hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL;
-}
-
-void anx7447_tcpc_clear_hpd_status(int port)
-{
- anx7447_hpd_output_en(port);
- anx7447_set_hpd_level(port, 0);
-}
-
-#ifdef CONFIG_USB_PD_TCPM_MUX
-static int anx7447_mux_init(int port)
-{
- ASSERT(port < CONFIG_USB_PD_PORT_MAX_COUNT);
-
- memset(&mux[port], 0, sizeof(struct anx_usb_mux));
-
- /* init hpd status */
- anx7447_hpd_mode_en(port);
- anx7447_set_hpd_level(port, 0);
- anx7447_hpd_output_en(port);
-
- /*
- * ANX initializes its muxes to (MUX_USB_ENABLED | MUX_DP_ENABLED)
- * when reinitialized, we need to force initialize it to
- * TYPEC_MUX_NONE
- */
- return anx7447_mux_set(port, TYPEC_MUX_NONE);
-}
-
-#ifdef CONFIG_USB_PD_TCPM_ANX7447_AUX_PU_PD
-static void anx7447_mux_safemode(int port, int on_off)
-{
- int reg;
-
- mux_read(port, ANX7447_REG_ANALOG_CTRL_9, &reg);
-
- if (on_off)
- reg |= ANX7447_REG_SAFE_MODE;
- else
- reg &= ~(ANX7447_REG_SAFE_MODE);
-
- mux_write(port, ANX7447_REG_ANALOG_CTRL_9, reg);
- CPRINTS("C%d set mux to safemode %s, reg = 0x%x",
- port, (on_off) ? "on" : "off", reg);
-}
-
-static inline void anx7447_configure_aux_src(int port, int on_off)
-{
- int reg;
-
- mux_read(port, ANX7447_REG_ANALOG_CTRL_9, &reg);
-
- if (on_off)
- reg |= ANX7447_REG_R_AUX_RES_PULL_SRC;
- else
- reg &= ~(ANX7447_REG_R_AUX_RES_PULL_SRC);
-
- mux_write(port, ANX7447_REG_ANALOG_CTRL_9, reg);
-
- CPRINTS("C%d set aux_src to %s, reg = 0x%x",
- port, (on_off) ? "on" : "off", reg);
-}
-#endif
-
-/*
- * Set mux.
- *
- * sstx and ssrx are the USB superspeed transmit and receive pairs. ml is the
- * DisplayPort Main Link. There are four lanes total. For example, DP cases
- * connect them all and dock cases connect 2 DP and USB.
- *
- * a2, a3, a10, a11, b2, b3, b10, b11 are pins on the USB-C connector.
- */
-static int anx7447_mux_set(int port, mux_state_t mux_state)
-{
- int cc_direction;
- mux_state_t mux_type;
- int sw_sel = 0x00, aux_sw = 0x00;
- int rv;
-
- cc_direction = mux_state & MUX_POLARITY_INVERTED;
- mux_type = mux_state & TYPEC_MUX_DOCK;
- CPRINTS("C%d mux_state = 0x%x, mux_type = 0x%x",
- port, mux_state, mux_type);
- if (cc_direction == 0) {
- /* cc1 connection */
- if (mux_type == TYPEC_MUX_DOCK) {
- /* ml0-a10/11, ml1-b2/b3, sstx-a2/a3, ssrx-b10/11 */
- sw_sel = 0x21;
- /* aux+ <-> sbu1, aux- <-> sbu2 */
- aux_sw = 0x03;
- } else if (mux_type == TYPEC_MUX_DP) {
- /* ml0-a10/11, ml1-b2/b3, ml2-a2/a3, ml3-b10/11 */
- sw_sel = 0x09;
- /* aux+ <-> sbu1, aux- <-> sbu2 */
- aux_sw = 0x03;
- } else if (mux_type == TYPEC_MUX_USB) {
- /* ssrxp<->b11, ssrxn<->b10, sstxp<->a2, sstxn<->a3 */
- sw_sel = 0x20;
- }
- } else {
- /* cc2 connection */
- if (mux_type == TYPEC_MUX_DOCK) {
- /* ml0-b10/11, ml1-a2/b3, sstx-b2/a3, ssrx-a10/11 */
- sw_sel = 0x12;
- /* aux+ <-> sbu2, aux- <-> sbu1 */
- aux_sw = 0x0C;
- } else if (mux_type == TYPEC_MUX_DP) {
- /* ml0-b10/11, ml1-a2/b3, ml2-b2/a3, ml3-a10/11 */
- sw_sel = 0x06;
- /* aux+ <-> sbu2, aux- <-> sbu1 */
- aux_sw = 0x0C;
- } else if (mux_type == TYPEC_MUX_USB) {
- /* ssrxp<->a11, ssrxn<->a10, sstxp<->b2, sstxn<->b3 */
- sw_sel = 0x10;
- }
- }
-
- /*
- * Once need to configure the Mux, should set the mux to safe mode
- * first. After the mux configured, should set mux to normal mode.
- */
-#ifdef CONFIG_USB_PD_TCPM_ANX7447_AUX_PU_PD
- anx7447_mux_safemode(port, 1);
-#endif
- rv = mux_write(port, ANX7447_REG_TCPC_SWITCH_0, sw_sel);
- rv |= mux_write(port, ANX7447_REG_TCPC_SWITCH_1, sw_sel);
- rv |= mux_write(port, ANX7447_REG_TCPC_AUX_SWITCH, aux_sw);
-
- mux[port].state = mux_state;
-
-#ifdef CONFIG_USB_PD_TCPM_ANX7447_AUX_PU_PD
- /*
- * DP and Dock mode: after configured the Mux, change the Mux to
- * normal mode, otherwise: keep safe mode.
- */
- if (mux_type != TYPEC_MUX_NONE) {
- anx7447_configure_aux_src(port, 1);
- anx7447_mux_safemode(port, 0);
- } else
- anx7447_configure_aux_src(port, 0);
-#endif
-
- return rv;
-}
-
-/* current mux state */
-static int anx7447_mux_get(int port, mux_state_t *mux_state)
-{
- *mux_state = mux[port].state;
-
- return EC_SUCCESS;
-}
-#endif /* CONFIG_USB_PD_TCPM_MUX */
-
-/* ANX7447 is a TCPCI compatible port controller */
-const struct tcpm_drv anx7447_tcpm_drv = {
- .init = &anx7447_init,
- .release = &anx7447_release,
- .get_cc = &tcpci_tcpm_get_cc,
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
- .get_vbus_level = &tcpci_tcpm_get_vbus_level,
-#endif
- .select_rp_value = &tcpci_tcpm_select_rp_value,
- .set_cc = &tcpci_tcpm_set_cc,
- .set_polarity = &tcpci_tcpm_set_polarity,
- .set_vconn = &tcpci_tcpm_set_vconn,
- .set_msg_header = &tcpci_tcpm_set_msg_header,
- .set_rx_enable = &tcpci_tcpm_set_rx_enable,
- .get_message_raw = &tcpci_tcpm_get_message_raw,
- .transmit = &tcpci_tcpm_transmit,
- .tcpc_alert = &anx7447_tcpc_alert,
-#ifdef CONFIG_USB_PD_DISCHARGE_TCPC
- .tcpc_discharge_vbus = &tcpci_tcpc_discharge_vbus,
-#endif
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- .drp_toggle = &tcpci_tcpc_drp_toggle,
-#endif
- .get_chip_info = &tcpci_get_chip_info,
-#ifdef CONFIG_USBC_PPC
- .set_snk_ctrl = &tcpci_tcpm_set_snk_ctrl,
- .set_src_ctrl = &tcpci_tcpm_set_src_ctrl,
-#endif
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- .enter_low_power_mode = &tcpci_enter_low_power_mode,
-#endif
-};
-
-#ifdef CONFIG_USB_PD_TCPM_MUX
-const struct usb_mux_driver anx7447_usb_mux_driver = {
- .init = anx7447_mux_init,
- .set = anx7447_mux_set,
- .get = anx7447_mux_get,
-};
-#endif /* CONFIG_USB_PD_TCPM_MUX */
-
diff --git a/driver/tcpm/anx7447.h b/driver/tcpm/anx7447.h
deleted file mode 100644
index 4da300884c..0000000000
--- a/driver/tcpm/anx7447.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/* Copyright 2018 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.
- */
-
-/* USB Power delivery port management */
-
-#ifndef __CROS_EC_USB_PD_TCPM_ANX7447_H
-#define __CROS_EC_USB_PD_TCPM_ANX7447_H
-
-/* Registers: TCPC slave address used */
-#define ANX7447_REG_TCPC_SWITCH_0 0xB4
-#define ANX7447_REG_TCPC_SWITCH_1 0xB5
-#define ANX7447_REG_TCPC_AUX_SWITCH 0xB6
-
-#define ANX7447_REG_INTR_ALERT_MASK_0 0xC9
-
-#define ANX7447_REG_TCPC_CTRL_2 0xCD
-#define ANX7447_REG_ENABLE_VBUS_PROTECT 0x20
-
-#define ANX7447_REG_ADC_CTRL_1 0xBF
-#define ANX7447_REG_ADCFSM_EN 0x20
-
-/* Registers: SPI slave address used */
-#define ANX7447_REG_HPD_CTRL_0 0x7E
-#define ANX7447_REG_HPD_MODE 0x01
-#define ANX7447_REG_HPD_OUT 0x02
-
-#define ANX7447_REG_HPD_DEGLITCH_H 0x80
-#define ANX7447_REG_HPD_OEN 0x40
-
-#define ANX7447_REG_INTP_CTRL_0 0x9E
-
-#define ANX7447_REG_ANALOG_CTRL_8 0xA8
-#define ANX7447_REG_VCONN_OCP_MASK 0x0C
-#define ANX7447_REG_VCONN_OCP_240mA 0x00
-#define ANX7447_REG_VCONN_OCP_310mA 0x04
-#define ANX7447_REG_VCONN_OCP_370mA 0x08
-#define ANX7447_REG_VCONN_OCP_440mA 0x0C
-
-#define ANX7447_REG_ANALOG_CTRL_10 0xAA
-#define ANX7447_REG_R_VCONN_PWR_PRT_INRUSH_TIME_MASK 0x38
-#define ANX7447_REG_R_VCONN_PWR_PRT_INRUSH_TIME_19US 0x00
-#define ANX7447_REG_R_VCONN_PWR_PRT_INRUSH_TIME_38US 0x08
-#define ANX7447_REG_R_VCONN_PWR_PRT_INRUSH_TIME_76US 0x10
-#define ANX7447_REG_R_VCONN_PWR_PRT_INRUSH_TIME_152US 0x18
-#define ANX7447_REG_R_VCONN_PWR_PRT_INRUSH_TIME_303US 0x20
-#define ANX7447_REG_R_VCONN_PWR_PRT_INRUSH_TIME_607US 0x28
-#define ANX7447_REG_R_VCONN_PWR_PRT_INRUSH_TIME_1210US 0x30
-#define ANX7447_REG_R_VCONN_PWR_PRT_INRUSH_TIME_2430US 0x38
-
-#define ANX7447_REG_ANALOG_CTRL_9 0xA9
-#define ANX7447_REG_SAFE_MODE 0x80
-#define ANX7447_REG_R_AUX_RES_PULL_SRC 0x20
-
-/*
- * This section of defines are only required to support the config option
- * CONFIG_USB_PD_TCPM_ANX7447_OCM_ERASE_COMMAND.
- */
-/* SPI registers used for OCM flash operations */
-#define ANX7447_DELAY_IN_US (20*1000)
-
-#define ANX7447_REG_R_RAM_CTRL 0x05
-#define ANX7447_REG_R_FLASH_RW_CTRL 0x30
-#define ANX7447_REG_R_FLASH_STATUS_0 0x31
-#define ANX7447_REG_FLASH_INST_TYPE 0x33
-#define ANX7447_REG_FLASH_ERASE_TYPE 0x34
-#define ANX7447_REG_OCM_CTRL_0 0x6E
-#define ANX7447_REG_ADDR_GPIO_CTRL_0 0x88
-#define ANX7447_REG_OCM_VERSION 0xB4
-
-/* R_RAM_CTRL bit definitions */
-#define ANX7447_R_RAM_CTRL_FLASH_DONE (1<<7)
-
-/* R_FLASH_RW_CTRL bit definitions */
-#define ANX7447_R_FLASH_RW_CTRL_GENERAL_INST_EN (1<<6)
-#define ANX7447_R_FLASH_RW_CTRL_FLASH_ERASE_EN (1<<5)
-#define ANX7447_R_FLASH_RW_CTRL_WRITE_STATUS_EN (1<<2)
-#define ANX7447_R_FLASH_RW_CTRL_FLASH_READ (1<<1)
-#define ANX7447_R_FLASH_RW_CTRL_FLASH_WRITE (1<<0)
-
-/* R_FLASH_STATUS_0 definitions */
-#define ANX7447_FLASH_STATUS_SPI_STATUS_0 0x43
-
-/* FLASH_ERASE_TYPE bit definitions */
-#define ANX7447_FLASH_INST_TYPE_WRITEENABLE 0x06
-#define ANX7447_FLASH_ERASE_TYPE_CHIPERASE 0x60
-
-/* OCM_CTRL_0 bit definitions */
-#define ANX7447_OCM_CTRL_OCM_RESET (1<<6)
-
-/* ADDR_GPIO_CTRL_0 bit definitions */
-#define ANX7447_ADDR_GPIO_CTRL_0_SPI_WP (1<<7)
-#define ANX7447_ADDR_GPIO_CTRL_0_SPI_CLK_ENABLE (1<<6)
-/* End of defines used for CONFIG_USB_PD_TCPM_ANX7447_OCM_ERASE_COMMAND */
-
-struct anx7447_i2c_addr {
- uint16_t tcpc_slave_addr_flags;
- uint16_t spi_slave_addr_flags;
-};
-
-#define AN7447_TCPC0_I2C_ADDR_FLAGS 0x2C
-#define AN7447_TCPC1_I2C_ADDR_FLAGS 0x2B
-#define AN7447_TCPC2_I2C_ADDR_FLAGS 0x2A
-#define AN7447_TCPC3_I2C_ADDR_FLAGS 0x29
-
-#define AN7447_SPI0_I2C_ADDR_FLAGS 0x3F
-#define AN7447_SPI1_I2C_ADDR_FLAGS 0x37
-#define AN7447_SPI2_I2C_ADDR_FLAGS 0x32
-#define AN7447_SPI3_I2C_ADDR_FLAGS 0x31
-
-/*
- * Time TEST_R must be held high for a reset
- */
-#define ANX74XX_RESET_HOLD_MS 1
-/*
- * Time after TEST_R reset to wait for eFuse loading
- */
-#define ANX74XX_RESET_FINISH_MS 2
-
-int anx7447_set_power_supply_ready(int port);
-int anx7447_power_supply_reset(int port);
-int anx7447_board_charging_enable(int port, int enable);
-
-void anx7447_hpd_mode_en(int port);
-void anx7447_hpd_output_en(int port);
-
-extern const struct tcpm_drv anx7447_tcpm_drv;
-extern const struct usb_mux_driver anx7447_usb_mux_driver;
-void anx7447_tcpc_update_hpd_status(int port, int hpd_lvl, int hpd_irq);
-void anx7447_tcpc_clear_hpd_status(int port);
-
-/**
- * Erase OCM flash if it's not empty
- *
- * @param port: USB-C port number
- * @return: EC_SUCCESS or EC_ERROR_*
- */
-int anx7447_flash_erase(int port);
-
-#endif /* __CROS_EC_USB_PD_TCPM_ANX7688_H */
diff --git a/driver/tcpm/anx74xx.c b/driver/tcpm/anx74xx.c
deleted file mode 100644
index 0e7ec021d8..0000000000
--- a/driver/tcpm/anx74xx.c
+++ /dev/null
@@ -1,1180 +0,0 @@
-/* Copyright 2016 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.
- *
- * Author : Analogix Semiconductor.
- */
-
-/* Type-C port manager for Analogix's anx74xx chips */
-
-#include "console.h"
-#include "anx74xx.h"
-#include "task.h"
-#include "tcpci.h"
-#include "tcpm.h"
-#include "timer.h"
-#include "usb_charge.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpc.h"
-#include "util.h"
-
-#if !defined(CONFIG_USB_PD_TCPM_TCPCI)
-#error "ANX74xx is using part of standard TCPCI control"
-#error "Please upgrade your board configuration"
-#endif
-
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-
-struct anx_state {
- int polarity;
- int vconn_en;
- int mux_state;
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- int prev_mode;
-#endif
-};
-#define clear_recvd_msg_int(port) do {\
- int reg, rv; \
- rv = tcpc_read(port, ANX74XX_REG_RECVD_MSG_INT, &reg); \
- if (!rv) \
- tcpc_write(port, ANX74XX_REG_RECVD_MSG_INT, \
- reg | 0x01); \
- } while (0)
-
-static struct anx_state anx[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Save the selected rp value */
-static int selected_rp[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-#ifdef CONFIG_USB_PD_DECODE_SOP
-/* Save the message address */
-static int msg_sop[CONFIG_USB_PD_PORT_MAX_COUNT];
-#endif
-
-static int anx74xx_tcpm_init(int port);
-
-static void anx74xx_tcpm_set_auto_good_crc(int port, int enable)
-{
- int reply_sop_en = 0;
-
- if (enable) {
- reply_sop_en = ANX74XX_REG_REPLY_SOP_EN;
-#ifdef CONFIG_USB_PD_DECODE_SOP
- /*
- * Only the VCONN Source is allowed to communicate
- * with the Cable Plugs.
- */
- if (anx[port].vconn_en) {
- reply_sop_en |= ANX74XX_REG_REPLY_SOP_1_EN |
- ANX74XX_REG_REPLY_SOP_2_EN;
- }
-#endif
- }
-
- tcpc_write(port, ANX74XX_REG_TX_AUTO_GOODCRC_2, reply_sop_en);
-}
-
-static void anx74xx_update_cable_det(int port, int mode)
-{
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- int reg;
-
- if (anx[port].prev_mode == mode)
- return;
-
- /* Update power mode */
- anx[port].prev_mode = mode;
-
- /* Get ANALOG_CTRL_0 for cable det bit */
- if (tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_0, &reg))
- return;
-
- if (mode == ANX74XX_STANDBY_MODE) {
- int cc_reg;
-
- /*
- * The ANX4329 enters standby mode by setting PWR_EN signal
- * low. In addition, RESET_L must be set low to keep the ANX3429
- * in standby mode.
- *
- * Clearing bit 7 of ANX74XX_REG_ANALOG_CTRL_0 will cause the
- * ANX3429 to clear the cable_det signal that goes from the
- * ANX3429 to the EC. If this bit is cleared when a cable is
- * attached then cable_det will go high once standby is entered.
- *
- * In some cases, such as when the chipset power state is
- * S3/S5/G3 and a sink only adapter is connected to the port,
- * this behavior is undesirable. The constant toggling between
- * standby and normal mode means that effectively the ANX3429 is
- * not in standby mode only consumes ~1 mW less than just
- * remaining in normal mode. However when an E mark cable is
- * connected, clearing bit 7 is required so that while the E
- * mark cable configuration happens, the USB PD state machine
- * will continue to wake up until the USB PD attach event can be
- * regtistered.
- *
- * Therefore, the decision to clear bit 7 is based on the
- * current CC status of the port. If the CC status is open for
- * both CC lines OR if either CC line is showing Ra, then clear
- * bit 7. Not clearing bit 7 has no impact for normal cables and
- * prevents the constant toggle of standby<->normal when an
- * adapter is connected that isn't allowed to attach. Clearing
- * bit 7 when CC status reads Ra for either CC line allows the
- * USB PD state machine to be woken until the attach event can
- * happen. Note that in the case an E mark cable is connected
- * and can't attach (i.e. sink only port <- Emark cable -> sink
- * only adapter), then the ANX3429 will toggle indefinitely,
- * until either the cable is removed, or the port drp status
- * changes so the attach event can occur.
- * .
- */
-
- /* Read CC status to see if cable_det bit should be cleared */
- if (tcpc_read(port, ANX74XX_REG_CC_STATUS, &cc_reg))
- return;
- /* If open or either CC line is Ra, then clear cable_det */
- if (!cc_reg || (cc_reg & ANX74XX_CC_RA_MASK &&
- !(cc_reg & ANX74XX_CC_RD_MASK)))
- reg &= ~ANX74XX_REG_R_PIN_CABLE_DET;
- } else {
- reg |= ANX74XX_REG_R_PIN_CABLE_DET;
- }
-
- tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_0, reg);
-#endif
-}
-
-static void anx74xx_set_power_mode(int port, int mode)
-{
- /*
- * Update PWR_EN and RESET_N signals to the correct level. High for
- * Normal mode and low for Standby mode. When transitioning from standby
- * to normal mode, must set the PWR_EN and RESET_N before attempting to
- * modify cable_det bit of analog_ctrl_0. If going from Normal to
- * Standby, updating analog_ctrl_0 must happen before setting PWR_EN and
- * RESET_N low.
- */
- if (mode == ANX74XX_NORMAL_MODE) {
- /* Take chip out of standby mode */
- board_set_tcpc_power_mode(port, mode);
- /* Update the cable det signal */
- anx74xx_update_cable_det(port, mode);
- } else {
- /* Update cable cable det signal */
- anx74xx_update_cable_det(port, mode);
- /*
- * Delay between setting cable_det low and setting RESET_L low
- * as recommended the ANX3429 datasheet.
- */
- msleep(1);
- /* Put chip into standby mode */
- board_set_tcpc_power_mode(port, mode);
- }
-}
-
-#if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && \
- defined(CONFIG_USB_PD_TCPC_LOW_POWER)
-
-static int anx74xx_tcpc_drp_toggle(int port)
-{
- /*
- * The ANX3429 always auto-toggles when in low power mode. Since this is
- * not configurable, there is nothing to do here. DRP auto-toggle will
- * happen once low power mode is set via anx74xx_enter_low_power_mode().
- * Note: this means the ANX3429 auto-toggles in PD_DRP_FORCE_SINK mode,
- * which is undesirable (b/72007056).
- */
- return EC_SUCCESS;
-}
-
-static int anx74xx_enter_low_power_mode(int port)
-{
- anx74xx_set_power_mode(port, ANX74XX_STANDBY_MODE);
- return EC_SUCCESS;
-}
-
-#endif
-
-void anx74xx_tcpc_set_vbus(int port, int enable)
-{
- int reg;
-
- tcpc_read(port, ANX74XX_REG_GPIO_CTRL_4_5, &reg);
- if (enable)
- reg |= ANX74XX_REG_SET_VBUS;
- else
- reg &= ~ANX74XX_REG_SET_VBUS;
- tcpc_write(port, ANX74XX_REG_GPIO_CTRL_4_5, reg);
-}
-
-#ifdef CONFIG_USB_PD_DISCHARGE_TCPC
-static void anx74xx_tcpc_discharge_vbus(int port, int enable)
-{
- int reg;
-
- tcpc_read(port, ANX74XX_REG_HPD_CTRL_0, &reg);
- if (enable)
- reg |= ANX74XX_REG_DISCHARGE_CTRL;
- else
- reg &= ~ANX74XX_REG_DISCHARGE_CTRL;
- tcpc_write(port, ANX74XX_REG_HPD_CTRL_0, reg);
-}
-#endif
-
-/*
- * timestamp of the next possible toggle to ensure the 2-ms spacing
- * between IRQ_HPD.
- */
-static uint64_t hpd_deadline[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-void anx74xx_tcpc_update_hpd_status(int port, int hpd_lvl, int hpd_irq)
-{
- int reg;
-
- mux_read(port, ANX74XX_REG_HPD_CTRL_0, &reg);
- if (hpd_lvl)
- reg |= ANX74XX_REG_HPD_OUT_DATA;
- else
- reg &= ~ANX74XX_REG_HPD_OUT_DATA;
- mux_write(port, ANX74XX_REG_HPD_CTRL_0, reg);
-
- if (hpd_irq) {
- uint64_t now = get_time().val;
- /* wait for the minimum spacing between IRQ_HPD if needed */
- if (now < hpd_deadline[port])
- usleep(hpd_deadline[port] - now);
-
- mux_read(port, ANX74XX_REG_HPD_CTRL_0, &reg);
- reg &= ~ANX74XX_REG_HPD_OUT_DATA;
- mux_write(port, ANX74XX_REG_HPD_CTRL_0, reg);
- usleep(HPD_DSTREAM_DEBOUNCE_IRQ);
- reg |= ANX74XX_REG_HPD_OUT_DATA;
- mux_write(port, ANX74XX_REG_HPD_CTRL_0, reg);
- }
- /* enforce 2-ms delay between HPD pulses */
- hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL;
-}
-
-void anx74xx_tcpc_clear_hpd_status(int port)
-{
- int reg;
-
- tcpc_read(port, ANX74XX_REG_HPD_CTRL_0, &reg);
- reg &= 0xcf;
- tcpc_write(port, ANX74XX_REG_HPD_CTRL_0, reg);
-}
-
-#ifdef CONFIG_USB_PD_TCPM_MUX
-static int anx74xx_tcpm_mux_init(int port)
-{
- /* Nothing to do here, ANX initializes its muxes
- * as (MUX_USB_ENABLED | MUX_DP_ENABLED)
- */
- anx[port].mux_state = MUX_USB_ENABLED | MUX_DP_ENABLED;
-
- return EC_SUCCESS;
-}
-
-static int anx74xx_tcpm_mux_enter_safe_mode(int port)
-{
- int reg;
-
- if (mux_read(port, ANX74XX_REG_ANALOG_CTRL_2, &reg))
- return EC_ERROR_UNKNOWN;
- if (mux_write(port, ANX74XX_REG_ANALOG_CTRL_2, reg |
- ANX74XX_REG_MODE_TRANS))
- return EC_ERROR_UNKNOWN;
-
-
- return EC_SUCCESS;
-}
-
-static int anx74xx_tcpm_mux_exit_safe_mode(int port)
-{
- int reg;
-
- if (mux_read(port, ANX74XX_REG_ANALOG_CTRL_2, &reg))
- return EC_ERROR_UNKNOWN;
- if (mux_write(port, ANX74XX_REG_ANALOG_CTRL_2, reg &
- ~ANX74XX_REG_MODE_TRANS))
- return EC_ERROR_UNKNOWN;
-
-
- return EC_SUCCESS;
-}
-
-static int anx74xx_tcpm_mux_exit(int port)
-{
- int reg;
-
- /*
- * Safe mode must be entered before any changes are made to the mux
- * settings used to enable ALT_DP mode. This funciton is called either
- * from anx74xx_tcpm_mux_set when TYPEC_MUX_NONE is selected as the new
- * mux state, or when both cc lines are determined to be
- * TYPEC_CC_VOLT_OPEN. Therefore, safe mode must be entered and exited
- * here so that both entry paths are handled.
- */
- if (anx74xx_tcpm_mux_enter_safe_mode(port))
- return EC_ERROR_UNKNOWN;
-
- /* Disconnect aux from sbu */
- if (mux_read(port, ANX74XX_REG_ANALOG_CTRL_2, &reg))
- return EC_ERROR_UNKNOWN;
- if (mux_write(port, ANX74XX_REG_ANALOG_CTRL_2, reg & 0xf))
- return EC_ERROR_UNKNOWN;
-
- /* Clear Bit[7:0] R_SWITCH */
- if (mux_write(port, ANX74XX_REG_ANALOG_CTRL_1, 0x0))
- return EC_ERROR_UNKNOWN;
- /* Clear Bit[7:4] R_SWITCH_H */
- if (mux_read(port, ANX74XX_REG_ANALOG_CTRL_5, &reg))
- return EC_ERROR_UNKNOWN;
- if (mux_write(port, ANX74XX_REG_ANALOG_CTRL_5, reg & 0x0f))
- return EC_ERROR_UNKNOWN;
-
- /* Exit safe mode */
- if (anx74xx_tcpm_mux_exit_safe_mode(port))
- return EC_ERROR_UNKNOWN;
-
- return EC_SUCCESS;
-}
-
-
-static int anx74xx_mux_aux_to_sbu(int port, int polarity, int enabled)
-{
- int reg;
- const int aux_mask = ANX74XX_REG_AUX_SWAP_SET_CC2 |
- ANX74XX_REG_AUX_SWAP_SET_CC1;
-
- /*
- * Get the current value of analog_ctrl_2 register. Note, that safe mode
- * is enabled and exited by the calling function, so only have to worry
- * about setting the correct value for the upper 4 bits of analog_ctrl_2
- * here.
- */
- if (mux_read(port, ANX74XX_REG_ANALOG_CTRL_2, &reg))
- return EC_ERROR_UNKNOWN;
-
- /* Assume aux_p/n lines are not connected */
- reg &= ~aux_mask;
-
- if (enabled) {
- /* If enabled, connect aux to sbu based on desired polarity */
- if (polarity)
- reg |= ANX74XX_REG_AUX_SWAP_SET_CC2;
- else
- reg |= ANX74XX_REG_AUX_SWAP_SET_CC1;
- }
- /* Write new aux <-> sbu settings */
- if (mux_write(port, ANX74XX_REG_ANALOG_CTRL_2, reg))
- return EC_ERROR_UNKNOWN;
-
- return EC_SUCCESS;
-}
-
-static int anx74xx_tcpm_mux_set(int i2c_addr, mux_state_t mux_state)
-{
- int ctrl5;
- int ctrl1 = 0;
- int rv;
- int port = i2c_addr;
-
- if (!(mux_state & ~MUX_POLARITY_INVERTED)) {
- anx[port].mux_state = mux_state;
- return anx74xx_tcpm_mux_exit(port);
- }
-
- rv = mux_read(port, ANX74XX_REG_ANALOG_CTRL_5, &ctrl5);
- if (rv)
- return EC_ERROR_UNKNOWN;
- ctrl5 &= 0x0f;
-
- if (mux_state & MUX_USB_ENABLED) {
- /* Connect USB SS switches */
- if (mux_state & MUX_POLARITY_INVERTED) {
- ctrl1 = ANX74XX_REG_MUX_SSRX_RX2;
- ctrl5 |= ANX74XX_REG_MUX_SSTX_TX2;
- } else {
- ctrl1 = ANX74XX_REG_MUX_SSRX_RX1;
- ctrl5 |= ANX74XX_REG_MUX_SSTX_TX1;
- }
- if (mux_state & MUX_DP_ENABLED) {
- /* Set pin assignment D */
- if (mux_state & MUX_POLARITY_INVERTED)
- ctrl1 |= (ANX74XX_REG_MUX_ML0_RX1 |
- ANX74XX_REG_MUX_ML1_TX1);
- else
- ctrl1 |= (ANX74XX_REG_MUX_ML0_RX2 |
- ANX74XX_REG_MUX_ML1_TX2);
- }
- /* Keep ML0/ML1 unconnected if DP is not enabled */
- } else if (mux_state & MUX_DP_ENABLED) {
- /* Set pin assignment C */
- if (mux_state & MUX_POLARITY_INVERTED) {
- ctrl1 = (ANX74XX_REG_MUX_ML0_RX1 |
- ANX74XX_REG_MUX_ML1_TX1 |
- ANX74XX_REG_MUX_ML3_RX2);
- ctrl5 |= ANX74XX_REG_MUX_ML2_TX2;
- } else {
- ctrl1 = (ANX74XX_REG_MUX_ML0_RX2 |
- ANX74XX_REG_MUX_ML1_TX2 |
- ANX74XX_REG_MUX_ML3_RX1);
- ctrl5 |= ANX74XX_REG_MUX_ML2_TX1;
- }
- } else if (!mux_state) {
- return anx74xx_tcpm_mux_exit(port);
- } else {
- return EC_ERROR_UNIMPLEMENTED;
- }
-
- /*
- * Safe mode must be entererd prior to any changes to the mux related to
- * ALT_DP mode. Therefore, first enable safe mode prior to updating the
- * values for analog_ctrl_1, analog_ctrl_5, and analog_ctrl_2.
- */
- if (anx74xx_tcpm_mux_enter_safe_mode(port))
- return EC_ERROR_UNKNOWN;
-
- /* Write updated pin assignment */
- rv = mux_write(port, ANX74XX_REG_ANALOG_CTRL_1, ctrl1);
- /* Write Rswitch config bits */
- rv |= mux_write(port, ANX74XX_REG_ANALOG_CTRL_5, ctrl5);
- if (rv)
- return EC_ERROR_UNKNOWN;
-
- /* Configure DP aux to sbu settings */
- if (anx74xx_mux_aux_to_sbu(port, mux_state & MUX_POLARITY_INVERTED,
- mux_state & MUX_DP_ENABLED))
- return EC_ERROR_UNKNOWN;
-
- /* Exit safe mode */
- if (anx74xx_tcpm_mux_exit_safe_mode(port))
- return EC_ERROR_UNKNOWN;
-
- anx[port].mux_state = mux_state;
-
- return EC_SUCCESS;
-}
-
-/* current mux state */
-static int anx74xx_tcpm_mux_get(int port, mux_state_t *mux_state)
-{
- *mux_state = anx[port].mux_state;
-
- return EC_SUCCESS;
-}
-
-const struct usb_mux_driver anx74xx_tcpm_usb_mux_driver = {
- .init = anx74xx_tcpm_mux_init,
- .set = anx74xx_tcpm_mux_set,
- .get = anx74xx_tcpm_mux_get,
-};
-#endif /* CONFIG_USB_PD_TCPM_MUX */
-
-static int anx74xx_init_analog(int port)
-{
- int reg, rv = EC_SUCCESS;
-
- /* Analog settings for chip */
- rv |= tcpc_write(port, ANX74XX_REG_HPD_CONTROL,
- ANX74XX_REG_HPD_OP_MODE);
- rv |= tcpc_write(port, ANX74XX_REG_HPD_CTRL_0,
- ANX74XX_REG_HPD_DEFAULT);
- if (rv)
- return rv;
- rv = tcpc_read(port, ANX74XX_REG_GPIO_CTRL_4_5, &reg);
- if (rv)
- return rv;
- reg &= ANX74XX_REG_VBUS_GPIO_MODE;
- reg |= ANX74XX_REG_VBUS_OP_ENABLE;
- rv = tcpc_write(port, ANX74XX_REG_GPIO_CTRL_4_5, reg);
- if (rv)
- return rv;
- rv = tcpc_read(port, ANX74XX_REG_CC_SOFTWARE_CTRL, &reg);
- if (rv)
- return rv;
- reg |= ANX74XX_REG_TX_MODE_ENABLE;
- rv = tcpc_write(port, ANX74XX_REG_CC_SOFTWARE_CTRL, reg);
-
- return rv;
-}
-
-static int anx74xx_send_message(int port, uint16_t header,
- const uint32_t *payload,
- int type,
- uint8_t len)
-{
- int reg, rv = EC_SUCCESS;
- uint8_t *buf = NULL;
- int num_retry = 0, i = 0;
- /* If sending Soft_reset, clear received message */
- /* Soft Reset Message type = 1101 and Number of Data Object = 0 */
- if ((header & 0x700f) == 0x000d) {
- /*
- * When sending soft reset,
- * the Rx buffer of ANX3429 shall be clear
- */
- rv = tcpc_read(port, ANX74XX_REG_CTRL_FW, &reg);
- rv |= tcpc_write(
- port, ANX74XX_REG_CTRL_FW, reg | CLEAR_RX_BUFFER);
- if (rv)
- return EC_ERROR_UNKNOWN;
- tcpc_write(port, ANX74XX_REG_RECVD_MSG_INT, 0xFF);
- }
- /* Inform chip about message length and TX type
- * type->bit-0..2, len->bit-3..7
- */
- reg = (len << 3) & 0xf8;
- reg |= type & 0x07;
- rv |= tcpc_write(port, ANX74XX_REG_TX_CTRL_2, reg);
- if (rv)
- return EC_ERROR_UNKNOWN;
-
- /* Enqueue Header */
- rv = tcpc_write(port, ANX74XX_REG_TX_HEADER_L, (header & 0xff));
- if (rv)
- return EC_ERROR_UNKNOWN;
- rv = tcpc_write(port, ANX74XX_REG_TX_HEADER_H, (header >> 8));
- if (rv)
- return EC_ERROR_UNKNOWN;
- /* Enqueue payload */
- if (len > 2) {
- len -= 2;
- buf = (uint8_t *)payload;
- while (1) {
- if (i < 18)
- rv = tcpc_write(port,
- ANX74XX_REG_TX_START_ADDR_0 + i,
- *buf);
- else
- rv = tcpc_write(port,
- ANX74XX_REG_TX_START_ADDR_1 + i - 18,
- *buf);
- if (rv) {
- num_retry++;
- } else {
- buf++;
- len--;
- num_retry = 0;
- i++;
- }
- if (len == 0 || num_retry >= 3)
- break;
- }
- /* If enqueue failed, do not request anx to transmit
- * messages, FIFO will get cleared in next call
- * before enqueue.
- * num_retry = 0, refer to success
- */
- if (num_retry)
- return EC_ERROR_UNKNOWN;
- }
- /* Request a data transmission
- * This bit will be cleared by ANX after TX success
- */
- rv = tcpc_read(port, ANX74XX_REG_CTRL_COMMAND, &reg);
- if (rv)
- return EC_ERROR_UNKNOWN;
- reg |= ANX74XX_REG_TX_SEND_DATA_REQ;
- rv |= tcpc_write(port, ANX74XX_REG_CTRL_COMMAND, reg);
-
- return rv;
-}
-
-static int anx74xx_read_pd_obj(int port,
- uint8_t *buf,
- int plen)
-{
- int rv = EC_SUCCESS, i;
- int reg, addr = ANX74XX_REG_PD_RX_DATA_OBJ;
-
- /* Read PD data objects from ANX */
- for (i = 0; i < plen ; i++) {
- /* Register sequence changes for last two bytes, if
- * plen is greater than 26
- */
- if (i == 26)
- addr = ANX74XX_REG_PD_RX_DATA_OBJ_M;
- rv = tcpc_read(port, addr + i, &reg);
- if (rv)
- break;
- buf[i] = reg;
- }
- clear_recvd_msg_int(port);
- return rv;
-}
-
-static int anx74xx_check_cc_type(int cc_reg)
-{
- int cc;
-
- switch (cc_reg & ANX74XX_REG_CC_STATUS_MASK) {
- case BIT_VALUE_OF_SRC_CC_RD:
- cc = TYPEC_CC_VOLT_RD;
- break;
-
- case BIT_VALUE_OF_SRC_CC_RA:
- cc = TYPEC_CC_VOLT_RA;
- break;
-
- case BIT_VALUE_OF_SNK_CC_DEFAULT:
- cc = TYPEC_CC_VOLT_RP_DEF;
- break;
-
- case BIT_VALUE_OF_SNK_CC_1_P_5:
- cc = TYPEC_CC_VOLT_RP_1_5;
- break;
-
- case BIT_VALUE_OF_SNK_CC_3_P_0:
- cc = TYPEC_CC_VOLT_RP_3_0;
- break;
-
- default:
- /* If no bits are set, then nothing is attached */
- cc = TYPEC_CC_VOLT_OPEN;
- }
-
- return cc;
-}
-
-static int anx74xx_tcpm_get_cc(int port, enum tcpc_cc_voltage_status *cc1,
- enum tcpc_cc_voltage_status *cc2)
-{
- int rv = EC_SUCCESS;
- int reg = 0;
-
- /* Read tcpc cc status register */
- rv |= tcpc_read(port, ANX74XX_REG_CC_STATUS, &reg);
- /* Check for cc1 type */
- *cc1 = anx74xx_check_cc_type(reg);
- /*
- * Check for cc2 type (note cc2 bits are upper 4 of cc status
- * register.
- */
- *cc2 = anx74xx_check_cc_type(reg >> 4);
-
- /* clear HPD status*/
- if (!(*cc1) && !(*cc2)) {
- anx74xx_tcpc_clear_hpd_status(port);
-#ifdef CONFIG_USB_PD_TCPM_MUX
- anx74xx_tcpm_mux_exit(port);
-#endif
- }
-
- return EC_SUCCESS;
-}
-
-static int anx74xx_rp_control(int port, int rp)
-{
- int reg;
- int rv;
-
- rv = tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_6, &reg);
- if (rv)
- return EC_ERROR_UNKNOWN;
-
- /* clear Bit[0,1] R_RP to default Rp's value */
- reg &= ~0x03;
-
- switch (rp) {
- case TYPEC_RP_1A5:
- /* Set Rp strength to 12K for presenting 1.5A */
- reg |= ANX74XX_REG_CC_PULL_RP_12K;
- break;
- case TYPEC_RP_3A0:
- /* Set Rp strength to 4K for presenting 3A */
- reg |= ANX74XX_REG_CC_PULL_RP_4K;
- break;
- case TYPEC_RP_USB:
- default:
- /* default: Set Rp strength to 36K */
- break;
- }
-
- return tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_6, reg);
-}
-
-static int anx74xx_tcpm_select_rp_value(int port, int rp)
-{
- /* For ANX3429 cannot get cc correctly when Rp != USB_Default */
- selected_rp[port] = rp;
- return EC_SUCCESS;
-}
-
-
-static int anx74xx_cc_software_ctrl(int port, int enable)
-{
- int rv;
- int reg;
-
- rv = tcpc_read(port, ANX74XX_REG_CC_SOFTWARE_CTRL, &reg);
- if (rv)
- return EC_ERROR_UNKNOWN;
-
- if (enable)
- reg |= ANX74XX_REG_CC_SW_CTRL_ENABLE;
- else
- reg &= ~ANX74XX_REG_CC_SW_CTRL_ENABLE;
-
- rv |= tcpc_write(port, ANX74XX_REG_CC_SOFTWARE_CTRL, reg);
- return rv;
-}
-
-static int anx74xx_tcpm_set_cc(int port, int pull)
-{
- int rv = EC_SUCCESS;
- int reg;
-
- /* Enable CC software Control */
- rv = anx74xx_cc_software_ctrl(port, 1);
- if (rv)
- return EC_ERROR_UNKNOWN;
-
- switch (pull) {
- case TYPEC_CC_RP:
- /* Enable Rp */
- rv |= tcpc_read(port, ANX74XX_REG_ANALOG_STATUS, &reg);
- if (rv)
- return EC_ERROR_UNKNOWN;
- reg |= ANX74XX_REG_CC_PULL_RP;
- rv |= tcpc_write(port, ANX74XX_REG_ANALOG_STATUS, reg);
- break;
- case TYPEC_CC_RD:
- /* Enable Rd */
- rv |= tcpc_read(port, ANX74XX_REG_ANALOG_STATUS, &reg);
- if (rv)
- return EC_ERROR_UNKNOWN;
- reg &= ANX74XX_REG_CC_PULL_RD;
- rv |= tcpc_write(port, ANX74XX_REG_ANALOG_STATUS, reg);
- break;
- default:
- rv = EC_ERROR_UNKNOWN;
- break;
- }
-
- return rv;
-}
-
-static int anx74xx_tcpm_set_polarity(int port, int polarity)
-{
- int reg, mux_state, rv = EC_SUCCESS;
-
- rv |= tcpc_read(port, ANX74XX_REG_CC_SOFTWARE_CTRL, &reg);
- if (polarity) /* Inform ANX to use CC2 */
- reg &= ~ANX74XX_REG_SELECT_CC1;
- else /* Inform ANX to use CC1 */
- reg |= ANX74XX_REG_SELECT_CC1;
- rv |= tcpc_write(port, ANX74XX_REG_CC_SOFTWARE_CTRL, reg);
-
- anx[port].polarity = polarity;
-
- /* Update mux polarity */
-#ifdef CONFIG_USB_PD_TCPM_MUX
- mux_state = anx[port].mux_state & ~MUX_POLARITY_INVERTED;
- if (polarity)
- mux_state |= MUX_POLARITY_INVERTED;
- anx74xx_tcpm_mux_set(port, mux_state);
-#endif
- return rv;
-}
-
-static int anx74xx_tcpm_set_vconn(int port, int enable)
-{
- int reg, rv = EC_SUCCESS;
-
- /* switch VCONN to Non CC line */
- rv |= tcpc_read(port, ANX74XX_REG_INTP_VCONN_CTRL, &reg);
- if (rv)
- return EC_ERROR_UNKNOWN;
- if (enable) {
- if (anx[port].polarity)
- reg |= ANX74XX_REG_VCONN_1_ENABLE;
- else
- reg |= ANX74XX_REG_VCONN_2_ENABLE;
- } else {
- reg &= ANX74XX_REG_VCONN_DISABLE;
- }
- rv |= tcpc_write(port, ANX74XX_REG_INTP_VCONN_CTRL, reg);
- anx[port].vconn_en = enable;
-
-#ifdef CONFIG_USB_PD_DECODE_SOP
- rv |= tcpc_read(port, ANX74XX_REG_TX_AUTO_GOODCRC_2, &reg);
- if (rv)
- return EC_ERROR_UNKNOWN;
-
- if (reg & ANX74XX_REG_REPLY_SOP_EN) {
- if (enable) {
- reg |= ANX74XX_REG_REPLY_SOP_1_EN |
- ANX74XX_REG_REPLY_SOP_2_EN;
- } else {
- reg &= ~(ANX74XX_REG_REPLY_SOP_1_EN |
- ANX74XX_REG_REPLY_SOP_2_EN);
- }
-
- tcpc_write(port, ANX74XX_REG_TX_AUTO_GOODCRC_2, reg);
- }
-#endif
- return rv;
-}
-
-static int anx74xx_tcpm_set_msg_header(int port, int power_role, int data_role)
-{
- return tcpc_write(port, ANX74XX_REG_TX_AUTO_GOODCRC_1,
- ANX74XX_REG_AUTO_GOODCRC_SET(!!data_role, !!power_role));
-}
-
-static int anx74xx_tcpm_set_rx_enable(int port, int enable)
-{
- int reg, rv;
-
- rv = tcpc_read(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG_MASK, &reg);
- if (rv)
- return rv;
- if (enable) {
- reg &= ~(ANX74XX_REG_IRQ_CC_MSG_INT);
- anx74xx_tcpm_set_auto_good_crc(port, 1);
- anx74xx_rp_control(port, selected_rp[port]);
- } else {
- /* Disable RX message by masking interrupt */
- reg |= (ANX74XX_REG_IRQ_CC_MSG_INT);
- anx74xx_tcpm_set_auto_good_crc(port, 0);
- anx74xx_rp_control(port, TYPEC_RP_USB);
- }
- /*When this function was call, the interrupt status shall be cleared*/
- tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, 0);
-
- return tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG_MASK, reg);
-}
-
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
-static int anx74xx_tcpm_get_vbus_level(int port)
-{
- int reg = 0;
-
- tcpc_read(port, ANX74XX_REG_ANALOG_STATUS, &reg);
- return ((reg & ANX74XX_REG_VBUS_STATUS) ? 1 : 0);
-}
-#endif
-
-static int anx74xx_tcpm_get_message_raw(int port, uint32_t *payload, int *head)
-{
- int reg;
- int len;
-
- /* Fetch the header */
- if (tcpc_read16(port, ANX74XX_REG_PD_HEADER, &reg)) {
- clear_recvd_msg_int(port);
- return EC_ERROR_UNKNOWN;
- }
- *head = reg;
-#ifdef CONFIG_USB_PD_DECODE_SOP
- *head |= PD_HEADER_SOP(msg_sop[port]);
-#endif
-
- len = PD_HEADER_CNT(*head) * 4;
- if (!len) {
- clear_recvd_msg_int(port);
- return EC_SUCCESS;
- }
-
- /* Receive message : assuming payload have enough
- * memory allocated
- */
- return anx74xx_read_pd_obj(port, (uint8_t *)payload, len);
-}
-
-static int anx74xx_tcpm_transmit(int port, enum tcpm_transmit_type type,
- uint16_t header,
- const uint32_t *data)
-{
- uint8_t len = 0;
- int ret = 0, reg = 0;
-
- switch (type) {
- /* ANX is aware of type */
- case TCPC_TX_SOP:
- case TCPC_TX_SOP_PRIME:
- case TCPC_TX_SOP_PRIME_PRIME:
- len = PD_HEADER_CNT(header) * 4 + 2;
- ret = anx74xx_send_message(port, header,
- data, type, len);
- break;
- case TCPC_TX_HARD_RESET:
- /* Request HARD RESET */
- tcpc_read(port, ANX74XX_REG_TX_CTRL_1, &reg);
- reg |= ANX74XX_REG_TX_HARD_RESET_REQ;
- ret = tcpc_write(port, ANX74XX_REG_TX_CTRL_1, reg);
- /*After Hard Reset, TCPM shall disable goodCRC*/
- anx74xx_tcpm_set_auto_good_crc(port, 0);
- break;
- case TCPC_TX_CABLE_RESET:
- /* Request CABLE RESET */
- tcpc_read(port, ANX74XX_REG_TX_CTRL_1, &reg);
- reg |= ANX74XX_REG_TX_CABLE_RESET_REQ;
- ret = tcpc_write(port, ANX74XX_REG_TX_CTRL_1, reg);
- break;
- case TCPC_TX_BIST_MODE_2:
- /* Request BIST MODE 2 */
- reg = ANX74XX_REG_TX_BIST_START
- | ANX74XX_REG_TX_BIXT_FOREVER | (0x02 << 4);
- ret = tcpc_write(port, ANX74XX_REG_TX_BIST_CTRL, reg);
- msleep(1);
- ret = tcpc_write(port, ANX74XX_REG_TX_BIST_CTRL,
- reg | ANX74XX_REG_TX_BIST_ENABLE);
- msleep(30);
- tcpc_read(port, ANX74XX_REG_TX_BIST_CTRL, &reg);
- ret = tcpc_write(port, ANX74XX_REG_TX_BIST_CTRL,
- reg | ANX74XX_REG_TX_BIST_STOP);
- ret = tcpc_write(port, ANX74XX_REG_TX_BIST_CTRL,
- reg & (~ANX74XX_REG_TX_BIST_STOP));
- ret = tcpc_write(port, ANX74XX_REG_TX_BIST_CTRL, 0);
- break;
- default:
- return EC_ERROR_UNIMPLEMENTED;
- }
-
- return ret;
-}
-
-/*
- * Don't let the TCPC try to pull from the RX buffer forever. We typical only
- * have 1 or 2 messages waiting.
- */
-#define MAX_ALLOW_FAILED_RX_READS 10
-
-void anx74xx_tcpc_alert(int port)
-{
- int reg;
- int failed_attempts;
-
- /* Clear soft irq bit */
- tcpc_write(port, ANX74XX_REG_IRQ_EXT_SOURCE_3,
- ANX74XX_REG_CLEAR_SOFT_IRQ);
-
- /* Read main alert register for pending alerts */
- reg = 0;
- tcpc_read(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, &reg);
-
- /* Prioritize TX completion because PD state machine is waiting */
- if (reg & ANX74XX_REG_IRQ_GOOD_CRC_INT)
- pd_transmit_complete(port, TCPC_TX_COMPLETE_SUCCESS);
-
- if (reg & ANX74XX_REG_IRQ_TX_FAIL_INT)
- pd_transmit_complete(port, TCPC_TX_COMPLETE_FAILED);
-
- /* Pull all RX messages from TCPC into EC memory */
- failed_attempts = 0;
- while (reg & ANX74XX_REG_IRQ_CC_MSG_INT) {
- if (tcpm_enqueue_message(port))
- ++failed_attempts;
- if (tcpc_read(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, &reg))
- ++failed_attempts;
-
- /* Ensure we don't loop endlessly */
- if (failed_attempts >= MAX_ALLOW_FAILED_RX_READS) {
- CPRINTF("C%d Cannot consume RX buffer after %d failed "
- "attempts!", port, failed_attempts);
- /*
- * The port is in a bad state, we don't want to consume
- * all EC resources so suspend the port for a little
- * while.
- */
- pd_set_suspend(port, 1);
- pd_deferred_resume(port);
- return;
- }
- }
-
- /* Clear all pending alerts */
- tcpc_write(port, ANX74XX_REG_RECVD_MSG_INT, reg);
-
- if (reg & ANX74XX_REG_IRQ_CC_STATUS_INT)
- /* CC status changed, wake task */
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC, 0);
-
- /* Read and clear extended alert register 1 */
- reg = 0;
- tcpc_read(port, ANX74XX_REG_IRQ_EXT_SOURCE_1, &reg);
- tcpc_write(port, ANX74XX_REG_IRQ_EXT_SOURCE_1, reg);
-
-#ifdef CONFIG_USB_PD_DECODE_SOP
- if (reg & ANX74XX_REG_EXT_SOP)
- msg_sop[port] = PD_MSG_SOP;
- else if (reg & ANX74XX_REG_EXT_SOP_PRIME)
- msg_sop[port] = PD_MSG_SOPP;
-#endif
-
- /* Check for Hard Reset done bit */
- if (reg & ANX74XX_REG_ALERT_TX_HARD_RESETOK)
- /* ANX hardware clears the request bit */
- pd_transmit_complete(port, TCPC_TX_COMPLETE_SUCCESS);
-
- /* Read and clear TCPC extended alert register 2 */
- reg = 0;
- tcpc_read(port, ANX74XX_REG_IRQ_EXT_SOURCE_2, &reg);
- tcpc_write(port, ANX74XX_REG_IRQ_EXT_SOURCE_2, reg);
-
-#ifdef CONFIG_USB_PD_DECODE_SOP
- if (reg & ANX74XX_REG_EXT_SOP_PRIME_PRIME)
- msg_sop[port] = PD_MSG_SOPPP;
-#endif
-
- if (reg & ANX74XX_REG_EXT_HARD_RST) {
- /* hard reset received */
- pd_execute_hard_reset(port);
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-static int anx74xx_tcpm_init(int port)
-{
- int rv = 0, reg;
-
- memset(&anx[port], 0, sizeof(struct anx_state));
- /* Bring chip in normal mode to work */
- anx74xx_set_power_mode(port, ANX74XX_NORMAL_MODE);
-
- /* Initialize analog section of ANX */
- rv |= anx74xx_init_analog(port);
-
- /* disable all interrupts */
- rv |= tcpc_write(port, ANX74XX_REG_IRQ_EXT_MASK_1,
- ANX74XX_REG_CLEAR_SET_BITS);
-
- /* Initialize interrupt open-drain */
- rv |= tcpc_read(port, ANX74XX_REG_INTP_VCONN_CTRL, &reg);
- if (tcpc_config[port].flags & TCPC_FLAGS_ALERT_OD)
- reg |= ANX74XX_REG_R_INTERRUPT_OPEN_DRAIN;
- else
- reg &= ~ANX74XX_REG_R_INTERRUPT_OPEN_DRAIN;
- rv |= tcpc_write(port, ANX74XX_REG_INTP_VCONN_CTRL, reg);
-
- /* Initialize interrupt polarity */
- reg = tcpc_config[port].flags & TCPC_FLAGS_ALERT_ACTIVE_HIGH ?
- ANX74XX_REG_IRQ_POL_HIGH : ANX74XX_REG_IRQ_POL_LOW;
- rv |= tcpc_write(port, ANX74XX_REG_IRQ_STATUS, reg);
-
- /* unmask interrupts */
- rv |= tcpc_read(port, ANX74XX_REG_IRQ_EXT_MASK_1, &reg);
- reg &= (~ANX74XX_REG_ALERT_TX_MSG_ERROR);
- reg &= (~ANX74XX_REG_ALERT_TX_CABLE_RESETOK);
- reg &= (~ANX74XX_REG_ALERT_TX_HARD_RESETOK);
- rv |= tcpc_write(port, ANX74XX_REG_IRQ_EXT_MASK_1, reg);
-
- rv |= tcpc_read(port, ANX74XX_REG_IRQ_EXT_MASK_2, &reg);
- reg &= (~ANX74XX_REG_EXT_HARD_RST);
- rv |= tcpc_write(port, ANX74XX_REG_IRQ_EXT_MASK_2, reg);
-
- /* HPD pin output enable*/
- rv |= tcpc_write(port, ANX74XX_REG_HPD_CTRL_0, ANX74XX_REG_HPD_DEFAULT);
-
- if (rv)
- return EC_ERROR_UNKNOWN;
-
- /* Set AVDD10_BMC to 1.08 */
- rv |= tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_5, &reg);
- if (rv)
- return EC_ERROR_UNKNOWN;
- rv = tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_5, (reg & 0xf3));
- if (rv)
- return EC_ERROR_UNKNOWN;
-
- /* Decrease BMC TX lowest swing voltage */
- rv |= tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_11, &reg);
- if (rv)
- return EC_ERROR_UNKNOWN;
- rv = tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_11, (reg & 0x3f) | 0x40);
- if (rv)
- return EC_ERROR_UNKNOWN;
-
- /* Set BMC TX cap slew rate to 400ns */
- rv = tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_12, 0x4);
- if (rv)
- return EC_ERROR_UNKNOWN;
-
- tcpm_get_chip_info(port, 1, NULL);
-
- return EC_SUCCESS;
-}
-
-static int anx74xx_get_chip_info(int port, int live,
- struct ec_response_pd_chip_info_v1 **chip_info)
-{
- int rv = tcpci_get_chip_info(port, live, chip_info);
- int val;
-
- if (rv)
- return rv;
-
- if ((*chip_info)->fw_version_number == 0 ||
- (*chip_info)->fw_version_number == -1 || live) {
- rv = tcpc_read(port, ANX74XX_REG_FW_VERSION, &val);
-
- if (rv)
- return rv;
-
- (*chip_info)->fw_version_number = val;
- }
-
-#ifdef CONFIG_USB_PD_TCPM_ANX3429
- /*
- * Min firmware version of ANX3429 to ensure that false SOP' detection
- * doesn't occur for e-marked cables. See b/116255749#comment8 and
- * b/64752060#comment11
- */
- (*chip_info)->min_req_fw_version_number = 0x16;
-#endif
-
- return rv;
-}
-
-/*
- * Dissociate from the TCPC.
- */
-
-static int anx74xx_tcpm_release(int port)
-{
- return EC_SUCCESS;
-}
-
-const struct tcpm_drv anx74xx_tcpm_drv = {
- .init = &anx74xx_tcpm_init,
- .release = &anx74xx_tcpm_release,
- .get_cc = &anx74xx_tcpm_get_cc,
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
- .get_vbus_level = &anx74xx_tcpm_get_vbus_level,
-#endif
- .select_rp_value = &anx74xx_tcpm_select_rp_value,
- .set_cc = &anx74xx_tcpm_set_cc,
- .set_polarity = &anx74xx_tcpm_set_polarity,
- .set_vconn = &anx74xx_tcpm_set_vconn,
- .set_msg_header = &anx74xx_tcpm_set_msg_header,
- .set_rx_enable = &anx74xx_tcpm_set_rx_enable,
- .get_message_raw = &anx74xx_tcpm_get_message_raw,
- .transmit = &anx74xx_tcpm_transmit,
- .tcpc_alert = &anx74xx_tcpc_alert,
-#ifdef CONFIG_USB_PD_DISCHARGE_TCPC
- .tcpc_discharge_vbus = &anx74xx_tcpc_discharge_vbus,
-#endif
- .get_chip_info = &anx74xx_get_chip_info,
-#if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && \
- defined(CONFIG_USB_PD_TCPC_LOW_POWER)
- .drp_toggle = &anx74xx_tcpc_drp_toggle,
- .enter_low_power_mode = &anx74xx_enter_low_power_mode,
-#endif
-};
-
-#ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC
-struct i2c_stress_test_dev anx74xx_i2c_stress_test_dev = {
- .reg_info = {
- .read_reg = ANX74XX_REG_VENDOR_ID_L,
- .read_val = ANX74XX_VENDOR_ID & 0xFF,
- .write_reg = ANX74XX_REG_CC_SOFTWARE_CTRL,
- },
- .i2c_read = &tcpc_i2c_read,
- .i2c_write = &tcpc_i2c_write,
-};
-#endif /* CONFIG_CMD_I2C_STRESS_TEST_TCPC */
diff --git a/driver/tcpm/anx74xx.h b/driver/tcpm/anx74xx.h
deleted file mode 100644
index 2648013abf..0000000000
--- a/driver/tcpm/anx74xx.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/* Copyright 2016 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.
- *
- * Author : Analogix Semiconductor.
- */
-
-/* USB Power delivery port management */
-
-#ifndef __CROS_EC_USB_PD_TCPM_ANX74XX_H
-#define __CROS_EC_USB_PD_TCPM_ANX74XX_H
-
-/* I2C interface */
-#define ANX74XX_I2C_ADDR1_FLAGS 0x28
-#define ANX74XX_I2C_ADDR2_FLAGS 0x39
-#define ANX74XX_I2C_ADDR3_FLAGS 0x3E
-#define ANX74XX_I2C_ADDR4_FLAGS 0x40
-
-#define ANX74XX_REG_IRQ_POL_LOW 0x00
-#define ANX74XX_REG_IRQ_POL_HIGH 0x02
-
-#define ANX74XX_REG_VENDOR_ID_L 0x00
-#define ANX74XX_REG_VENDOR_ID_H 0x01
-#define ANX74XX_VENDOR_ID 0xAAAA
-
-/* ANX F/W version:0x50:0x44 which contains otp firmware version */
-#define ANX74XX_REG_FW_VERSION 0x44
-
-#define ANX74XX_REG_IRQ_STATUS 0x53
-
-#define ANX74XX_REG_INTP_VCONN_CTRL 0x33
-#define ANX74XX_REG_VCONN_DISABLE 0x0f
-#define ANX74XX_REG_VCONN_1_ENABLE BIT(4)
-#define ANX74XX_REG_VCONN_2_ENABLE BIT(5)
-#define ANX74XX_REG_R_INTERRUPT_OPEN_DRAIN BIT(2)
-
-#define ANX74XX_STANDBY_MODE (0)
-#define ANX74XX_NORMAL_MODE (1)
-
-#define ANX74XX_REG_TX_CTRL_1 0x81
-#define ANX74XX_REG_TX_HARD_RESET_REQ BIT(1)
-#define ANX74XX_REG_TX_CABLE_RESET_REQ BIT(2)
-
-#define ANX74XX_REG_TX_CTRL_2 0x82
-#define ANX74XX_REG_TX_WR_FIFO 0x83
-#define ANX74XX_REG_TX_FIFO_CTRL 0x9a
-#define ANX74XX_REG_TX_HEADER_L 0x2c
-#define ANX74XX_REG_TX_HEADER_H 0x2d
-#define ANX74XX_REG_TX_START_ADDR_0 0x6d
-#define ANX74XX_REG_TX_START_ADDR_1 0xd0
-
-#define ANX74XX_REG_CTRL_COMMAND 0xdb
-#define ANX74XX_REG_TX_SEND_DATA_REQ BIT(0)
-#define ANX74XX_REG_TX_HARD_RST_REQ BIT(1)
-
-#define ANX74XX_REG_TX_BIST_CTRL 0x9D
-#define ANX74XX_REG_TX_BIST_MODE BIT(4)
-#define ANX74XX_REG_TX_BIST_STOP BIT(3)
-#define ANX74XX_REG_TX_BIXT_FOREVER BIT(2)
-#define ANX74XX_REG_TX_BIST_ENABLE BIT(1)
-#define ANX74XX_REG_TX_BIST_START BIT(0)
-
-#define ANX74XX_REG_PD_HEADER 0x69
-#define ANX74XX_REG_PD_RX_DATA_OBJ 0x11
-#define ANX74XX_REG_PD_RX_DATA_OBJ_M 0x4d
-
-#define ANX74XX_REG_ANALOG_STATUS 0x40
-#define ANX74XX_REG_VBUS_STATUS BIT(4)
-#define ANX74XX_REG_CC_PULL_RD 0xfd
-#define ANX74XX_REG_CC_PULL_RP 0x02
-
-
-#define ANX74XX_REG_TX_AUTO_GOODCRC_2 0x94
-#define ANX74XX_REG_REPLY_SOP_EN BIT(3)
-#define ANX74XX_REG_REPLY_SOP_1_EN BIT(4)
-#define ANX74XX_REG_REPLY_SOP_2_EN BIT(5)
-
-#define ANX74XX_REG_TX_AUTO_GOODCRC_1 0x9c
-#define ANX74XX_REG_SPEC_REV_BIT_POS (3)
-#define ANX74XX_REG_DATA_ROLE_BIT_POS (2)
-#define ANX74XX_REG_PWR_ROLE_BIT_POS (1)
-#define ANX74XX_REG_AUTO_GOODCRC_EN BIT(0)
-#define ANX74XX_REG_AUTO_GOODCRC_SET(drole, prole) \
- ((PD_REV20 << ANX74XX_REG_SPEC_REV_BIT_POS) | \
- ((drole) << ANX74XX_REG_DATA_ROLE_BIT_POS) | \
- ((prole) << ANX74XX_REG_PWR_ROLE_BIT_POS) | \
- ANX74XX_REG_AUTO_GOODCRC_EN)
-
-
-#define ANX74XX_REG_ANALOG_CTRL_0 0x41
-#define ANX74XX_REG_R_PIN_CABLE_DET BIT(7)
-
-#define ANX74XX_REG_ANALOG_CTRL_1 0x42
-#define ANX74XX_REG_ANALOG_CTRL_5 0x46
-#define ANX74XX_REG_ANALOG_CTRL_6 0x47
-#define ANX74XX_REG_CC_PULL_RP_36K 0x00
-#define ANX74XX_REG_CC_PULL_RP_12K 0x01
-#define ANX74XX_REG_CC_PULL_RP_4K 0x02
-
-#define ANX74XX_REG_R_SWITCH_CC_CLR 0x0f
-#define ANX74XX_REG_R_SWITCH_CC2_SET 0x10
-#define ANX74XX_REG_R_SWITCH_CC1_SET 0x20
-#define ANX74XX_REG_AUX_SWAP_SET_CC1 0x30
-#define ANX74XX_REG_AUX_SWAP_SET_CC2 0xc0
-
-#define ANX74XX_REG_ANALOG_CTRL_11 0x4c
-#define ANX74XX_REG_ANALOG_CTRL_12 0x4d
-
-#define ANX74XX_REG_MUX_ML0_RX2 BIT(0)
-#define ANX74XX_REG_MUX_ML0_RX1 BIT(1)
-#define ANX74XX_REG_MUX_ML3_RX2 BIT(2)
-#define ANX74XX_REG_MUX_ML3_RX1 BIT(3)
-#define ANX74XX_REG_MUX_SSRX_RX2 BIT(4)
-#define ANX74XX_REG_MUX_SSRX_RX1 BIT(5)
-#define ANX74XX_REG_MUX_ML1_TX2 BIT(6)
-#define ANX74XX_REG_MUX_ML1_TX1 BIT(7)
-
-#define ANX74XX_REG_MUX_ML2_TX2 BIT(4)
-#define ANX74XX_REG_MUX_ML2_TX1 BIT(5)
-#define ANX74XX_REG_MUX_SSTX_TX2 BIT(6)
-#define ANX74XX_REG_MUX_SSTX_TX1 BIT(7)
-
-#define ANX74XX_REG_CC_SOFTWARE_CTRL 0x4a
-#define ANX74XX_REG_CC_SW_CTRL_ENABLE 0x01
-#define ANX74XX_REG_TX_MODE_ENABLE 0x04
-
-#define ANX74XX_REG_SELECT_CC1 0x02
-
-#define ANX74XX_REG_GPIO_CTRL_4_5 0x3f
-#define ANX74XX_REG_VBUS_OP_ENABLE 0x04
-#define ANX74XX_REG_VBUS_GPIO_MODE 0xfe
-
-#define ANX74XX_REG_IRQ_EXT_MASK_1 0x3b
-#define ANX74XX_REG_IRQ_EXT_MASK_2 0x3c
-#define ANX74XX_REG_IRQ_EXT_SOURCE_1 0x3e
-#define ANX74XX_REG_EXT_SOP BIT(6)
-#define ANX74XX_REG_EXT_SOP_PRIME BIT(7)
-#define ANX74XX_REG_IRQ_EXT_SOURCE_2 0x4e
-#define ANX74XX_REG_EXT_SOP_PRIME_PRIME BIT(0)
-#define ANX74XX_REG_EXT_HARD_RST BIT(2)
-#define ANX74XX_REG_IRQ_EXT_SOURCE_3 0x4f
-#define ANX74XX_REG_CLEAR_SOFT_IRQ BIT(2)
-
-#define ANX74XX_REG_IRQ_SOURCE_RECV_MSG 0x6b
-#define ANX74XX_REG_IRQ_CC_MSG_INT BIT(0)
-#define ANX74XX_REG_IRQ_CC_STATUS_INT BIT(1)
-#define ANX74XX_REG_IRQ_GOOD_CRC_INT BIT(2)
-#define ANX74XX_REG_IRQ_TX_FAIL_INT BIT(3)
-#define ANX74XX_REG_IRQ_SOURCE_RECV_MSG_MASK 0x6c
-
-#define ANX74XX_REG_CLEAR_SET_BITS 0xff
-#define ANX74XX_REG_ALERT_HARD_RST_RECV BIT(6)
-#define ANX74XX_REG_ALERT_MSG_RECV BIT(5)
-#define ANX74XX_REG_ALERT_TX_MSG_ERROR BIT(4)
-#define ANX74XX_REG_ALERT_TX_ACK_RECV BIT(3)
-#define ANX74XX_REG_ALERT_TX_CABLE_RESETOK BIT(2)
-#define ANX74XX_REG_ALERT_TX_HARD_RESETOK BIT(1)
-#define ANX74XX_REG_ALERT_CC_CHANGE BIT(0)
-
-#define ANX74XX_REG_ANALOG_CTRL_2 0x43
-#define ANX74XX_REG_MODE_TRANS 0x01
-
-#define ANX74XX_REG_SET_VBUS 0x20
-
-#define ANX74XX_REG_ANALOG_CTRL_7 0x48
-#define ANX74XX_REG_STATUS_CC_RD 0x01
-#define ANX74XX_REG_STATUS_CC_RA 0x03
-#define ANX74XX_REG_STATUS_CC1(reg) ((reg & 0x0C) >> 2)
-#define ANX74XX_REG_STATUS_CC2(reg) ((reg & 0x03) >> 0)
-
-#define ANX74XX_REG_HPD_CONTROL 0xfd
-
-#define ANX74XX_REG_HPD_CTRL_0 0x36
-#define ANX74XX_REG_DISCHARGE_CTRL 0x80
-#define ANX74XX_REG_HPD_OP_MODE 0x08
-#define ANX74XX_REG_HPD_DEFAULT 0x00
-#define ANX74XX_REG_HPD_OUT_DATA 0x10
-
-#define ANX74XX_REG_RECVD_MSG_INT 0x98
-#define ANX74XX_REG_CC_STATUS 0x99
-#define ANX74XX_REG_CTRL_FW 0x2E
-#define CLEAR_RX_BUFFER (1)
-#define ANX74XX_REG_POWER_DOWN_CTRL 0x0d
-#define ANX74XX_REG_STATUS_CC1_VRD_USB BIT(7)
-#define ANX74XX_REG_STATUS_CC1_VRD_1P5 BIT(6)
-#define ANX74XX_REG_STATUS_CC1_VRD_3P0 BIT(5)
-#define ANX74XX_REG_STATUS_CC2_VRD_USB BIT(4)
-#define ANX74XX_REG_STATUS_CC2_VRD_1P5 BIT(3)
-#define ANX74XX_REG_STATUS_CC2_VRD_3P0 BIT(2)
-
-/* defined in the inter-bock Spec: 4.2.10 CC Detect Status */
-#define ANX74XX_REG_CC_STATUS_MASK 0xf
-#define BIT_VALUE_OF_SRC_CC_RD 0x01
-#define BIT_VALUE_OF_SRC_CC_RA 0x02
-#define BIT_VALUE_OF_SNK_CC_DEFAULT 0x04
-#define BIT_VALUE_OF_SNK_CC_1_P_5 0x08
-#define BIT_VALUE_OF_SNK_CC_3_P_0 0x0C
-#define ANX74XX_CC_RA_MASK (BIT_VALUE_OF_SRC_CC_RA | \
- (BIT_VALUE_OF_SRC_CC_RA << 4))
-#define ANX74XX_CC_RD_MASK (BIT_VALUE_OF_SRC_CC_RD | \
- (BIT_VALUE_OF_SRC_CC_RD << 4))
-
-/*
- * RESETN low to PWR_EN low delay
- */
-#define ANX74XX_RST_L_PWR_L_DELAY_MS 1
-/*
- * minimum power off-to-on delay to reset chip
- */
-#define ANX74XX_PWR_L_PWR_H_DELAY_MS 10
-/*
- * parameter T4: PWR_EN high to RESETN high delay
- */
-#define ANX74XX_PWR_H_RST_H_DELAY_MS 10
-
-extern const struct tcpm_drv anx74xx_tcpm_drv;
-extern const struct usb_mux_driver anx74xx_tcpm_usb_mux_driver;
-void anx74xx_tcpc_set_vbus(int port, int enable);
-void anx74xx_tcpc_update_hpd_status(int port, int hpd_lvl, int hpd_irq);
-void anx74xx_tcpc_clear_hpd_status(int port);
-
-#ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC
-extern struct i2c_stress_test_dev anx74xx_i2c_stress_test_dev;
-#endif
-
-#endif /* __CROS_EC_USB_PD_TCPM_ANX74XX_H */
diff --git a/driver/tcpm/anx7688.c b/driver/tcpm/anx7688.c
deleted file mode 100644
index fe1d2498d4..0000000000
--- a/driver/tcpm/anx7688.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/* Copyright 2016 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.
- */
-
-/* ANX7688 port manager */
-
-#include "hooks.h"
-#include "tcpci.h"
-#include "tcpm.h"
-#include "timer.h"
-#include "usb_mux.h"
-
-#if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) || \
- defined(CONFIG_USB_PD_TCPC_LOW_POWER) || \
- defined(CONFIG_USB_PD_DISCHARGE_TCPC)
-#error "Unsupported config options of anx7688 PD driver"
-#endif
-
-#define ANX7688_VENDOR_ALERT BIT(15)
-
-#define ANX7688_REG_STATUS 0x82
-#define ANX7688_REG_STATUS_LINK BIT(0)
-
-#define ANX7688_REG_HPD 0x83
-#define ANX7688_REG_HPD_HIGH BIT(0)
-#define ANX7688_REG_HPD_IRQ BIT(1)
-#define ANX7688_REG_HPD_ENABLE BIT(2)
-
-#define ANX7688_USBC_ADDR_FLAGS 0x28
-#define ANX7688_REG_RAMCTRL 0xe7
-#define ANX7688_REG_RAMCTRL_BOOT_DONE BIT(6)
-
-static int anx7688_init(int port)
-{
- int rv = 0;
- int mask = 0;
-
- /*
- * 7688 POWER_STATUS[6] is not reliable for tcpci_tcpm_init() to poll
- * due to it is default 0 in HW, and we cannot write TCPC until it is
- * ready, or something goes wrong. (Issue 52772)
- * Instead we poll TCPC 0x50:0xe7 bit6 here to make sure bootdone is
- * ready(50ms). Then PD main flow can process cc debounce in 50ms ~
- * 100ms to follow cts.
- */
- while (1) {
- rv = i2c_read8(I2C_PORT_TCPC, ANX7688_USBC_ADDR_FLAGS,
- ANX7688_REG_RAMCTRL, &mask);
-
- if (rv == EC_SUCCESS && (mask & ANX7688_REG_RAMCTRL_BOOT_DONE))
- break;
- msleep(10);
- }
-
- rv = tcpci_tcpm_drv.init(port);
- if (rv)
- return rv;
-
- rv = tcpc_read16(port, TCPC_REG_ALERT_MASK, &mask);
- if (rv)
- return rv;
-
- /* enable vendor specific alert */
- mask |= ANX7688_VENDOR_ALERT;
- rv = tcpc_write16(port, TCPC_REG_ALERT_MASK, mask);
- return rv;
-}
-
-static int anx7688_release(int port)
-{
- return EC_ERROR_UNIMPLEMENTED;
-}
-
-static void anx7688_update_hpd_enable(int port)
-{
- int status, reg, rv;
-
- rv = tcpc_read(port, ANX7688_REG_STATUS, &status);
- rv |= tcpc_read(port, ANX7688_REG_HPD, &reg);
- if (rv)
- return;
-
- if (!(reg & ANX7688_REG_HPD_ENABLE) ||
- !(status & ANX7688_REG_STATUS_LINK)) {
- reg &= ~ANX7688_REG_HPD_IRQ;
- tcpc_write(port, ANX7688_REG_HPD,
- (status & ANX7688_REG_STATUS_LINK)
- ? reg | ANX7688_REG_HPD_ENABLE
- : reg & ~ANX7688_REG_HPD_ENABLE);
- }
-}
-
-int anx7688_hpd_disable(int port)
-{
- return tcpc_write(port, ANX7688_REG_HPD, 0);
-}
-
-int anx7688_update_hpd(int port, int level, int irq)
-{
- int reg, rv;
-
- rv = tcpc_read(port, ANX7688_REG_HPD, &reg);
- if (rv)
- return rv;
-
- if (level)
- reg |= ANX7688_REG_HPD_HIGH;
- else
- reg &= ~ANX7688_REG_HPD_HIGH;
-
- if (irq)
- reg |= ANX7688_REG_HPD_IRQ;
- else
- reg &= ~ANX7688_REG_HPD_IRQ;
-
- return tcpc_write(port, ANX7688_REG_HPD, reg);
-}
-
-int anx7688_enable_cable_detection(int port)
-{
- return tcpc_write(port, TCPC_REG_COMMAND, 0xff);
-}
-
-int anx7688_set_power_supply_ready(int port)
-{
- return tcpc_write(port, TCPC_REG_COMMAND, 0x77);
-}
-
-int anx7688_power_supply_reset(int port)
-{
- return tcpc_write(port, TCPC_REG_COMMAND, 0x66);
-}
-
-static void anx7688_tcpc_alert(int port)
-{
- int alert, rv;
-
- rv = tcpc_read16(port, TCPC_REG_ALERT, &alert);
- /* process and clear alert status */
- tcpci_tcpc_alert(port);
-
- if (!rv && (alert & ANX7688_VENDOR_ALERT))
- anx7688_update_hpd_enable(port);
-}
-
-static int anx7688_mux_set(int port, mux_state_t mux_state)
-{
- int reg = 0;
- int rv, polarity;
-
- rv = mux_read(port, TCPC_REG_CONFIG_STD_OUTPUT, &reg);
- if (rv != EC_SUCCESS)
- return rv;
-
- reg &= ~TCPC_REG_CONFIG_STD_OUTPUT_MUX_MASK;
- if (mux_state & MUX_USB_ENABLED)
- reg |= TCPC_REG_CONFIG_STD_OUTPUT_MUX_USB;
- if (mux_state & MUX_DP_ENABLED)
- reg |= TCPC_REG_CONFIG_STD_OUTPUT_MUX_DP;
-
- /* ANX7688 needs to set bit0 */
- rv = mux_read(port, TCPC_REG_TCPC_CTRL, &polarity);
- if (rv != EC_SUCCESS)
- return rv;
-
- /* copy the polarity from TCPC_CTRL[0], take care clear then set */
- reg &= ~TCPC_REG_TCPC_CTRL_POLARITY(1);
- reg |= TCPC_REG_TCPC_CTRL_POLARITY(polarity);
- return mux_write(port, TCPC_REG_CONFIG_STD_OUTPUT, reg);
-}
-
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
-static int anx7688_tcpm_get_vbus_level(int port)
-{
- int reg = 0;
-
- /* On ANX7688, POWER_STATUS.VBusPresent (bit 2) is averaged 16 times, so
- * its value may not be set to 1 quickly enough during power role swap.
- * Therefore, we use a proprietary register to read the unfiltered VBus
- * value. See crosbug.com/p/55221 .
- */
- i2c_read8(I2C_PORT_TCPC, 0x28, 0x40, &reg);
- return ((reg & 0x10) ? 1 : 0);
-}
-#endif
-
-/* ANX7688 is a TCPCI compatible port controller */
-const struct tcpm_drv anx7688_tcpm_drv = {
- .init = &anx7688_init,
- .release = &anx7688_release,
- .get_cc = &tcpci_tcpm_get_cc,
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
- .get_vbus_level = &anx7688_tcpm_get_vbus_level,
-#endif
- .select_rp_value = &tcpci_tcpm_select_rp_value,
- .set_cc = &tcpci_tcpm_set_cc,
- .set_polarity = &tcpci_tcpm_set_polarity,
- .set_vconn = &tcpci_tcpm_set_vconn,
- .set_msg_header = &tcpci_tcpm_set_msg_header,
- .set_rx_enable = &tcpci_tcpm_set_rx_enable,
- .get_message_raw = &tcpci_tcpm_get_message_raw,
- .transmit = &tcpci_tcpm_transmit,
- .tcpc_alert = &anx7688_tcpc_alert,
-};
-
-#ifdef CONFIG_USB_PD_TCPM_MUX
-const struct usb_mux_driver anx7688_usb_mux_driver = {
- .init = tcpci_tcpm_mux_init,
- .set = anx7688_mux_set,
- .get = tcpci_tcpm_mux_get,
-};
-#endif /* CONFIG_USB_PD_TCPM_MUX */
diff --git a/driver/tcpm/anx7688.h b/driver/tcpm/anx7688.h
deleted file mode 100644
index 534e4155b1..0000000000
--- a/driver/tcpm/anx7688.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Copyright 2016 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.
- */
-
-/* USB Power delivery port management */
-
-#ifndef __CROS_EC_USB_PD_TCPM_ANX7688_H
-#define __CROS_EC_USB_PD_TCPM_ANX7688_H
-
-int anx7688_update_hpd(int port, int level, int irq);
-int anx7688_set_dp_pin_mode(int port, int pin_mode);
-int anx7688_enable_cable_detection(int port);
-int anx7688_set_power_supply_ready(int port);
-int anx7688_power_supply_reset(int port);
-int anx7688_hpd_disable(int port);
-
-extern struct tcpm_drv anx7688_tcpm_drv;
-extern struct usb_mux_driver anx7688_usb_mux_driver;
-
-#endif /* __CROS_EC_USB_PD_TCPM_ANX7688_H */
diff --git a/driver/tcpm/fusb302.c b/driver/tcpm/fusb302.c
deleted file mode 100644
index 66c131fb37..0000000000
--- a/driver/tcpm/fusb302.c
+++ /dev/null
@@ -1,1036 +0,0 @@
-/* Copyright 2015 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.
- *
- * Author: Gabe Noblesmith
- */
-
-/* Type-C port manager for Fairchild's FUSB302 */
-
-#include "console.h"
-#include "fusb302.h"
-#include "task.h"
-#include "hooks.h"
-#include "tcpm.h"
-#include "timer.h"
-#include "usb_charge.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpc.h"
-#include "util.h"
-
-#if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) || \
- defined(CONFIG_USB_PD_DISCHARGE_TCPC)
-#error "Unsupported config options of fusb302 PD driver"
-#endif
-
-#define PACKET_IS_GOOD_CRC(head) (PD_HEADER_TYPE(head) == PD_CTRL_GOOD_CRC && \
- PD_HEADER_CNT(head) == 0)
-
-static struct fusb302_chip_state {
- int cc_polarity;
- int vconn_enabled;
- /* 1 = pulling up (DFP) 0 = pulling down (UFP) */
- int pulling_up;
- int rx_enable;
- uint8_t mdac_vnc;
- uint8_t mdac_rd;
-} state[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/*
- * Bring the FUSB302 out of reset after Hard Reset signaling. This will
- * automatically flush both the Rx and Tx FIFOs.
- */
-static void fusb302_pd_reset(int port)
-{
- tcpc_write(port, TCPC_REG_RESET, TCPC_REG_RESET_PD_RESET);
-}
-
-/*
- * Flush our Rx FIFO. To prevent packet framing issues, this function should
- * only be called when Rx is disabled.
- */
-static void fusb302_flush_rx_fifo(int port)
-{
- /*
- * other bits in the register _should_ be 0
- * until the day we support other SOP* types...
- * then we'll have to keep a shadow of what this register
- * value should be so we don't clobber it here!
- */
- tcpc_write(port, TCPC_REG_CONTROL1, TCPC_REG_CONTROL1_RX_FLUSH);
-}
-
-static void fusb302_flush_tx_fifo(int port)
-{
- int reg;
-
- tcpc_read(port, TCPC_REG_CONTROL0, &reg);
- reg |= TCPC_REG_CONTROL0_TX_FLUSH;
- tcpc_write(port, TCPC_REG_CONTROL0, reg);
-}
-
-static void fusb302_auto_goodcrc_enable(int port, int enable)
-{
- int reg;
-
- tcpc_read(port, TCPC_REG_SWITCHES1, &reg);
-
- if (enable)
- reg |= TCPC_REG_SWITCHES1_AUTO_GCRC;
- else
- reg &= ~TCPC_REG_SWITCHES1_AUTO_GCRC;
-
- tcpc_write(port, TCPC_REG_SWITCHES1, reg);
-}
-
-/* Convert BC LVL values (in FUSB302) to Type-C CC Voltage Status */
-static int convert_bc_lvl(int port, int bc_lvl)
-{
- /* assume OPEN unless one of the following conditions is true... */
- int ret = TYPEC_CC_VOLT_OPEN;
-
- if (state[port].pulling_up) {
- if (bc_lvl == 0x00)
- ret = TYPEC_CC_VOLT_RA;
- else if (bc_lvl < 0x3)
- ret = TYPEC_CC_VOLT_RD;
- } else {
- if (bc_lvl == 0x1)
- ret = TYPEC_CC_VOLT_RP_DEF;
- else if (bc_lvl == 0x2)
- ret = TYPEC_CC_VOLT_RP_1_5;
- else if (bc_lvl == 0x3)
- ret = TYPEC_CC_VOLT_RP_3_0;
- }
-
- return ret;
-}
-
-static int measure_cc_pin_source(int port, int cc_measure)
-{
- int switches0_reg;
- int reg;
- int cc_lvl;
-
- /* Read status register */
- tcpc_read(port, TCPC_REG_SWITCHES0, &reg);
- /* Save current value */
- switches0_reg = reg;
- /* Clear pull-up register settings and measure bits */
- reg &= ~(TCPC_REG_SWITCHES0_MEAS_CC1 | TCPC_REG_SWITCHES0_MEAS_CC2);
- /* Set desired pullup register bit */
- if (cc_measure == TCPC_REG_SWITCHES0_MEAS_CC1)
- reg |= TCPC_REG_SWITCHES0_CC1_PU_EN;
- else
- reg |= TCPC_REG_SWITCHES0_CC2_PU_EN;
- /* Set CC measure bit */
- reg |= cc_measure;
-
- /* Set measurement switch */
- tcpc_write(port, TCPC_REG_SWITCHES0, reg);
-
- /* Set MDAC for Open vs Rd/Ra comparison */
- tcpc_write(port, TCPC_REG_MEASURE, state[port].mdac_vnc);
-
- /* Wait on measurement */
- usleep(250);
-
- /* Read status register */
- tcpc_read(port, TCPC_REG_STATUS0, &reg);
-
- /* Assume open */
- cc_lvl = TYPEC_CC_VOLT_OPEN;
-
- /* CC level is below the 'no connect' threshold (vOpen) */
- if ((reg & TCPC_REG_STATUS0_COMP) == 0) {
- /* Set MDAC for Rd vs Ra comparison */
- tcpc_write(port, TCPC_REG_MEASURE, state[port].mdac_rd);
-
- /* Wait on measurement */
- usleep(250);
-
- /* Read status register */
- tcpc_read(port, TCPC_REG_STATUS0, &reg);
-
- cc_lvl = (reg & TCPC_REG_STATUS0_COMP) ? TYPEC_CC_VOLT_RD
- : TYPEC_CC_VOLT_RA;
- }
-
- /* Restore SWITCHES0 register to its value prior */
- tcpc_write(port, TCPC_REG_SWITCHES0, switches0_reg);
-
- return cc_lvl;
-}
-
-/* Determine cc pin state for source when in manual detect mode */
-static void detect_cc_pin_source_manual(int port,
- enum tcpc_cc_voltage_status *cc1_lvl,
- enum tcpc_cc_voltage_status *cc2_lvl)
-{
- int cc1_measure = TCPC_REG_SWITCHES0_MEAS_CC1;
- int cc2_measure = TCPC_REG_SWITCHES0_MEAS_CC2;
-
- if (state[port].vconn_enabled) {
- /* If VCONN enabled, measure cc_pin that matches polarity */
- if (state[port].cc_polarity)
- *cc2_lvl = measure_cc_pin_source(port, cc2_measure);
- else
- *cc1_lvl = measure_cc_pin_source(port, cc1_measure);
- } else {
- /* If VCONN not enabled, measure both cc1 and cc2 */
- *cc1_lvl = measure_cc_pin_source(port, cc1_measure);
- *cc2_lvl = measure_cc_pin_source(port, cc2_measure);
- }
-
-}
-
-/* Determine cc pin state for sink */
-static void detect_cc_pin_sink(int port, enum tcpc_cc_voltage_status *cc1,
- enum tcpc_cc_voltage_status *cc2)
-{
- int reg;
- int orig_meas_cc1;
- int orig_meas_cc2;
- int bc_lvl_cc1;
- int bc_lvl_cc2;
-
- /*
- * Measure CC1 first.
- */
- tcpc_read(port, TCPC_REG_SWITCHES0, &reg);
-
- /* save original state to be returned to later... */
- if (reg & TCPC_REG_SWITCHES0_MEAS_CC1)
- orig_meas_cc1 = 1;
- else
- orig_meas_cc1 = 0;
-
- if (reg & TCPC_REG_SWITCHES0_MEAS_CC2)
- orig_meas_cc2 = 1;
- else
- orig_meas_cc2 = 0;
-
-
- /* Disable CC2 measurement switch, enable CC1 measurement switch */
- reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2;
- reg |= TCPC_REG_SWITCHES0_MEAS_CC1;
-
- tcpc_write(port, TCPC_REG_SWITCHES0, reg);
-
- /* CC1 is now being measured by FUSB302. */
-
- /* Wait on measurement */
- usleep(250);
-
- tcpc_read(port, TCPC_REG_STATUS0, &bc_lvl_cc1);
-
- /* mask away unwanted bits */
- bc_lvl_cc1 &= (TCPC_REG_STATUS0_BC_LVL0 | TCPC_REG_STATUS0_BC_LVL1);
-
- /*
- * Measure CC2 next.
- */
-
- tcpc_read(port, TCPC_REG_SWITCHES0, &reg);
-
- /* Disable CC1 measurement switch, enable CC2 measurement switch */
- reg &= ~TCPC_REG_SWITCHES0_MEAS_CC1;
- reg |= TCPC_REG_SWITCHES0_MEAS_CC2;
-
- tcpc_write(port, TCPC_REG_SWITCHES0, reg);
-
- /* CC2 is now being measured by FUSB302. */
-
- /* Wait on measurement */
- usleep(250);
-
- tcpc_read(port, TCPC_REG_STATUS0, &bc_lvl_cc2);
-
- /* mask away unwanted bits */
- bc_lvl_cc2 &= (TCPC_REG_STATUS0_BC_LVL0 | TCPC_REG_STATUS0_BC_LVL1);
-
- *cc1 = convert_bc_lvl(port, bc_lvl_cc1);
- *cc2 = convert_bc_lvl(port, bc_lvl_cc2);
-
- /* return MEAS_CC1/2 switches to original state */
- tcpc_read(port, TCPC_REG_SWITCHES0, &reg);
- if (orig_meas_cc1)
- reg |= TCPC_REG_SWITCHES0_MEAS_CC1;
- else
- reg &= ~TCPC_REG_SWITCHES0_MEAS_CC1;
- if (orig_meas_cc2)
- reg |= TCPC_REG_SWITCHES0_MEAS_CC2;
- else
- reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2;
-
- tcpc_write(port, TCPC_REG_SWITCHES0, reg);
-}
-
-/* Parse header bytes for the size of packet */
-static int get_num_bytes(uint16_t header)
-{
- int rv;
-
- /* Grab the Number of Data Objects field.*/
- rv = PD_HEADER_CNT(header);
-
- /* Multiply by four to go from 32-bit words -> bytes */
- rv *= 4;
-
- /* Plus 2 for header */
- rv += 2;
-
- return rv;
-}
-
-static int fusb302_send_message(int port, uint16_t header, const uint32_t *data,
- uint8_t *buf, int buf_pos)
-{
- int rv;
- int reg;
- int len;
-
- len = get_num_bytes(header);
-
- /*
- * packsym tells the TXFIFO that the next X bytes are payload,
- * and should not be interpreted as special tokens.
- * The 5 LSBs represent X, the number of bytes.
- */
- reg = FUSB302_TKN_PACKSYM;
- reg |= (len & 0x1F);
-
- buf[buf_pos++] = reg;
-
- /* write in the header */
- reg = header;
- buf[buf_pos++] = reg & 0xFF;
-
- reg >>= 8;
- buf[buf_pos++] = reg & 0xFF;
-
- /* header is done, subtract from length to make this for-loop simpler */
- len -= 2;
-
- /* write data objects, if present */
- memcpy(&buf[buf_pos], data, len);
- buf_pos += len;
-
- /* put in the CRC */
- buf[buf_pos++] = FUSB302_TKN_JAMCRC;
-
- /* put in EOP */
- buf[buf_pos++] = FUSB302_TKN_EOP;
-
- /* Turn transmitter off after sending message */
- buf[buf_pos++] = FUSB302_TKN_TXOFF;
-
- /* Start transmission */
- reg = FUSB302_TKN_TXON;
- buf[buf_pos++] = FUSB302_TKN_TXON;
-
- /* burst write for speed! */
- rv = tcpc_xfer(port, buf, buf_pos, 0, 0);
-
- return rv;
-}
-
-static int fusb302_tcpm_select_rp_value(int port, int rp)
-{
- int reg;
- int rv;
- uint8_t vnc, rd;
-
- rv = tcpc_read(port, TCPC_REG_CONTROL0, &reg);
- if (rv)
- return rv;
-
- /* Set the current source for Rp value */
- reg &= ~TCPC_REG_CONTROL0_HOST_CUR_MASK;
- switch (rp) {
- case TYPEC_RP_1A5:
- reg |= TCPC_REG_CONTROL0_HOST_CUR_1A5;
- vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_1_5_VNC_MV);
- rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_1_5_RD_THRESH_MV);
- break;
- case TYPEC_RP_3A0:
- reg |= TCPC_REG_CONTROL0_HOST_CUR_3A0;
- vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_3_0_VNC_MV);
- rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_3_0_RD_THRESH_MV);
- break;
- case TYPEC_RP_USB:
- default:
- reg |= TCPC_REG_CONTROL0_HOST_CUR_USB;
- vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_VNC_MV);
- rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_RD_THRESH_MV);
- }
- state[port].mdac_vnc = vnc;
- state[port].mdac_rd = rd;
- return tcpc_write(port, TCPC_REG_CONTROL0, reg);
-}
-
-static int fusb302_tcpm_init(int port)
-{
- int reg;
-
- /* set default */
- state[port].cc_polarity = -1;
-
- /* set the voltage threshold for no connect detection (vOpen) */
- state[port].mdac_vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_VNC_MV);
- /* set the voltage threshold for Rd vs Ra detection */
- state[port].mdac_rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_RD_THRESH_MV);
-
- /* all other variables assumed to default to 0 */
-
- /* Restore default settings */
- tcpc_write(port, TCPC_REG_RESET, TCPC_REG_RESET_SW_RESET);
-
- /* Turn on retries and set number of retries */
- tcpc_read(port, TCPC_REG_CONTROL3, &reg);
- reg |= TCPC_REG_CONTROL3_AUTO_RETRY;
- reg |= (PD_RETRY_COUNT & 0x3) <<
- TCPC_REG_CONTROL3_N_RETRIES_POS;
- tcpc_write(port, TCPC_REG_CONTROL3, reg);
-
- /* Create interrupt masks */
- reg = 0xFF;
- /* CC level changes */
- reg &= ~TCPC_REG_MASK_BC_LVL;
- /* collisions */
- reg &= ~TCPC_REG_MASK_COLLISION;
- /* misc alert */
- reg &= ~TCPC_REG_MASK_ALERT;
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
- /* TODO(crbug.com/791109): Clean up VBUS notification. */
-
- /* VBUS threshold crossed (~4.0V) */
- reg &= ~TCPC_REG_MASK_VBUSOK;
-#endif
- tcpc_write(port, TCPC_REG_MASK, reg);
-
- reg = 0xFF;
- /* when all pd message retries fail... */
- reg &= ~TCPC_REG_MASKA_RETRYFAIL;
- /* when fusb302 send a hard reset. */
- reg &= ~TCPC_REG_MASKA_HARDSENT;
- /* when fusb302 receives GoodCRC ack for a pd message */
- reg &= ~TCPC_REG_MASKA_TX_SUCCESS;
- /* when fusb302 receives a hard reset */
- reg &= ~TCPC_REG_MASKA_HARDRESET;
- tcpc_write(port, TCPC_REG_MASKA, reg);
-
- reg = 0xFF;
- /* when fusb302 sends GoodCRC to ack a pd message */
- reg &= ~TCPC_REG_MASKB_GCRCSENT;
- tcpc_write(port, TCPC_REG_MASKB, reg);
-
- /* Interrupt Enable */
- tcpc_read(port, TCPC_REG_CONTROL0, &reg);
- reg &= ~TCPC_REG_CONTROL0_INT_MASK;
- tcpc_write(port, TCPC_REG_CONTROL0, reg);
-
- /* Set VCONN switch defaults */
- tcpm_set_polarity(port, 0);
- tcpm_set_vconn(port, 0);
-
- /* Turn on the power! */
- /* TODO: Reduce power consumption */
- tcpc_write(port, TCPC_REG_POWER, TCPC_REG_POWER_PWR_ALL);
-
-#if defined(CONFIG_USB_PD_VBUS_DETECT_TCPC) && defined(CONFIG_USB_CHARGER)
- /* Wait for the reference voltage to stablize */
- usleep(250);
- /*
- * Initialize VBUS supplier when VBUS is already present before
- * init (e.g. Cold reboot with charger plugged).
- */
- tcpc_read(port, TCPC_REG_STATUS0, &reg);
- if (reg & TCPC_REG_STATUS0_VBUSOK)
- usb_charger_vbus_change(port, 1);
-#endif
-
- return 0;
-}
-
-static int fusb302_tcpm_release(int port)
-{
- return EC_ERROR_UNIMPLEMENTED;
-}
-
-static int fusb302_tcpm_get_cc(int port, enum tcpc_cc_voltage_status *cc1,
- enum tcpc_cc_voltage_status *cc2)
-{
- if (state[port].pulling_up) {
- /* Source mode? */
- detect_cc_pin_source_manual(port, cc1, cc2);
- } else {
- /* Sink mode? */
- detect_cc_pin_sink(port, cc1, cc2);
- }
-
- return 0;
-}
-
-static int fusb302_tcpm_set_cc(int port, int pull)
-{
- int reg;
-
- /* NOTE: FUSB302 toggles a single pull-up between CC1 and CC2 */
- /* NOTE: FUSB302 Does not support Ra. */
- switch (pull) {
- case TYPEC_CC_RP:
- /* enable the pull-up we know to be necessary */
- tcpc_read(port, TCPC_REG_SWITCHES0, &reg);
-
- reg &= ~(TCPC_REG_SWITCHES0_CC2_PU_EN |
- TCPC_REG_SWITCHES0_CC1_PU_EN |
- TCPC_REG_SWITCHES0_CC1_PD_EN |
- TCPC_REG_SWITCHES0_CC2_PD_EN |
- TCPC_REG_SWITCHES0_VCONN_CC1 |
- TCPC_REG_SWITCHES0_VCONN_CC2);
-
- reg |= TCPC_REG_SWITCHES0_CC1_PU_EN |
- TCPC_REG_SWITCHES0_CC2_PU_EN;
-
- if (state[port].vconn_enabled)
- reg |= state[port].cc_polarity ?
- TCPC_REG_SWITCHES0_VCONN_CC1 :
- TCPC_REG_SWITCHES0_VCONN_CC2;
-
- tcpc_write(port, TCPC_REG_SWITCHES0, reg);
-
- state[port].pulling_up = 1;
- break;
- case TYPEC_CC_RD:
- /* Enable UFP Mode */
-
- /* turn off toggle */
- tcpc_read(port, TCPC_REG_CONTROL2, &reg);
- reg &= ~TCPC_REG_CONTROL2_TOGGLE;
- tcpc_write(port, TCPC_REG_CONTROL2, reg);
-
- /* enable pull-downs, disable pullups */
- tcpc_read(port, TCPC_REG_SWITCHES0, &reg);
-
- reg &= ~(TCPC_REG_SWITCHES0_CC2_PU_EN);
- reg &= ~(TCPC_REG_SWITCHES0_CC1_PU_EN);
- reg |= (TCPC_REG_SWITCHES0_CC1_PD_EN);
- reg |= (TCPC_REG_SWITCHES0_CC2_PD_EN);
- tcpc_write(port, TCPC_REG_SWITCHES0, reg);
-
- state[port].pulling_up = 0;
- break;
- case TYPEC_CC_OPEN:
- /* Disable toggling */
- tcpc_read(port, TCPC_REG_CONTROL2, &reg);
- reg &= ~TCPC_REG_CONTROL2_TOGGLE;
- tcpc_write(port, TCPC_REG_CONTROL2, reg);
-
- /* Ensure manual switches are opened */
- tcpc_read(port, TCPC_REG_SWITCHES0, &reg);
- reg &= ~TCPC_REG_SWITCHES0_CC1_PU_EN;
- reg &= ~TCPC_REG_SWITCHES0_CC2_PU_EN;
- reg &= ~TCPC_REG_SWITCHES0_CC1_PD_EN;
- reg &= ~TCPC_REG_SWITCHES0_CC2_PD_EN;
- tcpc_write(port, TCPC_REG_SWITCHES0, reg);
-
- state[port].pulling_up = 0;
- break;
- default:
- /* Unsupported... */
- return EC_ERROR_UNIMPLEMENTED;
- }
- return 0;
-}
-
-static int fusb302_tcpm_set_polarity(int port, int polarity)
-{
- /* Port polarity : 0 => CC1 is CC line, 1 => CC2 is CC line */
- int reg;
-
- tcpc_read(port, TCPC_REG_SWITCHES0, &reg);
-
- /* clear VCONN switch bits */
- reg &= ~TCPC_REG_SWITCHES0_VCONN_CC1;
- reg &= ~TCPC_REG_SWITCHES0_VCONN_CC2;
-
- if (state[port].vconn_enabled) {
- /* set VCONN switch to be non-CC line */
- if (polarity)
- reg |= TCPC_REG_SWITCHES0_VCONN_CC1;
- else
- reg |= TCPC_REG_SWITCHES0_VCONN_CC2;
- }
-
- /* clear meas_cc bits (RX line select) */
- reg &= ~TCPC_REG_SWITCHES0_MEAS_CC1;
- reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2;
-
- /* set rx polarity */
- if (polarity)
- reg |= TCPC_REG_SWITCHES0_MEAS_CC2;
- else
- reg |= TCPC_REG_SWITCHES0_MEAS_CC1;
-
- tcpc_write(port, TCPC_REG_SWITCHES0, reg);
-
- tcpc_read(port, TCPC_REG_SWITCHES1, &reg);
-
- /* clear tx_cc bits */
- reg &= ~TCPC_REG_SWITCHES1_TXCC1_EN;
- reg &= ~TCPC_REG_SWITCHES1_TXCC2_EN;
-
- /* set tx polarity */
- if (polarity)
- reg |= TCPC_REG_SWITCHES1_TXCC2_EN;
- else
- reg |= TCPC_REG_SWITCHES1_TXCC1_EN;
-
- tcpc_write(port, TCPC_REG_SWITCHES1, reg);
-
- /* Save the polarity for later */
- state[port].cc_polarity = polarity;
-
- return 0;
-}
-
-static int fusb302_tcpm_set_vconn(int port, int enable)
-{
- /*
- * FUSB302 does not have dedicated VCONN Enable switch.
- * We'll get through this by disabling both of the
- * VCONN - CC* switches to disable, and enabling the
- * saved polarity when enabling.
- * Therefore at startup, tcpm_set_polarity should be called first,
- * or else live with the default put into tcpm_init.
- */
- int reg;
-
- /* save enable state for later use */
- state[port].vconn_enabled = enable;
-
- if (enable) {
- /* set to saved polarity */
- tcpm_set_polarity(port, state[port].cc_polarity);
-
-#ifdef CONFIG_USB_PD_DECODE_SOP
- if (state[port].rx_enable) {
- if (tcpc_read(port, TCPC_REG_CONTROL1, &reg))
- return EC_ERROR_UNKNOWN;
-
- reg |= (TCPC_REG_CONTROL1_ENSOP1 |
- TCPC_REG_CONTROL1_ENSOP2);
- tcpc_write(port, TCPC_REG_CONTROL1, reg);
- }
-#endif
- } else {
-
- tcpc_read(port, TCPC_REG_SWITCHES0, &reg);
-
- /* clear VCONN switch bits */
- reg &= ~TCPC_REG_SWITCHES0_VCONN_CC1;
- reg &= ~TCPC_REG_SWITCHES0_VCONN_CC2;
-
- tcpc_write(port, TCPC_REG_SWITCHES0, reg);
-
-#ifdef CONFIG_USB_PD_DECODE_SOP
- if (state[port].rx_enable) {
- if (tcpc_read(port, TCPC_REG_CONTROL1, &reg))
- return EC_ERROR_UNKNOWN;
-
- reg &= ~(TCPC_REG_CONTROL1_ENSOP1 |
- TCPC_REG_CONTROL1_ENSOP2);
- tcpc_write(port, TCPC_REG_CONTROL1, reg);
- }
-#endif
- }
-
- return 0;
-}
-
-static int fusb302_tcpm_set_msg_header(int port, int power_role, int data_role)
-{
- int reg;
-
- tcpc_read(port, TCPC_REG_SWITCHES1, &reg);
-
- reg &= ~TCPC_REG_SWITCHES1_POWERROLE;
- reg &= ~TCPC_REG_SWITCHES1_DATAROLE;
-
- if (power_role)
- reg |= TCPC_REG_SWITCHES1_POWERROLE;
- if (data_role)
- reg |= TCPC_REG_SWITCHES1_DATAROLE;
-
- tcpc_write(port, TCPC_REG_SWITCHES1, reg);
-
- return 0;
-}
-
-static int fusb302_tcpm_set_rx_enable(int port, int enable)
-{
- int reg;
-
- state[port].rx_enable = enable;
-
- /* Get current switch state */
- tcpc_read(port, TCPC_REG_SWITCHES0, &reg);
-
- /* Clear CC1/CC2 measure bits */
- reg &= ~TCPC_REG_SWITCHES0_MEAS_CC1;
- reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2;
-
- if (enable) {
- switch (state[port].cc_polarity) {
- /* if CC polarity hasnt been determined, can't enable */
- case -1:
- return EC_ERROR_UNKNOWN;
- case 0:
- reg |= TCPC_REG_SWITCHES0_MEAS_CC1;
- break;
- case 1:
- reg |= TCPC_REG_SWITCHES0_MEAS_CC2;
- break;
- default:
- /* "shouldn't get here" */
- return EC_ERROR_UNKNOWN;
- }
- tcpc_write(port, TCPC_REG_SWITCHES0, reg);
-
- /* Disable BC_LVL interrupt when enabling PD comm */
- if (!tcpc_read(port, TCPC_REG_MASK, &reg))
- tcpc_write(port, TCPC_REG_MASK,
- reg | TCPC_REG_MASK_BC_LVL);
-
- /* flush rx fifo in case messages have been coming our way */
- fusb302_flush_rx_fifo(port);
-
-
- } else {
- tcpc_write(port, TCPC_REG_SWITCHES0, reg);
-
- /* Enable BC_LVL interrupt when disabling PD comm */
- if (!tcpc_read(port, TCPC_REG_MASK, &reg))
- tcpc_write(port, TCPC_REG_MASK,
- reg & ~TCPC_REG_MASK_BC_LVL);
- }
-
-#ifdef CONFIG_USB_PD_DECODE_SOP
- /*
- * Only the VCONN Source is allowed to communicate
- * with the Cable Plugs.
- */
- if (state[port].vconn_enabled) {
- if (tcpc_read(port, TCPC_REG_CONTROL1, &reg))
- return EC_ERROR_UNKNOWN;
-
- reg |= (TCPC_REG_CONTROL1_ENSOP1 | TCPC_REG_CONTROL1_ENSOP2);
- tcpc_write(port, TCPC_REG_CONTROL1, reg);
- }
-#endif
-
- fusb302_auto_goodcrc_enable(port, enable);
-
- return 0;
-}
-
-/* Return true if our Rx FIFO is empty */
-static int fusb302_rx_fifo_is_empty(int port)
-{
- int reg;
-
- return (!tcpc_read(port, TCPC_REG_STATUS1, &reg)) &&
- (reg & TCPC_REG_STATUS1_RX_EMPTY);
-}
-
-static int fusb302_tcpm_get_message_raw(int port, uint32_t *payload, int *head)
-{
- /*
- * This is the buffer that will get the burst-read data
- * from the fusb302.
- *
- * It's re-used in a couple different spots, the worst of which
- * is the PD packet (not header) and CRC.
- * maximum size necessary = 28 + 4 = 32
- */
- uint8_t buf[32];
- int rv, len;
-
- /* Read until we have a non-GoodCRC packet or an empty FIFO */
- do {
- buf[0] = TCPC_REG_FIFOS;
- tcpc_lock(port, 1);
-
- /*
- * PART 1 OF BURST READ: Write in register address.
- * Issue a START, no STOP.
- */
- rv = tcpc_xfer_unlocked(port, buf, 1, 0, 0, I2C_XFER_START);
-
- /*
- * PART 2 OF BURST READ: Read up to the header.
- * Issue a repeated START, no STOP.
- * only grab three bytes so we can get the header
- * and determine how many more bytes we need to read.
- * TODO: Check token to ensure valid packet.
- */
- rv |= tcpc_xfer_unlocked(port, 0, 0, buf, 3, I2C_XFER_START);
-
- /* Grab the header */
- *head = (buf[1] & 0xFF);
- *head |= ((buf[2] << 8) & 0xFF00);
-
- /* figure out packet length, subtract header bytes */
- len = get_num_bytes(*head) - 2;
-
- /*
- * PART 3 OF BURST READ: Read everything else.
- * No START, but do issue a STOP at the end.
- * add 4 to len to read CRC out
- */
- rv |= tcpc_xfer_unlocked(port, 0, 0, buf, len+4, I2C_XFER_STOP);
-
- tcpc_lock(port, 0);
- } while (!rv && PACKET_IS_GOOD_CRC(*head) &&
- !fusb302_rx_fifo_is_empty(port));
-
- if (!rv) {
- /* Discard GoodCRC packets */
- if (PACKET_IS_GOOD_CRC(*head))
- rv = EC_ERROR_UNKNOWN;
- else
- memcpy(payload, buf, len);
- }
-
-#ifdef CONFIG_USB_PD_DECODE_SOP
- {
- int reg;
-
- if (tcpc_read(port, TCPC_REG_STATUS1, &reg))
- return EC_ERROR_UNKNOWN;
-
- if (reg & TCPC_REG_STATUS1_RXSOP1)
- *head |= PD_HEADER_SOP(PD_MSG_SOPP);
- else if (reg & TCPC_REG_STATUS1_RXSOP2)
- *head |= PD_HEADER_SOP(PD_MSG_SOPPP);
- }
-#endif
-
- return rv;
-}
-
-static int fusb302_tcpm_transmit(int port, enum tcpm_transmit_type type,
- uint16_t header, const uint32_t *data)
-{
- /*
- * this is the buffer that will be burst-written into the fusb302
- * maximum size necessary =
- * 1: FIFO register address
- * 4: SOP* tokens
- * 1: Token that signifies "next X bytes are not tokens"
- * 30: 2 for header and up to 7*4 = 28 for rest of message
- * 1: "Insert CRC" Token
- * 1: EOP Token
- * 1: "Turn transmitter off" token
- * 1: "Star Transmission" Command
- * -
- * 40: 40 bytes worst-case
- */
- uint8_t buf[40];
- int buf_pos = 0;
-
- int reg;
-
- /* Flush the TXFIFO */
- fusb302_flush_tx_fifo(port);
-
- switch (type) {
- case TCPC_TX_SOP:
-
- /* put register address first for of burst tcpc write */
- buf[buf_pos++] = TCPC_REG_FIFOS;
-
- /* Write the SOP Ordered Set into TX FIFO */
- buf[buf_pos++] = FUSB302_TKN_SYNC1;
- buf[buf_pos++] = FUSB302_TKN_SYNC1;
- buf[buf_pos++] = FUSB302_TKN_SYNC1;
- buf[buf_pos++] = FUSB302_TKN_SYNC2;
-
- return fusb302_send_message(port, header, data, buf, buf_pos);
- case TCPC_TX_HARD_RESET:
- /* Simply hit the SEND_HARD_RESET bit */
- tcpc_read(port, TCPC_REG_CONTROL3, &reg);
- reg |= TCPC_REG_CONTROL3_SEND_HARDRESET;
- tcpc_write(port, TCPC_REG_CONTROL3, reg);
-
- break;
- case TCPC_TX_BIST_MODE_2:
- /* Hit the BIST_MODE2 bit and start TX */
- tcpc_read(port, TCPC_REG_CONTROL1, &reg);
- reg |= TCPC_REG_CONTROL1_BIST_MODE2;
- tcpc_write(port, TCPC_REG_CONTROL1, reg);
-
- tcpc_read(port, TCPC_REG_CONTROL0, &reg);
- reg |= TCPC_REG_CONTROL0_TX_START;
- tcpc_write(port, TCPC_REG_CONTROL0, reg);
-
- task_wait_event(PD_T_BIST_TRANSMIT);
-
- /* Clear BIST mode bit, TX_START is self-clearing */
- tcpc_read(port, TCPC_REG_CONTROL1, &reg);
- reg &= ~TCPC_REG_CONTROL1_BIST_MODE2;
- tcpc_write(port, TCPC_REG_CONTROL1, reg);
-
- break;
- default:
- return EC_ERROR_UNIMPLEMENTED;
- }
-
- return 0;
-}
-
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
-static int fusb302_tcpm_get_vbus_level(int port)
-{
- int reg;
-
- /* Read status register */
- tcpc_read(port, TCPC_REG_STATUS0, &reg);
-
- return (reg & TCPC_REG_STATUS0_VBUSOK) ? 1 : 0;
-}
-#endif
-
-void fusb302_tcpc_alert(int port)
-{
- /* interrupt has been received */
- int interrupt;
- int interrupta;
- int interruptb;
-
- /* reading interrupt registers clears them */
-
- tcpc_read(port, TCPC_REG_INTERRUPT, &interrupt);
- tcpc_read(port, TCPC_REG_INTERRUPTA, &interrupta);
- tcpc_read(port, TCPC_REG_INTERRUPTB, &interruptb);
-
- /*
- * Ignore BC_LVL changes when transmitting / receiving PD,
- * since CC level will constantly change.
- */
- if (state[port].rx_enable)
- interrupt &= ~TCPC_REG_INTERRUPT_BC_LVL;
-
- if (interrupt & TCPC_REG_INTERRUPT_BC_LVL) {
- /* CC Status change */
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC, 0);
- }
-
- if (interrupt & TCPC_REG_INTERRUPT_COLLISION) {
- /* packet sending collided */
- pd_transmit_complete(port, TCPC_TX_COMPLETE_FAILED);
- }
-
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
- if (interrupt & TCPC_REG_INTERRUPT_VBUSOK) {
- /* VBUS crossed threshold */
-#ifdef CONFIG_USB_CHARGER
- usb_charger_vbus_change(port,
- fusb302_tcpm_get_vbus_level(port));
-#else
- if (!fusb302_tcpm_get_vbus_level(port))
- pd_vbus_low(port);
-#endif
- task_wake(PD_PORT_TO_TASK_ID(port));
- hook_notify(HOOK_AC_CHANGE);
- }
-#endif
-
- /* GoodCRC was received, our FIFO is now non-empty */
- if (interrupta & TCPC_REG_INTERRUPTA_TX_SUCCESS) {
- pd_transmit_complete(port, TCPC_TX_COMPLETE_SUCCESS);
- }
-
- if (interrupta & TCPC_REG_INTERRUPTA_RETRYFAIL) {
- /* all retries have failed to get a GoodCRC */
- pd_transmit_complete(port, TCPC_TX_COMPLETE_FAILED);
- }
-
- if (interrupta & TCPC_REG_INTERRUPTA_HARDSENT) {
- /* hard reset has been sent */
-
- /* bring FUSB302 out of reset */
- fusb302_pd_reset(port);
-
- pd_transmit_complete(port, TCPC_TX_COMPLETE_SUCCESS);
- }
-
- if (interrupta & TCPC_REG_INTERRUPTA_HARDRESET) {
- /* hard reset has been received */
-
- /* bring FUSB302 out of reset */
- fusb302_pd_reset(port);
-
- pd_execute_hard_reset(port);
-
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-
- if (interruptb & TCPC_REG_INTERRUPTB_GCRCSENT) {
- /* Packet received and GoodCRC sent */
- /* (this interrupt fires after the GoodCRC finishes) */
- if (state[port].rx_enable) {
- /* Pull all RX messages from TCPC into EC memory */
- while (!fusb302_rx_fifo_is_empty(port))
- tcpm_enqueue_message(port);
- } else {
- /* flush rx fifo if rx isn't enabled */
- fusb302_flush_rx_fifo(port);
- }
- }
-
-}
-
-/* For BIST receiving */
-void tcpm_set_bist_test_data(int port)
-{
- int reg;
-
- /* Read control3 register */
- tcpc_read(port, TCPC_REG_CONTROL3, &reg);
-
- /* Set the BIST_TMODE bit (Clears on Hard Reset) */
- reg |= TCPC_REG_CONTROL3_BIST_TMODE;
-
- /* Write the updated value */
- tcpc_write(port, TCPC_REG_CONTROL3, reg);
-}
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
-static int fusb302_tcpm_enter_low_power_mode(int port)
-{
- return tcpc_write(port, TCPC_REG_POWER, TCPC_REG_POWER_PWR_LOW);
-}
-#endif
-
-const struct tcpm_drv fusb302_tcpm_drv = {
- .init = &fusb302_tcpm_init,
- .release = &fusb302_tcpm_release,
- .get_cc = &fusb302_tcpm_get_cc,
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
- .get_vbus_level = &fusb302_tcpm_get_vbus_level,
-#endif
- .select_rp_value = &fusb302_tcpm_select_rp_value,
- .set_cc = &fusb302_tcpm_set_cc,
- .set_polarity = &fusb302_tcpm_set_polarity,
- .set_vconn = &fusb302_tcpm_set_vconn,
- .set_msg_header = &fusb302_tcpm_set_msg_header,
- .set_rx_enable = &fusb302_tcpm_set_rx_enable,
- .get_message_raw = &fusb302_tcpm_get_message_raw,
- .transmit = &fusb302_tcpm_transmit,
- .tcpc_alert = &fusb302_tcpc_alert,
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- .enter_low_power_mode = &fusb302_tcpm_enter_low_power_mode,
-#endif
-};
diff --git a/driver/tcpm/fusb302.h b/driver/tcpm/fusb302.h
deleted file mode 100644
index ec418407f7..0000000000
--- a/driver/tcpm/fusb302.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/* Copyright 2015 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.
- *
- * Author: Gabe Noblesmith
- */
-
-/* USB Power delivery port management */
-/* For Fairchild FUSB302 */
-#ifndef __CROS_EC_DRIVER_TCPM_FUSB302_H
-#define __CROS_EC_DRIVER_TCPM_FUSB302_H
-
-/* Chip Device ID - 302A or 302B */
-#define FUSB302_DEVID_302A 0x08
-#define FUSB302_DEVID_302B 0x09
-
-/* I2C slave address varies by part number */
-/* FUSB302BUCX / FUSB302BMPX */
-#define FUSB302_I2C_SLAVE_ADDR_FLAGS 0x22
-/* FUSB302B01MPX */
-#define FUSB302_I2C_SLAVE_ADDR_B01_FLAGS 0x23
-/* FUSB302B10MPX */
-#define FUSB302_I2C_SLAVE_ADDR_B10_FLAGS 0x24
-/* FUSB302B11MPX */
-#define FUSB302_I2C_SLAVE_ADDR_B11_FLAGS 0x25
-
-/* Default retry count for transmitting */
-#define PD_RETRY_COUNT 3
-
-#define TCPC_REG_DEVICE_ID 0x01
-
-#define TCPC_REG_SWITCHES0 0x02
-#define TCPC_REG_SWITCHES0_CC2_PU_EN (1<<7)
-#define TCPC_REG_SWITCHES0_CC1_PU_EN (1<<6)
-#define TCPC_REG_SWITCHES0_VCONN_CC2 (1<<5)
-#define TCPC_REG_SWITCHES0_VCONN_CC1 (1<<4)
-#define TCPC_REG_SWITCHES0_MEAS_CC2 (1<<3)
-#define TCPC_REG_SWITCHES0_MEAS_CC1 (1<<2)
-#define TCPC_REG_SWITCHES0_CC2_PD_EN (1<<1)
-#define TCPC_REG_SWITCHES0_CC1_PD_EN (1<<0)
-
-#define TCPC_REG_SWITCHES1 0x03
-#define TCPC_REG_SWITCHES1_POWERROLE (1<<7)
-#define TCPC_REG_SWITCHES1_SPECREV1 (1<<6)
-#define TCPC_REG_SWITCHES1_SPECREV0 (1<<5)
-#define TCPC_REG_SWITCHES1_DATAROLE (1<<4)
-#define TCPC_REG_SWITCHES1_AUTO_GCRC (1<<2)
-#define TCPC_REG_SWITCHES1_TXCC2_EN (1<<1)
-#define TCPC_REG_SWITCHES1_TXCC1_EN (1<<0)
-
-#define TCPC_REG_MEASURE 0x04
-#define TCPC_REG_MEASURE_VBUS (1<<6)
-/*
- * MDAC reference voltage step size is 42 mV. Round our thresholds to reduce
- * maximum error, which also matches suggested thresholds in datasheet
- * (Table 3. Host Interrupt Summary).
- */
-#define TCPC_REG_MEASURE_MDAC_MV(mv) (DIV_ROUND_NEAREST((mv), 42) & 0x3f)
-
-#define TCPC_REG_CONTROL0 0x06
-#define TCPC_REG_CONTROL0_TX_FLUSH (1<<6)
-#define TCPC_REG_CONTROL0_INT_MASK (1<<5)
-#define TCPC_REG_CONTROL0_HOST_CUR_MASK (3<<2)
-#define TCPC_REG_CONTROL0_HOST_CUR_3A0 (3<<2)
-#define TCPC_REG_CONTROL0_HOST_CUR_1A5 (2<<2)
-#define TCPC_REG_CONTROL0_HOST_CUR_USB (1<<2)
-#define TCPC_REG_CONTROL0_TX_START (1<<0)
-
-#define TCPC_REG_CONTROL1 0x07
-#define TCPC_REG_CONTROL1_ENSOP2DB (1<<6)
-#define TCPC_REG_CONTROL1_ENSOP1DB (1<<5)
-#define TCPC_REG_CONTROL1_BIST_MODE2 (1<<4)
-#define TCPC_REG_CONTROL1_RX_FLUSH (1<<2)
-#define TCPC_REG_CONTROL1_ENSOP2 (1<<1)
-#define TCPC_REG_CONTROL1_ENSOP1 (1<<0)
-
-#define TCPC_REG_CONTROL2 0x08
-/* two-bit field, valid values below */
-#define TCPC_REG_CONTROL2_MODE (1<<1)
-#define TCPC_REG_CONTROL2_MODE_DFP (0x3)
-#define TCPC_REG_CONTROL2_MODE_UFP (0x2)
-#define TCPC_REG_CONTROL2_MODE_DRP (0x1)
-#define TCPC_REG_CONTROL2_MODE_POS (1)
-#define TCPC_REG_CONTROL2_TOGGLE (1<<0)
-
-#define TCPC_REG_CONTROL3 0x09
-#define TCPC_REG_CONTROL3_SEND_HARDRESET (1<<6)
-#define TCPC_REG_CONTROL3_BIST_TMODE (1<<5) /* 302B Only */
-#define TCPC_REG_CONTROL3_AUTO_HARDRESET (1<<4)
-#define TCPC_REG_CONTROL3_AUTO_SOFTRESET (1<<3)
-/* two-bit field */
-#define TCPC_REG_CONTROL3_N_RETRIES (1<<1)
-#define TCPC_REG_CONTROL3_N_RETRIES_POS (1)
-#define TCPC_REG_CONTROL3_N_RETRIES_SIZE (2)
-#define TCPC_REG_CONTROL3_AUTO_RETRY (1<<0)
-
-#define TCPC_REG_MASK 0x0A
-#define TCPC_REG_MASK_VBUSOK (1<<7)
-#define TCPC_REG_MASK_ACTIVITY (1<<6)
-#define TCPC_REG_MASK_COMP_CHNG (1<<5)
-#define TCPC_REG_MASK_CRC_CHK (1<<4)
-#define TCPC_REG_MASK_ALERT (1<<3)
-#define TCPC_REG_MASK_WAKE (1<<2)
-#define TCPC_REG_MASK_COLLISION (1<<1)
-#define TCPC_REG_MASK_BC_LVL (1<<0)
-
-#define TCPC_REG_POWER 0x0B
-#define TCPC_REG_POWER_PWR (1<<0) /* four-bit field */
-#define TCPC_REG_POWER_PWR_LOW 0x1 /* Bandgap + Wake circuitry */
-#define TCPC_REG_POWER_PWR_MEDIUM 0x3 /* LOW + Receiver + Current refs */
-#define TCPC_REG_POWER_PWR_HIGH 0x7 /* MEDIUM + Measure block */
-#define TCPC_REG_POWER_PWR_ALL 0xF /* HIGH + Internal Oscillator */
-
-#define TCPC_REG_RESET 0x0C
-#define TCPC_REG_RESET_PD_RESET (1<<1)
-#define TCPC_REG_RESET_SW_RESET (1<<0)
-
-#define TCPC_REG_MASKA 0x0E
-#define TCPC_REG_MASKA_OCP_TEMP (1<<7)
-#define TCPC_REG_MASKA_TOGDONE (1<<6)
-#define TCPC_REG_MASKA_SOFTFAIL (1<<5)
-#define TCPC_REG_MASKA_RETRYFAIL (1<<4)
-#define TCPC_REG_MASKA_HARDSENT (1<<3)
-#define TCPC_REG_MASKA_TX_SUCCESS (1<<2)
-#define TCPC_REG_MASKA_SOFTRESET (1<<1)
-#define TCPC_REG_MASKA_HARDRESET (1<<0)
-
-#define TCPC_REG_MASKB 0x0F
-#define TCPC_REG_MASKB_GCRCSENT (1<<0)
-
-#define TCPC_REG_STATUS0A 0x3C
-#define TCPC_REG_STATUS0A_SOFTFAIL (1<<5)
-#define TCPC_REG_STATUS0A_RETRYFAIL (1<<4)
-#define TCPC_REG_STATUS0A_POWER (1<<2) /* two-bit field */
-#define TCPC_REG_STATUS0A_RX_SOFT_RESET (1<<1)
-#define TCPC_REG_STATUS0A_RX_HARD_RESEt (1<<0)
-
-#define TCPC_REG_STATUS1A 0x3D
-/* three-bit field, valid values below */
-#define TCPC_REG_STATUS1A_TOGSS (1<<3)
-#define TCPC_REG_STATUS1A_TOGSS_RUNNING 0x0
-#define TCPC_REG_STATUS1A_TOGSS_SRC1 0x1
-#define TCPC_REG_STATUS1A_TOGSS_SRC2 0x2
-#define TCPC_REG_STATUS1A_TOGSS_SNK1 0x5
-#define TCPC_REG_STATUS1A_TOGSS_SNK2 0x6
-#define TCPC_REG_STATUS1A_TOGSS_AA 0x7
-#define TCPC_REG_STATUS1A_TOGSS_POS (3)
-#define TCPC_REG_STATUS1A_TOGSS_MASK (0x7)
-
-#define TCPC_REG_STATUS1A_RXSOP2DB (1<<2)
-#define TCPC_REG_STATUS1A_RXSOP1DB (1<<1)
-#define TCPC_REG_STATUS1A_RXSOP (1<<0)
-
-#define TCPC_REG_INTERRUPTA 0x3E
-#define TCPC_REG_INTERRUPTA_OCP_TEMP (1<<7)
-#define TCPC_REG_INTERRUPTA_TOGDONE (1<<6)
-#define TCPC_REG_INTERRUPTA_SOFTFAIL (1<<5)
-#define TCPC_REG_INTERRUPTA_RETRYFAIL (1<<4)
-#define TCPC_REG_INTERRUPTA_HARDSENT (1<<3)
-#define TCPC_REG_INTERRUPTA_TX_SUCCESS (1<<2)
-#define TCPC_REG_INTERRUPTA_SOFTRESET (1<<1)
-#define TCPC_REG_INTERRUPTA_HARDRESET (1<<0)
-
-#define TCPC_REG_INTERRUPTB 0x3F
-#define TCPC_REG_INTERRUPTB_GCRCSENT (1<<0)
-
-#define TCPC_REG_STATUS0 0x40
-#define TCPC_REG_STATUS0_VBUSOK (1<<7)
-#define TCPC_REG_STATUS0_ACTIVITY (1<<6)
-#define TCPC_REG_STATUS0_COMP (1<<5)
-#define TCPC_REG_STATUS0_CRC_CHK (1<<4)
-#define TCPC_REG_STATUS0_ALERT (1<<3)
-#define TCPC_REG_STATUS0_WAKE (1<<2)
-#define TCPC_REG_STATUS0_BC_LVL1 (1<<1) /* two-bit field */
-#define TCPC_REG_STATUS0_BC_LVL0 (1<<0) /* two-bit field */
-
-#define TCPC_REG_STATUS1 0x41
-#define TCPC_REG_STATUS1_RXSOP2 (1<<7)
-#define TCPC_REG_STATUS1_RXSOP1 (1<<6)
-#define TCPC_REG_STATUS1_RX_EMPTY (1<<5)
-#define TCPC_REG_STATUS1_RX_FULL (1<<4)
-#define TCPC_REG_STATUS1_TX_EMPTY (1<<3)
-#define TCPC_REG_STATUS1_TX_FULL (1<<2)
-
-#define TCPC_REG_INTERRUPT 0x42
-#define TCPC_REG_INTERRUPT_VBUSOK (1<<7)
-#define TCPC_REG_INTERRUPT_ACTIVITY (1<<6)
-#define TCPC_REG_INTERRUPT_COMP_CHNG (1<<5)
-#define TCPC_REG_INTERRUPT_CRC_CHK (1<<4)
-#define TCPC_REG_INTERRUPT_ALERT (1<<3)
-#define TCPC_REG_INTERRUPT_WAKE (1<<2)
-#define TCPC_REG_INTERRUPT_COLLISION (1<<1)
-#define TCPC_REG_INTERRUPT_BC_LVL (1<<0)
-
-#define TCPC_REG_FIFOS 0x43
-
-/* Tokens defined for the FUSB302 TX FIFO */
-enum fusb302_txfifo_tokens {
- FUSB302_TKN_TXON = 0xA1,
- FUSB302_TKN_SYNC1 = 0x12,
- FUSB302_TKN_SYNC2 = 0x13,
- FUSB302_TKN_SYNC3 = 0x1B,
- FUSB302_TKN_RST1 = 0x15,
- FUSB302_TKN_RST2 = 0x16,
- FUSB302_TKN_PACKSYM = 0x80,
- FUSB302_TKN_JAMCRC = 0xFF,
- FUSB302_TKN_EOP = 0x14,
- FUSB302_TKN_TXOFF = 0xFE,
-};
-
-extern const struct tcpm_drv fusb302_tcpm_drv;
-
-#endif /* __CROS_EC_DRIVER_TCPM_FUSB302_H */
diff --git a/driver/tcpm/it83xx.c b/driver/tcpm/it83xx.c
deleted file mode 100644
index 14e7571dc6..0000000000
--- a/driver/tcpm/it83xx.c
+++ /dev/null
@@ -1,644 +0,0 @@
-/* Copyright 2016 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.
- */
-
-/* TCPM for MCU also running TCPC */
-
-#include "common.h"
-#include "config.h"
-#include "console.h"
-#include "it83xx_pd.h"
-#include "registers.h"
-#include "system.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
-#include "hooks.h"
-
-#if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) || \
- defined(CONFIG_USB_PD_VBUS_DETECT_TCPC) || \
- defined(CONFIG_USB_PD_TCPC_LOW_POWER) || \
- defined(CONFIG_USB_PD_DISCHARGE_TCPC)
-#error "Unsupported config options of IT83xx PD driver"
-#endif
-
-/* Wait time for vconn power switch to turn off. */
-#ifndef PD_IT83XX_VCONN_TURN_OFF_DELAY_US
-#define PD_IT83XX_VCONN_TURN_OFF_DELAY_US 500
-#endif
-
-const struct usbpd_ctrl_t usbpd_ctrl_regs[] = {
- {&IT83XX_GPIO_GPCRF4, &IT83XX_GPIO_GPCRF5, IT83XX_IRQ_USBPD0},
- {&IT83XX_GPIO_GPCRH1, &IT83XX_GPIO_GPCRH2, IT83XX_IRQ_USBPD1},
-};
-BUILD_ASSERT(ARRAY_SIZE(usbpd_ctrl_regs) == USBPD_PORT_COUNT);
-
-/*
- * This function disables integrated pd module and enables 5.1K resistor for
- * dead battery. A EC reset or calling _init() is able to re-active pd module.
- */
-void it83xx_disable_pd_module(int port)
-{
- /* This only apply to PD port. */
- if (*usbpd_ctrl_regs[port].cc1 == IT83XX_USBPD_CC_PIN_CONFIG &&
- *usbpd_ctrl_regs[port].cc2 == IT83XX_USBPD_CC_PIN_CONFIG) {
- /* Disable PD PHY */
- IT83XX_USBPD_GCR(port) &= ~(BIT(0) | BIT(4));
- /* Power down CC1/CC2 */
- IT83XX_USBPD_CCGCR(port) |= 0x1f;
- /* Disable CC1/CC2 voltage detector */
- IT83XX_USBPD_CCCSR(port) = 0xff;
- /* Connect 5.1K resistor to CC1/CC2 for dead battery. */
- IT83XX_USBPD_CCPSR(port) = 0x33;
- }
-}
-
-static enum tcpc_cc_voltage_status it83xx_get_cc(
- enum usbpd_port port,
- enum usbpd_cc_pin cc_pin)
-{
- enum usbpd_ufp_volt_status ufp_volt;
- enum usbpd_dfp_volt_status dfp_volt;
- enum tcpc_cc_voltage_status cc_state = TYPEC_CC_VOLT_OPEN;
- int pull;
-
- pull = (cc_pin == USBPD_CC_PIN_1) ?
- USBPD_GET_CC1_PULL_REGISTER_SELECTION(port) :
- USBPD_GET_CC2_PULL_REGISTER_SELECTION(port);
-
- /* select Rp */
- if (pull)
- CLEAR_MASK(cc_state, BIT(2));
- /* select Rd */
- else
- SET_MASK(cc_state, BIT(2));
-
- /* sink */
- if (USBPD_GET_POWER_ROLE(port) == USBPD_POWER_ROLE_CONSUMER) {
- if (cc_pin == USBPD_CC_PIN_1)
- ufp_volt = IT83XX_USBPD_UFPVDR(port) & 0x7;
- else
- ufp_volt = (IT83XX_USBPD_UFPVDR(port) >> 4) & 0x7;
-
- switch (ufp_volt) {
- case USBPD_UFP_STATE_SNK_DEF:
- cc_state |= (TYPEC_CC_VOLT_RP_DEF & 3);
- break;
- case USBPD_UFP_STATE_SNK_1_5:
- cc_state |= (TYPEC_CC_VOLT_RP_1_5 & 3);
- break;
- case USBPD_UFP_STATE_SNK_3_0:
- cc_state |= (TYPEC_CC_VOLT_RP_3_0 & 3);
- break;
- case USBPD_UFP_STATE_SNK_OPEN:
- cc_state = TYPEC_CC_VOLT_OPEN;
- break;
- default:
- cc_state = TYPEC_CC_VOLT_OPEN;
- break;
- }
- /* source */
- } else {
- if (cc_pin == USBPD_CC_PIN_1)
- dfp_volt = IT83XX_USBPD_DFPVDR(port) & 0xf;
- else
- dfp_volt = (IT83XX_USBPD_DFPVDR(port) >> 4) & 0xf;
-
- switch (dfp_volt) {
- case USBPD_DFP_STATE_SRC_RA:
- cc_state |= TYPEC_CC_VOLT_RA;
- break;
- case USBPD_DFP_STATE_SRC_RD:
- cc_state |= TYPEC_CC_VOLT_RD;
- break;
- case USBPD_DFP_STATE_SRC_OPEN:
- cc_state = TYPEC_CC_VOLT_OPEN;
- break;
- default:
- cc_state = TYPEC_CC_VOLT_OPEN;
- break;
- }
- }
-
- return cc_state;
-}
-
-static int it83xx_tcpm_get_message_raw(int port, uint32_t *buf, int *head)
-{
- int cnt = PD_HEADER_CNT(IT83XX_USBPD_RMH(port));
-
- if (!USBPD_IS_RX_DONE(port))
- return EC_ERROR_UNKNOWN;
-
- /* store header */
- *head = IT83XX_USBPD_RMH(port);
- /* check data message */
- if (cnt)
- memcpy(buf, (uint32_t *)&IT83XX_USBPD_RDO0(port), cnt * 4);
- /*
- * Note: clear RX done interrupt after get the data.
- * If clear this bit, USBPD receives next packet
- */
- IT83XX_USBPD_MRSR(port) = USBPD_REG_MASK_RX_MSG_VALID;
-
- return EC_SUCCESS;
-}
-
-static enum tcpc_transmit_complete it83xx_tx_data(
- enum usbpd_port port,
- enum tcpm_transmit_type type,
- uint16_t header,
- const uint32_t *buf)
-{
- int r;
- uint32_t evt;
- uint8_t length = PD_HEADER_CNT(header);
-
- /* set message header */
- IT83XX_USBPD_TMHLR(port) = (uint8_t)header;
- IT83XX_USBPD_TMHHR(port) = (header >> 8);
-
- /*
- * SOP type bit[6~4]:
- * on bx version and before:
- * x00b=SOP, x01b=SOP', x10b=SOP", bit[6] is reserved.
- * on dx version:
- * 000b=SOP, 001b=SOP', 010b=SOP", 011b=Debug SOP', 100b=Debug SOP''.
- */
- IT83XX_USBPD_MTSR1(port) =
- (IT83XX_USBPD_MTSR1(port) & ~0x70) | ((type & 0x7) << 4);
- /* bit7: transmit message is send to cable or not */
- if (TCPC_TX_SOP == type)
- IT83XX_USBPD_MTSR0(port) &= ~USBPD_REG_MASK_CABLE_ENABLE;
- else
- IT83XX_USBPD_MTSR0(port) |= USBPD_REG_MASK_CABLE_ENABLE;
- /* clear msg length */
- IT83XX_USBPD_MTSR1(port) &= (~0x7);
- /* Limited by PD_HEADER_CNT() */
- ASSERT(length <= 0x7);
-
- if (length) {
- /* set data bit */
- IT83XX_USBPD_MTSR0(port) |= BIT(4);
- /* set data length setting */
- IT83XX_USBPD_MTSR1(port) |= length;
- /* set data */
- memcpy((uint32_t *)&IT83XX_USBPD_TDO(port), buf, length * 4);
- }
-
- for (r = 0; r <= PD_RETRY_COUNT; r++) {
- /* Start TX */
- USBPD_KICK_TX_START(port);
- evt = task_wait_event_mask(TASK_EVENT_PHY_TX_DONE,
- PD_T_TCPC_TX_TIMEOUT);
- /* check TX status */
- if (USBPD_IS_TX_ERR(port) || (evt & TASK_EVENT_TIMER)) {
- /*
- * If discard, means HW doesn't send the msg and resend.
- */
- if (USBPD_IS_TX_DISCARD(port))
- continue;
- /*
- * Or port partner doesn't respond GoodCRC
- */
- else
- return TCPC_TX_COMPLETE_FAILED;
- } else {
- break;
- }
- }
-
- if (r > PD_RETRY_COUNT)
- return TCPC_TX_COMPLETE_DISCARDED;
-
- return TCPC_TX_COMPLETE_SUCCESS;
-}
-
-static enum tcpc_transmit_complete it83xx_send_hw_reset(enum usbpd_port port,
- enum tcpm_transmit_type reset_type)
-{
- if (reset_type == TCPC_TX_CABLE_RESET)
- IT83XX_USBPD_MTSR0(port) |= USBPD_REG_MASK_CABLE_ENABLE;
- else
- IT83XX_USBPD_MTSR0(port) &= ~USBPD_REG_MASK_CABLE_ENABLE;
-
- /* send hard reset */
- USBPD_SEND_HARD_RESET(port);
- usleep(MSEC);
-
- if (IT83XX_USBPD_MTSR0(port) & USBPD_REG_MASK_SEND_HW_RESET)
- return TCPC_TX_COMPLETE_FAILED;
-
- return TCPC_TX_COMPLETE_SUCCESS;
-}
-
-static void it83xx_send_bist_mode2_pattern(enum usbpd_port port)
-{
- USBPD_ENABLE_SEND_BIST_MODE_2(port);
- usleep(PD_T_BIST_TRANSMIT);
- USBPD_DISABLE_SEND_BIST_MODE_2(port);
-}
-
-static void it83xx_enable_vconn(enum usbpd_port port, int enabled)
-{
- enum usbpd_cc_pin cc_pin;
-
- if (USBPD_GET_PULL_CC_SELECTION(port))
- cc_pin = USBPD_CC_PIN_1;
- else
- cc_pin = USBPD_CC_PIN_2;
-
- if (enabled) {
- /* Disable unused CC to become VCONN */
- if (cc_pin == USBPD_CC_PIN_1) {
- IT83XX_USBPD_CCCSR(port) = USBPD_CC2_DISCONNECTED(port);
- IT83XX_USBPD_CCPSR(port) = (IT83XX_USBPD_CCPSR(port)
- & ~USBPD_REG_MASK_DISCONNECT_POWER_CC2)
- | USBPD_REG_MASK_DISCONNECT_POWER_CC1;
- } else {
- IT83XX_USBPD_CCCSR(port) = USBPD_CC1_DISCONNECTED(port);
- IT83XX_USBPD_CCPSR(port) = (IT83XX_USBPD_CCPSR(port)
- & ~USBPD_REG_MASK_DISCONNECT_POWER_CC1)
- | USBPD_REG_MASK_DISCONNECT_POWER_CC2;
- }
- } else {
- /* Enable cc1 and cc2 */
- IT83XX_USBPD_CCCSR(port) &= ~0xaa;
- IT83XX_USBPD_CCPSR(port) |=
- (USBPD_REG_MASK_DISCONNECT_POWER_CC1 |
- USBPD_REG_MASK_DISCONNECT_POWER_CC2);
- }
-}
-
-static void it83xx_enable_cc(enum usbpd_port port, int enable)
-{
- if (enable)
- CLEAR_MASK(IT83XX_USBPD_CCGCR(port), BIT(4));
- else
- SET_MASK(IT83XX_USBPD_CCGCR(port), BIT(4));
-}
-
-static void it83xx_set_power_role(enum usbpd_port port, int power_role)
-{
- /* PD_ROLE_SINK 0, PD_ROLE_SOURCE 1 */
- if (power_role == PD_ROLE_SOURCE) {
- /*
- * bit[2,3] BMC Rx threshold setting
- * 00b: power neutral
- * 01b: sinking power =>
- * High to low Y3Rx threshold = 0.38,
- * Low to high Y3Rx threshold = 0.54.
- * 10b: sourcing power =>
- * High to low Y3Rx threshold = 0.64,
- * Low to high Y3Rx threshold = 0.79.
- */
- IT83XX_USBPD_CCADCR(port) = 0x08;
- /* bit0: source */
- SET_MASK(IT83XX_USBPD_PDMSR(port), BIT(0));
- /* bit1: CC1 select Rp */
- SET_MASK(IT83XX_USBPD_CCGCR(port), BIT(1));
- /* bit3: CC2 select Rp */
- SET_MASK(IT83XX_USBPD_BMCSR(port), BIT(3));
- } else {
- /*
- * bit[2,3] BMC Rx threshold setting
- * 00b: power neutral
- * 01b: sinking power =>
- * High to low Y3Rx threshold = 0.38,
- * Low to high Y3Rx threshold = 0.54
- * 10b: sourcing power =>
- * High to low Y3Rx threshold = 0.64,
- * Low to high Y3Rx threshold = 0.79
- */
- IT83XX_USBPD_CCADCR(port) = 0x04;
- /* bit0: sink */
- CLEAR_MASK(IT83XX_USBPD_PDMSR(port), BIT(0));
- /* bit1: CC1 select Rd */
- CLEAR_MASK(IT83XX_USBPD_CCGCR(port), BIT(1));
- /* bit3: CC2 select Rd */
- CLEAR_MASK(IT83XX_USBPD_BMCSR(port), BIT(3));
- }
-}
-
-static void it83xx_set_data_role(enum usbpd_port port, int pd_role)
-{
- /* 0: PD_ROLE_UFP 1: PD_ROLE_DFP */
- IT83XX_USBPD_PDMSR(port) =
- (IT83XX_USBPD_PDMSR(port) & ~0xc) | ((pd_role & 0x1) << 2);
-}
-
-static void it83xx_init(enum usbpd_port port, int role)
-{
-#ifdef IT83XX_USBPD_CC_PARAMETER_RELOAD
- /* bit7: Reload CC parameter setting. */
- IT83XX_USBPD_CCPSR0(port) |= BIT(7);
-#endif
- /* reset and disable HW auto generate message header */
- IT83XX_USBPD_GCR(port) = BIT(5);
- USBPD_SW_RESET(port);
- /* set SOP: receive SOP message only.
- * bit[7]: SOP" support enable.
- * bit[6]: SOP' support enable.
- * bit[5]: SOP support enable.
- */
- IT83XX_USBPD_PDMSR(port) = USBPD_REG_MASK_SOP_ENABLE;
- /* W/C status */
- IT83XX_USBPD_ISR(port) = 0xff;
- /* enable cc, select cc1 and Rd. */
- IT83XX_USBPD_CCGCR(port) = 0xd;
- /* change data role as the same power role */
- it83xx_set_data_role(port, role);
- /* set power role */
- it83xx_set_power_role(port, role);
- /* disable all interrupts */
- IT83XX_USBPD_IMR(port) = 0xff;
- /* enable tx done and reset detect interrupt */
- IT83XX_USBPD_IMR(port) &= ~(USBPD_REG_MASK_MSG_TX_DONE |
- USBPD_REG_MASK_HARD_RESET_DETECT);
-#ifdef IT83XX_INTC_PLUG_IN_SUPPORT
- /*
- * when tcpc detect type-c plug in (cc lines voltage change), it will
- * interrupt fw to wake pd task, so task can react immediately.
- *
- * w/c status and unmask TCDCR (detect type-c plug in interrupt default
- * is enable).
- */
- IT83XX_USBPD_TCDCR(port) = USBPD_REG_PLUG_IN_OUT_DETECT_STAT;
-#endif //IT83XX_INTC_PLUG_IN_SUPPORT
- IT83XX_USBPD_CCPSR(port) = 0xff;
- /* cc connect */
- IT83XX_USBPD_CCCSR(port) = 0;
- /* disable vconn */
- it83xx_enable_vconn(port, 0);
- /* TX start from high */
- IT83XX_USBPD_CCADCR(port) |= BIT(6);
- /* enable cc1/cc2 */
- *usbpd_ctrl_regs[port].cc1 = IT83XX_USBPD_CC_PIN_CONFIG;
- *usbpd_ctrl_regs[port].cc2 = IT83XX_USBPD_CC_PIN_CONFIG;
- task_clear_pending_irq(usbpd_ctrl_regs[port].irq);
- task_enable_irq(usbpd_ctrl_regs[port].irq);
- USBPD_START(port);
-}
-
-static void it83xx_select_polarity(enum usbpd_port port,
- enum usbpd_cc_pin cc_pin)
-{
- /* cc1/cc2 selection */
- if (cc_pin == USBPD_CC_PIN_1)
- SET_MASK(IT83XX_USBPD_CCGCR(port), BIT(0));
- else
- CLEAR_MASK(IT83XX_USBPD_CCGCR(port), BIT(0));
-}
-
-static int it83xx_set_cc(enum usbpd_port port, int pull)
-{
- int enable_cc = 1;
-
- switch (pull) {
- case TYPEC_CC_RD:
- it83xx_set_power_role(port, PD_ROLE_SINK);
- break;
- case TYPEC_CC_RP:
- it83xx_set_power_role(port, PD_ROLE_SOURCE);
- break;
- case TYPEC_CC_OPEN:
- /* Power-down CC1 & CC2 to remove Rp/Rd */
- enable_cc = 0;
- break;
- default:
- return EC_ERROR_UNIMPLEMENTED;
- }
-
- it83xx_enable_cc(port, enable_cc);
- return EC_SUCCESS;
-}
-
-static int it83xx_tcpm_init(int port)
-{
- /* Initialize physical layer */
- it83xx_init(port, PD_ROLE_DEFAULT(port));
-
- return EC_SUCCESS;
-}
-
-static int it83xx_tcpm_release(int port)
-{
- return EC_ERROR_UNIMPLEMENTED;
-}
-
-static int it83xx_tcpm_get_cc(int port, enum tcpc_cc_voltage_status *cc1,
- enum tcpc_cc_voltage_status *cc2)
-{
- *cc2 = it83xx_get_cc(port, USBPD_CC_PIN_2);
- *cc1 = it83xx_get_cc(port, USBPD_CC_PIN_1);
-
- return EC_SUCCESS;
-}
-
-static int it83xx_tcpm_select_rp_value(int port, int rp_sel)
-{
- uint8_t rp;
- /*
- * bit[3-2]: CC output current (when Rp selected)
- * 00: reserved
- * 01: 330uA outpt (3.0A)
- * 10: 180uA outpt (1.5A)
- * 11: 80uA outpt (USB default)
- */
- switch (rp_sel) {
- case TYPEC_RP_1A5:
- rp = 2 << 2;
- break;
- case TYPEC_RP_3A0:
- rp = BIT(2);
- break;
- case TYPEC_RP_USB:
- default:
- rp = 3 << 2;
- break;
- }
- IT83XX_USBPD_CCGCR(port) = (IT83XX_USBPD_CCGCR(port) & ~(3 << 2)) | rp;
-
- return EC_SUCCESS;
-}
-
-static int it83xx_tcpm_set_cc(int port, int pull)
-{
- return it83xx_set_cc(port, pull);
-}
-
-static int it83xx_tcpm_set_polarity(int port, int polarity)
-{
- it83xx_select_polarity(port, polarity);
-
- return EC_SUCCESS;
-}
-
-static int it83xx_tcpm_set_vconn(int port, int enable)
-{
- /*
- * IT83XX doesn't have integrated circuit to source CC lines for VCONN.
- * An external device like PPC or Power Switch has to source the VCONN.
- */
- if (IS_ENABLED(CONFIG_USBC_VCONN)) {
- if (enable) {
- /*
- * Unused cc will become Vconn SRC, disable cc analog
- * module (ex.UP/RD/DET/Tx/Rx) and enable 5v tolerant.
- */
- it83xx_enable_vconn(port, enable);
- if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP))
- /* Enable tcpc receive SOP' packet */
- IT83XX_USBPD_PDMSR(port) |=
- USBPD_REG_MASK_SOPP_ENABLE;
- }
-
- /* Turn on/off vconn power switch. */
- board_pd_vconn_ctrl(port,
- USBPD_GET_PULL_CC_SELECTION(port) ?
- USBPD_CC_PIN_2 : USBPD_CC_PIN_1, enable);
-
- if (!enable) {
- /* Disable tcpc receive SOP' packet */
- if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP))
- IT83XX_USBPD_PDMSR(port) &=
- ~USBPD_REG_MASK_SOPP_ENABLE;
- /*
- * We need to make sure cc voltage detector is enabled
- * after vconn is turned off to avoid the potential risk
- * of voltage fed back into Vcore.
- */
- usleep(PD_IT83XX_VCONN_TURN_OFF_DELAY_US);
- /*
- * Since our cc are not Vconn SRC, enable cc analog
- * module (ex.UP/RD/DET/Tx/Rx) and disable 5v tolerant.
- */
- it83xx_enable_vconn(port, enable);
- }
- }
-
- return EC_SUCCESS;
-}
-
-static int it83xx_tcpm_set_msg_header(int port, int power_role, int data_role)
-{
- /* PD_ROLE_SINK 0, PD_ROLE_SOURCE 1 */
- if (power_role == PD_ROLE_SOURCE)
- /* bit0: source */
- SET_MASK(IT83XX_USBPD_PDMSR(port), BIT(0));
- else
- /* bit0: sink */
- CLEAR_MASK(IT83XX_USBPD_PDMSR(port), BIT(0));
-
- it83xx_set_data_role(port, data_role);
-
- return EC_SUCCESS;
-}
-
-static int it83xx_tcpm_set_rx_enable(int port, int enable)
-{
- int i;
-
- if (enable) {
- IT83XX_USBPD_IMR(port) &= ~USBPD_REG_MASK_MSG_RX_DONE;
- USBPD_ENABLE_BMC_PHY(port);
- } else {
- IT83XX_USBPD_IMR(port) |= USBPD_REG_MASK_MSG_RX_DONE;
- USBPD_DISABLE_BMC_PHY(port);
- }
-
- /* If any PD port is connected, then disable deep sleep */
- for (i = 0; i < board_get_usb_pd_port_count(); ++i)
- if (IT83XX_USBPD_GCR(i) | USBPD_REG_MASK_BMC_PHY)
- break;
-
- if (i == board_get_usb_pd_port_count())
- enable_sleep(SLEEP_MASK_USB_PD);
- else
- disable_sleep(SLEEP_MASK_USB_PD);
-
- return EC_SUCCESS;
-}
-
-static int it83xx_tcpm_transmit(int port,
- enum tcpm_transmit_type type,
- uint16_t header,
- const uint32_t *data)
-{
- int status = TCPC_TX_COMPLETE_FAILED;
-
- switch (type) {
- case TCPC_TX_SOP:
- case TCPC_TX_SOP_PRIME:
- case TCPC_TX_SOP_PRIME_PRIME:
- case TCPC_TX_SOP_DEBUG_PRIME:
- case TCPC_TX_SOP_DEBUG_PRIME_PRIME:
- status = it83xx_tx_data(port,
- type,
- header,
- data);
- break;
- case TCPC_TX_BIST_MODE_2:
- it83xx_send_bist_mode2_pattern(port);
- status = TCPC_TX_COMPLETE_SUCCESS;
- break;
- case TCPC_TX_HARD_RESET:
- case TCPC_TX_CABLE_RESET:
- status = it83xx_send_hw_reset(port, type);
- break;
- default:
- status = TCPC_TX_COMPLETE_FAILED;
- break;
- }
- pd_transmit_complete(port, status);
-
- return EC_SUCCESS;
-}
-
-static int it83xx_tcpm_get_chip_info(int port, int live,
- struct ec_response_pd_chip_info_v1 **chip_info)
-{
- static struct ec_response_pd_chip_info_v1 i;
-
- *chip_info = &i;
- i.vendor_id = USB_VID_ITE;
- i.product_id = (IT83XX_GCTRL_CHIPID1 << 8) | IT83XX_GCTRL_CHIPID2;
- i.device_id = IT83XX_GCTRL_CHIPVER & 0xf;
- i.fw_version_number = 0xEC;
-
- return EC_SUCCESS;
-}
-
-static void it83xx_tcpm_sw_reset(void)
-{
- int port = TASK_ID_TO_PD_PORT(task_get_current());
-#ifdef IT83XX_INTC_PLUG_IN_SUPPORT
- /*
- * Enable detect type-c plug in interrupt, since the pd task has
- * detected a type-c physical disconnected.
- */
- IT83XX_USBPD_TCDCR(port) &= ~USBPD_REG_PLUG_IN_OUT_DETECT_DISABLE;
-#endif //IT83XX_INTC_PLUG_IN_SUPPORT
- /* exit BIST test data mode */
- USBPD_SW_RESET(port);
-}
-
-DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, it83xx_tcpm_sw_reset, HOOK_PRIO_DEFAULT);
-
-const struct tcpm_drv it83xx_tcpm_drv = {
- .init = &it83xx_tcpm_init,
- .release = &it83xx_tcpm_release,
- .get_cc = &it83xx_tcpm_get_cc,
- .select_rp_value = &it83xx_tcpm_select_rp_value,
- .set_cc = &it83xx_tcpm_set_cc,
- .set_polarity = &it83xx_tcpm_set_polarity,
- .set_vconn = &it83xx_tcpm_set_vconn,
- .set_msg_header = &it83xx_tcpm_set_msg_header,
- .set_rx_enable = &it83xx_tcpm_set_rx_enable,
- .get_message_raw = &it83xx_tcpm_get_message_raw,
- .transmit = &it83xx_tcpm_transmit,
- .get_chip_info = &it83xx_tcpm_get_chip_info,
-};
diff --git a/driver/tcpm/it83xx_pd.h b/driver/tcpm/it83xx_pd.h
deleted file mode 100644
index 9e8bff1342..0000000000
--- a/driver/tcpm/it83xx_pd.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* Copyright 2016 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.
- */
-
-/* USB Power delivery port management */
-#ifndef __CROS_EC_DRIVER_TCPM_IT83XX_H
-#define __CROS_EC_DRIVER_TCPM_IT83XX_H
-
-/*
- * Dedicated setting for CC pin.
- * This setting will connect CC pin to internal PD module directly without
- * applying any GPIO/ALT configuration.
- */
-#define IT83XX_USBPD_CC_PIN_CONFIG 0x86
-
-#define TASK_EVENT_PHY_TX_DONE TASK_EVENT_CUSTOM_BIT(PD_EVENT_FIRST_FREE_BIT)
-
-#define SET_MASK(reg, bit_mask) ((reg) |= (bit_mask))
-#define CLEAR_MASK(reg, bit_mask) ((reg) &= (~(bit_mask)))
-#define IS_MASK_SET(reg, bit_mask) (((reg) & (bit_mask)) != 0)
-#define IS_MASK_CLEAR(reg, bit_mask) (((reg) & (bit_mask)) == 0)
-
-/* macros for set */
-#define USBPD_KICK_TX_START(port) \
- SET_MASK(IT83XX_USBPD_MTCR(port), \
- USBPD_REG_MASK_TX_START)
-#define USBPD_SEND_HARD_RESET(port) \
- SET_MASK(IT83XX_USBPD_MTSR0(port), \
- USBPD_REG_MASK_SEND_HW_RESET)
-#define USBPD_SW_RESET(port) \
- SET_MASK(IT83XX_USBPD_GCR(port), \
- USBPD_REG_MASK_SW_RESET_BIT)
-#define USBPD_ENABLE_BMC_PHY(port) \
- SET_MASK(IT83XX_USBPD_GCR(port), \
- USBPD_REG_MASK_BMC_PHY)
-#define USBPD_DISABLE_BMC_PHY(port) \
- CLEAR_MASK(IT83XX_USBPD_GCR(port), \
- USBPD_REG_MASK_BMC_PHY)
-#define USBPD_START(port) \
- CLEAR_MASK(IT83XX_USBPD_CCGCR(port), \
- USBPD_REG_MASK_DISABLE_CC)
-#define USBPD_ENABLE_SEND_BIST_MODE_2(port) \
- SET_MASK(IT83XX_USBPD_MTSR0(port), \
- USBPD_REG_MASK_SEND_BIST_MODE_2)
-#define USBPD_DISABLE_SEND_BIST_MODE_2(port) \
- CLEAR_MASK(IT83XX_USBPD_MTSR0(port), \
- USBPD_REG_MASK_SEND_BIST_MODE_2)
-
-/* macros for get */
-#define USBPD_GET_POWER_ROLE(port) \
- (IT83XX_USBPD_PDMSR(port) & 1)
-#define USBPD_GET_CC1_PULL_REGISTER_SELECTION(port) \
- (IT83XX_USBPD_CCGCR(port) & BIT(1))
-#define USBPD_GET_CC2_PULL_REGISTER_SELECTION(port) \
- (IT83XX_USBPD_BMCSR(port) & BIT(3))
-#define USBPD_GET_PULL_CC_SELECTION(port) \
- (IT83XX_USBPD_CCGCR(port) & 1)
-
-/* macros for check */
-#define USBPD_IS_TX_ERR(port) \
- IS_MASK_SET(IT83XX_USBPD_MTCR(port), USBPD_REG_MASK_TX_ERR_STAT)
-#define USBPD_IS_TX_DISCARD(port) \
- IS_MASK_SET(IT83XX_USBPD_MTCR(port), USBPD_REG_MASK_TX_DISCARD_STAT)
-
-/* macros for PD ISR */
-#define USBPD_IS_HARD_RESET_DETECT(port) \
- IS_MASK_SET(IT83XX_USBPD_ISR(port), USBPD_REG_MASK_HARD_RESET_DETECT)
-#define USBPD_IS_TX_DONE(port) \
- IS_MASK_SET(IT83XX_USBPD_ISR(port), USBPD_REG_MASK_MSG_TX_DONE)
-#define USBPD_IS_RX_DONE(port) \
- IS_MASK_SET(IT83XX_USBPD_ISR(port), USBPD_REG_MASK_MSG_RX_DONE)
-#ifdef IT83XX_INTC_PLUG_IN_SUPPORT
-#define USBPD_IS_PLUG_IN_OUT_DETECT(port)\
- IS_MASK_SET(IT83XX_USBPD_TCDCR(port), USBPD_REG_PLUG_IN_OUT_DETECT_STAT)
-#endif //IT83XX_INTC_PLUG_IN_SUPPORT
-
-enum usbpd_ufp_volt_status {
- USBPD_UFP_STATE_SNK_OPEN = 0,
- USBPD_UFP_STATE_SNK_DEF = 1,
- USBPD_UFP_STATE_SNK_1_5 = 3,
- USBPD_UFP_STATE_SNK_3_0 = 7,
-};
-
-enum usbpd_dfp_volt_status {
- USBPD_DFP_STATE_SRC_RA = 0,
- USBPD_DFP_STATE_SRC_RD = 1,
- USBPD_DFP_STATE_SRC_OPEN = 3,
-};
-
-enum usbpd_power_role {
- USBPD_POWER_ROLE_CONSUMER,
- USBPD_POWER_ROLE_PROVIDER,
- USBPD_POWER_ROLE_CONSUMER_PROVIDER,
- USBPD_POWER_ROLE_PROVIDER_CONSUMER,
-};
-
-struct usbpd_ctrl_t {
- volatile uint8_t *cc1;
- volatile uint8_t *cc2;
- uint8_t irq;
-};
-
-extern const struct usbpd_ctrl_t usbpd_ctrl_regs[];
-extern const struct tcpm_drv it83xx_tcpm_drv;
-/* Disable integrated pd module */
-void it83xx_disable_pd_module(int port);
-
-#endif /* __CROS_EC_DRIVER_TCPM_IT83XX_H */
diff --git a/driver/tcpm/mt6370.c b/driver/tcpm/mt6370.c
deleted file mode 100644
index 8a50b480f6..0000000000
--- a/driver/tcpm/mt6370.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/* Copyright 2018 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.
- *
- * MT6370 TCPC Driver
- */
-
-#include "console.h"
-#include "hooks.h"
-#include "mt6370.h"
-#include "task.h"
-#include "tcpci.h"
-#include "tcpm.h"
-#include "timer.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args)
-
-static int mt6370_polarity;
-
-/* i2c_write function which won't wake TCPC from low power mode. */
-static int mt6370_i2c_write8(int port, int reg, int val)
-{
- return i2c_write8(tcpc_config[port].i2c_info.port,
- tcpc_config[port].i2c_info.addr_flags, reg, val);
-}
-
-static int mt6370_init(int port)
-{
- int rv, val;
-
- rv = tcpc_read(port, MT6370_REG_IDLE_CTRL, &val);
-
- /* Only do soft-reset in shipping mode. (b:122017882) */
- if (!(val & MT6370_REG_SHIPPING_OFF)) {
-
- /* Software reset. */
- rv = tcpc_write(port, MT6370_REG_SWRESET, 1);
- if (rv)
- return rv;
-
- /* Need 1 ms for software reset. */
- msleep(1);
- }
-
- /* The earliest point that we can do generic init. */
- rv = tcpci_tcpm_init(port);
-
- if (rv)
- return rv;
-
- /*
- * AUTO IDLE off, shipping off, select CK_300K from BICIO_320K,
- * PD3.0 ext-msg on.
- */
- rv = tcpc_write(port, MT6370_REG_IDLE_CTRL,
- MT6370_REG_IDLE_SET(0, 1, 0, 0));
- /* CC Detect Debounce 5 */
- rv |= tcpc_write(port, MT6370_REG_TTCPC_FILTER, 5);
- /* DRP Duty */
- rv |= tcpc_write(port, MT6370_REG_DRP_TOGGLE_CYCLE, 4);
- rv |= tcpc_write16(port, MT6370_REG_DRP_DUTY_CTRL, 400);
- /* Vconn OC on */
- rv |= tcpc_write(port, MT6370_REG_VCONN_CLIMITEN, 1);
- /* PHY control */
- rv |= tcpc_write(port, MT6370_REG_PHY_CTRL1,
- MT6370_REG_PHY_CTRL1_SET(0, 7, 0, 1));
- rv |= tcpc_write(port, MT6370_REG_PHY_CTRL3, 0x82);
-
- return rv;
-}
-
-static inline int mt6370_init_cc_params(int port, int cc_res)
-{
- int rv, en, sel;
-
- if (cc_res == TYPEC_CC_VOLT_RP_DEF) { /* RXCC threshold : 0.55V */
- en = 1;
- sel = MT6370_OCCTRL_600MA | MT6370_MASK_BMCIO_RXDZSEL;
- } else { /* RD threshold : 0.4V & RP threshold : 0.7V */
- en = 0;
- sel = MT6370_OCCTRL_600MA;
- }
- rv = tcpc_write(port, MT6370_REG_BMCIO_RXDZEN, en);
- if (!rv)
- rv = tcpc_write(port, MT6370_REG_BMCIO_RXDZSEL, sel);
- return rv;
-}
-
-static int mt6370_get_cc(int port, enum tcpc_cc_voltage_status *cc1,
- enum tcpc_cc_voltage_status *cc2)
-{
- int status;
- int rv;
- int role, is_snk;
-
- rv = tcpc_read(port, TCPC_REG_CC_STATUS, &status);
-
- /* If tcpc read fails, return error and CC as open */
- if (rv) {
- *cc1 = TYPEC_CC_VOLT_OPEN;
- *cc2 = TYPEC_CC_VOLT_OPEN;
- return rv;
- }
-
- *cc1 = TCPC_REG_CC_STATUS_CC1(status);
- *cc2 = TCPC_REG_CC_STATUS_CC2(status);
-
- /*
- * If status is not open, then OR in termination to convert to
- * enum tcpc_cc_voltage_status.
- *
- * MT6370 TCPC follows USB PD 1.0 protocol. When DRP not auto-toggling,
- * it will not update the DRP_RESULT bits in TCPC_REG_CC_STATUS,
- * instead, we should check CC1/CC2 bits in TCPC_REG_ROLE_CTRL.
- */
- rv = tcpc_read(port, TCPC_REG_ROLE_CTRL, &role);
-
- if (TCPC_REG_ROLE_CTRL_DRP(role))
- is_snk = TCPC_REG_CC_STATUS_TERM(status);
- else
- /* CC1/CC2 states are the same, checking one-side is enough. */
- is_snk = TCPC_REG_CC_STATUS_CC1(role) == TYPEC_CC_RD;
-
- if (is_snk) {
- if (*cc1 != TYPEC_CC_VOLT_OPEN)
- *cc1 |= 0x04;
- if (*cc2 != TYPEC_CC_VOLT_OPEN)
- *cc2 |= 0x04;
- }
-
- rv = mt6370_init_cc_params(port, (int)mt6370_polarity ? *cc1 : *cc2);
- return rv;
-}
-
-static int mt6370_set_cc(int port, int pull)
-{
- if (pull == TYPEC_CC_RD)
- mt6370_init_cc_params(port, TYPEC_CC_VOLT_RP_DEF);
- return tcpci_tcpm_set_cc(port, pull);
-}
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
-static int mt6370_enter_low_power_mode(int port)
-{
- int rv;
-
- /* VBUS_DET_EN for detecting charger plug. */
- rv = tcpc_write(port, MT6370_REG_BMC_CTRL,
- MT6370_REG_BMCIO_LPEN | MT6370_REG_VBUS_DET_EN);
-
- if (rv)
- return rv;
-
- return tcpci_enter_low_power_mode(port);
-}
-#endif
-
-static int mt6370_set_polarity(int port, int polarity)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
-
- mt6370_polarity = polarity;
- mt6370_get_cc(port, &cc1, &cc2);
- return tcpci_tcpm_set_polarity(port, polarity);
-}
-
-int mt6370_vconn_discharge(int port)
-{
- /*
- * Write to mt6370 in low-power mode may return fail, but it is
- * actually written. So we just ignore its return value.
- */
- mt6370_i2c_write8(port, MT6370_REG_OVP_FLAG_SEL,
- MT6370_REG_DISCHARGE_LVL);
- /* Set MT6370_REG_DISCHARGE_EN bit and also the rest default value. */
- mt6370_i2c_write8(port, MT6370_REG_BMC_CTRL,
- MT6370_REG_DISCHARGE_EN |
- MT6370_REG_BMC_CTRL_DEFAULT);
-
- return EC_SUCCESS;
-}
-
-/* MT6370 is a TCPCI compatible port controller */
-const struct tcpm_drv mt6370_tcpm_drv = {
- .init = &mt6370_init,
- .release = &tcpci_tcpm_release,
- .get_cc = &mt6370_get_cc,
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
- .get_vbus_level = &tcpci_tcpm_get_vbus_level,
-#endif
- .select_rp_value = &tcpci_tcpm_select_rp_value,
- .set_cc = &mt6370_set_cc,
- .set_polarity = &mt6370_set_polarity,
- .set_vconn = &tcpci_tcpm_set_vconn,
- .set_msg_header = &tcpci_tcpm_set_msg_header,
- .set_rx_enable = &tcpci_tcpm_set_rx_enable,
- .get_message_raw = &tcpci_tcpm_get_message_raw,
- .transmit = &tcpci_tcpm_transmit,
- .tcpc_alert = &tcpci_tcpc_alert,
-#ifdef CONFIG_USB_PD_DISCHARGE_TCPC
- .tcpc_discharge_vbus = &tcpci_tcpc_discharge_vbus,
-#endif
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- .drp_toggle = &tcpci_tcpc_drp_toggle,
-#endif
- .get_chip_info = &tcpci_get_chip_info,
-#ifdef CONFIG_USBC_PPC
- .set_snk_ctrl = &tcpci_tcpm_set_snk_ctrl,
- .set_src_ctrl = &tcpci_tcpm_set_src_ctrl,
-#endif
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- .enter_low_power_mode = &mt6370_enter_low_power_mode,
-#endif
-};
diff --git a/driver/tcpm/mt6370.h b/driver/tcpm/mt6370.h
deleted file mode 100644
index cdc3112a3e..0000000000
--- a/driver/tcpm/mt6370.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/* Copyright 2018 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.
- *
- * MT6370 TCPC Driver
- */
-
-#ifndef __CROS_EC_USB_PD_TCPM_MT6370_H
-#define __CROS_EC_USB_PD_TCPM_MT6370_H
-
-/* MT6370 Private RegMap */
-
-#define MT6370_REG_PHY_CTRL1 0x80
-#define MT6370_REG_PHY_CTRL2 0x81
-#define MT6370_REG_PHY_CTRL3 0x82
-#define MT6370_REG_PHY_CTRL6 0x85
-
-#define MT6370_REG_CLK_CTRL2 0x87
-#define MT6370_REG_CLK_CTRL3 0x88
-
-#define MT6370_REG_RUST_STATUS 0x8A
-#define MT6370_REG_RUST_INT_EVENT 0x8B
-#define MT6370_REG_RUST_MASK 0x8C
-#define MT6370_REG_BMC_CTRL 0x90
-#define MT6370_REG_BMCIO_RXDZSEL 0x93
-#define MT6370_REG_VCONN_CLIMITEN 0x95
-
-#define MT6370_REG_OVP_FLAG_SEL 0x96
-
-#define MT6370_REG_RT_STATUS 0x97
-#define MT6370_REG_RT_INT 0x98
-#define MT6370_REG_RT_MASK 0x99
-#define RT5081_REG_BMCIO_RXDZEN 0x9A
-#define MT6370_REG_IDLE_CTRL 0x9B
-#define MT6370_REG_INTRST_CTRL 0x9C
-#define MT6370_REG_WATCHDOG_CTRL 0x9D
-#define MT6370_REG_I2CRST_CTRL 0X9E
-
-#define MT6370_REG_SWRESET 0xA0
-#define MT6370_REG_TTCPC_FILTER 0xA1
-#define MT6370_REG_DRP_TOGGLE_CYCLE 0xA2
-#define MT6370_REG_DRP_DUTY_CTRL 0xA3
-#define MT6370_REG_RUST_DETECTION 0xAD
-#define MT6370_REG_RUST_CONTROL 0xAE
-#define MT6370_REG_BMCIO_RXDZEN 0xAF
-#define MT6370_REG_DRP_RUST 0xB9
-
-#define MT6370_REG_UNLOCK_PW2 0xF0
-#define MT6370_REG_UNLOCK_PW1 0xF1
-
-#define MT6370_TCPC_I2C_ADDR_FLAGS 0x4E
-
-/*
- * MT6370_REG_PHY_CTRL1 0x80
- */
-
-#define MT6370_REG_PHY_CTRL1_SET(retry_discard, toggle_cnt, bus_idle_cnt, \
- rx_filter) \
- ((retry_discard << 7) | (toggle_cnt << 4) | (bus_idle_cnt << 2) | \
- (rx_filter & 0x03))
-
-/*
- * MT6370_REG_CLK_CTRL2 0x87
- */
-
-#define MT6370_REG_CLK_DIV_600K_EN BIT(7)
-#define MT6370_REG_CLK_BCLK2_EN BIT(6)
-#define MT6370_REG_CLK_BCLK2_TG_EN BIT(5)
-#define MT6370_REG_CLK_DIV_300K_EN BIT(3)
-#define MT6370_REG_CLK_CK_300K_EN BIT(2)
-#define MT6370_REG_CLK_BCLK_EN BIT(1)
-#define MT6370_REG_CLK_BCLK_TH_EN BIT(0)
-
-/*
- * MT6370_REG_CLK_CTRL3 0x88
- */
-
-#define MT6370_REG_CLK_OSCMUX_RG_EN BIT(7)
-#define MT6370_REG_CLK_CK_24M_EN BIT(6)
-#define MT6370_REG_CLK_OSC_RG_EN BIT(5)
-#define MT6370_REG_CLK_DIV_2P4M_EN BIT(4)
-#define MT6370_REG_CLK_CK_2P4M_EN BIT(3)
-#define MT6370_REG_CLK_PCLK_EN BIT(2)
-#define MT6370_REG_CLK_PCLK_RG_EN BIT(1)
-#define MT6370_REG_CLK_PCLK_TG_EN BIT(0)
-
-/*
- * MT6370_REG_RX_TX_DBG 0x8b
- */
-
-#define MT6370_REG_RX_TX_DBG_RX_BUSY BIT(7)
-#define MT6370_REG_RX_TX_DBG_TX_BUSY BIT(6)
-
-/*
- * MT6370_REG_BMC_CTRL 0x90
- */
-
-#define MT6370_REG_IDLE_EN BIT(6)
-#define MT6370_REG_DISCHARGE_EN BIT(5)
-#define MT6370_REG_BMCIO_LPRPRD BIT(4)
-#define MT6370_REG_BMCIO_LPEN BIT(3)
-#define MT6370_REG_BMCIO_BG_EN BIT(2)
-#define MT6370_REG_VBUS_DET_EN BIT(1)
-#define MT6370_REG_BMCIO_OSC_EN BIT(0)
-#define MT6370_REG_BMC_CTRL_DEFAULT \
- (MT6370_REG_BMCIO_BG_EN | MT6370_REG_VBUS_DET_EN | \
- MT6370_REG_BMCIO_OSC_EN)
-
-/*
- * MT6370_REG_BMCIO_RXDZSEL 0x93
- */
-
-#define MT6370_MASK_OCCTRL_SEL 0xE0
-#define MT6370_OCCTRL_600MA 0x80
-#define MT6370_MASK_BMCIO_RXDZSEL BIT(0)
-
-/*
- * MT6370_REG_OVP_FLAG_SEL 0x96
- */
-
-#define MT6370_MASK_DISCHARGE_LVL 0x03
-#define MT6370_REG_DISCHARGE_LVL BIT(0)
-
-/*
- * MT6370_REG_RT_STATUS 0x97
- */
-
-#define MT6370_REG_RA_DETACH BIT(5)
-#define MT6370_REG_VBUS_80 BIT(1)
-
-/*
- * MT6370_REG_RT_INT 0x98
- */
-
-#define MT6370_REG_INT_RA_DETACH BIT(5)
-#define MT6370_REG_INT_WATCHDOG BIT(2)
-#define MT6370_REG_INT_VBUS_80 BIT(1)
-#define MT6370_REG_INT_WAKEUP BIT(0)
-
-/*
- * MT6370_REG_RT_MASK 0x99
- */
-
-#define MT6370_REG_M_RA_DETACH BIT(5)
-#define MT6370_REG_M_WATCHDOG BIT(2)
-#define MT6370_REG_M_VBUS_80 BIT(1)
-#define MT6370_REG_M_WAKEUP BIT(0)
-
-/*
- * MT6370_REG_IDLE_CTRL 0x9B
- */
-
-#define MT6370_REG_CK_300K_SEL BIT(7)
-#define MT6370_REG_SHIPPING_OFF BIT(5)
-#define MT6370_REG_ENEXTMSG BIT(4)
-#define MT6370_REG_AUTOIDLE_EN BIT(3)
-
-/* timeout = (tout*2+1) * 6.4ms */
-#ifdef CONFIG_USB_PD_REV30
-#define MT6370_REG_IDLE_SET(ck300, ship_dis, auto_idle, tout) \
- ((ck300 << 7) | (ship_dis << 5) | (auto_idle << 3) | (tout & 0x07) | \
- MT6370_REG_ENEXTMSG)
-#else
-#define MT6370_REG_IDLE_SET(ck300, ship_dis, auto_idle, tout) \
- ((ck300 << 7) | (ship_dis << 5) | (auto_idle << 3) | (tout & 0x07))
-#endif
-
-/*
- * MT6370_REG_INTRST_CTRL 0x9C
- */
-
-#define MT6370_REG_INTRST_EN BIT(7)
-
-/* timeout = (tout+1) * 0.2sec */
-#define MT6370_REG_INTRST_SET(en, tout) ((en << 7) | (tout & 0x03))
-
-/*
- * MT6370_REG_WATCHDOG_CTRL 0x9D
- */
-
-#define MT6370_REG_WATCHDOG_EN BIT(7)
-
-/* timeout = (tout+1) * 0.4sec */
-#define MT6370_REG_WATCHDOG_CTRL_SET(en, tout) ((en << 7) | (tout & 0x07))
-
-/*
- * MT6370_REG_I2CRST_CTRL 0x9E
- */
-
-#define MT6370_REG_I2CRST_EN BIT(7)
-
-/* timeout = (tout+1) * 12.5ms */
-#define MT6370_REG_I2CRST_SET(en, tout) ((en << 7) | (tout & 0x0f))
-
-extern const struct tcpm_drv mt6370_tcpm_drv;
-
-/* Enable VCONN discharge. */
-int mt6370_vconn_discharge(int port);
-
-#endif /* __CROS_EC_USB_PD_TCPM_MT6370_H */
diff --git a/driver/tcpm/nct38xx.c b/driver/tcpm/nct38xx.c
deleted file mode 100644
index 9d91c21b30..0000000000
--- a/driver/tcpm/nct38xx.c
+++ /dev/null
@@ -1,384 +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.
- */
-
-/* Type-C port manager for Nuvoton NCT38XX. */
-
-#include "common.h"
-#include "console.h"
-#include "ioexpander_nct38xx.h"
-#include "nct38xx.h"
-#include "tcpci.h"
-
-#if !defined(CONFIG_USB_PD_TCPM_TCPCI)
-#error "NCT38XX is using part of standard TCPCI control"
-#error "Please upgrade your board configuration"
-#endif
-
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-
-#define POLARITY_NORMAL 0
-#define POLARITY_FLIPPED 1
-#define POLARITY_NONE 3
-
-static int cable_polarity[CONFIG_USB_PD_PORT_MAX_COUNT];
-static unsigned char txBuf[33];
-static unsigned char rxBuf[33];
-/* Save the selected rp value */
-static int selected_rp[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-static int nct38xx_tcpm_init(int port)
-{
- int rv = 0;
- int reg;
-
- cable_polarity[port] = POLARITY_NONE;
-
- rv = tcpci_tcpm_init(port);
- if (rv)
- return rv;
-
- /*
- * Write to the CONTROL_OUT_EN register to enable:
- * [6] - CONNDIREN : Connector direction indication output enable
- * [2] - SNKEN : VBUS sink enable output enable
- * [0] - SRCEN : VBUS source voltage enable output enable
- */
- reg = NCT38XX_REG_CTRL_OUT_EN_SRCEN |
- NCT38XX_REG_CTRL_OUT_EN_SNKEN |
- NCT38XX_REG_CTRL_OUT_EN_CONNDIREN;
-
- rv = tcpc_write(port, NCT38XX_REG_CTRL_OUT_EN, reg);
- if (rv)
- return rv;
-
- /* Disable OVP */
- rv = tcpc_read(port, TCPC_REG_FAULT_CTRL, &reg);
- if (rv)
- return rv;
- reg = reg | TCPC_REG_FAULT_CTRL_VBUS_OVP_FAULT_DIS;
- rv = tcpc_write(port, TCPC_REG_FAULT_CTRL, reg);
- if (rv)
- return rv;
-
- /* Enable VBus monitor and Disable FRS */
- rv = tcpc_read(port, TCPC_REG_POWER_CTRL, &reg);
- if (rv)
- return rv;
- reg = reg & ~(TCPC_REG_POWER_CTRL_VBUS_VOL_MONITOR_DIS |
- TCPC_REG_POWER_CTRL_FRS_ENABLE);
- rv = tcpc_write(port, TCPC_REG_POWER_CTRL, reg);
- if (rv)
- return rv;
-
- /* Set FRS direction for SNK detect, if FRS is enabled */
- if (IS_ENABLED(CONFIG_USB_TYPEC_PD_FAST_ROLE_SWAP)) {
- reg = TCPC_REG_DEV_CAP_2_SNK_FR_SWAP;
- rv = tcpc_write(port, TCPC_REG_DEV_CAP_2, reg);
- if (rv)
- return rv;
-
- reg = TCPC_REG_CONFIG_EXT_1_FR_SWAP_SNK_DIR;
- rv = tcpc_write(port, TCPC_REG_CONFIG_EXT_1, reg);
- if (rv)
- return rv;
- }
-
- /* Start VBus monitor */
- rv = tcpc_write(port, TCPC_REG_COMMAND,
- TCPC_REG_COMMAND_ENABLE_VBUS_DETECT);
-
- /*
- * Enable the Vendor Define alert event only when the IO expander
- * feature is defined
- */
- if (IS_ENABLED(CONFIG_IO_EXPANDER_NCT38XX)) {
- int mask;
-
- rv |= tcpc_read16(port, TCPC_REG_ALERT_MASK, &mask);
- mask |= TCPC_REG_ALERT_VENDOR_DEF;
- rv |= tcpc_write16(port, TCPC_REG_ALERT_MASK, mask);
- }
- return rv;
-}
-
-static int tcpci_nct38xx_select_rp_value(int port, int rp)
-{
- selected_rp[port] = rp;
- return EC_SUCCESS;
-}
-
-static int auto_discharge_disconnect(int port, int enable)
-{
- int reg, rv;
-
- rv = tcpc_read(port, TCPC_REG_POWER_CTRL, &reg);
- if (rv)
- return rv;
-
- if (enable)
- reg = reg | TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT;
- else
- reg = reg & ~TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT;
- rv = tcpc_write(port, TCPC_REG_POWER_CTRL, reg);
- return rv;
-
-}
-
-static int tcpci_nct38xx_check_cable_polarity(int port)
-{
- int cc, rv;
-
- /* Try to check the polarity */
- rv = tcpc_read(port, TCPC_REG_CC_STATUS, &cc);
- if (rv)
- return rv;
-
- if (TCPC_REG_CC_STATUS_TERM(cc)) {
- /* TCPC is presenting RD (Sink mode) */
- if ((TCPC_REG_CC_STATUS_CC1(cc) != TYPEC_CC_VOLT_OPEN) &&
- (TCPC_REG_CC_STATUS_CC2(cc) == TYPEC_CC_VOLT_OPEN)) {
- /* CC1 active && CC2 open */
- cable_polarity[port] = POLARITY_NORMAL;
- }
- if ((TCPC_REG_CC_STATUS_CC1(cc) == TYPEC_CC_VOLT_OPEN) &&
- (TCPC_REG_CC_STATUS_CC2(cc) != TYPEC_CC_VOLT_OPEN)) {
- /* CC1 open && CC2 active */
- cable_polarity[port] = POLARITY_FLIPPED;
- }
- } else {
- /* TCPC is presenting RP (Source mode) */
- if ((TCPC_REG_CC_STATUS_CC1(cc) == TYPEC_CC_VOLT_RD) &&
- (TCPC_REG_CC_STATUS_CC2(cc) != TYPEC_CC_VOLT_RD)) {
- /* CC1 active && CC2 open */
- cable_polarity[port] = POLARITY_NORMAL;
- }
- if ((TCPC_REG_CC_STATUS_CC1(cc) != TYPEC_CC_VOLT_RD) &&
- (TCPC_REG_CC_STATUS_CC2(cc) == TYPEC_CC_VOLT_RD)) {
- /* CC1 open && CC2 active */
- cable_polarity[port] = POLARITY_FLIPPED;
- }
- }
- return rv;
-}
-
- /*
- * TODO(crbug.com/951681): This code can be simplified once that bug is fixed.
- */
-static int tcpci_nct38xx_set_cc(int port, int pull)
-{
-
- int rv;
-
- if (cable_polarity[port] == POLARITY_NONE) {
- rv = tcpci_nct38xx_check_cable_polarity(port);
- if (rv)
- return rv;
- }
-
- if (cable_polarity[port] == POLARITY_NORMAL) {
- rv = tcpc_write(port, TCPC_REG_ROLE_CTRL,
- TCPC_REG_ROLE_CTRL_SET(0, selected_rp[port],
- pull, TYPEC_CC_OPEN));
- } else if (cable_polarity[port] == POLARITY_FLIPPED) {
- rv = tcpc_write(port, TCPC_REG_ROLE_CTRL,
- TCPC_REG_ROLE_CTRL_SET(0, selected_rp[port],
- TYPEC_CC_OPEN, pull));
- } else {
- return -1;
- }
-
- return rv;
-}
-
-static int tcpci_nct38xx_get_cc(int port, enum tcpc_cc_voltage_status *cc1,
- enum tcpc_cc_voltage_status *cc2)
-{
- int rv;
- int rc;
-
- rv = tcpc_read(port, TCPC_REG_ROLE_CTRL, &rc);
- if (rv)
- return rv;
-
- rv = tcpci_tcpm_get_cc(port, cc1, cc2);
- if (rv)
- return rv;
-
- if (!TCPC_REG_ROLE_CTRL_DRP(rc)) {
- if ((*cc1 != TYPEC_CC_VOLT_OPEN) &&
- (TCPC_REG_ROLE_CTRL_CC1(rc) == TYPEC_CC_RD))
- *cc1 |= 0x4;
- if ((*cc2 != TYPEC_CC_VOLT_OPEN) &&
- (TCPC_REG_ROLE_CTRL_CC2(rc) == TYPEC_CC_RD))
- *cc2 |= 0x04;
- }
-
- return rv;
-}
-
-int tcpci_nct38xx_drp_toggle(int port)
-{
- int rv;
-
- cable_polarity[port] = POLARITY_NONE;
-
- /*
- * The port was disconnected so it is probably a good place to set
- * auto-discharge-disconnect to '0'
- *
- * TODO(crbug.com/951683: this should be removed when common code adds
- * auto discharge.
- */
- rv = auto_discharge_disconnect(port, 0);
- if (rv)
- return rv;
-
- return tcpci_tcpc_drp_toggle(port);
-
-}
-
-int tcpci_nct38xx_set_polarity(int port, int polarity)
-{
- int rv, reg;
-
- rv = tcpc_read(port, TCPC_REG_TCPC_CTRL, &reg);
- if (rv)
- return rv;
-
- reg = polarity ? (reg | TCPC_REG_TCPC_CTRL_SET(1)) :
- (reg & ~TCPC_REG_TCPC_CTRL_SET(1));
-
- rv = tcpc_write(port, TCPC_REG_TCPC_CTRL, reg);
- if (rv)
- return rv;
-
- /*
- * Polarity is set after connection so it is probably a good time to set
- * auto-discharge-disconnect to '1'
- */
- rv = auto_discharge_disconnect(port, 1);
- return rv;
-}
-
-int tcpci_nct38xx_transmit(int port, enum tcpm_transmit_type type,
- uint16_t header, const uint32_t *data)
-{
- int rv, num_obj_byte;
-
- num_obj_byte = PD_HEADER_CNT(header) * 4;
-
- txBuf[0] = num_obj_byte + 2;
-
- txBuf[1] = (unsigned char)(header & 0xFF);
- txBuf[2] = (unsigned char)((header >> 8) & 0xFF);
-
- if (num_obj_byte) {
- uint32_t *buf_ptr;
-
- buf_ptr = (uint32_t *)&txBuf[3];
- memcpy(buf_ptr, data, num_obj_byte);
- }
-
- /* total write size = size header (1 byte) + message size */
- rv = tcpc_write_block(port, TCPC_REG_TX_BYTE_CNT,
- (const uint8_t *)txBuf, txBuf[0] + 1);
-
- rv = tcpc_write(port, TCPC_REG_TRANSMIT,
- TCPC_REG_TRANSMIT_SET_WITH_RETRY(type));
- return rv;
-}
-
-static int tcpci_nct38xx_get_message_raw(int port, uint32_t *payload, int *head)
-{
- int rv, cnt, num_obj_byte;
-
- rv = tcpc_read(port, TCPC_REG_RX_BYTE_CNT, &cnt);
-
- if (rv != EC_SUCCESS || cnt < 3) {
- rv = EC_ERROR_UNKNOWN;
- goto clear;
- }
-
- rv = tcpc_read_block(port, TCPC_REG_RX_BYTE_CNT, rxBuf, cnt + 1);
- if (rv != EC_SUCCESS)
- goto clear;
-
- *head = *(int *)&rxBuf[2];
- num_obj_byte = PD_HEADER_CNT(*head) * 4;
-
- if (num_obj_byte) {
- uint32_t *buf_ptr;
-
- buf_ptr = (uint32_t *)&rxBuf[4];
- memcpy(payload, buf_ptr, num_obj_byte);
- }
-
-clear:
- /* Read complete, clear RX status alert bit */
- tcpc_write16(port, TCPC_REG_ALERT, TCPC_REG_ALERT_RX_STATUS);
-
- return rv;
-}
-
-static void nct38xx_tcpc_alert(int port)
-{
- int alert, rv;
-
- /*
- * If IO expander feature is defined, read the ALERT register first to
- * keep the status of Vendor Define bit. Otherwise, the status of ALERT
- * register will be cleared after tcpci_tcpc_alert() is executed.
- */
- if (IS_ENABLED(CONFIG_IO_EXPANDER_NCT38XX))
- rv = tcpc_read16(port, TCPC_REG_ALERT, &alert);
-
- /* Process normal TCPC ALERT event and clear status */
- tcpci_tcpc_alert(port);
-
- /*
- * If IO expander feature is defined, check the Vendor Define bit to
- * handle the IOEX IO's interrupt event
- */
- if (IS_ENABLED(CONFIG_IO_EXPANDER_NCT38XX))
- if (!rv && (alert & TCPC_REG_ALERT_VENDOR_DEF))
- nct38xx_ioex_event_handler(port);
-
-}
-const struct tcpm_drv nct38xx_tcpm_drv = {
- .init = &nct38xx_tcpm_init,
- .release = &tcpci_tcpm_release,
- .get_cc = &tcpci_nct38xx_get_cc,
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
- .get_vbus_level = &tcpci_tcpm_get_vbus_level,
-#endif
- .select_rp_value = &tcpci_nct38xx_select_rp_value,
- .set_cc = &tcpci_nct38xx_set_cc,
- .set_polarity = &tcpci_nct38xx_set_polarity,
- .set_vconn = &tcpci_tcpm_set_vconn,
- .set_msg_header = &tcpci_tcpm_set_msg_header,
- .set_rx_enable = &tcpci_tcpm_set_rx_enable,
- .get_message_raw = &tcpci_nct38xx_get_message_raw,
- .transmit = &tcpci_nct38xx_transmit,
- .tcpc_alert = &nct38xx_tcpc_alert,
-#ifdef CONFIG_USB_PD_DISCHARGE_TCPC
- .tcpc_discharge_vbus = &tcpci_tcpc_discharge_vbus,
-#endif
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- .drp_toggle = &tcpci_nct38xx_drp_toggle,
-#endif
-#ifdef CONFIG_USBC_PPC
- .set_snk_ctrl = &tcpci_tcpm_set_snk_ctrl,
- .set_src_ctrl = &tcpci_tcpm_set_src_ctrl,
-#endif
- .get_chip_info = &tcpci_get_chip_info,
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- .enter_low_power_mode = &tcpci_enter_low_power_mode,
-#endif
-#ifdef CONFIG_USB_TYPEC_PD_FAST_ROLE_SWAP
- .set_frs_enable = &tcpci_tcpc_fast_role_swap_enable,
-#endif
-};
diff --git a/driver/tcpm/nct38xx.h b/driver/tcpm/nct38xx.h
deleted file mode 100644
index 970c1c8c85..0000000000
--- a/driver/tcpm/nct38xx.h
+++ /dev/null
@@ -1,68 +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.
- */
-
-/* Nuvoton Type-C port controller */
-
-#ifndef __CROS_EC_USB_PD_TCPM_NCT38XX_H
-#define __CROS_EC_USB_PD_TCPM_NCT38XX_H
-
-/* Chip variant ID (Part number) */
-#define NCT38XX_VARIANT_MASK 0x1C
-#define NCT38XX_VARIANT_3807 0x0
-#define NCT38XX_VARIANT_3808 0x2
-
-/* There are two IO ports in NCT3807 */
-#define NCT38XX_NCT3807_MAX_IO_PORT 2
-/* There is only one IO port in NCT3808 */
-#define NCT38XX_NCT3808_MAX_IO_PORT 1
-
-#define NCT38XX_SUPPORT_GPIO_FLAGS (GPIO_OPEN_DRAIN | GPIO_INPUT | \
- GPIO_OUTPUT | GPIO_LOW | GPIO_HIGH | GPIO_INT_F_RISING | \
- GPIO_INT_F_FALLING | GPIO_INT_F_HIGH | GPIO_INT_F_LOW)
-
-/* I2C interface */
-#define NCT38XX_I2C_ADDR1_1_FLAGS 0x70
-#define NCT38XX_I2C_ADDR1_2_FLAGS 0x71
-#define NCT38XX_I2C_ADDR1_3_FLAGS 0x72
-#define NCT38XX_I2C_ADDR1_4_FLAGS 0x73
-
-#define NCT38XX_I2C_ADDR2_1_FLAGS 0x74
-#define NCT38XX_I2C_ADDR2_2_FLAGS 0x75
-#define NCT38XX_I2C_ADDR2_3_FLAGS 0x76
-#define NCT38XX_I2C_ADDR2_4_FLAGS 0x77
-
-#define NCT38XX_REG_VENDOR_ID_L 0x00
-#define NCT38XX_REG_VENDOR_ID_H 0x01
-#define NCT38XX_VENDOR_ID 0x0416
-
-#define NCT38XX_PRODUCT_ID 0xC301
-
-#define NCT38XX_REG_GPIO_DATA_IN(n) (0xC0 + ((n) * 8))
-#define NCT38XX_REG_GPIO_DATA_OUT(n) (0xC1 + ((n) * 8))
-#define NCT38XX_REG_GPIO_DIR(n) (0xC2 + ((n) * 8))
-#define NCT38XX_REG_GPIO_OD_SEL(n) (0xC3 + ((n) * 8))
-#define NCT38XX_REG_GPIO_ALERT_RISE(n) (0xC4 + ((n) * 8))
-#define NCT38XX_REG_GPIO_ALERT_FALL(n) (0xC5 + ((n) * 8))
-#define NCT38XX_REG_GPIO_ALERT_LEVEL(n) (0xC6 + ((n) * 8))
-#define NCT38XX_REG_GPIO_ALERT_MASK(n) (0xC7 + ((n) * 8))
-#define NCT38XX_REG_MUX_CONTROL 0xD0
-#define NCT38XX_REG_GPIO_ALERT_STAT(n) (0xD4 + (n))
-
-/* NCT3808 only supports GPIO 2/3/4/6/7 */
-#define NCT38XXX_3808_VALID_GPIO_MASK 0xDC
-
-#define NCT38XX_REG_CTRL_OUT_EN 0xD2
-#define NCT38XX_REG_CTRL_OUT_EN_SRCEN (1 << 0)
-#define NCT38XX_REG_CTRL_OUT_EN_FASTEN (1 << 1)
-#define NCT38XX_REG_CTRL_OUT_EN_SNKEN (1 << 2)
-#define NCT38XX_REG_CTRL_OUT_EN_CONNDIREN (1 << 6)
-
-#define NCT38XX_RESET_HOLD_DELAY_MS 1
-#define NCT38XX_RESET_POST_DELAY_MS 0
-
-extern const struct tcpm_drv nct38xx_tcpm_drv;
-
-#endif /* defined(__CROS_EC_USB_PD_TCPM_NCT38XX_H) */
diff --git a/driver/tcpm/ps8xxx.c b/driver/tcpm/ps8xxx.c
deleted file mode 100644
index 81117a5af1..0000000000
--- a/driver/tcpm/ps8xxx.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/* Copyright 2017 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.
- */
-
-/*
- * Type-C port manager for Parade PS8XXX with integrated superspeed muxes.
- *
- * Supported TCPCs:
- * - PS8751
- * - PS8805
- */
-
-#include "common.h"
-#include "ps8xxx.h"
-#include "tcpci.h"
-#include "tcpm.h"
-#include "timer.h"
-#include "usb_pd.h"
-
-#if !defined(CONFIG_USB_PD_TCPM_PS8751) && \
- !defined(CONFIG_USB_PD_TCPM_PS8805)
-#error "Unsupported PS8xxx TCPC."
-#endif
-
-#if !defined(CONFIG_USB_PD_TCPM_TCPCI) || \
- !defined(CONFIG_USB_PD_TCPM_MUX) || \
- !defined(CONFIG_USBC_SS_MUX)
-
-#error "PS8XXX is using a standard TCPCI interface with integrated mux control"
-#error "Please upgrade your board configuration"
-
-#endif
-
-/*
- * timestamp of the next possible toggle to ensure the 2-ms spacing
- * between IRQ_HPD.
- */
-static uint64_t hpd_deadline[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-static int dp_set_hpd(int port, int enable)
-{
- int reg;
- int rv;
-
- rv = mux_read(port, MUX_IN_HPD_ASSERTION_REG, &reg);
- if (rv)
- return rv;
- if (enable)
- reg |= IN_HPD;
- else
- reg &= ~IN_HPD;
- return mux_write(port, MUX_IN_HPD_ASSERTION_REG, reg);
-}
-
-static int dp_set_irq(int port, int enable)
-{
-
- int reg;
- int rv;
-
- rv = mux_read(port, MUX_IN_HPD_ASSERTION_REG, &reg);
- if (rv)
- return rv;
- if (enable)
- reg |= HPD_IRQ;
- else
- reg &= ~HPD_IRQ;
- return mux_write(port, MUX_IN_HPD_ASSERTION_REG, reg);
-}
-
-void ps8xxx_tcpc_update_hpd_status(int port, int hpd_lvl, int hpd_irq)
-{
- dp_set_hpd(port, hpd_lvl);
-
- if (hpd_irq) {
- uint64_t now = get_time().val;
- /* wait for the minimum spacing between IRQ_HPD if needed */
- if (now < hpd_deadline[port])
- usleep(hpd_deadline[port] - now);
-
- dp_set_irq(port, 0);
- usleep(HPD_DSTREAM_DEBOUNCE_IRQ);
- dp_set_irq(port, hpd_irq);
- }
- /* enforce 2-ms delay between HPD pulses */
- hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL;
-}
-
-static int ps8xxx_tcpc_bist_mode_2(int port)
-{
- int rv;
-
- /* Generate BIST for 50ms. */
- rv = tcpc_write(port,
- PS8XXX_REG_BIST_CONT_MODE_BYTE0, PS8751_BIST_COUNTER_BYTE0);
- rv |= tcpc_write(port,
- PS8XXX_REG_BIST_CONT_MODE_BYTE1, PS8751_BIST_COUNTER_BYTE1);
- rv |= tcpc_write(port,
- PS8XXX_REG_BIST_CONT_MODE_BYTE2, PS8751_BIST_COUNTER_BYTE2);
-
- /* Auto stop */
- rv |= tcpc_write(port, PS8XXX_REG_BIST_CONT_MODE_CTR, 0);
-
- /* Start BIST MODE 2 */
- rv |= tcpc_write(port, TCPC_REG_TRANSMIT, TCPC_TX_BIST_MODE_2);
-
- return rv;
-}
-
-static int ps8xxx_tcpm_transmit(int port, enum tcpm_transmit_type type,
- uint16_t header, const uint32_t *data)
-{
- if (type == TCPC_TX_BIST_MODE_2)
- return ps8xxx_tcpc_bist_mode_2(port);
- else
- return tcpci_tcpm_transmit(port, type, header, data);
-}
-
-static int ps8xxx_tcpm_release(int port)
-{
- int version;
- int status;
-
- status = tcpc_read(port, FW_VER_REG, &version);
- if (status != 0) {
- /* wait for chip to wake up */
- msleep(10);
- }
-
- return tcpci_tcpm_release(port);
-}
-
-static int ps8xxx_get_chip_info(int port, int live,
- struct ec_response_pd_chip_info_v1 **chip_info)
-{
- int val;
- int rv = tcpci_get_chip_info(port, live, chip_info);
-
- if (rv)
- return rv;
-
- if (!live) {
- (*chip_info)->vendor_id = PS8XXX_VENDOR_ID;
- (*chip_info)->product_id = PS8XXX_PRODUCT_ID;
- }
-
- if ((*chip_info)->fw_version_number == 0 ||
- (*chip_info)->fw_version_number == -1 || live) {
- rv = tcpc_read(port, FW_VER_REG, &val);
-
- if (rv)
- return rv;
-
- (*chip_info)->fw_version_number = val;
- }
-
-#if defined(CONFIG_USB_PD_TCPM_PS8751) && \
- defined(CONFIG_USB_PD_VBUS_DETECT_TCPC)
- /*
- * Min firmware version of PS8751 to ensure that it can detect Vbus
- * properly. See b/109769787#comment7
- */
- (*chip_info)->min_req_fw_version_number = 0x39;
-#endif
-
- return rv;
-}
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
-static int ps8xxx_enter_low_power_mode(int port)
-{
- return EC_SUCCESS;
-}
-#endif
-
-/*
- * DCI is enabled by default and burns about 40 mW when the port is in
- * USB2 mode or when a C-to-A dongle is attached, so force it off.
- */
-
-static int ps8xxx_addr_dci_disable(int port, int i2c_addr, int i2c_reg)
-{
- int status;
- int dci;
-
- status = tcpc_addr_read(port, i2c_addr, i2c_reg, &dci);
- if (status != EC_SUCCESS)
- return status;
- if ((dci & PS8XXX_REG_MUX_USB_DCI_CFG_MODE_MASK) !=
- PS8XXX_REG_MUX_USB_DCI_CFG_MODE_OFF) {
- dci &= ~PS8XXX_REG_MUX_USB_DCI_CFG_MODE_MASK;
- dci |= PS8XXX_REG_MUX_USB_DCI_CFG_MODE_OFF;
- if (tcpc_addr_write(port, i2c_addr, i2c_reg, dci) != EC_SUCCESS)
- return status;
- }
- return EC_SUCCESS;
-}
-
-#ifdef CONFIG_USB_PD_TCPM_PS8805
-static int ps8xxx_dci_disable(int port)
-{
- int status, e;
- int p1_addr;
-
- status = tcpc_write(port, PS8XXX_REG_I2C_DEBUGGING_ENABLE,
- PS8XXX_REG_I2C_DEBUGGING_ENABLE_ON);
- if (status != EC_SUCCESS)
- return status;
-
- p1_addr = tcpc_config[port].i2c_info.addr_flags -
- (PS8751_I2C_ADDR1_FLAGS - PS8751_I2C_ADDR1_P1_FLAGS);
- status = ps8xxx_addr_dci_disable(port, p1_addr,
- PS8805_P1_REG_MUX_USB_DCI_CFG);
-
- e = tcpc_write(port, PS8XXX_REG_I2C_DEBUGGING_ENABLE,
- PS8XXX_REG_I2C_DEBUGGING_ENABLE_OFF);
- if (e != EC_SUCCESS) {
- if (status == EC_SUCCESS)
- status = e;
- }
-
- return status;
-}
-#endif /* CONFIG_USB_PD_TCPM_PS8805 */
-
-#ifdef CONFIG_USB_PD_TCPM_PS8751
-static int ps8xxx_dci_disable(int port)
-{
- int p3_addr;
-
- p3_addr = tcpc_config[port].i2c_info.addr_flags;
- return ps8xxx_addr_dci_disable(port, p3_addr,
- PS8751_REG_MUX_USB_DCI_CFG);
-}
-#endif /* CONFIG_USB_PD_TCPM_PS8751 */
-
-static int ps8xxx_tcpm_init(int port)
-{
- int status;
-
- status = tcpci_tcpm_init(port);
- if (status != EC_SUCCESS)
- return status;
-
- return ps8xxx_dci_disable(port);
-}
-
-const struct tcpm_drv ps8xxx_tcpm_drv = {
- .init = &ps8xxx_tcpm_init,
- .release = &ps8xxx_tcpm_release,
- .get_cc = &tcpci_tcpm_get_cc,
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
- .get_vbus_level = &tcpci_tcpm_get_vbus_level,
-#endif
- .select_rp_value = &tcpci_tcpm_select_rp_value,
- .set_cc = &tcpci_tcpm_set_cc,
- .set_polarity = &tcpci_tcpm_set_polarity,
- .set_vconn = &tcpci_tcpm_set_vconn,
- .set_msg_header = &tcpci_tcpm_set_msg_header,
- .set_rx_enable = &tcpci_tcpm_set_rx_enable,
- .get_message_raw = &tcpci_tcpm_get_message_raw,
- .transmit = &ps8xxx_tcpm_transmit,
- .tcpc_alert = &tcpci_tcpc_alert,
-#ifdef CONFIG_USB_PD_DISCHARGE_TCPC
- .tcpc_discharge_vbus = &tcpci_tcpc_discharge_vbus,
-#endif
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- .drp_toggle = &tcpci_tcpc_drp_toggle,
-#endif
-#ifdef CONFIG_USBC_PPC
- .set_snk_ctrl = &tcpci_tcpm_set_snk_ctrl,
- .set_src_ctrl = &tcpci_tcpm_set_src_ctrl,
-#endif
- .get_chip_info = &ps8xxx_get_chip_info,
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- .enter_low_power_mode = &ps8xxx_enter_low_power_mode,
-#endif
-};
-
-#ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC
-struct i2c_stress_test_dev ps8xxx_i2c_stress_test_dev = {
- .reg_info = {
- .read_reg = PS8XXX_REG_VENDOR_ID_L,
- .read_val = PS8XXX_VENDOR_ID & 0xFF,
- .write_reg = MUX_IN_HPD_ASSERTION_REG,
- },
- .i2c_read = &tcpc_i2c_read,
- .i2c_write = &tcpc_i2c_write,
-};
-#endif /* CONFIG_CMD_I2C_STRESS_TEST_TCPC */
-
-static int ps8xxx_mux_init(int port)
-{
- tcpci_tcpm_mux_init(port);
-
- /* If this MUX is also the TCPC, then skip init */
- if (!(usb_muxes[port].flags & USB_MUX_FLAG_NOT_TCPC))
- return EC_SUCCESS;
-
- /* We always want to be a sink when this device is only being used as a mux
- * to support external peripherals better.
- */
- return mux_write(port, TCPC_REG_ROLE_CTRL,
- TCPC_REG_ROLE_CTRL_SET(0, 1, TYPEC_CC_RD, TYPEC_CC_RD));
-}
-
-static int ps8xxx_mux_enter_low_power_mode(int port)
-{
- mux_write(port, TCPC_REG_ROLE_CTRL,
- TCPC_REG_ROLE_CTRL_SET(0, 0, TYPEC_CC_RP, TYPEC_CC_RP));
- return tcpci_tcpm_mux_enter_low_power(port);
-}
-
-/* This is meant for mux-only applications */
-const struct usb_mux_driver ps8xxx_usb_mux_driver = {
- .init = &ps8xxx_mux_init,
- .set = &tcpci_tcpm_mux_set,
- .get = &tcpci_tcpm_mux_get,
- .enter_low_power_mode = &ps8xxx_mux_enter_low_power_mode,
-};
diff --git a/driver/tcpm/ps8xxx.h b/driver/tcpm/ps8xxx.h
deleted file mode 100644
index e2927c8531..0000000000
--- a/driver/tcpm/ps8xxx.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* Copyright 2017 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.
- */
-
-/* Parade Tech Type-C port controller */
-
-#ifndef __CROS_EC_USB_PD_TCPM_PS8XXX_H
-#define __CROS_EC_USB_PD_TCPM_PS8XXX_H
-
-/* I2C interface */
-#define PS8751_I2C_ADDR1_P1_FLAGS 0x09
-#define PS8751_I2C_ADDR1_FLAGS 0x0B
-#define PS8751_I2C_ADDR2_FLAGS 0x1B
-#define PS8751_I2C_ADDR3_FLAGS 0x2B
-#define PS8751_I2C_ADDR4_FLAGS 0x4B
-
-/* Minimum Delay for reset assertion */
-#define PS8XXX_RESET_DELAY_MS 1
-
-#define PS8751_BIST_TIMER_FREQ 15000000
-#define PS8751_BIST_DELAY_MS 50
-
-#define PS8751_BIST_COUNTER (PS8751_BIST_TIMER_FREQ / MSEC \
- * PS8751_BIST_DELAY_MS)
-
-#define PS8751_BIST_COUNTER_BYTE0 (PS8751_BIST_COUNTER & 0xff)
-#define PS8751_BIST_COUNTER_BYTE1 ((PS8751_BIST_COUNTER >> 8) & 0xff)
-#define PS8751_BIST_COUNTER_BYTE2 ((PS8751_BIST_COUNTER >> 16) & 0xff)
-
-#define PS8XXX_VENDOR_ID 0x1DA0
-#define PS8XXX_REG_I2C_DEBUGGING_ENABLE 0xA0
-#define PS8XXX_REG_I2C_DEBUGGING_ENABLE_ON 0x30
-#define PS8XXX_REG_I2C_DEBUGGING_ENABLE_OFF 0x31 /* default */
-#define PS8XXX_REG_BIST_CONT_MODE_BYTE0 0xBC
-#define PS8XXX_REG_BIST_CONT_MODE_BYTE1 0xBD
-#define PS8XXX_REG_BIST_CONT_MODE_BYTE2 0xBE
-#define PS8XXX_REG_BIST_CONT_MODE_CTR 0xBF
-#define PS8XXX_REG_DET_CTRL0 0x08
-
-#define PS8XXX_REG_MUX_USB_DCI_CFG_MODE_MASK 0xC0
-#define PS8XXX_REG_MUX_USB_DCI_CFG_MODE_OFF 0x80
-
-#if defined(CONFIG_USB_PD_TCPM_PS8751)
-/* Vendor defined registers */
-#define PS8XXX_PRODUCT_ID 0x8751
-
-#define FW_VER_REG 0x90
-#define PS8XXX_REG_VENDOR_ID_L 0x00
-#define PS8XXX_REG_VENDOR_ID_H 0x01
-#define MUX_IN_HPD_ASSERTION_REG 0xD0
-#define IN_HPD BIT(0)
-#define HPD_IRQ BIT(1)
-#define PS8XXX_REG_MUX_DP_EQ_CONFIGURATION 0xD3
-#define PS8XXX_REG_MUX_DP_OUTPUT_CONFIGURATION 0xD4
-#define PS8XXX_REG_MUX_USB_C2SS_EQ 0xE7
-#define PS8XXX_REG_MUX_USB_C2SS_HS_THRESHOLD 0xE8
-#define PS8751_REG_MUX_USB_DCI_CFG 0xED
-
-#elif defined(CONFIG_USB_PD_TCPM_PS8805)
-/* Vendor defined registers */
-#define PS8XXX_PRODUCT_ID 0x8805
-
-#define PS8805_P1_REG_MUX_USB_DCI_CFG 0x4B
-#define FW_VER_REG 0x82
-#define MUX_IN_HPD_ASSERTION_REG 0xD0
-#define IN_HPD BIT(0)
-#define HPD_IRQ BIT(1)
-
-#endif
-
-extern const struct tcpm_drv ps8xxx_tcpm_drv;
-void ps8xxx_tcpc_update_hpd_status(int port, int hpd_lvl, int hpd_irq);
-
-#ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC
-extern struct i2c_stress_test_dev ps8xxx_i2c_stress_test_dev;
-#endif /* defined(CONFIG_CMD_I2C_STRESS_TEST_TCPC) */
-
-extern const struct usb_mux_driver ps8xxx_usb_mux_driver;
-
-#endif /* defined(__CROS_EC_USB_PD_TCPM_PS8XXX_H) */
diff --git a/driver/tcpm/stub.c b/driver/tcpm/stub.c
deleted file mode 100644
index 0ebe8af999..0000000000
--- a/driver/tcpm/stub.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/* Copyright 2015 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.
- */
-
-/* TCPM for MCU also running TCPC */
-
-#include "task.h"
-#include "tcpci.h"
-#include "tcpm.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpc.h"
-#include "usb_pd_tcpm.h"
-
-static int init_alert_mask(int port)
-{
- uint16_t mask;
- int rv;
-
- /*
- * Create mask of alert events that will cause the TCPC to
- * signal the TCPM via the Alert# gpio line.
- */
- mask = TCPC_REG_ALERT_TX_SUCCESS | TCPC_REG_ALERT_TX_FAILED |
- TCPC_REG_ALERT_TX_DISCARDED | TCPC_REG_ALERT_RX_STATUS |
- TCPC_REG_ALERT_RX_HARD_RST | TCPC_REG_ALERT_CC_STATUS;
- /* Set the alert mask in TCPC */
- rv = tcpc_alert_mask_set(port, mask);
-
- return rv;
-}
-
-static int init_power_status_mask(int port)
-{
- return tcpc_set_power_status_mask(port, 0);
-}
-
-int tcpm_init(int port)
-{
- int rv;
-
- tcpc_init(port);
- rv = init_alert_mask(port);
- if (rv)
- return rv;
-
- return init_power_status_mask(port);
-}
-
-int tcpm_get_cc(int port, enum tcpc_cc_voltage_status *cc1,
- enum tcpc_cc_voltage_status *cc2)
-{
- return tcpc_get_cc(port, cc1, cc2);
-}
-
-int tcpm_select_rp_value(int port, int rp)
-{
- return tcpc_select_rp_value(port, rp);
-}
-
-int tcpm_set_cc(int port, int pull)
-{
- return tcpc_set_cc(port, pull);
-}
-
-int tcpm_set_polarity(int port, int polarity)
-{
- return tcpc_set_polarity(port, polarity);
-}
-
-int tcpm_set_vconn(int port, int enable)
-{
- return tcpc_set_vconn(port, enable);
-}
-
-int tcpm_set_msg_header(int port, int power_role, int data_role)
-{
- return tcpc_set_msg_header(port, power_role, data_role);
-}
-
-static int tcpm_alert_status(int port, int *alert)
-{
- /* Read TCPC Alert register */
- return tcpc_alert_status(port, alert);
-}
-
-int tcpm_set_rx_enable(int port, int enable)
-{
- return tcpc_set_rx_enable(port, enable);
-}
-
-int tcpm_has_pending_message(int port)
-{
- return !rx_buf_is_empty(port);
-}
-
-int tcpm_dequeue_message(int port, uint32_t *payload, int *head)
-{
- int ret = tcpc_get_message(port, payload, head);
-
- /* Read complete, clear RX status alert bit */
- tcpc_alert_status_clear(port, TCPC_REG_ALERT_RX_STATUS);
-
- return ret;
-}
-
-void tcpm_clear_pending_messages(int port)
-{
- rx_buf_clear(port);
-}
-
-int tcpm_transmit(int port, enum tcpm_transmit_type type, uint16_t header,
- const uint32_t *data)
-{
- return tcpc_transmit(port, type, header, data);
-}
-
-void tcpc_alert(int port)
-{
- int status;
-
- /* Read the Alert register from the TCPC */
- tcpm_alert_status(port, &status);
-
- /*
- * Clear alert status for everything except RX_STATUS, which shouldn't
- * be cleared until we have successfully retrieved message.
- */
- if (status & ~TCPC_REG_ALERT_RX_STATUS)
- tcpc_alert_status_clear(port,
- status & ~TCPC_REG_ALERT_RX_STATUS);
-
- if (status & TCPC_REG_ALERT_CC_STATUS) {
- /* CC status changed, wake task */
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC, 0);
- }
- if (status & TCPC_REG_ALERT_RX_STATUS) {
- /*
- * message received. since TCPC is compiled in, we
- * already woke the PD task up from the phy layer via
- * pd_rx_event(), so we don't need to wake it again.
- */
- }
- if (status & TCPC_REG_ALERT_RX_HARD_RST) {
- /* hard reset received */
- pd_execute_hard_reset(port);
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
- if (status & TCPC_REG_ALERT_TX_COMPLETE) {
- /* transmit complete */
- pd_transmit_complete(port, status & TCPC_REG_ALERT_TX_SUCCESS ?
- TCPC_TX_COMPLETE_SUCCESS :
- TCPC_TX_COMPLETE_FAILED);
- }
-}
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c
deleted file mode 100644
index 001a7ee579..0000000000
--- a/driver/tcpm/tcpci.c
+++ /dev/null
@@ -1,1014 +0,0 @@
-/* Copyright 2015 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.
- */
-
-/* Type-C port manager */
-
-#include "atomic.h"
-#include "anx74xx.h"
-#include "compile_time_macros.h"
-#include "console.h"
-#include "ec_commands.h"
-#include "ps8xxx.h"
-#include "task.h"
-#include "tcpci.h"
-#include "tcpm.h"
-#include "timer.h"
-#include "usb_charge.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpc.h"
-#include "util.h"
-
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-
-#ifdef CONFIG_USB_PD_DECODE_SOP
-static int vconn_en[CONFIG_USB_PD_PORT_MAX_COUNT];
-static int rx_en[CONFIG_USB_PD_PORT_MAX_COUNT];
-#endif
-static int tcpc_vbus[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Save the selected rp value */
-static int selected_rp[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
-int tcpc_addr_write(int port, int i2c_addr, int reg, int val)
-{
- int rv;
-
- pd_wait_exit_low_power(port);
-
- rv = i2c_write8(tcpc_config[port].i2c_info.port,
- i2c_addr, reg, val);
-
- pd_device_accessed(port);
- return rv;
-}
-
-int tcpc_write16(int port, int reg, int val)
-{
- int rv;
-
- pd_wait_exit_low_power(port);
-
- rv = i2c_write16(tcpc_config[port].i2c_info.port,
- tcpc_config[port].i2c_info.addr_flags,
- reg, val);
-
- pd_device_accessed(port);
- return rv;
-}
-
-int tcpc_addr_read(int port, int i2c_addr, int reg, int *val)
-{
- int rv;
-
- pd_wait_exit_low_power(port);
-
- rv = i2c_read8(tcpc_config[port].i2c_info.port,
- i2c_addr, reg, val);
-
- pd_device_accessed(port);
- return rv;
-}
-
-int tcpc_read16(int port, int reg, int *val)
-{
- int rv;
-
- pd_wait_exit_low_power(port);
-
- rv = i2c_read16(tcpc_config[port].i2c_info.port,
- tcpc_config[port].i2c_info.addr_flags,
- reg, val);
-
- pd_device_accessed(port);
- return rv;
-}
-
-int tcpc_read_block(int port, int reg, uint8_t *in, int size)
-{
- int rv;
-
- pd_wait_exit_low_power(port);
-
- rv = i2c_read_block(tcpc_config[port].i2c_info.port,
- tcpc_config[port].i2c_info.addr_flags,
- reg, in, size);
-
- pd_device_accessed(port);
- return rv;
-}
-
-int tcpc_write_block(int port, int reg, const uint8_t *out, int size)
-{
- int rv;
-
- pd_wait_exit_low_power(port);
-
- rv = i2c_write_block(tcpc_config[port].i2c_info.port,
- tcpc_config[port].i2c_info.addr_flags,
- reg, out, size);
-
- pd_device_accessed(port);
- return rv;
-}
-
-int tcpc_xfer(int port, const uint8_t *out, int out_size,
- uint8_t *in, int in_size)
-{
- int rv;
- /* Dispatching to tcpc_xfer_unlocked reduces code size growth. */
- tcpc_lock(port, 1);
- rv = tcpc_xfer_unlocked(port, out, out_size, in, in_size,
- I2C_XFER_SINGLE);
- tcpc_lock(port, 0);
- return rv;
-}
-
-int tcpc_xfer_unlocked(int port, const uint8_t *out, int out_size,
- uint8_t *in, int in_size, int flags)
-{
- int rv;
-
- pd_wait_exit_low_power(port);
-
- rv = i2c_xfer_unlocked(tcpc_config[port].i2c_info.port,
- tcpc_config[port].i2c_info.addr_flags,
- out, out_size, in, in_size, flags);
-
- pd_device_accessed(port);
- return rv;
-}
-#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */
-
-static int init_alert_mask(int port)
-{
- int rv;
- uint16_t mask;
-
- /*
- * Create mask of alert events that will cause the TCPC to
- * signal the TCPM via the Alert# gpio line.
- */
- mask = TCPC_REG_ALERT_TX_SUCCESS | TCPC_REG_ALERT_TX_FAILED |
- TCPC_REG_ALERT_TX_DISCARDED | TCPC_REG_ALERT_RX_STATUS |
- TCPC_REG_ALERT_RX_HARD_RST | TCPC_REG_ALERT_CC_STATUS
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
- | TCPC_REG_ALERT_POWER_STATUS
-#endif
- ;
- /* Set the alert mask in TCPC */
- rv = tcpc_write16(port, TCPC_REG_ALERT_MASK, mask);
-
- if (IS_ENABLED(CONFIG_USB_TYPEC_PD_FAST_ROLE_SWAP)) {
- if (rv)
- return rv;
-
- /* Sink FRS allowed */
- mask = TCPC_REG_ALERT_EXT_SNK_FRS;
- rv = tcpc_write(port, TCPC_REG_ALERT_EXT, mask);
- }
- return rv;
-}
-
-static int clear_alert_mask(int port)
-{
- return tcpc_write16(port, TCPC_REG_ALERT_MASK, 0);
-}
-
-static int init_power_status_mask(int port)
-{
- uint8_t mask;
- int rv;
-
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
- mask = TCPC_REG_POWER_STATUS_VBUS_PRES;
-#else
- mask = 0;
-#endif
- rv = tcpc_write(port, TCPC_REG_POWER_STATUS_MASK , mask);
-
- return rv;
-}
-
-static int clear_power_status_mask(int port)
-{
- return tcpc_write(port, TCPC_REG_POWER_STATUS_MASK, 0);
-}
-
-int tcpci_tcpm_get_cc(int port, enum tcpc_cc_voltage_status *cc1,
- enum tcpc_cc_voltage_status *cc2)
-{
- int status;
- int rv;
-
- rv = tcpc_read(port, TCPC_REG_CC_STATUS, &status);
-
- /* If tcpc read fails, return error and CC as open */
- if (rv) {
- *cc1 = TYPEC_CC_VOLT_OPEN;
- *cc2 = TYPEC_CC_VOLT_OPEN;
- return rv;
- }
-
- *cc1 = TCPC_REG_CC_STATUS_CC1(status);
- *cc2 = TCPC_REG_CC_STATUS_CC2(status);
-
- /*
- * If status is not open, then OR in termination to convert to
- * enum tcpc_cc_voltage_status.
- */
- if (*cc1 != TYPEC_CC_VOLT_OPEN)
- *cc1 |= TCPC_REG_CC_STATUS_TERM(status) << 2;
- if (*cc2 != TYPEC_CC_VOLT_OPEN)
- *cc2 |= TCPC_REG_CC_STATUS_TERM(status) << 2;
-
- return rv;
-}
-
-static int tcpci_tcpm_get_power_status(int port, int *status)
-{
- return tcpc_read(port, TCPC_REG_POWER_STATUS, status);
-}
-
-int tcpci_tcpm_select_rp_value(int port, int rp)
-{
- selected_rp[port] = rp;
- return EC_SUCCESS;
-}
-
-#ifdef CONFIG_USB_PD_DISCHARGE_TCPC
-void tcpci_tcpc_discharge_vbus(int port, int enable)
-{
- int reg;
-
- if (tcpc_read(port, TCPC_REG_POWER_CTRL, &reg))
- return;
-
- if (enable)
- reg |= TCPC_REG_POWER_CTRL_FORCE_DISCHARGE;
- else
- reg &= ~TCPC_REG_POWER_CTRL_FORCE_DISCHARGE;
-
- tcpc_write(port, TCPC_REG_POWER_CTRL, reg);
-}
-#endif
-
-static int set_role_ctrl(int port, int toggle, int rp, int pull)
-{
- return tcpc_write(port, TCPC_REG_ROLE_CTRL,
- TCPC_REG_ROLE_CTRL_SET(toggle, rp, pull, pull));
-}
-
-int tcpci_tcpm_set_cc(int port, int pull)
-{
- /* Set manual control, and set both CC lines to the same pull */
- return set_role_ctrl(port, 0, selected_rp[port], pull);
-}
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
-int tcpci_tcpc_drp_toggle(int port)
-{
- int rv;
-
- /* Set auto drp toggle */
- rv = set_role_ctrl(port, 1, TYPEC_RP_USB, TYPEC_CC_RD);
-
- /* Set Look4Connection command */
- rv |= tcpc_write(port, TCPC_REG_COMMAND,
- TCPC_REG_COMMAND_LOOK4CONNECTION);
-
- return rv;
-}
-#endif
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
-int tcpci_enter_low_power_mode(int port)
-{
- return tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_I2CIDLE);
-}
-#endif
-
-int tcpci_tcpm_set_polarity(int port, int polarity)
-{
- return tcpc_write(port, TCPC_REG_TCPC_CTRL,
- TCPC_REG_TCPC_CTRL_SET(polarity));
-}
-
-#ifdef CONFIG_USBC_PPC
-int tcpci_tcpm_set_snk_ctrl(int port, int enable)
-{
- int cmd = enable ? TCPC_REG_COMMAND_SNK_CTRL_HIGH :
- TCPC_REG_COMMAND_SNK_CTRL_LOW;
-
- return tcpc_write(port, TCPC_REG_COMMAND, cmd);
-}
-
-int tcpci_tcpm_set_src_ctrl(int port, int enable)
-{
- int cmd = enable ? TCPC_REG_COMMAND_SRC_CTRL_HIGH :
- TCPC_REG_COMMAND_SRC_CTRL_LOW;
-
- return tcpc_write(port, TCPC_REG_COMMAND, cmd);
-}
-#endif
-
-int tcpci_tcpm_set_vconn(int port, int enable)
-{
- int reg, rv;
-
- rv = tcpc_read(port, TCPC_REG_POWER_CTRL, &reg);
- if (rv)
- return rv;
-
-#ifdef CONFIG_USB_PD_DECODE_SOP
- /* save vconn */
- vconn_en[port] = enable;
-
- if (rx_en[port]) {
- int detect_sop_en = TCPC_REG_RX_DETECT_SOP_HRST_MASK;
-
- if (enable) {
- detect_sop_en =
- TCPC_REG_RX_DETECT_SOP_SOPP_SOPPP_HRST_MASK;
- }
-
- tcpc_write(port, TCPC_REG_RX_DETECT, detect_sop_en);
- }
-#endif
- reg &= ~TCPC_REG_POWER_CTRL_VCONN(1);
- reg |= TCPC_REG_POWER_CTRL_VCONN(enable);
- return tcpc_write(port, TCPC_REG_POWER_CTRL, reg);
-}
-
-int tcpci_tcpm_set_msg_header(int port, int power_role, int data_role)
-{
- return tcpc_write(port, TCPC_REG_MSG_HDR_INFO,
- TCPC_REG_MSG_HDR_INFO_SET(data_role, power_role));
-}
-
-static int tcpm_alert_status(int port, int *alert)
-{
- /* Read TCPC Alert register */
- return tcpc_read16(port, TCPC_REG_ALERT, alert);
-}
-
-static int tcpm_alert_ext_status(int port, int *alert_ext)
-{
- /* Read TCPC Extended Alert register */
- return tcpc_read(port, TCPC_REG_ALERT_EXT, alert_ext);
-}
-
-int tcpci_tcpm_set_rx_enable(int port, int enable)
-{
- int detect_sop_en = 0;
-
- if (enable) {
- detect_sop_en = TCPC_REG_RX_DETECT_SOP_HRST_MASK;
-
-#ifdef CONFIG_USB_PD_DECODE_SOP
- /* save rx_on */
- rx_en[port] = enable;
-
- /*
- * Only the VCONN Source is allowed to communicate
- * with the Cable Plugs.
- */
-
- if (vconn_en[port])
- detect_sop_en =
- TCPC_REG_RX_DETECT_SOP_SOPP_SOPPP_HRST_MASK;
-#endif
- }
-
- /* If enable, then set RX detect for SOP and HRST */
- return tcpc_write(port, TCPC_REG_RX_DETECT, detect_sop_en);
-}
-
-#ifdef CONFIG_USB_TYPEC_PD_FAST_ROLE_SWAP
-void tcpci_tcpc_fast_role_swap_enable(int port, int enable)
-{
- int reg;
-
- if (tcpc_read(port, TCPC_REG_POWER_CTRL, &reg))
- return;
-
- if (enable)
- reg |= TCPC_REG_POWER_CTRL_FRS_ENABLE;
- else
- reg &= ~TCPC_REG_POWER_CTRL_FRS_ENABLE;
-
- tcpc_write(port, TCPC_REG_POWER_CTRL, reg);
-
- board_tcpc_fast_role_swap_enable(port, enable);
-}
-#endif
-
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
-int tcpci_tcpm_get_vbus_level(int port)
-{
- return tcpc_vbus[port];
-}
-#endif
-
-struct cached_tcpm_message {
- uint32_t header;
- uint32_t payload[7];
-};
-
-int tcpci_tcpm_get_message_raw(int port, uint32_t *payload, int *head)
-{
- int rv, cnt, reg = TCPC_REG_RX_DATA;
-#ifdef CONFIG_USB_PD_DECODE_SOP
- int frm;
-#endif
-
- rv = tcpc_read(port, TCPC_REG_RX_BYTE_CNT, &cnt);
-
- /* RX_BYTE_CNT includes 3 bytes for frame type and header */
- if (rv != EC_SUCCESS || cnt < 3) {
- rv = EC_ERROR_UNKNOWN;
- goto clear;
- }
- cnt -= 3;
- if (cnt > member_size(struct cached_tcpm_message, payload)) {
- rv = EC_ERROR_UNKNOWN;
- goto clear;
- }
-
-#ifdef CONFIG_USB_PD_DECODE_SOP
- rv = tcpc_read(port, TCPC_REG_RX_BUF_FRAME_TYPE, &frm);
- if (rv != EC_SUCCESS) {
- rv = EC_ERROR_UNKNOWN;
- goto clear;
- }
-#endif
-
- rv = tcpc_read16(port, TCPC_REG_RX_HDR, (int *)head);
-
-#ifdef CONFIG_USB_PD_DECODE_SOP
- /* Encode message address in bits 31 to 28 */
- *head &= 0x0000ffff;
- *head |= PD_HEADER_SOP(frm & 7);
-#endif
- if (rv == EC_SUCCESS && cnt > 0) {
- tcpc_read_block(port, reg, (uint8_t *)payload, cnt);
- }
-
-clear:
- /* Read complete, clear RX status alert bit */
- tcpc_write16(port, TCPC_REG_ALERT, TCPC_REG_ALERT_RX_STATUS);
-
- return rv;
-}
-
-/* Cache depth needs to be power of 2 */
-#define CACHE_DEPTH BIT(2)
-#define CACHE_DEPTH_MASK (CACHE_DEPTH - 1)
-
-struct queue {
- /*
- * Head points to the index of the first empty slot to put a new RX
- * message. Must be masked before used in lookup.
- */
- uint32_t head;
- /*
- * Tail points to the index of the first message for the PD task to
- * consume. Must be masked before used in lookup.
- */
- uint32_t tail;
- struct cached_tcpm_message buffer[CACHE_DEPTH];
-};
-static struct queue cached_messages[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Note this method can be called from an interrupt context. */
-int tcpm_enqueue_message(const int port)
-{
- int rv;
- struct queue *const q = &cached_messages[port];
- struct cached_tcpm_message *const head =
- &q->buffer[q->head & CACHE_DEPTH_MASK];
-
- if (q->head - q->tail == CACHE_DEPTH) {
- CPRINTS("C%d RX EC Buffer full!", port);
- return EC_ERROR_OVERFLOW;
- }
-
- /* Blank any old message, just in case. */
- memset(head, 0, sizeof(*head));
- /* Call the raw driver without caching */
- rv = tcpc_config[port].drv->get_message_raw(port, head->payload,
- &head->header);
- if (rv) {
- CPRINTS("C%d: Could not retrieve RX message (%d)", port, rv);
- return rv;
- }
-
- /* Increment atomically to ensure get_message_raw happens-before */
- atomic_add(&q->head, 1);
-
- /* Wake PD task up so it can process incoming RX messages */
- task_set_event(PD_PORT_TO_TASK_ID(port), TASK_EVENT_WAKE, 0);
-
- return EC_SUCCESS;
-}
-
-int tcpm_has_pending_message(const int port)
-{
- const struct queue *const q = &cached_messages[port];
-
- return q->head != q->tail;
-}
-
-int tcpm_dequeue_message(const int port, uint32_t *const payload,
- int *const header)
-{
- struct queue *const q = &cached_messages[port];
- struct cached_tcpm_message *const tail =
- &q->buffer[q->tail & CACHE_DEPTH_MASK];
-
- if (!tcpm_has_pending_message(port)) {
- CPRINTS("C%d No message in RX buffer!", port);
- return EC_ERROR_BUSY;
- }
-
- /* Copy cache data in to parameters */
- *header = tail->header;
- memcpy(payload, tail->payload, sizeof(tail->payload));
-
- /* Increment atomically to ensure memcpy happens-before */
- atomic_add(&q->tail, 1);
-
- return EC_SUCCESS;
-}
-
-void tcpm_clear_pending_messages(int port)
-{
- struct queue *const q = &cached_messages[port];
-
- q->tail = q->head;
-}
-
-int tcpci_tcpm_transmit(int port, enum tcpm_transmit_type type,
- uint16_t header, const uint32_t *data)
-{
- int reg = TCPC_REG_TX_DATA;
- int rv, cnt = 4*PD_HEADER_CNT(header);
-
- /* If not SOP* transmission, just write to the transmit register */
- if (type >= NUM_SOP_STAR_TYPES) {
- /*
- * Per TCPCI spec, do not specify retry (although the TCPC
- * should ignore retry field for these 3 types).
- */
- return tcpc_write(port, TCPC_REG_TRANSMIT,
- TCPC_REG_TRANSMIT_SET_WITHOUT_RETRY(type));
- }
-
- /* TX_BYTE_CNT includes extra bytes for message header */
- rv = tcpc_write(port, TCPC_REG_TX_BYTE_CNT, cnt + sizeof(header));
-
- rv |= tcpc_write16(port, TCPC_REG_TX_HDR, header);
-
- /* If tcpc read fails, return error */
- if (rv)
- return rv;
-
- if (cnt > 0) {
- rv = tcpc_write_block(port, reg, (const uint8_t *)data, cnt);
-
- /* If tcpc read fails, return error */
- if (rv)
- return rv;
- }
-
- /*
- * On receiving a received message on SOP, protocol layer
- * discards the pending SOP messages queued for transmission.
- * But it doesn't do the same for SOP' message. So retry is
- * assigned to 0 to avoid multiple transmission.
- */
- return tcpc_write(port, TCPC_REG_TRANSMIT,
- (type == TCPC_TX_SOP_PRIME) ?
- TCPC_REG_TRANSMIT_SET_WITHOUT_RETRY(type) :
- TCPC_REG_TRANSMIT_SET_WITH_RETRY(type));
-}
-
-#ifndef CONFIG_USB_PD_TCPC_LOW_POWER
-/*
- * Returns true if TCPC has reset based on reading mask registers. Only need to
- * check this if the TCPC low power mode (LPM) code isn't compiled in because
- * LPM will automatically reset the device when the TCPC exits LPM.
- */
-static int register_mask_reset(int port)
-{
- int mask;
-
- mask = 0;
- tcpc_read16(port, TCPC_REG_ALERT_MASK, &mask);
- if (mask == TCPC_REG_ALERT_MASK_ALL)
- return 1;
-
- mask = 0;
- tcpc_read(port, TCPC_REG_POWER_STATUS_MASK, &mask);
- if (mask == TCPC_REG_POWER_STATUS_MASK_ALL)
- return 1;
-
- return 0;
-}
-#endif
-
-/*
- * Don't let the TCPC try to pull from the RX buffer forever. We typical only
- * have 1 or 2 messages waiting.
- */
-#define MAX_ALLOW_FAILED_RX_READS 10
-
-void tcpci_tcpc_alert(int port)
-{
- int status = 0;
- int alert_ext = 0;
- int failed_attempts;
- uint32_t pd_event = 0;
-
- /* Read the Alert register from the TCPC */
- tcpm_alert_status(port, &status);
-
- /* Get Extended Alert register if needed */
- if (status & TCPC_REG_ALERT_ALERT_EXT)
- tcpm_alert_ext_status(port, &alert_ext);
-
- /* Clear any pending faults */
- if (status & TCPC_REG_ALERT_FAULT) {
- int fault;
- int fault_rv;
-
- fault_rv = tcpc_read(port, TCPC_REG_FAULT_STATUS, &fault);
- if (!fault_rv) {
- CPRINTS("C%d FAULT=0x%02X", port, fault);
-
- /* Clear any faults that are set */
- fault_rv = tcpc_write(port,
- TCPC_REG_FAULT_STATUS,
- fault);
- if (fault_rv)
- CPRINTS("C%d Writing FAULT failed, rv=%d",
- port, fault_rv);
- } else {
- CPRINTS("C%d Reading FAULT failed, rv=%d",
- port, fault_rv);
- }
- }
-
- /*
- * Check for TX complete first b/c PD state machine waits on TX
- * completion events. This will send an event to the PD tasks
- * immediately
- */
- if (status & TCPC_REG_ALERT_TX_COMPLETE)
- pd_transmit_complete(port, status & TCPC_REG_ALERT_TX_SUCCESS ?
- TCPC_TX_COMPLETE_SUCCESS :
- TCPC_TX_COMPLETE_FAILED);
-
- /* Pull all RX messages from TCPC into EC memory */
- failed_attempts = 0;
- while (status & TCPC_REG_ALERT_RX_STATUS) {
- if (tcpm_enqueue_message(port))
- ++failed_attempts;
- if (tcpm_alert_status(port, &status))
- ++failed_attempts;
-
- /* Ensure we don't loop endlessly */
- if (failed_attempts >= MAX_ALLOW_FAILED_RX_READS) {
- CPRINTS("C%d Cannot consume RX buffer after %d failed attempts!",
- port, failed_attempts);
- /*
- * The port is in a bad state, we don't want to consume
- * all EC resources so suspend the port for a little
- * while.
- */
- pd_set_suspend(port, 1);
- pd_deferred_resume(port);
- return;
- }
- }
-
- /* Clear all pending alert bits */
- if (status)
- tcpc_write16(port, TCPC_REG_ALERT, status);
-
- if (status & TCPC_REG_ALERT_CC_STATUS) {
- /* CC status changed, wake task */
- pd_event |= PD_EVENT_CC;
- }
- if (status & TCPC_REG_ALERT_POWER_STATUS) {
- int reg = 0;
- /* Read Power Status register */
- tcpci_tcpm_get_power_status(port, &reg);
- /* Update VBUS status */
- tcpc_vbus[port] = reg &
- TCPC_REG_POWER_STATUS_VBUS_PRES ? 1 : 0;
-#if defined(CONFIG_USB_PD_VBUS_DETECT_TCPC) && defined(CONFIG_USB_CHARGER)
- /* Update charge manager with new VBUS state */
- usb_charger_vbus_change(port, tcpc_vbus[port]);
- pd_event |= TASK_EVENT_WAKE;
-#endif /* CONFIG_USB_PD_VBUS_DETECT_TCPC && CONFIG_USB_CHARGER */
- }
- if (status & TCPC_REG_ALERT_RX_HARD_RST) {
- /* hard reset received */
- pd_execute_hard_reset(port);
- pd_event |= TASK_EVENT_WAKE;
- }
-
- if (IS_ENABLED(CONFIG_USB_TYPEC_PD_FAST_ROLE_SWAP)
- && (alert_ext & TCPC_REG_ALERT_EXT_SNK_FRS))
- pd_got_frs_signal(port);
-
-#ifndef CONFIG_USB_PD_TCPC_LOW_POWER
- /*
- * Check registers to see if we can tell that the TCPC has reset. If
- * so, perform a tcpc_init. This only needs to happen for devices that
- * don't support low power mode as the transition from low power mode
- * will automatically reset the device.
- */
- if (register_mask_reset(port))
- pd_event |= PD_EVENT_TCPC_RESET;
-#endif
-
- /*
- * Wait until all possible TCPC accesses in this function are complete
- * prior to setting events and/or waking the pd task. When the PD
- * task is woken and runs (which will happen during I2C transactions in
- * this function), the pd task may put the TCPC into low power mode and
- * the next I2C transaction to the TCPC will cause it to wake again.
- */
- if (pd_event)
- task_set_event(PD_PORT_TO_TASK_ID(port), pd_event, 0);
-}
-
-/*
- * This call will wake up the TCPC if it is in low power mode upon accessing the
- * i2c bus (but the pd state machine should put it back into low power mode).
- *
- * Once it's called, the chip info will be stored in cache, which can be
- * accessed by tcpm_get_chip_info without worrying about chip states.
- */
-int tcpci_get_chip_info(int port, int live,
- struct ec_response_pd_chip_info_v1 **chip_info)
-{
- static struct ec_response_pd_chip_info_v1
- info[CONFIG_USB_PD_PORT_MAX_COUNT];
- struct ec_response_pd_chip_info_v1 *i;
- int error;
- int val;
-
- if (port >= board_get_usb_pd_port_count())
- return EC_ERROR_INVAL;
-
- i = &info[port];
-
- /* If chip_info is NULL, chip info will be stored in cache and can be
- * read later by another call. */
- if (chip_info)
- *chip_info = i;
-
- /* If already cached && live data is not asked, return cached value */
- if (i->vendor_id && !live)
- return EC_SUCCESS;
-
- error = tcpc_read16(port, TCPC_REG_VENDOR_ID, &val);
- if (error)
- return error;
- i->vendor_id = val;
-
- error = tcpc_read16(port, TCPC_REG_PRODUCT_ID, &val);
- if (error)
- return error;
- i->product_id = val;
-
- error = tcpc_read16(port, TCPC_REG_BCD_DEV, &val);
- if (error)
- return error;
- i->device_id = val;
-
- /*
- * This varies chip to chip; more specific driver code is expected to
- * override this value if it can.
- */
- i->fw_version_number = -1;
-
- return EC_SUCCESS;
-}
-
-/*
- * Dissociate from the TCPC.
- */
-
-int tcpci_tcpm_release(int port)
-{
- int error;
-
- error = clear_alert_mask(port);
- if (error)
- return error;
- error = clear_power_status_mask(port);
- if (error)
- return error;
- /* Clear pending interrupts */
- error = tcpc_write16(port, TCPC_REG_ALERT, 0xffff);
- if (error)
- return error;
-
- return EC_SUCCESS;
-}
-
-/*
- * On TCPC i2c failure, make 30 tries (at least 300ms) before giving up
- * in order to allow the TCPC time to boot / reset.
- */
-#define TCPM_INIT_TRIES 30
-
-int tcpci_tcpm_init(int port)
-{
- int error;
- int power_status;
- int tries = TCPM_INIT_TRIES;
-
- if (port >= board_get_usb_pd_port_count())
- return EC_ERROR_INVAL;
-
- while (1) {
- error = tcpc_read(port, TCPC_REG_POWER_STATUS, &power_status);
- /*
- * If read succeeds and the uninitialized bit is clear, then
- * initialization is complete, clear all alert bits and write
- * the initial alert mask.
- */
- if (!error && !(power_status & TCPC_REG_POWER_STATUS_UNINIT))
- break;
- if (--tries <= 0)
- return error ? error : EC_ERROR_TIMEOUT;
- msleep(10);
- }
-
- tcpc_write16(port, TCPC_REG_ALERT, 0xffff);
- /* Initialize power_status_mask */
- init_power_status_mask(port);
- /* Update VBUS status */
- tcpc_vbus[port] = power_status &
- TCPC_REG_POWER_STATUS_VBUS_PRES ? 1 : 0;
-#if defined(CONFIG_USB_PD_VBUS_DETECT_TCPC) && defined(CONFIG_USB_CHARGER)
- /*
- * Set Vbus change now in case the TCPC doesn't send a power status
- * changed interrupt for it later.
- */
- usb_charger_vbus_change(port, tcpc_vbus[port]);
-#endif
- error = init_alert_mask(port);
- if (error)
- return error;
-
- /* Read chip info here when we know the chip is awake. */
- tcpm_get_chip_info(port, 1, NULL);
-
- return EC_SUCCESS;
-}
-
-#ifdef CONFIG_USB_PD_TCPM_MUX
-
-/*
- * When the TCPC/MUX device is only used for the MUX, we need to initialize it
- * via mux init because tcpc_init won't run for the device. This is borrowed
- * from tcpc_init.
- */
-int tcpci_tcpm_mux_init(int port)
-{
- int error;
- int power_status;
- int tries = TCPM_INIT_TRIES;
-
- /* If this MUX is also the TCPC, then skip init */
- if (!(usb_muxes[port].flags & USB_MUX_FLAG_NOT_TCPC))
- return EC_SUCCESS;
-
- /* Wait for the device to exit low power state */
- while (1) {
- error = mux_read(port, TCPC_REG_POWER_STATUS, &power_status);
- /*
- * If read succeeds and the uninitialized bit is clear, then
- * initialization is complete.
- */
- if (!error && !(power_status & TCPC_REG_POWER_STATUS_UNINIT))
- break;
- if (--tries <= 0)
- return error ? error : EC_ERROR_TIMEOUT;
- msleep(10);
- }
-
- /* Turn off all alerts and acknowledge any pending IRQ */
- error = mux_write16(port, TCPC_REG_ALERT_MASK, 0);
- error |= mux_write16(port, TCPC_REG_ALERT, 0xffff);
-
- return error ? EC_ERROR_UNKNOWN : EC_SUCCESS;
-}
-
-int tcpci_tcpm_mux_enter_low_power(int port)
-{
- /* If this MUX is also the TCPC, then skip low power */
- if (!(usb_muxes[port].flags & USB_MUX_FLAG_NOT_TCPC))
- return EC_SUCCESS;
-
- return mux_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_I2CIDLE);
-}
-
-int tcpci_tcpm_mux_set(int port, mux_state_t mux_state)
-{
- int reg = 0;
- int rv;
-
- /* Parameter is port only */
- rv = mux_read(port, TCPC_REG_CONFIG_STD_OUTPUT, &reg);
- if (rv != EC_SUCCESS)
- return rv;
-
- reg &= ~(TCPC_REG_CONFIG_STD_OUTPUT_MUX_MASK |
- TCPC_REG_CONFIG_STD_OUTPUT_CONNECTOR_FLIPPED);
- if (mux_state & MUX_USB_ENABLED)
- reg |= TCPC_REG_CONFIG_STD_OUTPUT_MUX_USB;
- if (mux_state & MUX_DP_ENABLED)
- reg |= TCPC_REG_CONFIG_STD_OUTPUT_MUX_DP;
- if (mux_state & MUX_POLARITY_INVERTED)
- reg |= TCPC_REG_CONFIG_STD_OUTPUT_CONNECTOR_FLIPPED;
-
- /* Parameter is port only */
- return mux_write(port, TCPC_REG_CONFIG_STD_OUTPUT, reg);
-}
-
-/* Reads control register and updates mux_state accordingly */
-int tcpci_tcpm_mux_get(int port, mux_state_t *mux_state)
-{
- int reg = 0;
- int rv;
-
- *mux_state = 0;
-
- /* Parameter is port only */
- rv = mux_read(port, TCPC_REG_CONFIG_STD_OUTPUT, &reg);
-
- if (rv != EC_SUCCESS)
- return rv;
-
- if (reg & TCPC_REG_CONFIG_STD_OUTPUT_MUX_USB)
- *mux_state |= MUX_USB_ENABLED;
- if (reg & TCPC_REG_CONFIG_STD_OUTPUT_MUX_DP)
- *mux_state |= MUX_DP_ENABLED;
- if (reg & TCPC_REG_CONFIG_STD_OUTPUT_CONNECTOR_FLIPPED)
- *mux_state |= MUX_POLARITY_INVERTED;
-
- return EC_SUCCESS;
-}
-
-const struct usb_mux_driver tcpci_tcpm_usb_mux_driver = {
- .init = &tcpci_tcpm_mux_init,
- .set = &tcpci_tcpm_mux_set,
- .get = &tcpci_tcpm_mux_get,
- .enter_low_power_mode = &tcpci_tcpm_mux_enter_low_power,
-};
-
-#endif /* CONFIG_USB_PD_TCPM_MUX */
-
-const struct tcpm_drv tcpci_tcpm_drv = {
- .init = &tcpci_tcpm_init,
- .release = &tcpci_tcpm_release,
- .get_cc = &tcpci_tcpm_get_cc,
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
- .get_vbus_level = &tcpci_tcpm_get_vbus_level,
-#endif
- .select_rp_value = &tcpci_tcpm_select_rp_value,
- .set_cc = &tcpci_tcpm_set_cc,
- .set_polarity = &tcpci_tcpm_set_polarity,
- .set_vconn = &tcpci_tcpm_set_vconn,
- .set_msg_header = &tcpci_tcpm_set_msg_header,
- .set_rx_enable = &tcpci_tcpm_set_rx_enable,
- .get_message_raw = &tcpci_tcpm_get_message_raw,
- .transmit = &tcpci_tcpm_transmit,
- .tcpc_alert = &tcpci_tcpc_alert,
-#ifdef CONFIG_USB_PD_DISCHARGE_TCPC
- .tcpc_discharge_vbus = &tcpci_tcpc_discharge_vbus,
-#endif
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- .drp_toggle = &tcpci_tcpc_drp_toggle,
-#endif
- .get_chip_info = &tcpci_get_chip_info,
-#ifdef CONFIG_USBC_PPC
- .set_snk_ctrl = &tcpci_tcpm_set_snk_ctrl,
- .set_src_ctrl = &tcpci_tcpm_set_src_ctrl,
-#endif
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- .enter_low_power_mode = &tcpci_enter_low_power_mode,
-#endif
-};
diff --git a/driver/tcpm/tcpci.h b/driver/tcpm/tcpci.h
deleted file mode 100644
index 930bfd6d70..0000000000
--- a/driver/tcpm/tcpci.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/* Copyright 2015 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.
- */
-
-/* USB Power delivery port management */
-
-#ifndef __CROS_EC_USB_PD_TCPM_TCPCI_H
-#define __CROS_EC_USB_PD_TCPM_TCPCI_H
-
-#include "tcpm.h"
-#include "usb_mux.h"
-#include "usb_pd_tcpm.h"
-
-#define TCPC_REG_VENDOR_ID 0x0
-#define TCPC_REG_PRODUCT_ID 0x2
-#define TCPC_REG_BCD_DEV 0x4
-#define TCPC_REG_TC_REV 0x6
-#define TCPC_REG_PD_REV 0x8
-#define TCPC_REG_PD_INT_REV 0xa
-
-#define TCPC_REG_ALERT 0x10
-#define TCPC_REG_ALERT_MASK_ALL 0xffff
-#define TCPC_REG_ALERT_VENDOR_DEF BIT(15)
-#define TCPC_REG_ALERT_ALERT_EXT BIT(14)
-#define TCPC_REG_ALERT_VBUS_DISCNCT BIT(11)
-#define TCPC_REG_ALERT_RX_BUF_OVF BIT(10)
-#define TCPC_REG_ALERT_FAULT BIT(9)
-#define TCPC_REG_ALERT_V_ALARM_LO BIT(8)
-#define TCPC_REG_ALERT_V_ALARM_HI BIT(7)
-#define TCPC_REG_ALERT_TX_SUCCESS BIT(6)
-#define TCPC_REG_ALERT_TX_DISCARDED BIT(5)
-#define TCPC_REG_ALERT_TX_FAILED BIT(4)
-#define TCPC_REG_ALERT_RX_HARD_RST BIT(3)
-#define TCPC_REG_ALERT_RX_STATUS BIT(2)
-#define TCPC_REG_ALERT_POWER_STATUS BIT(1)
-#define TCPC_REG_ALERT_CC_STATUS BIT(0)
-#define TCPC_REG_ALERT_TX_COMPLETE (TCPC_REG_ALERT_TX_SUCCESS | \
- TCPC_REG_ALERT_TX_DISCARDED | \
- TCPC_REG_ALERT_TX_FAILED)
-
-#define TCPC_REG_ALERT_MASK 0x12
-#define TCPC_REG_POWER_STATUS_MASK 0x14
-#define TCPC_REG_FAULT_STATUS_MASK 0x15
-
-#define TCPC_REG_CONFIG_STD_OUTPUT 0x18
-#define TCPC_REG_CONFIG_STD_OUTPUT_MUX_MASK (3 << 2)
-#define TCPC_REG_CONFIG_STD_OUTPUT_MUX_NONE (0 << 2)
-#define TCPC_REG_CONFIG_STD_OUTPUT_MUX_USB BIT(2)
-#define TCPC_REG_CONFIG_STD_OUTPUT_MUX_DP (2 << 2)
-#define TCPC_REG_CONFIG_STD_OUTPUT_CONNECTOR_FLIPPED BIT(0)
-
-#define TCPC_REG_TCPC_CTRL 0x19
-#define TCPC_REG_TCPC_CTRL_SET(polarity) (polarity)
-#define TCPC_REG_TCPC_CTRL_POLARITY(reg) ((reg) & 0x1)
-
-#define TCPC_REG_ROLE_CTRL 0x1a
-#define TCPC_REG_ROLE_CTRL_SET(drp, rp, cc1, cc2) \
- ((drp) << 6 | (rp) << 4 | (cc2) << 2 | (cc1))
-#define TCPC_REG_ROLE_CTRL_DRP(reg) (((reg) & 0x40) >> 6)
-#define TCPC_REG_ROLE_CTRL_RP_MASK 0x30
-#define TCPC_REG_ROLE_CTRL_RP(reg) (((reg) & TCPC_REG_ROLE_CTRL_RP_MASK) >> 4)
-#define TCPC_REG_ROLE_CTRL_CC2(reg) (((reg) & 0xc) >> 2)
-#define TCPC_REG_ROLE_CTRL_CC1(reg) ((reg) & 0x3)
-
-#define TCPC_REG_FAULT_CTRL 0x1b
-#define TCPC_REG_FAULT_CTRL_VBUS_OVP_FAULT_DIS BIT(1)
-
-#define TCPC_REG_POWER_CTRL 0x1c
-#define TCPC_REG_POWER_CTRL_FRS_ENABLE BIT(7)
-#define TCPC_REG_POWER_CTRL_VBUS_VOL_MONITOR_DIS BIT(6)
-#define TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT BIT(4)
-#define TCPC_REG_POWER_CTRL_FORCE_DISCHARGE BIT(2)
-#define TCPC_REG_POWER_CTRL_SET(vconn) (vconn)
-#define TCPC_REG_POWER_CTRL_VCONN(reg) ((reg) & 0x1)
-
-#define TCPC_REG_CC_STATUS 0x1d
-#define TCPC_REG_CC_STATUS_LOOK4CONNECTION(reg) ((reg & 0x20) >> 5)
-#define TCPC_REG_CC_STATUS_SET(term, cc1, cc2) \
- ((term) << 4 | ((cc2) & 0x3) << 2 | ((cc1) & 0x3))
-#define TCPC_REG_CC_STATUS_TERM(reg) (((reg) & 0x10) >> 4)
-#define TCPC_REG_CC_STATUS_CC2(reg) (((reg) & 0xc) >> 2)
-#define TCPC_REG_CC_STATUS_CC1(reg) ((reg) & 0x3)
-
-#define TCPC_REG_POWER_STATUS 0x1e
-#define TCPC_REG_POWER_STATUS_MASK_ALL 0xff
-#define TCPC_REG_POWER_STATUS_UNINIT BIT(6)
-#define TCPC_REG_POWER_STATUS_VBUS_DET BIT(3)
-#define TCPC_REG_POWER_STATUS_VBUS_PRES BIT(2)
-
-#define TCPC_REG_FAULT_STATUS 0x1f
-
-#define TCPC_REG_ALERT_EXT 0x21
-#define TCPC_REG_ALERT_EXT_TIMER_EXPIRED BIT(2)
-#define TCPC_REG_ALERT_EXT_SRC_FRS BIT(1)
-#define TCPC_REG_ALERT_EXT_SNK_FRS BIT(0)
-
-#define TCPC_REG_COMMAND 0x23
-#define TCPC_REG_COMMAND_ENABLE_VBUS_DETECT 0x33
-#define TCPC_REG_COMMAND_SNK_CTRL_LOW 0x44
-#define TCPC_REG_COMMAND_SNK_CTRL_HIGH 0x55
-#define TCPC_REG_COMMAND_SRC_CTRL_LOW 0x66
-#define TCPC_REG_COMMAND_SRC_CTRL_HIGH 0x77
-#define TCPC_REG_COMMAND_LOOK4CONNECTION 0x99
-#define TCPC_REG_COMMAND_I2CIDLE 0xFF
-
-#define TCPC_REG_DEV_CAP_1 0x24
-
-#define TCPC_REG_DEV_CAP_2 0x26
-#define TCPC_REG_DEV_CAP_2_SNK_FR_SWAP BIT(9)
-
-#define TCPC_REG_STD_INPUT_CAP 0x28
-#define TCPC_REG_STD_OUTPUT_CAP 0x29
-
-#define TCPC_REG_CONFIG_EXT_1 0x2A
-#define TCPC_REG_CONFIG_EXT_1_FR_SWAP_SNK_DIR BIT(1)
-
-#define TCPC_REG_MSG_HDR_INFO 0x2e
-#define TCPC_REG_MSG_HDR_INFO_SET(drole, prole) \
- ((drole) << 3 | (PD_REV20 << 1) | (prole))
-#define TCPC_REG_MSG_HDR_INFO_DROLE(reg) (((reg) & 0x8) >> 3)
-#define TCPC_REG_MSG_HDR_INFO_PROLE(reg) ((reg) & 0x1)
-
-#define TCPC_REG_RX_DETECT 0x2f
-#define TCPC_REG_RX_DETECT_SOP_HRST_MASK 0x21
-#define TCPC_REG_RX_DETECT_SOP_SOPP_SOPPP_HRST_MASK 0x27
-#define TCPC_REG_RX_BYTE_CNT 0x30
-#define TCPC_REG_RX_BUF_FRAME_TYPE 0x31
-
-#define TCPC_REG_RX_HDR 0x32
-#define TCPC_REG_RX_DATA 0x34 /* through 0x4f */
-
-#define TCPC_REG_TRANSMIT 0x50
-#define TCPC_REG_TRANSMIT_SET_WITH_RETRY(type) \
- (PD_RETRY_COUNT << 4 | (type))
-#define TCPC_REG_TRANSMIT_SET_WITHOUT_RETRY(type) (type)
-#define TCPC_REG_TRANSMIT_RETRY(reg) (((reg) & 0x30) >> 4)
-#define TCPC_REG_TRANSMIT_TYPE(reg) ((reg) & 0x7)
-
-#define TCPC_REG_TX_BYTE_CNT 0x51
-#define TCPC_REG_TX_HDR 0x52
-#define TCPC_REG_TX_DATA 0x54 /* through 0x6f */
-
-#define TCPC_REG_VBUS_VOLTAGE 0x70
-#define TCPC_REG_VBUS_SINK_DISCONNECT_THRESH 0x72
-#define TCPC_REG_VBUS_STOP_DISCHARGE_THRESH 0x74
-#define TCPC_REG_VBUS_VOLTAGE_ALARM_HI_CFG 0x76
-#define TCPC_REG_VBUS_VOLTAGE_ALARM_LO_CFG 0x78
-
-extern const struct tcpm_drv tcpci_tcpm_drv;
-extern const struct usb_mux_driver tcpci_tcpm_usb_mux_driver;
-
-void tcpci_tcpc_alert(int port);
-int tcpci_tcpm_init(int port);
-int tcpci_tcpm_get_cc(int port, enum tcpc_cc_voltage_status *cc1,
- enum tcpc_cc_voltage_status *cc2);
-int tcpci_tcpm_get_vbus_level(int port);
-int tcpci_tcpm_select_rp_value(int port, int rp);
-int tcpci_tcpm_set_cc(int port, int pull);
-int tcpci_tcpm_set_polarity(int port, int polarity);
-int tcpci_tcpm_set_vconn(int port, int enable);
-int tcpci_tcpm_set_msg_header(int port, int power_role, int data_role);
-int tcpci_tcpm_set_rx_enable(int port, int enable);
-int tcpci_tcpm_get_message_raw(int port, uint32_t *payload, int *head);
-int tcpci_tcpm_transmit(int port, enum tcpm_transmit_type type,
- uint16_t header, const uint32_t *data);
-int tcpci_tcpm_release(int port);
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
-int tcpci_tcpc_drp_toggle(int port);
-#endif
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
-int tcpci_enter_low_power_mode(int port);
-#endif
-#ifdef CONFIG_USB_PD_DISCHARGE_TCPC
-void tcpci_tcpc_discharge_vbus(int port, int enable);
-#endif
-
-int tcpci_tcpm_mux_init(int i2c_addr);
-int tcpci_tcpm_mux_set(int i2c_addr, mux_state_t mux_state);
-int tcpci_tcpm_mux_get(int i2c_addr, mux_state_t *mux_state);
-int tcpci_tcpm_mux_enter_low_power(int port);
-int tcpci_get_chip_info(int port, int live,
- struct ec_response_pd_chip_info_v1 **chip_info);
-#ifdef CONFIG_USBC_PPC
-int tcpci_tcpm_set_snk_ctrl(int port, int enable);
-int tcpci_tcpm_set_src_ctrl(int port, int enable);
-#endif
-
-void tcpci_tcpc_fast_role_swap_enable(int port, int enable);
-
-#endif /* __CROS_EC_USB_PD_TCPM_TCPCI_H */
diff --git a/driver/tcpm/tcpm.h b/driver/tcpm/tcpm.h
deleted file mode 100644
index 51b315fb77..0000000000
--- a/driver/tcpm/tcpm.h
+++ /dev/null
@@ -1,418 +0,0 @@
-/* Copyright 2015 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.
- */
-
-/* USB Power delivery port management - common header for TCPM drivers */
-
-#ifndef __CROS_EC_USB_PD_TCPM_TCPM_H
-#define __CROS_EC_USB_PD_TCPM_TCPM_H
-
-#include "common.h"
-#include "ec_commands.h"
-#include "gpio.h"
-#include "i2c.h"
-#include "usb_pd_tcpm.h"
-#include "util.h"
-
-#if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && \
- !defined(CONFIG_USB_PD_DUAL_ROLE)
-#error "DRP auto toggle requires board to have DRP support"
-#error "Please upgrade your board configuration"
-#endif
-
-#ifndef CONFIG_USB_PD_TCPC
-
-/* I2C wrapper functions - get I2C port / slave addr from config struct. */
-#ifndef CONFIG_USB_PD_TCPC_LOW_POWER
-static inline int tcpc_addr_write(int port, int i2c_addr, int reg, int val)
-{
- return i2c_write8(tcpc_config[port].i2c_info.port,
- i2c_addr, reg, val);
-}
-
-static inline int tcpc_write16(int port, int reg, int val)
-{
- return i2c_write16(tcpc_config[port].i2c_info.port,
- tcpc_config[port].i2c_info.addr_flags,
- reg, val);
-}
-
-static inline int tcpc_addr_read(int port, int i2c_addr, int reg, int *val)
-{
- return i2c_read8(tcpc_config[port].i2c_info.port,
- i2c_addr, reg, val);
-}
-
-static inline int tcpc_read16(int port, int reg, int *val)
-{
- return i2c_read16(tcpc_config[port].i2c_info.port,
- tcpc_config[port].i2c_info.addr_flags,
- reg, val);
-}
-
-static inline int tcpc_xfer(int port, const uint8_t *out, int out_size,
- uint8_t *in, int in_size)
-{
- return i2c_xfer(tcpc_config[port].i2c_info.port,
- tcpc_config[port].i2c_info.addr_flags,
- out, out_size, in, in_size);
-}
-
-static inline int tcpc_xfer_unlocked(int port, const uint8_t *out, int out_size,
- uint8_t *in, int in_size, int flags)
-{
- return i2c_xfer_unlocked(tcpc_config[port].i2c_info.port,
- tcpc_config[port].i2c_info.addr_flags,
- out, out_size, in, in_size, flags);
-}
-
-static inline int tcpc_read_block(int port, int reg, uint8_t *in, int size)
-{
- return i2c_read_block(tcpc_config[port].i2c_info.port,
- tcpc_config[port].i2c_info.addr_flags,
- reg, in, size);
-}
-
-static inline int tcpc_write_block(int port, int reg,
- const uint8_t *out, int size)
-{
- return i2c_write_block(tcpc_config[port].i2c_info.port,
- tcpc_config[port].i2c_info.addr_flags,
- reg, out, size);
-}
-
-#else /* !CONFIG_USB_PD_TCPC_LOW_POWER */
-int tcpc_addr_write(int port, int i2c_addr, int reg, int val);
-int tcpc_write16(int port, int reg, int val);
-int tcpc_addr_read(int port, int i2c_addr, int reg, int *val);
-int tcpc_read16(int port, int reg, int *val);
-int tcpc_read_block(int port, int reg, uint8_t *in, int size);
-int tcpc_write_block(int port, int reg, const uint8_t *out, int size);
-int tcpc_xfer(int port, const uint8_t *out, int out_size,
- uint8_t *in, int in_size);
-int tcpc_xfer_unlocked(int port, const uint8_t *out, int out_size,
- uint8_t *in, int in_size, int flags);
-
-#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */
-
-static inline int tcpc_write(int port, int reg, int val)
-{
- return tcpc_addr_write(port,
- tcpc_config[port].i2c_info.addr_flags, reg, val);
-}
-
-static inline int tcpc_read(int port, int reg, int *val)
-{
- return tcpc_addr_read(port,
- tcpc_config[port].i2c_info.addr_flags, reg, val);
-}
-
-static inline void tcpc_lock(int port, int lock)
-{
- i2c_lock(tcpc_config[port].i2c_info.port, lock);
-}
-
-/* TCPM driver wrapper function */
-static inline int tcpm_init(int port)
-{
- int rv;
-
- rv = tcpc_config[port].drv->init(port);
- if (rv)
- return rv;
-
- /* Board specific post TCPC init */
- if (board_tcpc_post_init)
- rv = board_tcpc_post_init(port);
-
- return rv;
-}
-
-static inline int tcpm_release(int port)
-{
- return tcpc_config[port].drv->release(port);
-}
-
-static inline int tcpm_get_cc(int port, enum tcpc_cc_voltage_status *cc1,
- enum tcpc_cc_voltage_status *cc2)
-{
- return tcpc_config[port].drv->get_cc(port, cc1, cc2);
-}
-
-static inline int tcpm_get_vbus_level(int port)
-{
- return tcpc_config[port].drv->get_vbus_level(port);
-}
-
-static inline int tcpm_select_rp_value(int port, int rp)
-{
- return tcpc_config[port].drv->select_rp_value(port, rp);
-}
-
-static inline int tcpm_set_cc(int port, int pull)
-{
- return tcpc_config[port].drv->set_cc(port, pull);
-}
-
-static inline int tcpm_set_polarity(int port, int polarity)
-{
- return tcpc_config[port].drv->set_polarity(port, polarity);
-}
-
-static inline int tcpm_set_vconn(int port, int enable)
-{
- return tcpc_config[port].drv->set_vconn(port, enable);
-}
-
-static inline int tcpm_set_msg_header(int port, int power_role, int data_role)
-{
- return tcpc_config[port].drv->set_msg_header(port, power_role,
- data_role);
-}
-
-static inline int tcpm_set_rx_enable(int port, int enable)
-{
- return tcpc_config[port].drv->set_rx_enable(port, enable);
-}
-
-/**
- * Reads a message using get_message_raw driver method and puts it into EC's
- * cache.
- */
-int tcpm_enqueue_message(int port);
-
-static inline int tcpm_transmit(int port, enum tcpm_transmit_type type,
- uint16_t header, const uint32_t *data)
-{
- return tcpc_config[port].drv->transmit(port, type, header, data);
-}
-
-#ifdef CONFIG_USBC_PPC
-static inline int tcpm_set_snk_ctrl(int port, int enable)
-{
- if (tcpc_config[port].drv->set_snk_ctrl != NULL)
- return tcpc_config[port].drv->set_snk_ctrl(port, enable);
- else
- return EC_ERROR_UNIMPLEMENTED;
-}
-
-static inline int tcpm_set_src_ctrl(int port, int enable)
-{
- if (tcpc_config[port].drv->set_src_ctrl != NULL)
- return tcpc_config[port].drv->set_src_ctrl(port, enable);
- else
- return EC_ERROR_UNIMPLEMENTED;
-}
-#endif
-
-static inline void tcpc_alert(int port)
-{
- tcpc_config[port].drv->tcpc_alert(port);
-}
-
-static inline void tcpc_discharge_vbus(int port, int enable)
-{
- tcpc_config[port].drv->tcpc_discharge_vbus(port, enable);
-}
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
-static inline int tcpm_auto_toggle_supported(int port)
-{
- return !!tcpc_config[port].drv->drp_toggle;
-}
-
-static inline int tcpm_enable_drp_toggle(int port)
-{
- return tcpc_config[port].drv->drp_toggle(port);
-}
-#endif
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
-static inline int tcpm_enter_low_power_mode(int port)
-{
- return tcpc_config[port].drv->enter_low_power_mode(port);
-}
-#endif
-
-#ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC
-static inline int tcpc_i2c_read(const int port, const uint16_t addr_flags,
- const int reg, int *data)
-{
- return tcpc_read(port, reg, data);
-}
-
-static inline int tcpc_i2c_write(const int port, const uint16_t addr_flags,
- const int reg, int data)
-{
- return tcpc_write(port, reg, data);
-}
-#endif
-
-static inline int tcpm_get_chip_info(int port, int live,
- struct ec_response_pd_chip_info_v1 **info)
-{
- if (tcpc_config[port].drv->get_chip_info)
- return tcpc_config[port].drv->get_chip_info(port, live, info);
- return EC_ERROR_UNIMPLEMENTED;
-}
-
-#else
-
-/**
- * Initialize TCPM driver and wait for TCPC readiness.
- *
- * @param port Type-C port number
- *
- * @return EC_SUCCESS or error
- */
-int tcpm_init(int port);
-
-/**
- * Read the CC line status.
- *
- * @param port Type-C port number
- * @param cc1 pointer to CC status for CC1
- * @param cc2 pointer to CC status for CC2
- *
- * @return EC_SUCCESS or error
- */
-int tcpm_get_cc(int port, enum tcpc_cc_voltage_status *cc1,
- enum tcpc_cc_voltage_status *cc2);
-
-/**
- * Read VBUS
- *
- * @param port Type-C port number
- *
- * @return 0 => VBUS not detected, 1 => VBUS detected
- */
-int tcpm_get_vbus_level(int port);
-
-/**
- * Set the value of the CC pull-up used when we are a source.
- *
- * @param port Type-C port number
- * @param rp One of enum tcpc_rp_value
- *
- * @return EC_SUCCESS or error
- */
-int tcpm_select_rp_value(int port, int rp);
-
-/**
- * Set the CC pull resistor. This sets our role as either source or sink.
- *
- * @param port Type-C port number
- * @param pull One of enum tcpc_cc_pull
- *
- * @return EC_SUCCESS or error
- */
-int tcpm_set_cc(int port, int pull);
-
-/**
- * Set polarity
- *
- * @param port Type-C port number
- * @param polarity 0=> transmit on CC1, 1=> transmit on CC2
- *
- * @return EC_SUCCESS or error
- */
-int tcpm_set_polarity(int port, int polarity);
-
-/**
- * Set Vconn.
- *
- * @param port Type-C port number
- * @param polarity Polarity of the CC line to read
- *
- * @return EC_SUCCESS or error
- */
-int tcpm_set_vconn(int port, int enable);
-
-/**
- * Set PD message header to use for goodCRC
- *
- * @param port Type-C port number
- * @param power_role Power role to use in header
- * @param data_role Data role to use in header
- *
- * @return EC_SUCCESS or error
- */
-int tcpm_set_msg_header(int port, int power_role, int data_role);
-
-/**
- * Set RX enable flag
- *
- * @param port Type-C port number
- * @enable true for enable, false for disable
- *
- * @return EC_SUCCESS or error
- */
-int tcpm_set_rx_enable(int port, int enable);
-
-/**
- * Transmit PD message
- *
- * @param port Type-C port number
- * @param type Transmit type
- * @param header Packet header
- * @param cnt Number of bytes in payload
- * @param data Payload
- *
- * @return EC_SUCCESS or error
- */
-int tcpm_transmit(int port, enum tcpm_transmit_type type, uint16_t header,
- const uint32_t *data);
-
-/**
- * TCPC is asserting alert
- *
- * @param port Type-C port number
- */
-void tcpc_alert(int port);
-
-#endif
-
-/**
- * Gets the next waiting RX message.
- *
- * @param port Type-C port number
- * @param payload Pointer to location to copy payload of PD message
- * @param header The header of PD message
- *
- * @return EC_SUCCESS or error
- */
-int tcpm_dequeue_message(int port, uint32_t *payload, int *header);
-
-/**
- * Returns true if the tcpm has RX messages waiting to be consumed.
- */
-int tcpm_has_pending_message(int port);
-
-/**
- * Clear any pending messages in the RX queue. This function must be
- * called from the same context as the caller of tcpm_dequeue_message to avoid
- * race conditions.
- */
-void tcpm_clear_pending_messages(int port);
-
-/**
- * Enable/Disable TCPC Fast Role Swap detection
- *
- * @param port Type-C port number
- * @param enable FRS enable (true) disable (false)
- */
-static inline void tcpm_set_frs_enable(int port, int enable)
-{
- const struct tcpm_drv *tcpc;
-
- /*
- * set_frs_enable will be set to tcpci_tcp_fast_role_swap_enable
- * if it is handled by the tcpci for the tcpc chipset
- */
- tcpc = tcpc_config[port].drv;
- if (tcpc->set_frs_enable)
- tcpc->set_frs_enable(port, enable);
-}
-
-#endif
diff --git a/driver/tcpm/tusb422.c b/driver/tcpm/tusb422.c
deleted file mode 100644
index 0e6a6c51d5..0000000000
--- a/driver/tcpm/tusb422.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Copyright 2018 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.
- */
-
-/* Type-C port manager for TI TUSB422 Port Controller */
-
-#include "common.h"
-#include "tusb422.h"
-#include "tcpci.h"
-#include "tcpm.h"
-#include "timer.h"
-#include "usb_pd.h"
-
-#ifndef CONFIG_USB_PD_TCPM_TCPCI
-#error "TUSB422 is using a standard TCPCI interface"
-#error "Please upgrade your board configuration"
-
-#endif
-
-int tusb422_tcpci_tcpn_init(int port)
-{
- int rv = tcpci_tcpm_init(port);
-
- if (rv)
- return rv;
-
- /*
- * VBUS detection is supposed to be enabled by default, however the
- * TUSB422 has this disabled following reset.
- */
- /* Enable VBUS detection */
- return tcpc_write16(port, TCPC_REG_COMMAND, 0x33);
-}
-
-const struct tcpm_drv tusb422_tcpm_drv = {
- .init = &tusb422_tcpci_tcpn_init,
- .release = &tcpci_tcpm_release,
- .get_cc = &tcpci_tcpm_get_cc,
-#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
- .get_vbus_level = &tcpci_tcpm_get_vbus_level,
-#endif
- .select_rp_value = &tcpci_tcpm_select_rp_value,
- .set_cc = &tcpci_tcpm_set_cc,
- .set_polarity = &tcpci_tcpm_set_polarity,
- .set_vconn = &tcpci_tcpm_set_vconn,
- .set_msg_header = &tcpci_tcpm_set_msg_header,
- .set_rx_enable = &tcpci_tcpm_set_rx_enable,
- .get_message_raw = &tcpci_tcpm_get_message_raw,
- .transmit = &tcpci_tcpm_transmit,
- .tcpc_alert = &tcpci_tcpc_alert,
-#ifdef CONFIG_USB_PD_DISCHARGE_TCPC
- .tcpc_discharge_vbus = &tcpci_tcpc_discharge_vbus,
-#endif
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- .drp_toggle = &tcpci_tcpc_drp_toggle,
-#endif
-#ifdef CONFIG_USBC_PPC
- .set_snk_ctrl = &tcpci_tcpm_set_snk_ctrl,
- .set_src_ctrl = &tcpci_tcpm_set_src_ctrl,
-#endif
- .get_chip_info = &tcpci_get_chip_info,
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- .enter_low_power_mode = &tcpci_enter_low_power_mode,
-#endif
-};
diff --git a/driver/tcpm/tusb422.h b/driver/tcpm/tusb422.h
deleted file mode 100644
index 52d0a079d6..0000000000
--- a/driver/tcpm/tusb422.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* Copyright 2018 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.
- */
-
-/* TI TUSB422 Type-C port controller */
-
-#ifndef __CROS_EC_USB_PD_TCPM_TUSB422_H
-#define __CROS_EC_USB_PD_TCPM_TUSB422_H
-
-/* I2C interface */
-#define TUSB422_I2C_ADDR_FLAGS 0x20
-
-extern const struct tcpm_drv tusb422_tcpm_drv;
-
-#endif /* defined(__CROS_EC_USB_PD_TCPM_TUSB422_H) */
diff --git a/include/charge_manager.h b/include/charge_manager.h
deleted file mode 100644
index 2a3ca27d74..0000000000
--- a/include/charge_manager.h
+++ /dev/null
@@ -1,301 +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.
- */
-
-#ifndef __CROS_EC_CHARGE_MANAGER_H
-#define __CROS_EC_CHARGE_MANAGER_H
-
-#include "common.h"
-#include "ec_commands.h"
-
-/* Charge port that indicates no active port */
-#define CHARGE_PORT_NONE -1
-#define CHARGE_CEIL_NONE -1
-
-/* Initial charge state */
-#define CHARGE_CURRENT_UNINITIALIZED -1
-#define CHARGE_VOLTAGE_UNINITIALIZED -1
-
-/* Only track BC1.2 charge current if we support BC1.2 charging */
-#if defined(HAS_TASK_USB_CHG) || defined(HAS_TASK_USB_CHG_P0) || \
-defined(TEST_BUILD)
-#define CHARGE_MANAGER_BC12
-#endif
-
-/**
- * Time to delay for detecting the charger type (must be long enough for BC1.2
- * driver to get supplier information and notify charge manager).
- */
-#define CHARGE_DETECT_DELAY (2*SECOND)
-
-/* Commonly-used charge suppliers listed in no particular order */
-enum charge_supplier {
- CHARGE_SUPPLIER_NONE = -1,
- CHARGE_SUPPLIER_PD,
- CHARGE_SUPPLIER_TYPEC,
- CHARGE_SUPPLIER_TYPEC_DTS,
-#ifdef CHARGE_MANAGER_BC12
- CHARGE_SUPPLIER_BC12_DCP,
- CHARGE_SUPPLIER_BC12_CDP,
- CHARGE_SUPPLIER_BC12_SDP,
- CHARGE_SUPPLIER_PROPRIETARY,
- CHARGE_SUPPLIER_TYPEC_UNDER_1_5A,
- CHARGE_SUPPLIER_OTHER,
- CHARGE_SUPPLIER_VBUS,
-#endif /* CHARGE_MANAGER_BC12 */
-#if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0
- CHARGE_SUPPLIER_DEDICATED,
-#endif
-#ifdef CONFIG_WIRELESS_CHARGER_P9221_R7
- CHARGE_SUPPLIER_WPC_BPP,
- CHARGE_SUPPLIER_WPC_EPP,
- CHARGE_SUPPLIER_WPC_GPP,
-#endif
- CHARGE_SUPPLIER_COUNT
-};
-
-/*
- * Charge supplier priority: lower number indicates higher priority.
- * Default priority is in charge_manager.c. It can be overridden by boards.
- */
-extern const int supplier_priority[];
-
-/* Charge tasks report available current and voltage */
-struct charge_port_info {
- int current;
- int voltage;
-};
-
-/**
- * Called by charging tasks to update their available charge.
- *
- * @param supplier Charge supplier to update.
- * @param port Charge port to update.
- * @param charge Charge port current / voltage. If NULL, current = 0
- * voltage = 0 will be used.
- */
-void charge_manager_update_charge(int supplier,
- int port,
- const struct charge_port_info *charge);
-
-/* Partner port dualrole capabilities */
-enum dualrole_capabilities {
- CAP_UNKNOWN,
- CAP_DUALROLE,
- CAP_DEDICATED,
-};
-
-/**
- * Notify charge_manager of a partner dualrole capability change.
- *
- * @param port Charge port which changed.
- * @param cap New port capability.
- */
-void charge_manager_update_dualrole(int port, enum dualrole_capabilities cap);
-
-/**
- * Tell charge_manager to leave safe mode and switch to standard port / ILIM
- * selection logic.
- */
-void charge_manager_leave_safe_mode(void);
-
-/**
- * Charge ceiling can be set independently by different tasks / functions,
- * for different purposes.
- */
-enum ceil_requestor {
- /* Set by PD task, during negotiation */
- CEIL_REQUESTOR_PD,
- /* Set by host commands */
- CEIL_REQUESTOR_HOST,
- /* Number of ceiling groups */
- CEIL_REQUESTOR_COUNT,
-};
-
-#define CHARGE_PORT_COUNT (CONFIG_USB_PD_PORT_MAX_COUNT + \
- CONFIG_DEDICATED_CHARGE_PORT_COUNT)
-#if (CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0)
-
-/**
- * By default, dedicated port has following properties:
- *
- * - dedicated port is sink only.
- * - dedicated port is always connected.
- * - dedicated port is given highest priority (supplier type is always
- * CHARGE_SUPPLIER_DEDICATED).
- * - dualrole capability of dedicated port is always CAP_DEDICATED.
- * - there's only one dedicated port, its number is larger than PD port number.
- *
- * Sink property can be customized by implementing board_charge_port_is_sink()
- * and board_fill_source_power_info().
- * Connected can be customized by implementing board_charge_port_is_connected().
- */
-#if !defined(DEDICATED_CHARGE_PORT)
-#error "DEDICATED_CHARGE_PORT must be defined"
-#elif DEDICATED_CHARGE_PORT < CONFIG_USB_PD_PORT_MAX_COUNT
-#error "DEDICATED_CHARGE_PORT must larger than pd port numbers"
-#endif /* !defined(DEDICATED_CHARGE_PORT) */
-
-#endif /* CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0 */
-
-/**
- * Update charge ceiling for a given port. The ceiling can be set independently
- * for several requestors, and the min. ceil will be enforced.
- *
- * @param port Charge port to update.
- * @param requestor Charge ceiling requestor.
- * @param ceil Charge ceiling (mA).
- */
-void charge_manager_set_ceil(int port, enum ceil_requestor requestor, int ceil);
-
-/*
- * Update PD charge ceiling for a given port. In the event that our ceiling
- * is currently above ceil, change the current limit before returning, without
- * waiting for a charge manager refresh. This function should only be used in
- * time-critical situations where we absolutely cannot proceed without limiting
- * our input current, and it should only be called from the PD tasks.
- * If you ever call this function then you are a terrible person.
- */
-void charge_manager_force_ceil(int port, int ceil);
-
-/**
- * Select an 'override port', a port which is always the preferred charge port.
- *
- * @param port Charge port to select as override, or
- * OVERRIDE_OFF to select no override port,
- * or OVERRIDE_DONT_CHARGE to specific that no
- * charge port should be selected.
- * @return EC_SUCCESS on success,
- * the other ec_error_list status on failure.
- */
-int charge_manager_set_override(int port);
-
-/**
- * Get the override port.
- *
- * @return Port number or OVERRIDE_OFF or OVERRIDE_DONT_CHARGE.
- */
-int charge_manager_get_override(void);
-
-/**
- * Get the current active charge port, as determined by charge manager.
- *
- * @return Current active charge port.
- */
-int charge_manager_get_active_charge_port(void);
-
-/**
- * Get the power limit set by charge manager.
- *
- * @return Power limit (uW).
- */
-int charge_manager_get_power_limit_uw(void);
-
-/**
- * Get the charger current (mA) value.
- *
- * @return Charger current (mA) or CHARGE_CURRENT_UNINITIALIZED.
- */
-int charge_manager_get_charger_current(void);
-
-/**
- * Get the charger voltage (mV) value.
- *
- * @return Charger voltage (mV) or CHARGE_VOLTAGE_UNINITIALIZED.
- */
-int charge_manager_get_charger_voltage(void);
-
-#ifdef CONFIG_USB_PD_LOGGING
-/* Save power state log entry for the given port */
-void charge_manager_save_log(int port);
-#endif
-
-/**
- * Update whether a given port is sourcing current.
- *
- * @param port Port number to be updated.
- * @param enable 0 if the source port is disabled;
- * Otherwise the source port is enabled.
- */
-void charge_manager_source_port(int port, int enable);
-
-/**
- * Get PD source power data objects.
- *
- * @param src_pdo Pointer to the data to return.
- * @param port Current port to evaluate against.
- * @return number of PDOs returned.
- */
-int charge_manager_get_source_pdo(const uint32_t **src_pdo, const int port);
-
-/* Board-level callback functions */
-
-/**
- * Set the passed charge port as active.`
- *
- * @param charge_port Charge port to be enabled.
- * @return EC_SUCCESS if the charge port is accepted,
- * other ec_error_list status otherwise.
- */
-int board_set_active_charge_port(int charge_port);
-
-/**
- * Set the charge current limit.
- *
- * @param port PD port.
- * @param supplier Identified CHARGE_SUPPLIER_*.
- * @param charge_ma Desired charge current limit, <= max_ma.
- * @param max_ma Maximum charge current limit, >= charge_ma.
- * @param charge_mv Negotiated charge voltage (mV).
- */
-void board_set_charge_limit(int port, int supplier, int charge_ma,
- int max_ma, int charge_mv);
-
-/**
- * Get whether the port is sourcing power on VBUS.
- *
- * @param port PD port.
- * @return VBUS power state.
- */
-int board_vbus_source_enabled(int port);
-
-#ifdef CONFIG_USB_PD_VBUS_MEASURE_ADC_EACH_PORT
-/**
- * Gets the adc_channel for the specified port.
- *
- * @param port PD port.
- * @return adc_channel that measures the Vbus voltage.
- */
-enum adc_channel board_get_vbus_adc(int port);
-#endif /* CONFIG_USB_PD_VBUS_MEASURE_ADC_EACH_PORT */
-
-/**
- * Board specific callback to check if the given port is sink.
- *
- * @param port Dedicated charge port.
- * @return 1 if the port is sink.
- */
-__override_proto int board_charge_port_is_sink(int port);
-
-/**
- * Board specific callback to check if the given port is connected.
- *
- * @param port Dedicated charge port.
- * @return 1 if the port is connected.
- */
-__override_proto int board_charge_port_is_connected(int port);
-
-/**
- * Board specific callback to fill passed power_info structure with current info
- * about the passed dedicate port.
- * This function is responsible for filling r->meas.* and r->max_power.
- *
- * @param port Dedicated charge port.
- * @param r USB PD power info to be updated.
- */
-__override_proto
-void board_fill_source_power_info(int port,
- struct ec_response_usb_pd_power_info *r);
-
-#endif /* __CROS_EC_CHARGE_MANAGER_H */
diff --git a/include/config.h b/include/config.h
index 3c57bb1487..e82af70e28 100644
--- a/include/config.h
+++ b/include/config.h
@@ -897,41 +897,6 @@
#undef CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA
/*
- * Define to use Power Delivery State Machine Framework. Along with
- * CONFIG_USB_SM_FRAMEWORK, you must ensure the follow options are defined to
- * use the new statemachine for USB-C:
- *
- * CONFIG_USB_TYPEC_SM (defined by default)
- * CONFIG_USB_PRL_SM (defined by default)
- * One of CONFIG_USB_PE_* policy engine options.
- */
-#undef CONFIG_USB_SM_FRAMEWORK
-
-/*
- * Define to enable Type-C State Machine. Must be enabled
- * with CONFIG_USB_SM_FRAMEWORK
- */
-#define CONFIG_USB_TYPEC_SM
-
-/*
- * Define to enable Protocol Layer State Machine. Must be enabled
- * with CONFIG_USB_SM_FRAMEWORK and CONFIG_USB_TYPEC_SM
- */
-#define CONFIG_USB_PRL_SM
-
-/*
- * Define to enable Policy Engine State Machine. Must be enabled
- * with CONFIG_USB_SM_FRAMEWORK and CONFIG_USB_TYPEC_SM
- */
-#define CONFIG_USB_PE_SM
-
-/*
- * Define to enable Policy Engine State Machine. This is an override
- * that is used to just pull in PE for unit testing.
- */
-#undef CONFIG_TEST_USB_PE_SM
-
-/*
* Board specific maximum input current limit, in mA.
*/
#undef CONFIG_CHARGER_MAX_INPUT_CURRENT
diff --git a/include/usb_charge.h b/include/usb_charge.h
deleted file mode 100644
index a14c696daa..0000000000
--- a/include/usb_charge.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* Copyright 2012 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.
- */
-
-/* USB charging control module for Chrome EC */
-
-#ifndef __CROS_EC_USB_CHARGE_H
-#define __CROS_EC_USB_CHARGE_H
-
-#include "common.h"
-#include "ec_commands.h"
-
-/* USB charger voltage */
-#define USB_CHARGER_VOLTAGE_MV 5000
-/* USB charger minimum current */
-#define USB_CHARGER_MIN_CURR_MA 500
-
-/**
- * Set USB charge mode for the port.
- *
- * @param usb_port_id Port to set.
- * @param mode New mode for port.
- * @param inhibit_charge Inhibit charging during system suspend.
- * @return EC_SUCCESS, or non-zero if error.
- */
-int usb_charge_set_mode(int usb_port_id, enum usb_charge_mode mode,
- enum usb_suspend_charge inhibit_charge);
-
-#ifdef HAS_TASK_USB_CHG_P0
-#define USB_CHG_EVENT_BC12 TASK_EVENT_CUSTOM_BIT(0)
-#define USB_CHG_EVENT_VBUS TASK_EVENT_CUSTOM_BIT(1)
-#define USB_CHG_EVENT_INTR TASK_EVENT_CUSTOM_BIT(2)
-#define USB_CHG_EVENT_DR_UFP TASK_EVENT_CUSTOM_BIT(3)
-#define USB_CHG_EVENT_DR_DFP TASK_EVENT_CUSTOM_BIT(4)
-#define USB_CHG_EVENT_CC_OPEN TASK_EVENT_CUSTOM_BIT(5)
-#define USB_CHG_EVENT_MUX TASK_EVENT_CUSTOM_BIT(6)
-#endif
-
-/*
- * Define USB_CHG_PORT_TO_TASK_ID() and TASK_ID_TO_USB_CHG__PORT() macros to
- * go between USB_CHG port number and task ID. Assume that TASK_ID_USB_CHG_P0,
- * is the lowest task ID and IDs are on a continuous range.
- */
-#ifdef HAS_TASK_USB_CHG_P0
-#define USB_CHG_PORT_TO_TASK_ID(port) (TASK_ID_USB_CHG_P0 + (port))
-#define TASK_ID_TO_USB_CHG_PORT(id) ((id) - TASK_ID_USB_CHG_P0)
-#else
-#define USB_CHG_PORT_TO_TASK_ID(port) -1 /* dummy task ID */
-#define TASK_ID_TO_USB_CHG_PORT(id) 0
-#endif /* HAS_TASK_USB_CHG_P0 */
-
-/**
- * Returns true if the passed port is a power source.
- *
- * @param port Port number.
- * @return True if port is sourcing vbus.
- */
-int usb_charger_port_is_sourcing_vbus(int port);
-
-enum usb_switch {
- USB_SWITCH_CONNECT,
- USB_SWITCH_DISCONNECT,
- USB_SWITCH_RESTORE,
-};
-
-/**
- * Configure USB data switches on type-C port.
- *
- * @param port port number.
- * @param setting new switch setting to configure.
- */
-void usb_charger_set_switches(int port, enum usb_switch setting);
-
-/**
- * Notify USB_CHG task that VBUS level has changed.
- *
- * @param port port number.
- * @param vbus_level new VBUS level
- */
-void usb_charger_vbus_change(int port, int vbus_level);
-
-/**
- * Check if ramping is allowed for given supplier
- *
- * @supplier Supplier to check
- *
- * @return Ramping is allowed for given supplier
- */
-int usb_charger_ramp_allowed(int supplier);
-
-/**
- * Get the maximum current limit that we are allowed to ramp to
- *
- * @supplier Active supplier type
- * @sup_curr Input current limit based on supplier
- *
- * @return Maximum current in mA
- */
-int usb_charger_ramp_max(int supplier, int sup_curr);
-
-
-/**
- * Reset available BC 1.2 chargers on all ports
- * @param port
- */
-void usb_charger_reset_charge(int port);
-
-#endif /* __CROS_EC_USB_CHARGE_H */
diff --git a/include/usb_common.h b/include/usb_common.h
deleted file mode 100644
index b35e5f27f9..0000000000
--- a/include/usb_common.h
+++ /dev/null
@@ -1,106 +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.
- */
-#ifndef __CROS_EC_USB_COMMON_H
-#define __CROS_EC_USB_COMMON_H
-
-/* Functions that are shared between old and new PD stacks */
-#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
-#include "task_id.h"
-
-enum pd_drp_next_states {
- DRP_TC_DEFAULT,
- DRP_TC_UNATTACHED_SNK,
- DRP_TC_UNATTACHED_SRC,
- DRP_TC_DRP_AUTO_TOGGLE
-};
-
-/**
- * Returns the next state to transition to while in the drp auto toggle state.
- *
- * @param drp_sink_time timer for handling TOGGLE_OFF/FORCE_SINK mode when
- * auto-toggle enabled. This is an in/out variable.
- * @param power_role current power role
- * @param drp_state dual role states
- * @param cc1 value of CC1 set by tcpm_get_cc
- * @param cc2 value of CC2 set by tcpm_get_cc
- *
- */
-enum pd_drp_next_states drp_auto_toggle_next_state(uint64_t *drp_sink_time,
- enum pd_power_role power_role, enum pd_dual_role_states drp_state,
- enum tcpc_cc_voltage_status cc1, enum tcpc_cc_voltage_status cc2);
-
-/* Returns the battery percentage [0-100] of the system. */
-int usb_get_battery_soc(void);
-
-/*
- * Returns type C current limit (mA), potentially with the DTS flag, based upon
- * states of the CC lines on the partner side.
- *
- * @param polarity 0 if cc1 is primary, otherwise 1
- * @param cc1 value of CC1 set by tcpm_get_cc
- * @param cc2 value of CC2 set by tcpm_get_cc
- * @return current limit (mA) with DTS flag set if appropriate
- */
-typec_current_t usb_get_typec_current_limit(enum pd_cc_polarity_type polarity,
- enum tcpc_cc_voltage_status cc1, enum tcpc_cc_voltage_status cc2);
-
-/**
- * Returns the polarity of a Sink.
- *
- * @param cc1 value of CC1 set by tcpm_get_cc
- * @param cc2 value of CC2 set by tcpm_get_cc
- * @return 0 if cc1 is primary, else 1 for cc2 being primary
- */
-enum pd_cc_polarity_type get_snk_polarity(enum tcpc_cc_voltage_status cc1,
- enum tcpc_cc_voltage_status cc2);
-
-/**
- * Find PDO index that offers the most amount of power and stays within
- * max_mv voltage.
- *
- * @param src_cap_cnt
- * @param src_caps
- * @param max_mv maximum voltage (or -1 if no limit)
- * @param pdo raw pdo corresponding to index, or index 0 on error (output)
- * @return index of PDO within source cap packet
- */
-int pd_find_pdo_index(uint32_t src_cap_cnt, const uint32_t * const src_caps,
- int max_mv, uint32_t *selected_pdo);
-
-/**
- * Extract power information out of a Power Data Object (PDO)
- *
- * @param pdo raw pdo to extract
- * @param ma current of the PDO (output)
- * @param mv voltage of the PDO (output)
- */
-void pd_extract_pdo_power(uint32_t pdo, uint32_t *ma, uint32_t *mv);
-
-/**
- * Decide which PDO to choose from the source capabilities.
- *
- * @param src_cap_cnt
- * @param src_caps
- * @param rdo requested Request Data Object.
- * @param ma selected current limit (stored on success)
- * @param mv selected supply voltage (stored on success)
- * @param req_type request type
- * @param max_request_mv max voltage a sink can request before getting
- * source caps
- */
-void pd_build_request(uint32_t src_cap_cnt, const uint32_t * const src_caps,
- int32_t vpd_vdo, uint32_t *rdo, uint32_t *ma, uint32_t *mv,
- enum pd_request_type req_type, uint32_t max_request_mv);
-
-/**
- * Notifies a task that is waiting on a system jump, that it's complete.
- *
- * @param sysjump_task_waiting indicates if the task is waiting on the
- * system jump.
- */
-void notify_sysjump_ready(volatile const task_id_t * const
- sysjump_task_waiting);
-#endif /* __CROS_EC_USB_COMMON_H */
diff --git a/include/usb_pd.h b/include/usb_pd.h
deleted file mode 100644
index dcd1586486..0000000000
--- a/include/usb_pd.h
+++ /dev/null
@@ -1,2362 +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.
- */
-
-/* USB Power delivery module */
-
-#ifndef __CROS_EC_USB_PD_H
-#define __CROS_EC_USB_PD_H
-
-#include "common.h"
-#include "usb_pd_tcpm.h"
-
-/* PD Host command timeout */
-#define PD_HOST_COMMAND_TIMEOUT_US SECOND
-
-#ifdef CONFIG_USB_PD_PORT_MAX_COUNT
-/*
- * Define PD_PORT_TO_TASK_ID() and TASK_ID_TO_PD_PORT() macros to
- * go between PD port number and task ID. Assume that TASK_ID_PD_C0 is the
- * lowest task ID and IDs are on a continuous range.
- */
-#ifdef HAS_TASK_PD_C0
-#define PD_PORT_TO_TASK_ID(port) (TASK_ID_PD_C0 + (port))
-#define TASK_ID_TO_PD_PORT(id) ((id) - TASK_ID_PD_C0)
-#else
-#define PD_PORT_TO_TASK_ID(port) -1 /* dummy task ID */
-#define TASK_ID_TO_PD_PORT(id) 0
-#endif /* CONFIG_COMMON_RUNTIME */
-#endif /* CONFIG_USB_PD_PORT_MAX_COUNT */
-
-enum pd_rx_errors {
- PD_RX_ERR_INVAL = -1, /* Invalid packet */
- PD_RX_ERR_HARD_RESET = -2, /* Got a Hard-Reset packet */
- PD_RX_ERR_CRC = -3, /* CRC mismatch */
- PD_RX_ERR_ID = -4, /* Invalid ID number */
- PD_RX_ERR_UNSUPPORTED_SOP = -5, /* Unsupported SOP */
- PD_RX_ERR_CABLE_RESET = -6 /* Got a Cable-Reset packet */
-};
-
-/* Events for USB PD task */
-
-/* Outgoing packet event */
-#define PD_EVENT_TX TASK_EVENT_CUSTOM_BIT(3)
-/* CC line change event */
-#define PD_EVENT_CC TASK_EVENT_CUSTOM_BIT(4)
-/* TCPC has reset */
-#define PD_EVENT_TCPC_RESET TASK_EVENT_CUSTOM_BIT(5)
-/* DRP state has changed */
-#define PD_EVENT_UPDATE_DUAL_ROLE TASK_EVENT_CUSTOM_BIT(6)
-/*
- * A task, other than the task owning the PD port, accessed the TCPC. The task
- * that owns the port does not send itself this event.
- */
-#define PD_EVENT_DEVICE_ACCESSED TASK_EVENT_CUSTOM_BIT(7)
-/* Chipset power state changed */
-#define PD_EVENT_POWER_STATE_CHANGE TASK_EVENT_CUSTOM_BIT(8)
-/* Issue a Hard Reset. */
-#define PD_EVENT_SEND_HARD_RESET TASK_EVENT_CUSTOM_BIT(9)
-/* PD State machine event */
-#define PD_EVENT_SM TASK_EVENT_CUSTOM_BIT(10)
-/* Prepare for sysjump */
-#define PD_EVENT_SYSJUMP TASK_EVENT_CUSTOM_BIT(11)
-/* First free event on PD task */
-#define PD_EVENT_FIRST_FREE_BIT 12
-
-/* Ensure TCPC is out of low power mode before handling these events. */
-#define PD_EXIT_LOW_POWER_EVENT_MASK \
- (PD_EVENT_CC | \
- PD_EVENT_UPDATE_DUAL_ROLE | \
- PD_EVENT_POWER_STATE_CHANGE | \
- TASK_EVENT_WAKE)
-
-/* --- PD data message helpers --- */
-#define PDO_MAX_OBJECTS 7
-#define PDO_MODES (PDO_MAX_OBJECTS - 1)
-
-/* PDO : Power Data Object */
-/*
- * 1. The vSafe5V Fixed Supply Object shall always be the first object.
- * 2. The remaining Fixed Supply Objects,
- * if present, shall be sent in voltage order; lowest to highest.
- * 3. The Battery Supply Objects,
- * if present shall be sent in Minimum Voltage order; lowest to highest.
- * 4. The Variable Supply (non battery) Objects,
- * if present, shall be sent in Minimum Voltage order; lowest to highest.
- * 5. (PD3.0) The Augmented PDO is defined to allow extension beyond the 4 PDOs
- * above by examining bits <29:28> to determine the additional PDO function.
- */
-#define PDO_TYPE_FIXED (0 << 30)
-#define PDO_TYPE_BATTERY BIT(30)
-#define PDO_TYPE_VARIABLE (2 << 30)
-#define PDO_TYPE_AUGMENTED (3 << 30)
-#define PDO_TYPE_MASK (3 << 30)
-
-#define PDO_FIXED_DUAL_ROLE BIT(29) /* Dual role device */
-#define PDO_FIXED_SUSPEND BIT(28) /* USB Suspend supported */
-#define PDO_FIXED_EXTERNAL BIT(27) /* Externally powered */
-#define PDO_FIXED_COMM_CAP BIT(26) /* USB Communications Capable */
-#define PDO_FIXED_DATA_SWAP BIT(25) /* Data role swap command supported */
-#define PDO_FIXED_FRS_CURR_MASK (3 << 23) /* [23..24] FRS current */
-#define PDO_FIXED_FRS_CURR_NOT_SUPPORTED (0 << 23)
-#define PDO_FIXED_FRS_CURR_DFLT_USB_POWER (1 << 23)
-#define PDO_FIXED_FRS_CURR_1A5_AT_5V (2 << 23)
-#define PDO_FIXED_FRS_CURR_3A0_AT_5V (3 << 23)
-#define PDO_FIXED_PEAK_CURR () /* [21..20] Peak current */
-#define PDO_FIXED_VOLT(mv) (((mv)/50) << 10) /* Voltage in 50mV units */
-#define PDO_FIXED_CURR(ma) (((ma)/10) << 0) /* Max current in 10mA units */
-
-#define PDO_FIXED(mv, ma, flags) (PDO_FIXED_VOLT(mv) |\
- PDO_FIXED_CURR(ma) | (flags))
-
-#define PDO_VAR_MAX_VOLT(mv) ((((mv) / 50) & 0x3FF) << 20)
-#define PDO_VAR_MIN_VOLT(mv) ((((mv) / 50) & 0x3FF) << 10)
-#define PDO_VAR_OP_CURR(ma) ((((ma) / 10) & 0x3FF) << 0)
-
-#define PDO_VAR(min_mv, max_mv, op_ma) \
- (PDO_VAR_MIN_VOLT(min_mv) | \
- PDO_VAR_MAX_VOLT(max_mv) | \
- PDO_VAR_OP_CURR(op_ma) | \
- PDO_TYPE_VARIABLE)
-
-#define PDO_BATT_MAX_VOLT(mv) ((((mv) / 50) & 0x3FF) << 20)
-#define PDO_BATT_MIN_VOLT(mv) ((((mv) / 50) & 0x3FF) << 10)
-#define PDO_BATT_OP_POWER(mw) ((((mw) / 250) & 0x3FF) << 0)
-
-#define PDO_BATT(min_mv, max_mv, op_mw) \
- (PDO_BATT_MIN_VOLT(min_mv) | \
- PDO_BATT_MAX_VOLT(max_mv) | \
- PDO_BATT_OP_POWER(op_mw) | \
- PDO_TYPE_BATTERY)
-
-/* RDO : Request Data Object */
-#define RDO_OBJ_POS(n) (((n) & 0x7) << 28)
-#define RDO_POS(rdo) (((rdo) >> 28) & 0x7)
-#define RDO_GIVE_BACK BIT(27)
-#define RDO_CAP_MISMATCH BIT(26)
-#define RDO_COMM_CAP BIT(25)
-#define RDO_NO_SUSPEND BIT(24)
-#define RDO_FIXED_VAR_OP_CURR(ma) ((((ma) / 10) & 0x3FF) << 10)
-#define RDO_FIXED_VAR_MAX_CURR(ma) ((((ma) / 10) & 0x3FF) << 0)
-
-#define RDO_BATT_OP_POWER(mw) ((((mw) / 250) & 0x3FF) << 10)
-#define RDO_BATT_MAX_POWER(mw) ((((mw) / 250) & 0x3FF) << 10)
-
-#define RDO_FIXED(n, op_ma, max_ma, flags) \
- (RDO_OBJ_POS(n) | (flags) | \
- RDO_FIXED_VAR_OP_CURR(op_ma) | \
- RDO_FIXED_VAR_MAX_CURR(max_ma))
-
-
-#define RDO_BATT(n, op_mw, max_mw, flags) \
- (RDO_OBJ_POS(n) | (flags) | \
- RDO_BATT_OP_POWER(op_mw) | \
- RDO_BATT_MAX_POWER(max_mw))
-
-/* BDO : BIST Data Object */
-#define BDO_MODE_RECV (0 << 28)
-#define BDO_MODE_TRANSMIT BIT(28)
-#define BDO_MODE_COUNTERS (2 << 28)
-#define BDO_MODE_CARRIER0 (3 << 28)
-#define BDO_MODE_CARRIER1 (4 << 28)
-#define BDO_MODE_CARRIER2 (5 << 28)
-#define BDO_MODE_CARRIER3 (6 << 28)
-#define BDO_MODE_EYE (7 << 28)
-
-#define BDO(mode, cnt) ((mode) | ((cnt) & 0xFFFF))
-
-#define BIST_MODE(n) ((n) >> 28)
-#define BIST_ERROR_COUNTER(n) ((n) & 0xffff)
-#define BIST_RECEIVER_MODE 0
-#define BIST_TRANSMIT_MODE 1
-#define BIST_RETURNED_COUNTER 2
-#define BIST_CARRIER_MODE_0 3
-#define BIST_CARRIER_MODE_1 4
-#define BIST_CARRIER_MODE_2 5
-#define BIST_CARRIER_MODE_3 6
-#define BIST_EYE_PATTERN 7
-#define BIST_TEST_DATA 8
-
-#define SVID_DISCOVERY_MAX 16
-
-/* Timers */
-#define PD_T_SINK_TX (18*MSEC) /* between 16ms and 20 */
-#define PD_T_CHUNK_SENDER_RSP (24*MSEC) /* between 24ms and 30ms */
-#define PD_T_CHUNK_SENDER_REQ (24*MSEC) /* between 24ms and 30ms */
-#define PD_T_HARD_RESET_COMPLETE (5*MSEC) /* between 4ms and 5ms*/
-#define PD_T_HARD_RESET_RETRY (1*MSEC) /* 1ms */
-#define PD_T_SEND_SOURCE_CAP (100*MSEC) /* between 100ms and 200ms */
-#define PD_T_SINK_WAIT_CAP (600*MSEC) /* between 310ms and 620ms */
-#define PD_T_SINK_TRANSITION (35*MSEC) /* between 20ms and 35ms */
-#define PD_T_SOURCE_ACTIVITY (45*MSEC) /* between 40ms and 50ms */
-#define PD_T_SENDER_RESPONSE (30*MSEC) /* between 24ms and 30ms */
-#define PD_T_PS_TRANSITION (500*MSEC) /* between 450ms and 550ms */
-#define PD_T_PS_SOURCE_ON (480*MSEC) /* between 390ms and 480ms */
-#define PD_T_PS_SOURCE_OFF (920*MSEC) /* between 750ms and 920ms */
-#define PD_T_PS_HARD_RESET (25*MSEC) /* between 25ms and 35ms */
-#define PD_T_ERROR_RECOVERY (25*MSEC) /* 25ms */
-#define PD_T_CC_DEBOUNCE (100*MSEC) /* between 100ms and 200ms */
-/* DRP_SNK + DRP_SRC must be between 50ms and 100ms with 30%-70% duty cycle */
-#define PD_T_DRP_SNK (40*MSEC) /* toggle time for sink DRP */
-#define PD_T_DRP_SRC (30*MSEC) /* toggle time for source DRP */
-#define PD_T_DEBOUNCE (15*MSEC) /* between 10ms and 20ms */
-#define PD_T_TRY_CC_DEBOUNCE (15*MSEC) /* between 10ms and 20ms */
-#define PD_T_SINK_ADJ (55*MSEC) /* between PD_T_DEBOUNCE and 60ms */
-#define PD_T_SRC_RECOVER (760*MSEC) /* between 660ms and 1000ms */
-#define PD_T_SRC_RECOVER_MAX (1000*MSEC) /* 1000ms */
-#define PD_T_SRC_TURN_ON (275*MSEC) /* 275ms */
-#define PD_T_SAFE_0V (650*MSEC) /* 650ms */
-#define PD_T_NO_RESPONSE (5500*MSEC) /* between 4.5s and 5.5s */
-#define PD_T_BIST_TRANSMIT (50*MSEC) /* 50ms (used for task_wait arg) */
-#define PD_T_BIST_RECEIVE (60*MSEC) /* 60ms (max time to process bist) */
-#define PD_T_BIST_CONT_MODE (60*MSEC) /* 30ms to 60ms */
-#define PD_T_VCONN_SOURCE_ON (100*MSEC) /* 100ms */
-#define PD_T_DRP_TRY (125*MSEC) /* btween 75 and 150ms(monitor Vbus) */
-#define PD_T_TRY_TIMEOUT (550*MSEC) /* between 550ms and 1100ms */
-#define PD_T_TRY_WAIT (600*MSEC) /* Max time for TryWait.SNK state */
-#define PD_T_SINK_REQUEST (100*MSEC) /* Wait 100ms before next request */
-#define PD_T_PD_DEBOUNCE (15*MSEC) /* between 10ms and 20ms */
-#define PD_T_CHUNK_SENDER_RESPONSE (25*MSEC) /* 25ms */
-#define PD_T_CHUNK_SENDER_REQUEST (25*MSEC) /* 25ms */
-#define PD_T_SWAP_SOURCE_START (25*MSEC) /* Min of 20ms */
-#define PD_T_RP_VALUE_CHANGE (20*MSEC) /* 20ms */
-#define PD_T_SRC_DISCONNECT (15*MSEC) /* 15ms */
-#define PD_T_VCONN_STABLE (50*MSEC) /* 50ms */
-#define PD_T_DISCOVER_IDENTITY (45*MSEC) /* between 40ms and 50ms */
-
-/* number of edges and time window to detect CC line is not idle */
-#define PD_RX_TRANSITION_COUNT 3
-#define PD_RX_TRANSITION_WINDOW 20 /* between 12us and 20us */
-
-/* from USB Type-C Specification Table 5-1 */
-#define PD_T_AME (1*SECOND) /* timeout from UFP attach to Alt Mode Entry */
-
-/* VDM Timers ( USB PD Spec Rev2.0 Table 6-30 )*/
-#define PD_T_VDM_BUSY (100*MSEC) /* at least 100ms */
-#define PD_T_VDM_E_MODE (25*MSEC) /* enter/exit the same max */
-#define PD_T_VDM_RCVR_RSP (15*MSEC) /* max of 15ms */
-#define PD_T_VDM_SNDR_RSP (30*MSEC) /* max of 30ms */
-#define PD_T_VDM_WAIT_MODE_E (100*MSEC) /* enter/exit the same max */
-
-/* CTVPD Timers ( USB Type-C ECN Table 4-27 ) */
-#define PD_T_VPDDETACH (20*MSEC) /* max of 20*MSEC */
-#define PD_T_VPDCTDD (4*MSEC) /* max of 4ms */
-#define PD_T_VPDDISABLE (25*MSEC) /* min of 25ms */
-
-/* function table for entered mode */
-struct amode_fx {
- int (*status)(int port, uint32_t *payload);
- int (*config)(int port, uint32_t *payload);
-};
-
-/* function table for alternate mode capable responders */
-struct svdm_response {
- int (*identity)(int port, uint32_t *payload);
- int (*svids)(int port, uint32_t *payload);
- int (*modes)(int port, uint32_t *payload);
- int (*enter_mode)(int port, uint32_t *payload);
- int (*exit_mode)(int port, uint32_t *payload);
- struct amode_fx *amode;
-};
-
-struct svdm_svid_data {
- uint16_t svid;
- int mode_cnt;
- uint32_t mode_vdo[PDO_MODES];
-};
-
-struct svdm_amode_fx {
- uint16_t svid;
- int (*enter)(int port, uint32_t mode_caps);
- int (*status)(int port, uint32_t *payload);
- int (*config)(int port, uint32_t *payload);
- void (*post_config)(int port);
- int (*attention)(int port, uint32_t *payload);
- void (*exit)(int port);
-};
-
-/* defined in <board>/usb_pd_policy.c */
-/* All UFP_U should have */
-extern const struct svdm_response svdm_rsp;
-/* All DFP_U should have */
-extern const struct svdm_amode_fx supported_modes[];
-extern const int supported_modes_cnt;
-
-/* DFP data needed to support alternate mode entry and exit */
-struct svdm_amode_data {
- const struct svdm_amode_fx *fx;
- /* VDM object position */
- int opos;
- /* mode capabilities specific to SVID amode. */
- struct svdm_svid_data *data;
-};
-
-enum hpd_event {
- hpd_none,
- hpd_low,
- hpd_high,
- hpd_irq,
-};
-
-/* DisplayPort flags */
-#define DP_FLAGS_DP_ON BIT(0) /* Display port mode is on */
-#define DP_FLAGS_HPD_HI_PENDING BIT(1) /* Pending HPD_HI */
-
-/* supported alternate modes */
-enum pd_alternate_modes {
- PD_AMODE_GOOGLE,
- PD_AMODE_DISPLAYPORT,
- /* not a real mode */
- PD_AMODE_COUNT,
-};
-
-/* Policy structure for driving alternate mode */
-struct pd_policy {
- /* index of svid currently being operated on */
- int svid_idx;
- /* count of svids discovered */
- int svid_cnt;
- /* SVDM identity info (Id, Cert Stat, 0-4 Typec specific) */
- uint32_t identity[PDO_MAX_OBJECTS - 1];
- /* supported svids & corresponding vdo mode data */
- struct svdm_svid_data svids[SVID_DISCOVERY_MAX];
- /* active modes */
- struct svdm_amode_data amodes[PD_AMODE_COUNT];
- /* Next index to insert DFP alternate mode into amodes */
- int amode_idx;
-};
-
-/*
- * VDO : Vendor Defined Message Object
- * VDM object is minimum of VDM header + 6 additional data objects.
- */
-#define VDO_HDR_SIZE 1
-#define VDO_MAX_SIZE 7
-
-#define VDM_VER10 0
-#define VDM_VER20 1
-
-#define PD_VDO_INVALID -1
-
-/*
- * VDM header
- * ----------
- * <31:16> :: SVID
- * <15> :: VDM type ( 1b == structured, 0b == unstructured )
- * <14:13> :: Structured VDM version (00b == Rev 2.0, 01b == Rev 3.0 )
- * <12:11> :: reserved
- * <10:8> :: object position (1-7 valid ... used for enter/exit mode only)
- * <7:6> :: command type (SVDM only?)
- * <5> :: reserved (SVDM), command type (UVDM)
- * <4:0> :: command
- */
-#define VDO(vid, type, custom) \
- (((vid) << 16) | \
- ((type) << 15) | \
- ((custom) & 0x7FFF))
-
-#define VDO_SVDM_TYPE BIT(15)
-#define VDO_SVDM_VERS(x) (x << 13)
-#define VDO_OPOS(x) (x << 8)
-#define VDO_CMDT(x) (x << 6)
-#define VDO_OPOS_MASK VDO_OPOS(0x7)
-#define VDO_CMDT_MASK VDO_CMDT(0x3)
-
-#define CMDT_INIT 0
-#define CMDT_RSP_ACK 1
-#define CMDT_RSP_NAK 2
-#define CMDT_RSP_BUSY 3
-
-
-/* reserved for SVDM ... for Google UVDM */
-#define VDO_SRC_INITIATOR (0 << 5)
-#define VDO_SRC_RESPONDER BIT(5)
-
-#define CMD_DISCOVER_IDENT 1
-#define CMD_DISCOVER_SVID 2
-#define CMD_DISCOVER_MODES 3
-#define CMD_ENTER_MODE 4
-#define CMD_EXIT_MODE 5
-#define CMD_ATTENTION 6
-#define CMD_DP_STATUS 16
-#define CMD_DP_CONFIG 17
-
-#define VDO_CMD_VENDOR(x) (((10 + (x)) & 0x1f))
-
-/* ChromeOS specific commands */
-#define VDO_CMD_VERSION VDO_CMD_VENDOR(0)
-#define VDO_CMD_SEND_INFO VDO_CMD_VENDOR(1)
-#define VDO_CMD_READ_INFO VDO_CMD_VENDOR(2)
-#define VDO_CMD_REBOOT VDO_CMD_VENDOR(5)
-#define VDO_CMD_FLASH_ERASE VDO_CMD_VENDOR(6)
-#define VDO_CMD_FLASH_WRITE VDO_CMD_VENDOR(7)
-#define VDO_CMD_ERASE_SIG VDO_CMD_VENDOR(8)
-#define VDO_CMD_PING_ENABLE VDO_CMD_VENDOR(10)
-#define VDO_CMD_CURRENT VDO_CMD_VENDOR(11)
-#define VDO_CMD_FLIP VDO_CMD_VENDOR(12)
-#define VDO_CMD_GET_LOG VDO_CMD_VENDOR(13)
-#define VDO_CMD_CCD_EN VDO_CMD_VENDOR(14)
-
-#define PD_VDO_VID(vdo) ((vdo) >> 16)
-#define PD_VDO_SVDM(vdo) (((vdo) >> 15) & 1)
-#define PD_VDO_OPOS(vdo) (((vdo) >> 8) & 0x7)
-#define PD_VDO_CMD(vdo) ((vdo) & 0x1f)
-#define PD_VDO_CMDT(vdo) (((vdo) >> 6) & 0x3)
-
-/*
- * SVDM Identity request -> response
- *
- * Request is simply properly formatted SVDM header
- *
- * Response is 4 data objects.
- * In case of Active cables, the response is 5 data objects:
- * [0] :: SVDM header
- * [1] :: Identitiy header
- * [2] :: Cert Stat VDO
- * [3] :: (Product | Cable) VDO
- * [4] :: AMA VDO
- * [4] :: Product type Cable VDO 1
- * [5] :: Product type Cable VDO 2
- *
- */
-#define VDO_INDEX_HDR 0
-#define VDO_INDEX_IDH 1
-#define VDO_INDEX_CSTAT 2
-#define VDO_INDEX_CABLE 3
-#define VDO_INDEX_PRODUCT 3
-#define VDO_INDEX_AMA 4
-#define VDO_INDEX_PTYPE_CABLE1 4
-#define VDO_INDEX_PTYPE_CABLE2 5
-#define VDO_I(name) VDO_INDEX_##name
-
-/*
- * SVDM Identity Header
- * --------------------
- * <31> :: data capable as a USB host
- * <30> :: data capable as a USB device
- * <29:27> :: product type
- * <26> :: modal operation supported (1b == yes)
- * <25:16> :: SBZ
- * <15:0> :: USB-IF assigned VID for this cable vendor
- */
-
-enum idh_ptype {
- IDH_PTYPE_UNDEF,
- IDH_PTYPE_HUB,
- IDH_PTYPE_PERIPH,
- IDH_PTYPE_PCABLE,
- IDH_PTYPE_ACABLE,
- IDH_PTYPE_AMA,
- IDH_PTYPE_VPD,
- IDH_PTYPE_COUNT,
-};
-#define VDO_IDH(usbh, usbd, ptype, is_modal, vid) \
- ((usbh) << 31 | (usbd) << 30 | ((ptype) & 0x7) << 27 \
- | (is_modal) << 26 | ((vid) & 0xffff))
-
-#define PD_IDH_PTYPE(vdo) (((vdo) >> 27) & 0x7)
-#define PD_IDH_VID(vdo) ((vdo) & 0xffff)
-
-/*
- * Cert Stat VDO
- * -------------
- * <31:20> : SBZ
- * <19:0> : USB-IF assigned TID for this cable
- */
-#define VDO_CSTAT(tid) ((tid) & 0xfffff)
-#define PD_CSTAT_TID(vdo) ((vdo) & 0xfffff)
-
-/*
- * Product VDO
- * -----------
- * <31:16> : USB Product ID
- * <15:0> : USB bcdDevice
- */
-#define VDO_PRODUCT(pid, bcd) (((pid) & 0xffff) << 16 | ((bcd) & 0xffff))
-#define PD_PRODUCT_PID(vdo) (((vdo) >> 16) & 0xffff)
-
-/*
- * Cable VDO (Ref: PD Spec 2.0 Version 1.3 - Table 6-28 and 6-29)
- * ---------
- * <31:28> :: Cable HW version
- * <27:24> :: Cable FW version
- * <23:20> :: Reserved
- * <19:18> :: Type-C to Type-A/B/C (00b == A, 01 == B, 10 == C)
- * <17> :: Reserved
- * <16:13> :: Cable latency (0001 == <10ns(~1m length))
- * <12:11> :: Cable termination type (11b == both ends active VCONN req)
- * <10> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable)
- * <9> :: SSTX2 Directionality support
- * <8> :: SSRX1 Directionality support
- * <7> :: SSRX2 Directionality support
- * <6:5> :: Vbus current handling capability
- * <4> :: Vbus through cable (0b == no, 1b == yes)
- * <3> :: SOP" controller present? (0b == no, 1b == yes)
- * <2:0> :: USB SS Signaling support
- */
-enum usb_ss_support {
- USB_SS_U2_ONLY,
- USB_SS_U31_GEN1,
- USB_SS_U31_GEN2,
-};
-
-enum cable_outlet {
- CABLE_PLUG = 0,
- CABLE_RECEPTACLE = 1,
-};
-
-enum current_capacity {
- CABLE_CURRENT_3A = 1,
- CABLE_CURRENT_5A,
-};
-
-enum cable_dir_support {
- CABLE_FIXED,
- CABLE_CHANGEABLE,
-};
-
-enum connector_type {
- CONNECTOR_ATYPE,
- CONNECTOR_BTYPE,
- CONNECTOR_CTYPE,
- CONNECTOR_CAPTIVE,
-};
-
-struct vdo_rev20 {
- enum usb_ss_support ss: 3;
- uint32_t controller : 1;
- uint32_t vbus_cable : 1;
- enum current_capacity current : 2;
- enum cable_dir_support ssrx2 : 1;
- enum cable_dir_support ssrx1 : 1;
- enum cable_dir_support sstx2 : 1;
- enum cable_dir_support sstx1 : 1;
- uint32_t termination : 2;
- uint32_t latency : 4;
- uint32_t reserved0 : 1;
- enum connector_type connector : 2;
- uint32_t reserved1 : 4;
- uint32_t fw_version : 4;
- uint32_t hw_version : 4;
-};
-
-#define VDO_CABLE(hw, fw, cbl, lat, term, tx1d, tx2d, rx1d, rx2d, cur, vps, \
- sopp, usbss) \
- (((hw) & 0xF) << 28 | ((fw) & 0xF) << 24 | ((cbl) & 0x3) << 18 \
- | ((lat) & 0xF) << 13 | ((term) & 0x3) << 11 | ((tx1d) & 0x1) << 10 \
- | ((tx2d) & 0x1) << 9 | ((rx1d) & 0x1) << 8 | ((rx2d) & 0x1) << 7 \
- | ((cur) & 0x3) << 5 | ((vps) & 0x1) << 4 | ((sopp) & 0x1) << 3 \
- | ((usbss) & 0x7))
-
-/*
- * Passive Cable VDO (Ref: PD Spec 3.0 Version 1.2 - Table 6-35)
- * ---------
- * <31:28> :: Cable HW version
- * <27:24> :: Cable FW version
- * <23:21> :: VDO version
- * <20> :: Reserved
- * <19:18> :: Connector Type (10b == USB-C, 11b == Captive)
- * <17> :: Reserved
- * <16:13> :: Cable latency (0001 == <10ns(~1m length))
- * <12:11> :: Cable termination type (00b == VCONN not req, 01b = VCONN req)
- * <10:9> :: Maximum cable vbus voltage
- * <8:7> :: Reserved
- * <6:5> :: Vbus current handling capability
- * <4:3> :: Reserved
- * <2:0> :: USB SS Signaling support
- */
-enum max_vbus_vtg {
- CABLE_VBUS_20V,
- CABLE_VBUS_30V,
- CABLE_VBUS_40V,
- CABLE_VBUS_50V,
-};
-
-struct passive_cable_vdo_rev30 {
- enum usb_ss_support ss: 3;
- uint32_t reserved0 : 2;
- enum current_capacity current : 2;
- uint32_t reserved1 : 2;
- enum max_vbus_vtg vbus_max : 2;
- uint32_t termination : 2;
- uint32_t latency : 4;
- uint32_t reserved2 : 1;
- enum connector_type connector : 2;
- uint32_t reserved3 : 1;
- uint32_t vdo_version : 3;
- uint32_t fw_version : 4;
- uint32_t hw_version : 4;
-};
-
-#define PASSIVE_VDO_CABLE_REV3(hw, fw, vdover, cbl, lat, term, vbusv, \
- cur, usbss) \
- (((hw) & 0xF) << 28 | ((fw) & 0xF) << 24 | ((vdov & 0x7) << 21) \
- | ((cbl) & 0x3) << 18 | ((lat) & 0xF) << 13 | ((term) & 0x3) << 11 \
- | ((vbusv) & 0x3) << 9 | ((cur) & 0x3) << 5 | ((usbss) & 0x7))
-
-/*
- * Active Cable VDO1 (Ref: PD Spec 3.0 Version 1.2 - Table 6-36)
- * ---------
- * <31:28> :: Cable HW version
- * <27:24> :: Cable FW version
- * <23:21> :: VDO version
- * <20> :: Reserved
- * <19:18> :: Connector Type (10b == USB-C, 11b == Captive)
- * <17> :: Reserved
- * <16:13> :: Cable latency (0001 == <10ns(~1m length))
- * <12:11> :: Cable termination type (11b == both ends active VCONN req)
- * <10:9> :: Maximum cable vbus voltage
- * <8> :: SBU Supported? (0b == yes, 1b == no)
- * <7> :: SBU Type (0b == passive, 1b == active)
- * <6:5> :: Vbus current handling capability
- * <4> :: Vbus through cable (0b == no, 1b == yes)
- * <3> :: SOP" controller present? (0b == no, 1b == yes)
- * <2:0> :: Reserved
- */
-struct active_cable_vdo_rev30 {
- uint32_t reserved0 : 3;
- uint32_t controller : 1;
- uint32_t vbus_cable : 1;
- enum current_capacity current : 2;
- uint32_t sbu_type : 1;
- uint32_t sbu_support : 1;
- enum max_vbus_vtg vbus_max : 2;
- uint32_t termination : 2;
- uint32_t latency : 4;
- uint32_t reserved1 : 1;
- enum connector_type connector : 2;
- uint32_t reserved2 : 1;
- uint32_t vdo_version : 3;
- uint32_t cable_fw_version : 4;
- uint32_t cable_hw_version : 4;
-};
-#define ACTIVE_VDO1_CABLE_REV3(hw, fw, vdover, cbl, lat, term, vbusv, sbus, \
- sbut, cur, vps, sopp) \
- (((hw) & 0xF) << 28 | ((fw) & 0xF) << 24 | ((vdov) & 0x7) << 21 \
- | ((cbl) & 0x3) << 18 | ((lat) & 0xF) << 13 | ((term) & 0x3) << 11 \
- | ((vbusv) & 0x3) << 9 | ((sbus) & 0x1) << 8 | ((sbut) & 0x1) << 7 \
- | ((cur) & 0x3) << 5 | ((vps) & 0x1) << 4 | ((sopp) & 0x1) << 3)
-
-struct cable_vdo {
- union {
- struct vdo_rev20 rev20;
- struct passive_cable_vdo_rev30 p_rev30;
- struct active_cable_vdo_rev30 a_rev30;
- uint32_t raw_value;
- };
-};
-
-/*
- * Active Cable VDO2 (Ref: PD Spec 3.0 Version 1.2 - Table 6-37)
- * ---------
- * <31:24> :: Maximum operating temperature
- * <23:16> :: Shutdown temperature
- * <15> :: Reserved
- * <14:12> :: USB3 power (000 == >10mW)
- * <11> :: U3 to U0 transition
- * <10:8> :: Reserved
- * <7:6> :: USB 2.0 Hub Hops Consumed
- * <5> :: USB 2.0 Supported? (0b == yes, 1b == no)
- * <4> :: SS Supported? (0b == yes, 1b == no)
- * <3> :: SS lanes supported (0b == one, 1b == two)
- * <2> :: Reserved
- * <1:0> :: SS signaling (0b == Gen1, 01b == Gen2)
- */
-#define ACTIVE_CABLE_VDO2_CABLE_REV3(opt, sdt, usb3p, u3u0, hhc, usb2, \
- ss, ssl, sss) \
- (((opt) & 0xFF) << 24 | ((sdt) & 0xFF) << 16 | ((usb3p) & 0x7) << 12 \
- | ((u3u0) & 0x1) << 11 | ((usb2) & 0x3) << 6 | ((ss) & 0x1) << 4 \
- | ((ssl) & 0x1) << 3 | (sss) & 0x3)
-
-enum ss_signaling {
- USB_SS_SIGNAL_SS_GEN1,
- USB_SS_SIGNAL_SS_GEN2,
-};
-
-enum ss_lane_support {
- USB_SS_ONE_LANE,
- USB_SS_TWO_LANES,
-};
-
-enum u0u3_transition_mode {
- U0_U3_DIRECT,
- U0_U3_U3S,
-};
-
-enum u3_power_support {
- U3_POWER_10mW,
- U3_POWER_5_10mW,
- U3_POWER_1_5mW,
- U3_POWER_500_1000uW,
- U3_POWER_200_500uW,
- U3_POWER_50_200uW,
- U3_POWER_0_50uW,
-};
-
-struct active_cable_vdo2_rev30 {
- enum ss_signaling sss: 2;
- uint32_t reserved0 : 1;
- enum ss_lane_support lanes : 1;
- uint32_t usb_ss_support : 1;
- uint32_t usb2_support : 1;
- uint32_t usb2_hub_hops : 2;
- uint32_t reserved1 : 3;
- enum u0u3_transition_mode u0u3: 1;
- enum u3_power_support u3_power : 3;
- uint32_t reserved2: 1;
- uint32_t shutdown_temp;
- uint32_t max_operating_temp;
-};
-
-struct active_cable_vdo2 {
- union {
- struct active_cable_vdo2_rev30 a2_rev30;
- uint32_t raw_value;
- };
-};
-
-/* Cable structure for storing cable attributes */
-struct pd_cable {
- uint8_t is_identified;
- /* Type of cable */
- enum idh_ptype type;
- /* Cable flags. See CABLE_FLAGS_* */
- uint8_t flags;
- /* Cable attribues */
- struct cable_vdo attr;
- /* Cable revision */
- uint8_t rev;
- /* For USB PD REV3, active cable has 2 VDOs */
- struct active_cable_vdo2 attr2;
-};
-
-/* Flag for sending SOP Prime packet */
-#define CABLE_FLAGS_SOP_PRIME_ENABLE BIT(0)
-
-/*
- * AMA VDO
- * ---------
- * <31:28> :: Cable HW version
- * <27:24> :: Cable FW version
- * <23:12> :: SBZ
- * <11> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable)
- * <10> :: SSTX2 Directionality support
- * <9> :: SSRX1 Directionality support
- * <8> :: SSRX2 Directionality support
- * <7:5> :: Vconn power
- * <4> :: Vconn power required
- * <3> :: Vbus power required
- * <2:0> :: USB SS Signaling support
- */
-#define VDO_AMA(hw, fw, tx1d, tx2d, rx1d, rx2d, vcpwr, vcr, vbr, usbss) \
- (((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 \
- | (tx1d) << 11 | (tx2d) << 10 | (rx1d) << 9 | (rx2d) << 8 \
- | ((vcpwr) & 0x3) << 5 | (vcr) << 4 | (vbr) << 3 \
- | ((usbss) & 0x7))
-
-#define PD_VDO_AMA_VCONN_REQ(vdo) (((vdo) >> 4) & 1)
-#define PD_VDO_AMA_VBUS_REQ(vdo) (((vdo) >> 3) & 1)
-
-#define AMA_VCONN_PWR_1W 0
-#define AMA_VCONN_PWR_1W5 1
-#define AMA_VCONN_PWR_2W 2
-#define AMA_VCONN_PWR_3W 3
-#define AMA_VCONN_PWR_4W 4
-#define AMA_VCONN_PWR_5W 5
-#define AMA_VCONN_PWR_6W 6
-#define AMA_USBSS_U2_ONLY 0
-#define AMA_USBSS_U31_GEN1 1
-#define AMA_USBSS_U31_GEN2 2
-#define AMA_USBSS_BBONLY 3
-
-/*
- * VPD VDO
- * ---------
- * <31:28> :: HW version
- * <27:24> :: FW version
- * <23:21> :: VDO version
- * <20:17> :: SBZ
- * <16:15> :: Maximum VBUS Voltage
- * <14:13> :: SBZ
- * <12:7> :: VBUS Impedance
- * <6:1> :: Ground Impedance
- * <0> :: Charge Through Support
- */
-#define VDO_VPD(hw, fw, vbus, vbusz, gndz, cts) \
- (((hw) & 0xf) << 28 | ((fw) & 0xf) << 24 \
- | ((vbus) & 0x3) << 15 \
- | ((vbusz) & 0x3f) << 7 \
- | ((gndz) & 0x3f) << 1 | (cts))
-
-#define VPD_MAX_VBUS_20V 0
-#define VPD_MAX_VBUS_30V 1
-#define VPD_MAX_VBUS_40V 2
-#define VPD_MAX_VBUS_50V 3
-#define VPD_VBUS_IMP(mo) ((mo + 1) >> 1)
-#define VPD_GND_IMP(mo) (mo)
-#define VPD_CTS_SUPPORTED 1
-#define VPD_CTS_NOT_SUPPORTED 0
-
-/*
- * SVDM Discover SVIDs request -> response
- *
- * Request is properly formatted VDM Header with discover SVIDs command.
- * Response is a set of SVIDs of all all supported SVIDs with all zero's to
- * mark the end of SVIDs. If more than 12 SVIDs are supported command SHOULD be
- * repeated.
- */
-#define VDO_SVID(svid0, svid1) (((svid0) & 0xffff) << 16 | ((svid1) & 0xffff))
-#define PD_VDO_SVID_SVID0(vdo) ((vdo) >> 16)
-#define PD_VDO_SVID_SVID1(vdo) ((vdo) & 0xffff)
-
-#define VPD_VDO_MAX_VBUS(vdo) (((vdo) >> 15) & 0x3)
-#define VPD_VDO_VBUS_IMP(vdo) (((vdo) >> 7) & 0x3f)
-#define VPD_VDO_GND_IMP(vdo) (((vdo) >> 1) & 0x3f)
-#define VPD_VDO_CTS(vdo) ((vdo) & 1)
-
-/*
- * Google modes capabilities
- * <31:8> : reserved
- * <7:0> : mode
- */
-#define VDO_MODE_GOOGLE(mode) (mode & 0xff)
-
-#define MODE_GOOGLE_FU 1 /* Firmware Update mode */
-
-/*
- * Mode Capabilities
- *
- * Number of VDOs supplied is SID dependent (but <= 6 VDOS?)
- */
-#define VDO_MODE_CNT_DISPLAYPORT 1
-
-/*
- * DisplayPort modes capabilities
- * -------------------------------
- * <31:24> : SBZ
- * <23:16> : UFP_D pin assignment supported
- * <15:8> : DFP_D pin assignment supported
- * <7> : USB 2.0 signaling (0b=yes, 1b=no)
- * <6> : Plug | Receptacle (0b == plug, 1b == receptacle)
- * <5:2> : xxx1: Supports DPv1.3, xx1x Supports USB Gen 2 signaling
- * Other bits are reserved.
- * <1:0> : signal direction ( 00b=rsv, 01b=sink, 10b=src 11b=both )
- */
-#define VDO_MODE_DP(snkp, srcp, usb, gdr, sign, sdir) \
- (((snkp) & 0xff) << 16 | ((srcp) & 0xff) << 8 \
- | ((usb) & 1) << 7 | ((gdr) & 1) << 6 | ((sign) & 0xF) << 2 \
- | ((sdir) & 0x3))
-
-#define MODE_DP_PIN_A 0x01
-#define MODE_DP_PIN_B 0x02
-#define MODE_DP_PIN_C 0x04
-#define MODE_DP_PIN_D 0x08
-#define MODE_DP_PIN_E 0x10
-#define MODE_DP_PIN_F 0x20
-#define MODE_DP_PIN_ALL 0x3f
-
-#define MODE_DP_DFP_PIN_SHIFT 8
-#define MODE_DP_UFP_PIN_SHIFT 16
-
-/* Pin configs B/D/F support multi-function */
-#define MODE_DP_PIN_MF_MASK 0x2a
-/* Pin configs A/B support BR2 signaling levels */
-#define MODE_DP_PIN_BR2_MASK 0x3
-/* Pin configs C/D/E/F support DP signaling levels */
-#define MODE_DP_PIN_DP_MASK 0x3c
-/* Pin configs A/B/C/D/E/F */
-#define MODE_DP_PIN_CAPS_MASK 0x3f
-
-#define MODE_DP_V13 0x1
-#define MODE_DP_GEN2 0x2
-
-#define MODE_DP_SNK 0x1
-#define MODE_DP_SRC 0x2
-#define MODE_DP_BOTH 0x3
-
-#define MODE_DP_CABLE_SHIFT 6
-
-/*
- * Determine which pin assignments are valid for DP
- *
- * Based on whether the DP adapter identifies itself as a plug (permanently
- * attached cable) or a receptacle, the pin assignments may be in the DFP_D
- * field or the UFP_D field.
- *
- * Refer to DisplayPort Alt Mode On USB Type-C Standard version 1.0, table 5-2
- * depending on state of receptacle bit, use pins for DFP_D (if receptacle==0)
- * or UFP_D (if receptacle==1)
- * Also refer to DisplayPort Alt Mode Capabilities Clarification (4/30/2015)
- */
-#define PD_DP_PIN_CAPS(x) ((((x) >> MODE_DP_CABLE_SHIFT) & 0x1) \
- ? (((x) >> MODE_DP_UFP_PIN_SHIFT) & MODE_DP_PIN_CAPS_MASK) \
- : (((x) >> MODE_DP_DFP_PIN_SHIFT) & MODE_DP_PIN_CAPS_MASK))
-
-/*
- * DisplayPort Status VDO
- * ----------------------
- * <31:9> : SBZ
- * <8> : IRQ_HPD : 1 == irq arrived since last message otherwise 0.
- * <7> : HPD state : 0 = HPD_LOW, 1 == HPD_HIGH
- * <6> : Exit DP Alt mode: 0 == maintain, 1 == exit
- * <5> : USB config : 0 == maintain current, 1 == switch to USB from DP
- * <4> : Multi-function preference : 0 == no pref, 1 == MF preferred.
- * <3> : enabled : is DPout on/off.
- * <2> : power low : 0 == normal or LPM disabled, 1 == DP disabled for LPM
- * <1:0> : connect status : 00b == no (DFP|UFP)_D is connected or disabled.
- * 01b == DFP_D connected, 10b == UFP_D connected, 11b == both.
- */
-#define VDO_DP_STATUS(irq, lvl, amode, usbc, mf, en, lp, conn) \
- (((irq) & 1) << 8 | ((lvl) & 1) << 7 | ((amode) & 1) << 6 \
- | ((usbc) & 1) << 5 | ((mf) & 1) << 4 | ((en) & 1) << 3 \
- | ((lp) & 1) << 2 | ((conn & 0x3) << 0))
-
-#define PD_VDO_DPSTS_MF_MASK BIT(4)
-
-#define PD_VDO_DPSTS_HPD_IRQ(x) (((x) >> 8) & 1)
-#define PD_VDO_DPSTS_HPD_LVL(x) (((x) >> 7) & 1)
-#define PD_VDO_DPSTS_MF_PREF(x) (((x) >> 4) & 1)
-
-/* Per DisplayPort Spec v1.3 Section 3.3 */
-#define HPD_USTREAM_DEBOUNCE_LVL (2*MSEC)
-#define HPD_USTREAM_DEBOUNCE_IRQ (250)
-#define HPD_DSTREAM_DEBOUNCE_IRQ (500) /* between 500-1000us */
-
-/*
- * DisplayPort Configure VDO
- * -------------------------
- * <31:24> : SBZ
- * <23:16> : SBZ
- * <15:8> : Pin assignment requested. Choose one from mode caps.
- * <7:6> : SBZ
- * <5:2> : signalling : 1h == DP v1.3, 2h == Gen 2
- * Oh is only for USB, remaining values are reserved
- * <1:0> : cfg : 00 == USB, 01 == DFP_D, 10 == UFP_D, 11 == reserved
- */
-#define VDO_DP_CFG(pin, sig, cfg) \
- (((pin) & 0xff) << 8 | ((sig) & 0xf) << 2 | ((cfg) & 0x3))
-
-#define PD_DP_CFG_DPON(x) (((x & 0x3) == 1) || ((x & 0x3) == 2))
-/*
- * Get the pin assignment mask
- * for backward compatibility, if it is null,
- * get the former sink pin assignment we used to be in <23:16>.
- */
-#define PD_DP_CFG_PIN(x) ((((x) >> 8) & 0xff) ? (((x) >> 8) & 0xff) \
- : (((x) >> 16) & 0xff))
-/*
- * ChromeOS specific PD device Hardware IDs. Used to identify unique
- * products and used in VDO_INFO. Note this field is 10 bits.
- */
-#define USB_PD_HW_DEV_ID_RESERVED 0
-#define USB_PD_HW_DEV_ID_ZINGER 1
-#define USB_PD_HW_DEV_ID_MINIMUFFIN 2
-#define USB_PD_HW_DEV_ID_DINGDONG 3
-#define USB_PD_HW_DEV_ID_HOHO 4
-#define USB_PD_HW_DEV_ID_HONEYBUNS 5
-
-/*
- * ChromeOS specific VDO_CMD_READ_INFO responds with device info including:
- * RW Hash: First 20 bytes of SHA-256 of RW (20 bytes)
- * HW Device ID: unique descriptor for each ChromeOS model (2 bytes)
- * top 6 bits are minor revision, bottom 10 bits are major
- * SW Debug Version: Software version useful for debugging (15 bits)
- * IS RW: True if currently in RW, False otherwise (1 bit)
- */
-#define VDO_INFO(id, id_minor, ver, is_rw) ((id_minor) << 26 \
- | ((id) & 0x3ff) << 16 \
- | ((ver) & 0x7fff) << 1 \
- | ((is_rw) & 1))
-#define VDO_INFO_HW_DEV_ID(x) ((x) >> 16)
-#define VDO_INFO_SW_DBG_VER(x) (((x) >> 1) & 0x7fff)
-#define VDO_INFO_IS_RW(x) ((x) & 1)
-
-#define HW_DEV_ID_MAJ(x) (x & 0x3ff)
-#define HW_DEV_ID_MIN(x) ((x) >> 10)
-
-/* USB-IF SIDs */
-#define USB_SID_PD 0xff00 /* power delivery */
-#define USB_SID_DISPLAYPORT 0xff01
-
-#define USB_GOOGLE_TYPEC_URL "http://www.google.com/chrome/devices/typec"
-/* USB Vendor ID assigned to Google Inc. */
-#define USB_VID_GOOGLE 0x18d1
-
-/* Other Vendor IDs */
-#define USB_VID_APPLE 0x05ac
-#define USB_PID1_APPLE 0x1012
-#define USB_PID2_APPLE 0x1013
-
-/* Timeout for message receive in microseconds */
-#define USB_PD_RX_TMOUT_US 1800
-
-/* --- Protocol layer functions --- */
-
-enum pd_states {
- PD_STATE_DISABLED, /* C0 */
- PD_STATE_SUSPENDED, /* C1 */
- PD_STATE_SNK_DISCONNECTED, /* C2 */
- PD_STATE_SNK_DISCONNECTED_DEBOUNCE, /* C3 */
- PD_STATE_SNK_HARD_RESET_RECOVER, /* C4 */
- PD_STATE_SNK_DISCOVERY, /* C5 */
- PD_STATE_SNK_REQUESTED, /* C6 */
- PD_STATE_SNK_TRANSITION, /* C7 */
- PD_STATE_SNK_READY, /* C8 */
- PD_STATE_SNK_SWAP_INIT, /* C9 */
- PD_STATE_SNK_SWAP_SNK_DISABLE, /* C10 */
- PD_STATE_SNK_SWAP_SRC_DISABLE, /* C11 */
- PD_STATE_SNK_SWAP_STANDBY, /* C12 */
- PD_STATE_SNK_SWAP_COMPLETE, /* C13 */
- PD_STATE_SRC_DISCONNECTED, /* C14 */
- PD_STATE_SRC_DISCONNECTED_DEBOUNCE, /* C15 */
- PD_STATE_SRC_HARD_RESET_RECOVER, /* C16 */
- PD_STATE_SRC_STARTUP, /* C17 */
- PD_STATE_SRC_DISCOVERY, /* C18 */
- PD_STATE_SRC_NEGOCIATE, /* C19 */
- PD_STATE_SRC_ACCEPTED, /* C20 */
- PD_STATE_SRC_POWERED, /* C21 */
- PD_STATE_SRC_TRANSITION, /* C22 */
- PD_STATE_SRC_READY, /* C23 */
- PD_STATE_SRC_GET_SINK_CAP, /* C24 */
- PD_STATE_DR_SWAP, /* C25 */
- PD_STATE_SRC_SWAP_INIT, /* C26 */
- PD_STATE_SRC_SWAP_SNK_DISABLE, /* C27 */
- PD_STATE_SRC_SWAP_SRC_DISABLE, /* C28 */
- PD_STATE_SRC_SWAP_STANDBY, /* C29 */
- PD_STATE_VCONN_SWAP_SEND, /* C30 */
- PD_STATE_VCONN_SWAP_INIT, /* C31 */
- PD_STATE_VCONN_SWAP_READY, /* C32 */
- PD_STATE_SOFT_RESET, /* C33 */
- PD_STATE_HARD_RESET_SEND, /* C34 */
- PD_STATE_HARD_RESET_EXECUTE, /* C35 */
- PD_STATE_BIST_RX, /* C36 */
- PD_STATE_BIST_TX, /* C37 */
- PD_STATE_DRP_AUTO_TOGGLE, /* C38 */
- /* Number of states. Not an actual state. */
- PD_STATE_COUNT,
-};
-
-/* Generate compile-time errors for unsupported states */
-#ifndef CONFIG_USB_PD_DUAL_ROLE
-#define PD_STATE_SNK_DISCONNECTED UNSUPPORTED_PD_STATE_SNK_DISCONNECTED
-#define PD_STATE_SNK_DISCONNECTED_DEBOUNCE UNSUPPORTED_SNK_DISCONNECTED_DEBOUNCE
-#define PD_STATE_SNK_HARD_RESET_RECOVER UNSUPPORTED_SNK_HARD_RESET_RECOVER
-#define PD_STATE_SNK_DISCOVERY UNSUPPORTED_PD_STATE_SNK_DISCOVERY
-#define PD_STATE_SNK_REQUESTED UNSUPPORTED_PD_STATE_SNK_REQUESTED
-#define PD_STATE_SNK_TRANSITION UNSUPPORTED_PD_STATE_SNK_TRANSITION
-#define PD_STATE_SNK_READY UNSUPPORTED_PD_STATE_SNK_READY
-#define PD_STATE_SNK_SWAP_INIT UNSUPPORTED_PD_STATE_SNK_SWAP_INIT
-#define PD_STATE_SNK_SWAP_SNK_DISABLE UNSUPPORTED_PD_STATE_SNK_SWAP_SNK_DISABLE
-#define PD_STATE_SNK_SWAP_SRC_DISABLE UNSUPPORTED_PD_STATE_SNK_SWAP_SRC_DISABLE
-#define PD_STATE_SNK_SWAP_STANDBY UNSUPPORTED_PD_STATE_SNK_SWAP_STANDBY
-#define PD_STATE_SNK_SWAP_COMPLETE UNSUPPORTED_PD_STATE_SNK_SWAP_COMPLETE
-#define PD_STATE_SRC_SWAP_INIT UNSUPPORTED_PD_STATE_SRC_SWAP_INIT
-#define PD_STATE_SRC_SWAP_SNK_DISABLE UNSUPPORTED_PD_STATE_SRC_SWAP_SNK_DISABLE
-#define PD_STATE_SRC_SWAP_SRC_DISABLE UNSUPPORTED_PD_STATE_SRC_SWAP_SRC_DISABLE
-#define PD_STATE_SRC_SWAP_STANDBY UNSUPPORTED_PD_STATE_SRC_SWAP_STANDBY
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
-
-/* Generate compile-time errors for unsupported states */
-#if !defined(CONFIG_USBC_VCONN_SWAP) || !defined(CONFIG_USB_PD_DUAL_ROLE)
-#define PD_STATE_VCONN_SWAP_SEND UNSUPPORTED_PD_STATE_VCONN_SWAP_SEND
-#define PD_STATE_VCONN_SWAP_INIT UNSUPPORTED_PD_STATE_VCONN_SWAP_INIT
-#define PD_STATE_VCONN_SWAP_READY UNSUPPORTED_PD_STATE_VCONN_SWAP_READY
-#endif
-
-/* Generate compile-time errors for unsupported states */
-#ifndef CONFIG_COMMON_RUNTIME
-#define PD_STATE_BIST_RX UNSUPPORTED_PD_STATE_BIST_RX
-#define PD_STATE_BIST_TX UNSUPPORTED_PD_STATE_BIST_TX
-#endif
-
-/* Generate compile-time errors for unsupported states */
-#ifndef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
-#define PD_STATE_DRP_AUTO_TOGGLE UNSUPPORTED_PD_STATE_DRP_AUTO_TOGGLE
-#endif
-
-#define PD_FLAGS_PING_ENABLED BIT(0) /* SRC_READY pings enabled */
-#define PD_FLAGS_PARTNER_DR_POWER BIT(1) /* port partner is dualrole power */
-#define PD_FLAGS_PARTNER_DR_DATA BIT(2) /* port partner is dualrole data */
-#define PD_FLAGS_CHECK_IDENTITY BIT(3) /* discover identity in READY */
-#define PD_FLAGS_SNK_CAP_RECVD BIT(4) /* sink capabilities received */
-#define PD_FLAGS_TCPC_DRP_TOGGLE BIT(5) /* TCPC-controlled DRP toggling */
-#define PD_FLAGS_EXPLICIT_CONTRACT BIT(6) /* explicit pwr contract in place */
-#define PD_FLAGS_VBUS_NEVER_LOW BIT(7) /* VBUS input has never been low */
-#define PD_FLAGS_PREVIOUS_PD_CONN BIT(8) /* previously PD connected */
-#define PD_FLAGS_CHECK_PR_ROLE BIT(9) /* check power role in READY */
-#define PD_FLAGS_CHECK_DR_ROLE BIT(10)/* check data role in READY */
-#define PD_FLAGS_PARTNER_EXTPOWER BIT(11)/* port partner has external pwr */
-#define PD_FLAGS_VCONN_ON BIT(12)/* vconn is being sourced */
-#define PD_FLAGS_TRY_SRC BIT(13)/* Try.SRC states are active */
-#define PD_FLAGS_PARTNER_USB_COMM BIT(14)/* port partner is USB comms */
-#define PD_FLAGS_UPDATE_SRC_CAPS BIT(15)/* send new source capabilities */
-#define PD_FLAGS_TS_DTS_PARTNER BIT(16)/* partner has rp/rp or rd/rd */
-/*
- * These PD_FLAGS_LPM* flags track the software state (PD_LPM_FLAGS_REQUESTED)
- * and hardware state (PD_LPM_FLAGS_ENGAGED) of the TCPC low power mode.
- * PD_FLAGS_LPM_TRANSITION is set while the HW is transitioning into or out of
- * low power (when PD_LPM_FLAGS_ENGAGED is changing).
- */
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
-#define PD_FLAGS_LPM_REQUESTED BIT(17)/* Tracks SW LPM state */
-#define PD_FLAGS_LPM_ENGAGED BIT(18)/* Tracks HW LPM state */
-#define PD_FLAGS_LPM_TRANSITION BIT(19)/* Tracks HW LPM transition */
-#endif
-
-/*
- * Tracks whether port negotiation may have stalled due to not starting reset
- * timers in SNK_DISCOVERY
- */
-#define PD_FLAGS_SNK_WAITING_BATT BIT(20)
-
-/* Flags to clear on a disconnect */
-#define PD_FLAGS_RESET_ON_DISCONNECT_MASK (PD_FLAGS_PARTNER_DR_POWER | \
- PD_FLAGS_PARTNER_DR_DATA | \
- PD_FLAGS_CHECK_IDENTITY | \
- PD_FLAGS_SNK_CAP_RECVD | \
- PD_FLAGS_TCPC_DRP_TOGGLE | \
- PD_FLAGS_EXPLICIT_CONTRACT | \
- PD_FLAGS_PREVIOUS_PD_CONN | \
- PD_FLAGS_CHECK_PR_ROLE | \
- PD_FLAGS_CHECK_DR_ROLE | \
- PD_FLAGS_PARTNER_EXTPOWER | \
- PD_FLAGS_VCONN_ON | \
- PD_FLAGS_TRY_SRC | \
- PD_FLAGS_PARTNER_USB_COMM | \
- PD_FLAGS_UPDATE_SRC_CAPS | \
- PD_FLAGS_TS_DTS_PARTNER | \
- PD_FLAGS_SNK_WAITING_BATT)
-
-/* Per-port battery backed RAM flags */
-#define PD_BBRMFLG_EXPLICIT_CONTRACT BIT(0)
-#define PD_BBRMFLG_POWER_ROLE BIT(1)
-#define PD_BBRMFLG_DATA_ROLE BIT(2)
-#define PD_BBRMFLG_VCONN_ROLE BIT(3)
-
-/* Initial value for CC debounce variable */
-#define PD_CC_UNSET -1
-
-enum pd_dual_role_states {
- /* While disconnected, toggle between src and sink */
- PD_DRP_TOGGLE_ON,
- /* Stay in src until disconnect, then stay in sink forever */
- PD_DRP_TOGGLE_OFF,
- /* Stay in current power role, don't switch. No auto-toggle support */
- PD_DRP_FREEZE,
- /* Switch to sink */
- PD_DRP_FORCE_SINK,
- /* Switch to source */
- PD_DRP_FORCE_SOURCE,
-};
-/**
- * Get dual role state
- *
- * @param port Port number from which to get state
- * @return Current dual-role state, from enum pd_dual_role_states
- */
-enum pd_dual_role_states pd_get_dual_role(int port);
-/**
- * Set dual role state, from among enum pd_dual_role_states
- *
- * @param port Port number of which to set state
- * @param state New state of dual-role port, selected from
- * enum pd_dual_role_states
- */
-void pd_set_dual_role(int port, enum pd_dual_role_states state);
-
-/**
- * Get role, from among PD_ROLE_SINK and PD_ROLE_SOURCE
- *
- * @param port Port number from which to get role
- */
-int pd_get_role(int port);
-
-/* Control Message type */
-enum pd_ctrl_msg_type {
- /* 0 Reserved */
- PD_CTRL_GOOD_CRC = 1,
- PD_CTRL_GOTO_MIN = 2,
- PD_CTRL_ACCEPT = 3,
- PD_CTRL_REJECT = 4,
- PD_CTRL_PING = 5,
- PD_CTRL_PS_RDY = 6,
- PD_CTRL_GET_SOURCE_CAP = 7,
- PD_CTRL_GET_SINK_CAP = 8,
- PD_CTRL_DR_SWAP = 9,
- PD_CTRL_PR_SWAP = 10,
- PD_CTRL_VCONN_SWAP = 11,
- PD_CTRL_WAIT = 12,
- PD_CTRL_SOFT_RESET = 13,
- /* 14-15 Reserved */
-
- /* Used for REV 3.0 */
- PD_CTRL_NOT_SUPPORTED = 16,
- PD_CTRL_GET_SOURCE_CAP_EXT = 17,
- PD_CTRL_GET_STATUS = 18,
- PD_CTRL_FR_SWAP = 19,
- PD_CTRL_GET_PPS_STATUS = 20,
- PD_CTRL_GET_COUNTRY_CODES = 21,
- /* 22-31 Reserved */
-};
-
-/* Battery Status Data Object fields for REV 3.0 */
-#define BSDO_CAP_UNKNOWN 0xffff
-#define BSDO_CAP(n) (((n) & 0xffff) << 16)
-#define BSDO_INVALID BIT(8)
-#define BSDO_PRESENT BIT(9)
-#define BSDO_DISCHARGING BIT(10)
-#define BSDO_IDLE BIT(11)
-
-/* Get Battery Cap Message fields for REV 3.0 */
-#define BATT_CAP_REF(n) (((n) >> 16) & 0xff)
-
-/* Extended message type for REV 3.0 */
-enum pd_ext_msg_type {
- /* 0 Reserved */
- PD_EXT_SOURCE_CAP = 1,
- PD_EXT_STATUS = 2,
- PD_EXT_GET_BATTERY_CAP = 3,
- PD_EXT_GET_BATTERY_STATUS = 4,
- PD_EXT_BATTERY_CAP = 5,
- PD_EXT_GET_MANUFACTURER_INFO = 6,
- PD_EXT_MANUFACTURER_INFO = 7,
- PD_EXT_SECURITY_REQUEST = 8,
- PD_EXT_SECURITY_RESPONSE = 9,
- PD_EXT_FIRMWARE_UPDATE_REQUEST = 10,
- PD_EXT_FIRMWARE_UPDATE_RESPONSE = 11,
- PD_EXT_PPS_STATUS = 12,
- PD_EXT_COUNTRY_INFO = 13,
- PD_EXT_COUNTRY_CODES = 14,
- /* 15-31 Reserved */
-};
-
-/* Data message type */
-enum pd_data_msg_type {
- /* 0 Reserved */
- PD_DATA_SOURCE_CAP = 1,
- PD_DATA_REQUEST = 2,
- PD_DATA_BIST = 3,
- PD_DATA_SINK_CAP = 4,
- /* 5-14 Reserved for REV 2.0 */
- PD_DATA_BATTERY_STATUS = 5,
- PD_DATA_ALERT = 6,
- PD_DATA_GET_COUNTRY_INFO = 7,
- /* 8-14 Reserved for REV 3.0 */
- PD_DATA_VENDOR_DEF = 15,
-};
-
-/* CC Polarity type */
-enum pd_cc_polarity_type {
- POLARITY_CC1 = 0,
- POLARITY_CC2 = 1,
-};
-
-/* Protocol revision */
-enum pd_rev_type {
- PD_REV10,
- PD_REV20,
- PD_REV30
-};
-
-/*
- * Power role. See 6.2.1.1.4 Port Power Role. Only applies to SOP packets.
- * Replaced by pd_cable_plug for SOP' and SOP" packets.
- */
-enum pd_power_role {
- PD_ROLE_SINK = 0,
- PD_ROLE_SOURCE = 1
-};
-
-/*
- * Data role. See 6.2.1.1.6 Port Data Role. Only applies to SOP.
- * Replaced by reserved field for SOP' and SOP" packets.
- */
-enum pd_data_role {
- PD_ROLE_UFP = 0,
- PD_ROLE_DFP = 1,
- PD_ROLE_DISCONNECTED = 2,
-};
-
-/*
- * Cable plug. See 6.2.1.1.7 Cable Plug. Only applies to SOP' and SOP".
- * Replaced by pd_power_role for SOP packets.
- */
-enum pd_cable_plug {
- PD_PLUG_FROM_DFP_UFP = 0,
- PD_PLUG_FROM_CABLE = 1
-};
-
-/* Vconn role */
-#define PD_ROLE_VCONN_OFF 0
-#define PD_ROLE_VCONN_ON 1
-
-/* chunk is a request or response in REV 3.0 */
-#define CHUNK_RESPONSE 0
-#define CHUNK_REQUEST 1
-
-/* collision avoidance Rp values in REV 3.0 */
-#define SINK_TX_OK TYPEC_RP_3A0
-#define SINK_TX_NG TYPEC_RP_1A5
-
-/* Port role at startup */
-#ifndef PD_ROLE_DEFAULT
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-#define PD_ROLE_DEFAULT(port) PD_ROLE_SINK
-#else
-#define PD_ROLE_DEFAULT(port) PD_ROLE_SOURCE
-#endif
-#endif
-
-/* Port default state at startup */
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-#define PD_DEFAULT_STATE(port) ((PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE) ? \
- PD_STATE_SRC_DISCONNECTED : \
- PD_STATE_SNK_DISCONNECTED)
-#else
-#define PD_DEFAULT_STATE(port) PD_STATE_SRC_DISCONNECTED
-#endif
-
-/* build extended message header */
-/* All extended messages are chunked, so set bit 15 */
-#define PD_EXT_HEADER(cnum, rchk, dsize) \
- (BIT(15) | ((cnum) << 11) | \
- ((rchk) << 10) | (dsize))
-
-/* build message header */
-#define PD_HEADER(type, prole, drole, id, cnt, rev, ext) \
- ((type) | ((rev) << 6) | \
- ((drole) << 5) | ((prole) << 8) | \
- ((id) << 9) | ((cnt) << 12) | ((ext) << 15))
-
-/* Used for processing pd header */
-#define PD_HEADER_EXT(header) (((header) >> 15) & 1)
-#define PD_HEADER_CNT(header) (((header) >> 12) & 7)
-/*
- * NOTE: bit 4 was added in PD 3.0, and should be reserved and set to 0 in PD
- * 2.0 messages
- */
-#define PD_HEADER_TYPE(header) ((header) & 0x1F)
-#define PD_HEADER_ID(header) (((header) >> 9) & 7)
-#define PD_HEADER_PROLE(header) (((header) >> 8) & 1)
-#define PD_HEADER_REV(header) (((header) >> 6) & 3)
-#define PD_HEADER_DROLE(header) (((header) >> 5) & 1)
-
-/*
- * The message header is a 16-bit value that's stored in a 32-bit data type.
- * SOP* is encoded in bits 31 to 28 of the 32-bit data type.
- * NOTE: This is not part of the PD spec.
- */
-#define PD_HEADER_GET_SOP(header) (((header) >> 28) & 0xf)
-#define PD_HEADER_SOP(sop) ((sop) << 28)
-#define PD_MSG_SOP 0
-#define PD_MSG_SOPP 1
-#define PD_MSG_SOPPP 2
-#define PD_MSG_SOP_DBGP 3
-#define PD_MSG_SOP_DBGPP 4
-#define PD_MSG_SOP_CBL_RST 5
-
-/* Used for processing pd extended header */
-#define PD_EXT_HEADER_CHUNKED(header) (((header) >> 15) & 1)
-#define PD_EXT_HEADER_CHUNK_NUM(header) (((header) >> 11) & 0xf)
-#define PD_EXT_HEADER_REQ_CHUNK(header) (((header) >> 10) & 1)
-#define PD_EXT_HEADER_DATA_SIZE(header) ((header) & 0x1ff)
-
-/* Used to get extended header from the first 32-bit word of the message */
-#define GET_EXT_HEADER(msg) (msg & 0xffff)
-
-/* K-codes for special symbols */
-#define PD_SYNC1 0x18
-#define PD_SYNC2 0x11
-#define PD_SYNC3 0x06
-#define PD_RST1 0x07
-#define PD_RST2 0x19
-#define PD_EOP 0x0D
-
-/* Minimum PD supply current (mA) */
-#define PD_MIN_MA 500
-
-/* Minimum PD voltage (mV) */
-#define PD_MIN_MV 5000
-
-/* No connect voltage threshold for sources based on Rp */
-#define PD_SRC_DEF_VNC_MV 1600
-#define PD_SRC_1_5_VNC_MV 1600
-#define PD_SRC_3_0_VNC_MV 2600
-
-/* Rd voltage threshold for sources based on Rp */
-#define PD_SRC_DEF_RD_THRESH_MV 200
-#define PD_SRC_1_5_RD_THRESH_MV 400
-#define PD_SRC_3_0_RD_THRESH_MV 800
-
-/* Voltage threshold to detect connection when presenting Rd */
-#define PD_SNK_VA_MV 250
-
-/* --- Policy layer functions --- */
-
-/** Schedules the interrupt handler for the TCPC on a high priority task. */
-void schedule_deferred_pd_interrupt(int port);
-
-/* Request types for pd_build_request() */
-enum pd_request_type {
- PD_REQUEST_VSAFE5V,
- PD_REQUEST_MAX,
-};
-
-#ifdef CONFIG_USB_PD_REV30
-/**
- * Get current PD Revision
- *
- * @param port USB-C port number
- * @return 0 for PD_REV1.0, 1 for PD_REV2.0, 2 for PD_REV3.0
- */
-int pd_get_rev(int port);
-
-/**
- * Get current PD VDO Version
- *
- * @param port USB-C port number
- * @return 0 for PD_REV1.0, 1 for PD_REV2.0
- */
-int pd_get_vdo_ver(int port);
-#else
-#define pd_get_rev(n) PD_REV20
-#define pd_get_vdo_ver(n) VDM_VER10
-#endif
-
-/**
- * Check if max voltage request is allowed (only used if
- * CONFIG_USB_PD_CHECK_MAX_REQUEST_ALLOWED is defined).
- *
- * @return True if max voltage request allowed, False otherwise
- */
-int pd_is_max_request_allowed(void);
-
-/**
- * Waits for the TCPC to exit low power mode (including re-initializing) if it
- * is currently in low power mode. If not, then the function immediately
- * returns.
- *
- * @param port USB-C port number
- */
-void pd_wait_exit_low_power(int port);
-
-/**
- * Informs the TCPM state machine that code within the EC has accessed the TCPC
- * via its communication bus (e.g. i2c). This is important to keep track of as
- * accessing a TCPC may pull the hardware out of low-power mode.
- *
- * Note: Call this function after finished accessing the hardware.
- *
- * @param port USB-C port number
- */
-void pd_device_accessed(int port);
-
-/**
- * Prevents the TCPC from going back into low power mode. Invocations must be
- * called in a pair from the same task, otherwise the TCPC will never re-enter
- * low power mode.
- *
- * Note: This will not wake the device up if it is in LPM.
- *
- * @param port USB-C port number
- * @param prevent 1 to prevent this port from entering LPM
- */
-void pd_prevent_low_power_mode(int port, int prevent);
-
-/**
- * Process source capabilities packet
- *
- * @param port USB-C port number
- * @param cnt the number of Power Data Objects.
- * @param src_caps Power Data Objects representing the source capabilities.
- */
-void pd_process_source_cap(int port, int cnt, uint32_t *src_caps);
-
-/**
- * Reduce the sink power consumption to a minimum value.
- *
- * @param port USB-C port number
- * @param ma reduce current to minimum value.
- * @param mv reduce voltage to minimum value.
- */
-void pd_snk_give_back(int port, uint32_t * const ma, uint32_t * const mv);
-
-/**
- * Put a cap on the max voltage requested as a sink.
- * @param mv maximum voltage in millivolts.
- */
-void pd_set_max_voltage(unsigned mv);
-
-/**
- * Get the max voltage that can be requested as set by pd_set_max_voltage().
- * @return max voltage
- */
-unsigned pd_get_max_voltage(void);
-
-/**
- * Check if this board supports the given input voltage.
- *
- * @mv input voltage
- * @return 1 if voltage supported, 0 if not
- */
-int pd_is_valid_input_voltage(int mv);
-
-/**
- * Request a new operating voltage.
- *
- * @param rdo Request Data Object with the selected operating point.
- * @param port The port which the request came in on.
- * @return EC_SUCCESS if we can get the requested voltage/OP, <0 else.
- */
-int pd_check_requested_voltage(uint32_t rdo, const int port);
-
-/**
- * Run board specific checks on request message
- *
- * @param rdo the request data object word sent by the sink.
- * @param pdo_cnt the total number of source PDOs.
- * @return EC_SUCCESS if request is ok , <0 else.
- */
-int pd_board_check_request(uint32_t rdo, int pdo_cnt);
-
-/**
- * Select a new output voltage.
- *
- * param idx index of the new voltage in the source PDO table.
- */
-void pd_transition_voltage(int idx);
-
-/**
- * Go back to the default/safe state of the power supply
- *
- * @param port USB-C port number
- */
-void pd_power_supply_reset(int port);
-
-/**
- * Enable or disable VBUS discharge for a given port.
- *
- * @param port USB-C port number
- * @enable 1 if enabling discharge, 0 if disabling
- */
-void pd_set_vbus_discharge(int port, int enable);
-
-/**
- * Enable the power supply output after the ready delay.
- *
- * @param port USB-C port number
- * @return EC_SUCCESS if the power supply is ready, <0 else.
- */
-int pd_set_power_supply_ready(int port);
-
-/**
- * Ask the specified voltage from the PD source.
- *
- * It triggers a new negotiation sequence with the source.
- * @param port USB-C port number
- * @param mv request voltage in millivolts.
- */
-void pd_request_source_voltage(int port, int mv);
-
-/**
- * Set a voltage limit from the PD source.
- *
- * If the source is currently active, it triggers a new negotiation.
- * @param port USB-C port number
- * @param mv limit voltage in millivolts.
- */
-void pd_set_external_voltage_limit(int port, int mv);
-
-/**
- * Set the PD input current limit.
- *
- * @param port USB-C port number
- * @param max_ma Maximum current limit
- * @param supply_voltage Voltage at which current limit is applied
- */
-void pd_set_input_current_limit(int port, uint32_t max_ma,
- uint32_t supply_voltage);
-
-
-/**
- * Update the power contract if it exists.
- *
- * @param port USB-C port number.
- */
-void pd_update_contract(int port);
-
-/* Encode DTS status of port partner in current limit parameter */
-typedef uint32_t typec_current_t;
-#define TYPEC_CURRENT_DTS_MASK BIT(31)
-#define TYPEC_CURRENT_ILIM_MASK (~TYPEC_CURRENT_DTS_MASK)
-
-/**
- * Set the type-C input current limit.
- *
- * @param port USB-C port number
- * @param max_ma Maximum current limit
- * @param supply_voltage Voltage at which current limit is applied
- */
-void typec_set_input_current_limit(int port, typec_current_t max_ma,
- uint32_t supply_voltage);
-
-/**
- * Set the type-C current limit when sourcing current..
- *
- * @param port USB-C port number
- * @param rp One of enum tcpc_rp_value (eg TYPEC_RP_3A0) defining the limit.
- */
-void typec_set_source_current_limit(int port, enum tcpc_rp_value rp);
-
-/**
- * Verify board specific health status : current, voltages...
- *
- * @return EC_SUCCESS if the board is good, <0 else.
- */
-int pd_board_checks(void);
-
-/**
- * Return if VBUS is detected on type-C port
- *
- * @param port USB-C port number
- * @return VBUS is detected
- */
-int pd_snk_is_vbus_provided(int port);
-
-/**
- * Notify PD protocol that VBUS has gone low
- *
- * @param port USB-C port number
- */
-void pd_vbus_low(int port);
-
-/**
- * Check if power swap is allowed.
- *
- * @param port USB-C port number
- * @return True if power swap is allowed, False otherwise
- */
-int pd_check_power_swap(int port);
-
-/**
- * Check if data swap is allowed.
- *
- * @param port USB-C port number
- * @param data_role current data role
- * @return True if data swap is allowed, False otherwise
- */
-int pd_check_data_swap(int port, int data_role);
-
-/**
- * Check if vconn swap is allowed.
- *
- * @param port USB-C port number
- * @return True if vconn swap is allowed, False otherwise
- */
-
-int pd_check_vconn_swap(int port);
-
-/**
- * Check current power role for potential power swap
- *
- * @param port USB-C port number
- * @param pr_role Our power role
- * @param flags PD flags
- */
-void pd_check_pr_role(int port, int pr_role, int flags);
-
-/**
- * Check current data role for potential data swap
- *
- * @param port USB-C port number
- * @param dr_role Our data role
- * @param flags PD flags
- */
-void pd_check_dr_role(int port, int dr_role, int flags);
-
-/**
- * Check if we should charge from this device. This is
- * basically a allow-list for chargers that are dual-role,
- * don't set the externally powered bit, but we should charge
- * from by default.
- *
- * @param vid Port partner Vendor ID
- * @param pid Port partner Product ID
- */
-int pd_charge_from_device(uint16_t vid, uint16_t pid);
-
-/**
- * Execute data swap.
- *
- * @param port USB-C port number
- * @param data_role new data role
- */
-void pd_execute_data_swap(int port, int data_role);
-
-/**
- * Get PD device info used for VDO_CMD_SEND_INFO / VDO_CMD_READ_INFO
- *
- * @param info_data pointer to info data array
- */
-void pd_get_info(uint32_t *info_data);
-
-/**
- * Handle Vendor Defined Messages
- *
- * @param port USB-C port number
- * @param cnt number of data objects in the payload.
- * @param payload payload data.
- * @param rpayload pointer to the data to send back.
- * @return if >0, number of VDOs to send back.
- */
-int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload);
-
-/**
- * Handle Structured Vendor Defined Messages
- *
- * @param port USB-C port number
- * @param cnt number of data objects in the payload.
- * @param payload payload data.
- * @param rpayload pointer to the data to send back.
- * @return if >0, number of VDOs to send back.
- */
-int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload);
-
-/**
- * Handle Custom VDMs for flashing.
- *
- * @param port USB-C port number
- * @param cnt number of data objects in the payload.
- * @param payload payload data.
- * @return if >0, number of VDOs to send back.
- */
-int pd_custom_flash_vdm(int port, int cnt, uint32_t *payload);
-
-/**
- * Enter alternate mode on DFP
- *
- * @param port USB-C port number
- * @param svid USB standard or vendor id to exit or zero for DFP amode reset.
- * @param opos object position of mode to exit.
- * @return vdm for UFP to be sent to enter mode or zero if not.
- */
-uint32_t pd_dfp_enter_mode(int port, uint16_t svid, int opos);
-
-/**
- * Get DisplayPort pin mode for DFP to request from UFP's capabilities.
- *
- * @param port USB-C port number.
- * @param status DisplayPort Status VDO.
- * @return one-hot PIN config to request.
- */
-int pd_dfp_dp_get_pin_mode(int port, uint32_t status);
-
-/**
- * Exit alternate mode on DFP
- *
- * @param port USB-C port number
- * @param svid USB standard or vendor id to exit or zero for DFP amode reset.
- * @param opos object position of mode to exit.
- * @return 1 if UFP should be sent exit mode VDM.
- */
-int pd_dfp_exit_mode(int port, uint16_t svid, int opos);
-
-/**
- * Initialize policy engine for DFP
- *
- * @param port USB-C port number
- */
-void pd_dfp_pe_init(int port);
-
-/**
- * Return the VID of the USB PD accessory connected to a specified port
- *
- * @param port USB-C port number
- * @return the USB Vendor Identifier or 0 if it doesn't exist
- */
-uint16_t pd_get_identity_vid(int port);
-
-/**
- * Return the PID of the USB PD accessory connected to a specified port
- *
- * @param port USB-C port number
- * @return the USB Product Identifier or 0 if it doesn't exist
- */
-uint16_t pd_get_identity_pid(int port);
-
-/**
- * Returns the status of cable flag - CABLE_FLAGS_SOP_PRIME_ENABLE
- *
- * @param port USB-C port number
- * @param data_role current data role
- * @param pd_flags current pd flags
- * @return For rev3.0, true if vconn is on
- * For rev2.0, true if vconn is on and data_role is dfp
- * False otherwise
- */
-uint8_t is_sop_prime_ready(int port, uint8_t data_role, uint32_t pd_flags);
-
-/**
- * Reset Cable type, Cable attributes and cable flags
- *
- * @param port USB-C port number
- */
-void reset_pd_cable(int port);
-
-/**
- * Return the type of cable attached
- *
- * @param port USB-C port number
- * @return cable type
- */
-enum idh_ptype get_usb_pd_mux_cable_type(int port);
-
-/**
- * Store Device ID & RW hash of device
- *
- * @param port USB-C port number
- * @param dev_id device identifier
- * @param rw_hash pointer to rw_hash
- * @param current_image current image: RW or RO
- * @return true if the dev / hash match an existing hash
- * in our table, false otherwise
- */
-int pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash,
- uint32_t ec_current_image);
-
-/**
- * Fast Role Swap was detected
- *
- * @param port USB-C port number
- */
-void pd_got_frs_signal(int port);
-
-/**
- * Try to fetch one PD log entry from accessory
- *
- * @param port USB-C accessory port number
- * @return EC_RES_SUCCESS if the VDM was sent properly else error code
- */
-int pd_fetch_acc_log_entry(int port);
-
-/**
- * Analyze the log entry received as the VDO_CMD_GET_LOG payload.
- *
- * @param port USB-C accessory port number
- * @param cnt number of data objects in payload
- * @param payload payload data
- */
-void pd_log_recv_vdm(int port, int cnt, uint32_t *payload);
-
-/**
- * Send Vendor Defined Message
- *
- * @param port USB-C port number
- * @param vid Vendor ID
- * @param cmd VDO command number
- * @param data Pointer to payload to send
- * @param count number of data objects in payload
- */
-void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data,
- int count);
-
-/* Power Data Objects for the source and the sink */
-extern const uint32_t pd_src_pdo[];
-extern const int pd_src_pdo_cnt;
-extern const uint32_t pd_src_pdo_max[];
-extern const int pd_src_pdo_max_cnt;
-extern const uint32_t pd_snk_pdo[];
-extern const int pd_snk_pdo_cnt;
-
-/**
- * Request that a host event be sent to notify the AP of a PD power event.
- *
- * @param mask host event mask.
- */
-#if defined(HAS_TASK_HOSTCMD) && !defined(TEST_BUILD)
-void pd_send_host_event(int mask);
-#else
-static inline void pd_send_host_event(int mask) { }
-#endif
-
-/**
- * Determine if in alternate mode or not.
- *
- * @param port port number.
- * @param svid USB standard or vendor id
- * @return object position of mode chosen in alternate mode otherwise zero.
- */
-int pd_alt_mode(int port, uint16_t svid);
-
-/**
- * Send hpd over USB PD.
- *
- * @param port port number.
- * @param hpd hotplug detect type.
- */
-void pd_send_hpd(int port, enum hpd_event hpd);
-
-/**
- * Enable USB Billboard Device.
- */
-extern const struct deferred_data pd_usb_billboard_deferred_data;
-/* --- Physical layer functions : chip specific --- */
-
-/* Packet preparation/retrieval */
-
-/**
- * Prepare packet reading state machine.
- *
- * @param port USB-C port number
- */
-void pd_init_dequeue(int port);
-
-/**
- * Prepare packet reading state machine.
- *
- * @param port USB-C port number
- * @param off current position in the packet buffer.
- * @param len minimum size to read in bits.
- * @param val the read bits.
- * @return new position in the packet buffer.
- */
-int pd_dequeue_bits(int port, int off, int len, uint32_t *val);
-
-/**
- * Advance until the end of the preamble.
- *
- * @param port USB-C port number
- * @return new position in the packet buffer.
- */
-int pd_find_preamble(int port);
-
-/**
- * Write the preamble in the TX buffer.
- *
- * @param port USB-C port number
- * @return new position in the packet buffer.
- */
-int pd_write_preamble(int port);
-
-/**
- * Write one 10-period symbol in the TX packet.
- * corresponding to a quartet with 4b5b encoding
- * and Biphase Mark Coding.
- *
- * @param port USB-C port number
- * @param bit_off current position in the packet buffer.
- * @param val10 the 10-bit integer.
- * @return new position in the packet buffer.
- */
-int pd_write_sym(int port, int bit_off, uint32_t val10);
-
-
-/**
- * Ensure that we have an edge after EOP and we end up at level 0,
- * also fill the last byte.
- *
- * @param port USB-C port number
- * @param bit_off current position in the packet buffer.
- * @return new position in the packet buffer.
- */
-int pd_write_last_edge(int port, int bit_off);
-
-/**
- * Do 4B5B encoding on a 32-bit word.
- *
- * @param port USB-C port number
- * @param off current offset in bits inside the message
- * @param val32 32-bit word value to encode
- * @return new offset in the message in bits.
- */
-int encode_word(int port, int off, uint32_t val32);
-
-/**
- * Ensure that we have an edge after EOP and we end up at level 0,
- * also fill the last byte.
- *
- * @param port USB-C port number
- * @param header PD packet header
- * @param cnt number of payload words
- * @param data payload content
- * @return length of the message in bits.
- */
-int prepare_message(int port, uint16_t header, uint8_t cnt,
- const uint32_t *data);
-
-/**
- * Dump the current PD packet on the console for debug.
- *
- * @param port USB-C port number
- * @param msg context string.
- */
-void pd_dump_packet(int port, const char *msg);
-
-/**
- * Change the TX data clock frequency.
- *
- * @param port USB-C port number
- * @param freq frequency in hertz.
- */
-void pd_set_clock(int port, int freq);
-
-/* TX/RX callbacks */
-
-/**
- * Start sending over the wire the prepared packet.
- *
- * @param port USB-C port number
- * @param polarity plug polarity (0=CC1, 1=CC2).
- * @param bit_len size of the packet in bits.
- * @return length transmitted or negative if error
- */
-int pd_start_tx(int port, int polarity, int bit_len);
-
-/**
- * Set PD TX DMA to use circular mode. Call this before pd_start_tx() to
- * continually loop over the transmit buffer given in pd_start_tx().
- *
- * @param port USB-C port number
- */
-void pd_tx_set_circular_mode(int port);
-
-/**
- * Stop PD TX DMA circular mode transaction already in progress.
- *
- * @param port USB-C port number
- */
-void pd_tx_clear_circular_mode(int port);
-
-/**
- * Call when we are done sending a packet.
- *
- * @param port USB-C port number
- * @param polarity plug polarity (0=CC1, 1=CC2).
- */
-void pd_tx_done(int port, int polarity);
-
-/**
- * Check whether the PD reception is started.
- *
- * @param port USB-C port number
- * @return true if the reception is on-going.
- */
-int pd_rx_started(int port);
-
-/**
- * Suspend the PD task.
- * @param port USB-C port number
- * @param enable pass 0 to resume, anything else to suspend
- */
-void pd_set_suspend(int port, int enable);
-
-/**
- * Resume the PD task for a port after a period of time has elapsed.
- * @param port USB-C port number
- */
-void pd_deferred_resume(int port);
-
-/**
- * Check if the port has been initialized and PD task has not been
- * suspended.
- *
- * @param port USB-C port number
- * @return true if the PD task is not suspended.
- */
-int pd_is_port_enabled(int port);
-
-/* Callback when the hardware has detected an incoming packet */
-void pd_rx_event(int port);
-/* Start sampling the CC line for reception */
-void pd_rx_start(int port);
-/* Call when we are done reading a packet */
-void pd_rx_complete(int port);
-
-/* restart listening to the CC wire */
-void pd_rx_enable_monitoring(int port);
-/* stop listening to the CC wire during transmissions */
-void pd_rx_disable_monitoring(int port);
-
-/* get time since last RX edge interrupt */
-uint64_t get_time_since_last_edge(int port);
-
-/**
- * Deinitialize the hardware used for PD.
- *
- * @param port USB-C port number
- */
-void pd_hw_release(int port);
-
-/**
- * Initialize the hardware used for PD RX/TX.
- *
- * @param port USB-C port number
- * @param role Role to initialize pins in
- */
-void pd_hw_init(int port, int role);
-
-/**
- * Initialize the reception side of hardware used for PD.
- *
- * This is a subset of pd_hw_init() including only :
- * the comparators + the RX edge delay timer + the RX DMA.
- *
- * @param port USB-C port number
- */
-void pd_hw_init_rx(int port);
-
-/* --- Protocol layer functions --- */
-
-/**
- * Decode a raw packet in the RX buffer.
- *
- * @param port USB-C port number
- * @param payload buffer to store the packet payload (must be 7x 32-bit)
- * @return the packet header or <0 in case of error
- */
-int pd_analyze_rx(int port, uint32_t *payload);
-
-/**
- * Check if PD communication is enabled
- *
- * @return true if it's enabled or false otherwise
- */
-int pd_comm_is_enabled(int port);
-
-/**
- * Get connected state
- *
- * @param port USB-C port number
- * @return True if port is in connected state
- */
-int pd_is_connected(int port);
-
-/**
- * Execute a hard reset
- *
- * @param port USB-C port number
- */
-void pd_execute_hard_reset(int port);
-
-/**
- * Signal to protocol layer that PD transmit is complete
- *
- * @param port USB-C port number
- * @param status status of the transmission
- */
-void pd_transmit_complete(int port, int status);
-
-/**
- * Get port polarity.
- *
- * @param port USB-C port number
- */
-int pd_get_polarity(int port);
-
-/**
- * Get port partner data swap capable status
- *
- * @param port USB-C port number
- */
-int pd_get_partner_data_swap_capable(int port);
-
-/**
- * Handle an overcurrent protection event. The port acting as a source has
- * reported an overcurrent event.
- *
- * @param port: USB-C port number.
- */
-void pd_handle_overcurrent(int port);
-
-/**
- * Request power swap command to be issued
- *
- * @param port USB-C port number
- */
-void pd_request_power_swap(int port);
-
-/**
- * Try to become the VCONN source, if we are not already the source and the
- * other side is willing to accept a VCONN swap.
- *
- * @param port USB-C port number
- */
-void pd_try_vconn_src(int port);
-
-/**
- * Request data swap command to be issued
- *
- * @param port USB-C port number
- */
-void pd_request_data_swap(int port);
-
-/**
- * Set the PD communication enabled flag. When communication is disabled,
- * the port can still detect connection and source power but will not
- * send or respond to any PD communication.
- *
- * @param port USB-C port number
- * @param enable Enable flag to set
- */
-void pd_comm_enable(int port, int enable);
-
-/**
- * Set the PD pings enabled flag. When source has negotiated power over
- * PD successfully, it can optionally send pings periodically based on
- * this enable flag.
- *
- * @param port USB-C port number
- * @param enable Enable flag to set
- */
-void pd_ping_enable(int port, int enable);
-
-/* Issue PD soft reset */
-void pd_soft_reset(void);
-
-/* Prepare PD communication for reset */
-void pd_prepare_reset(void);
-
-/**
- * Signal power request to indicate a charger update that affects the port.
- *
- * @param port USB-C port number
- */
-void pd_set_new_power_request(int port);
-
-/**
- * Return true if partner port is a DTS or TS capable of entering debug
- * mode (eg. is presenting Rp/Rp or Rd/Rd).
- *
- * @param port USB-C port number
- */
-int pd_ts_dts_plugged(int port);
-
-/**
- * Return true if partner port is known to be PD capable.
- *
- * @param port USB-C port number
- */
-int pd_capable(int port);
-
-/**
- * Returns the source caps list
- *
- * @param port USB-C port number
- */
-const uint32_t * const pd_get_src_caps(int port);
-
-/**
- * Returns the number of source caps
- *
- * @param port USB-C port number
- */
-uint8_t pd_get_src_cap_cnt(int port);
-
-/**
- * Return true if partner port is capable of communication over USB data
- * lines.
- *
- * @param port USB-C port number
- */
-int pd_get_partner_usb_comm_capable(int port);
-
-/**
- * Return true if vbus is present on the specified port.
- *
- * @param port USB-C port number
- */
-int pd_is_vbus_present(int port);
-
-/**
- * Get board specific current DisplayPort pin mode on the specified port.
- *
- * @param port USB-C port number
- * @return MODE_DP_PIN_[A-E] if used else 0
- */
-uint8_t board_get_dp_pin_mode(int port);
-
-#ifdef CONFIG_USB_PD_PORT_MAX_COUNT
-#ifdef CONFIG_USB_POWER_DELIVERY
-/**
- * Get board specific usb pd port count
- *
- * @return <= CONFIG_USB_PD_PORT_MAX_COUNT if configured in board file,
- * else return CONFIG_USB_PD_PORT_MAX_COUNT
- */
-uint8_t board_get_usb_pd_port_count(void);
-#else
-static inline uint8_t board_get_usb_pd_port_count(void)
-{
- return CONFIG_USB_PD_PORT_MAX_COUNT;
-}
-#endif /* CONFIG_USB_POWER_DELIVERY */
-#endif /* CONFIG_USB_PD_PORT_MAX_COUNT */
-
-/**
- * Return true if specified PD port partner is UFP.
- *
- * @param port USB-C port number
- */
-int pd_partner_is_ufp(int port);
-
-/**
- * Return true if specified PD port is debug accessory.
- *
- * @param port USB-C port number
- */
-int pd_is_debug_acc(int port);
-
-/*
- * Notify the AP that we have entered into DisplayPort Alternate Mode. This
- * sets a DP_ALT_MODE_ENTERED MKBP event which may wake the AP.
- */
-void pd_notify_dp_alt_mode_entry(void);
-
-/*
- * Determines the PD state of the port partner according to Table 4-10 in USB PD
- * specification.
- */
-enum pd_cc_states pd_get_cc_state(
- enum tcpc_cc_voltage_status cc1, enum tcpc_cc_voltage_status cc2);
-
-/* ----- Logging ----- */
-#ifdef CONFIG_USB_PD_LOGGING
-/**
- * Record one event in the PD logging FIFO.
- *
- * @param type event type as defined by PD_EVENT_xx in ec_commands.h
- * @param size_port payload size and port num (defined by PD_LOG_PORT_SIZE)
- * @param data type-defined information
- * @param payload pointer to the optional payload (0..16 bytes)
- */
-void pd_log_event(uint8_t type, uint8_t size_port,
- uint16_t data, void *payload);
-
-/**
- * Retrieve one logged event and prepare a VDM with it.
- *
- * Used to answer the VDO_CMD_GET_LOG unstructured VDM.
- *
- * @param payload pointer to the payload data buffer (must be 7 words)
- * @return number of 32-bit words in the VDM payload.
- */
-int pd_vdm_get_log_entry(uint32_t *payload);
-#else /* CONFIG_USB_PD_LOGGING */
-static inline void pd_log_event(uint8_t type, uint8_t size_port,
- uint16_t data, void *payload) {}
-static inline int pd_vdm_get_log_entry(uint32_t *payload) { return 0; }
-#endif /* CONFIG_USB_PD_LOGGING */
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-/**
- * Prepare for a sysjump by exiting any alternate modes, if PD communication is
- * allowed.
- *
- * Note: this call will block until the PD task has finished its exit mode and
- * re-awoken the calling task.
- */
-void pd_prepare_sysjump(void);
-#endif
-
-#endif /* __CROS_EC_USB_PD_H */
diff --git a/include/usb_pd_tcpc.h b/include/usb_pd_tcpc.h
deleted file mode 100644
index 4ac22d4d86..0000000000
--- a/include/usb_pd_tcpc.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Copyright 2015 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.
- */
-
-/* USB Power delivery port controller */
-
-#ifndef __CROS_EC_USB_PD_TCPC_H
-#define __CROS_EC_USB_PD_TCPC_H
-
-#include <stdint.h>
-#include "usb_pd_tcpm.h"
-
-/* If we are a TCPC but do not a TCPM, then we implement the slave TCPCI */
-#if defined(CONFIG_USB_PD_TCPC) && !defined(CONFIG_USB_PD_TCPM_STUB)
-#define TCPCI_I2C_SLAVE
-#endif
-
-#ifdef TCPCI_I2C_SLAVE
-/* Convert TCPC address to type-C port number */
-#define TCPC_ADDR_TO_PORT(addr) ((addr) \
- - I2C_GET_ADDR(CONFIG_TCPC_I2C_BASE_ADDR_FLAGS))
-/* Check if the i2c address belongs to TCPC */
-#define ADDR_IS_TCPC(addr) (((addr) & 0x7E) \
- == I2C_GET_ADDR(CONFIG_TCPC_I2C_BASE_ADDR_FLAGS))
-#endif
-
-/**
- * Process incoming TCPCI I2C command
- *
- * @param read This is a read request. If 0, this is a write request.
- * @param len Length of incoming payload
- * @param payload Pointer to incoming and outgoing data
- * @param send_response Function to call to send response if necessary
- */
-void tcpc_i2c_process(int read, int port, int len, uint8_t *payload,
- void (*send_response)(int));
-
-/**
- * Handle VBUS wake interrupts
- *
- * @param signal The VBUS wake interrupt signal
- */
-void pd_vbus_evt_p0(enum gpio_signal signal);
-void pd_vbus_evt_p1(enum gpio_signal signal);
-
-/* Methods for TCPCI slaves (e.g. zinger) to get/set their internal state */
-int tcpc_alert_status(int port, int *alert);
-int tcpc_alert_status_clear(int port, uint16_t mask);
-int tcpc_alert_mask_set(int port, uint16_t mask);
-int tcpc_get_cc(int port, enum tcpc_cc_voltage_status *cc1,
- enum tcpc_cc_voltage_status *cc2);
-int tcpc_select_rp_value(int port, int rp);
-int tcpc_set_cc(int port, int pull);
-int tcpc_set_polarity(int port, int polarity);
-int tcpc_set_power_status_mask(int port, uint8_t mask);
-int tcpc_set_vconn(int port, int enable);
-int tcpc_set_msg_header(int port, int power_role, int data_role);
-int tcpc_set_rx_enable(int port, int enable);
-int tcpc_get_message(int port, uint32_t *payload, int *head);
-int tcpc_transmit(int port, enum tcpm_transmit_type type, uint16_t header,
- const uint32_t *data);
-int rx_buf_is_empty(int port);
-void rx_buf_clear(int port);
-
-#endif /* __CROS_EC_USB_PD_TCPC_H */
diff --git a/include/usb_pd_tcpm.h b/include/usb_pd_tcpm.h
deleted file mode 100644
index ab70c9a7f7..0000000000
--- a/include/usb_pd_tcpm.h
+++ /dev/null
@@ -1,429 +0,0 @@
-/* Copyright 2015 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.
- */
-
-/* USB Power delivery port management */
-
-#ifndef __CROS_EC_USB_PD_TCPM_H
-#define __CROS_EC_USB_PD_TCPM_H
-
-#include "ec_commands.h"
-#include "i2c.h"
-
-/* Default retry count for transmitting */
-#define PD_RETRY_COUNT 3
-
-/* Time to wait for TCPC to complete transmit */
-#define PD_T_TCPC_TX_TIMEOUT (100*MSEC)
-
-enum usbpd_cc_pin {
- USBPD_CC_PIN_1,
- USBPD_CC_PIN_2,
-};
-
-/* Detected resistor values of port partner */
-enum tcpc_cc_voltage_status {
- TYPEC_CC_VOLT_OPEN = 0,
- TYPEC_CC_VOLT_RA = 1, /* Port partner is applying Ra */
- TYPEC_CC_VOLT_RD = 2, /* Port partner is applying Rd */
- TYPEC_CC_VOLT_RP_DEF = 5, /* Port partner is applying Rp (0.5A) */
- TYPEC_CC_VOLT_RP_1_5 = 6, /* Port partner is applying Rp (1.5A) */
- TYPEC_CC_VOLT_RP_3_0 = 7, /* Port partner is applying Rp (3.0A) */
-};
-
-/* Resistor types we apply on our side of the CC lines */
-enum tcpc_cc_pull {
- TYPEC_CC_RA = 0,
- TYPEC_CC_RP = 1,
- TYPEC_CC_RD = 2,
- TYPEC_CC_OPEN = 3,
- TYPEC_CC_RA_RD = 4, /* Powered cable with Sink */
-};
-
-/* Pull-up values we apply as a SRC to advertise different current limits */
-enum tcpc_rp_value {
- TYPEC_RP_USB = 0,
- TYPEC_RP_1A5 = 1,
- TYPEC_RP_3A0 = 2,
- TYPEC_RP_RESERVED = 3,
-};
-
-enum tcpm_transmit_type {
- TCPC_TX_SOP = 0,
- TCPC_TX_SOP_PRIME = 1,
- TCPC_TX_SOP_PRIME_PRIME = 2,
- TCPC_TX_SOP_DEBUG_PRIME = 3,
- TCPC_TX_SOP_DEBUG_PRIME_PRIME = 4,
- TCPC_TX_HARD_RESET = 5,
- TCPC_TX_CABLE_RESET = 6,
- TCPC_TX_BIST_MODE_2 = 7
-};
-
-/* Number of valid Transmit Types */
-#define NUM_SOP_STAR_TYPES (TCPC_TX_SOP_DEBUG_PRIME_PRIME + 1)
-
-enum tcpc_transmit_complete {
- TCPC_TX_UNSET = -1,
- TCPC_TX_COMPLETE_SUCCESS = 0,
- TCPC_TX_COMPLETE_DISCARDED = 1,
- TCPC_TX_COMPLETE_FAILED = 2,
-};
-
-/**
- * Returns whether the sink has detected a Rp resistor on the other side.
- */
-static inline int cc_is_rp(enum tcpc_cc_voltage_status cc)
-{
- return (cc == TYPEC_CC_VOLT_RP_DEF) || (cc == TYPEC_CC_VOLT_RP_1_5) ||
- (cc == TYPEC_CC_VOLT_RP_3_0);
-}
-
-/**
- * Returns true if both CC lines are completely open.
- */
-static inline int cc_is_open(enum tcpc_cc_voltage_status cc1,
- enum tcpc_cc_voltage_status cc2)
-{
- return cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_OPEN;
-}
-
-/**
- * Returns true if we detect the port partner is a snk debug accessory.
- */
-static inline int cc_is_snk_dbg_acc(enum tcpc_cc_voltage_status cc1,
- enum tcpc_cc_voltage_status cc2)
-{
- return cc1 == TYPEC_CC_VOLT_RD && cc2 == TYPEC_CC_VOLT_RD;
-}
-
-/**
- * Returns true if the port partner is an audio accessory.
- */
-static inline int cc_is_audio_acc(enum tcpc_cc_voltage_status cc1,
- enum tcpc_cc_voltage_status cc2)
-{
- return cc1 == TYPEC_CC_VOLT_RA && cc2 == TYPEC_CC_VOLT_RA;
-}
-
-/**
- * Returns true if the port partner is presenting at least one Rd
- */
-static inline int cc_is_at_least_one_rd(enum tcpc_cc_voltage_status cc1,
- enum tcpc_cc_voltage_status cc2)
-{
- return cc1 == TYPEC_CC_VOLT_RD || cc2 == TYPEC_CC_VOLT_RD;
-}
-
-/**
- * Returns true if the port partner is presenting Rd on only one CC line.
- */
-static inline int cc_is_only_one_rd(enum tcpc_cc_voltage_status cc1,
- enum tcpc_cc_voltage_status cc2)
-{
- return cc_is_at_least_one_rd(cc1, cc2) && cc1 != cc2;
-}
-
-struct tcpm_drv {
- /**
- * Initialize TCPM driver and wait for TCPC readiness.
- *
- * @param port Type-C port number
- *
- * @return EC_SUCCESS or error
- */
- int (*init)(int port);
-
- /**
- * Release the TCPM hardware and disconnect the driver.
- * Only .init() can be called after .release().
- *
- * @param port Type-C port number
- *
- * @return EC_SUCCESS or error
- */
- int (*release)(int port);
-
- /**
- * Read the CC line status.
- *
- * @param port Type-C port number
- * @param cc1 pointer to CC status for CC1
- * @param cc2 pointer to CC status for CC2
- *
- * @return EC_SUCCESS or error
- */
- int (*get_cc)(int port, enum tcpc_cc_voltage_status *cc1,
- enum tcpc_cc_voltage_status *cc2);
-
- /**
- * Read VBUS
- *
- * @param port Type-C port number
- *
- * @return 0 => VBUS not detected, 1 => VBUS detected
- */
- int (*get_vbus_level)(int port);
-
- /**
- * Set the value of the CC pull-up used when we are a source.
- *
- * @param port Type-C port number
- * @param rp One of enum tcpc_rp_value
- *
- * @return EC_SUCCESS or error
- */
- int (*select_rp_value)(int port, int rp);
-
- /**
- * Set the CC pull resistor. This sets our role as either source or sink.
- *
- * @param port Type-C port number
- * @param pull One of enum tcpc_cc_pull
- *
- * @return EC_SUCCESS or error
- */
- int (*set_cc)(int port, int pull);
-
- /**
- * Set polarity
- *
- * @param port Type-C port number
- * @param polarity 0=> transmit on CC1, 1=> transmit on CC2
- *
- * @return EC_SUCCESS or error
- */
- int (*set_polarity)(int port, int polarity);
-
- /**
- * Set Vconn.
- *
- * @param port Type-C port number
- * @param polarity Polarity of the CC line to read
- *
- * @return EC_SUCCESS or error
- */
- int (*set_vconn)(int port, int enable);
-
- /**
- * Set PD message header to use for goodCRC
- *
- * @param port Type-C port number
- * @param power_role Power role to use in header
- * @param data_role Data role to use in header
- *
- * @return EC_SUCCESS or error
- */
- int (*set_msg_header)(int port, int power_role, int data_role);
-
- /**
- * Set RX enable flag
- *
- * @param port Type-C port number
- * @enable true for enable, false for disable
- *
- * @return EC_SUCCESS or error
- */
- int (*set_rx_enable)(int port, int enable);
-
- /**
- * Read received PD message from the TCPC
- *
- * @param port Type-C port number
- * @param payload Pointer to location to copy payload of message
- * @param header of message
- *
- * @return EC_SUCCESS or error
- */
- int (*get_message_raw)(int port, uint32_t *payload, int *head);
-
- /**
- * Transmit PD message
- *
- * @param port Type-C port number
- * @param type Transmit type
- * @param header Packet header
- * @param cnt Number of bytes in payload
- * @param data Payload
- *
- * @return EC_SUCCESS or error
- */
- int (*transmit)(int port, enum tcpm_transmit_type type, uint16_t header,
- const uint32_t *data);
-
- /**
- * TCPC is asserting alert
- *
- * @param port Type-C port number
- */
- void (*tcpc_alert)(int port);
-
- /**
- * Discharge PD VBUS on src/sink disconnect & power role swap
- *
- * @param port Type-C port number
- * @param enable Discharge enable or disable
- */
- void (*tcpc_discharge_vbus)(int port, int enable);
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- /**
- * Enable TCPC auto DRP toggling.
- *
- * @param port Type-C port number
- *
- * @return EC_SUCCESS or error
- */
- int (*drp_toggle)(int port);
-#endif
-
- /**
- * Get firmware version.
- *
- * @param port Type-C port number
- * @param live Fetch live chip info or hard-coded + cached info
- * @param info Pointer to pointer to PD chip info
- *
- * @return EC_SUCCESS or error
- */
- int (*get_chip_info)(int port, int live,
- struct ec_response_pd_chip_info_v1 **info);
-
-#ifdef CONFIG_USBC_PPC
- /**
- * Send SinkVBUS or DisableSinkVBUS command
- *
- * @param port Type-C port number
- * @enable true for enable, false for disable
- *
- * @return EC_SUCCESS or error
- */
- int (*set_snk_ctrl)(int port, int enable);
-
- /**
- * Send SourceVBUS or DisableSourceVBUS command
- *
- * @param port Type-C port number
- * @enable true for enable, false for disable
- *
- * @return EC_SUCCESS or error
- */
- int (*set_src_ctrl)(int port, int enable);
-#endif
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /**
- * Instructs the TCPC to enter into low power mode.
- *
- * NOTE: Do no use tcpc_(read|write) style helper methods in this
- * function. You must use i2c_(read|write) directly.
- *
- * @param port Type-C port number
- *
- * @return EC_SUCCESS or error
- */
- int (*enter_low_power_mode)(int port);
-#endif
-
- /**
- * Enable/Disable TCPC FRS detection
- *
- * @param port Type-C port number
- * @param enable FRS enable (true) disable (false)
- */
- void (*set_frs_enable)(int port, int enable);
-};
-
-/*
- * Macros for tcpc_config_t flags field.
- *
- * Bit 0 --> Polarity for TCPC alert. Set to 1 if alert is active high.
- * Bit 1 --> Set to 1 if TCPC alert line is open-drain instead of push-pull.
- * Bit 2 --> Polarity for TCPC reset. Set to 1 if reset line is active high.
- */
-#define TCPC_FLAGS_ALERT_ACTIVE_HIGH BIT(0)
-#define TCPC_FLAGS_ALERT_OD BIT(1)
-#define TCPC_FLAGS_RESET_ACTIVE_HIGH BIT(2)
-
-struct tcpc_config_t {
- enum ec_bus_type bus_type; /* enum ec_bus_type */
- union {
- struct i2c_info_t i2c_info;
- };
- const struct tcpm_drv *drv;
- /* See TCPC_FLAGS_* above */
- uint32_t flags;
-#ifdef CONFIG_INTEL_VIRTUAL_MUX
- /*
- * 0-3: Corresponding USB2 port number (1 ~ 15)
- * 4-7: Corresponding USB3 port number (1 ~ 15)
- */
- uint8_t usb23;
-#endif
-};
-
-#ifndef CONFIG_USB_PD_TCPC_RUNTIME_CONFIG
-extern const struct tcpc_config_t tcpc_config[];
-#else
-extern struct tcpc_config_t tcpc_config[];
-#endif
-
-/**
- * Returns the PD_STATUS_TCPC_ALERT_* mask corresponding to the TCPC ports
- * that are currently asserting ALERT.
- *
- * @return PD_STATUS_TCPC_ALERT_* mask.
- */
-uint16_t tcpc_get_alert_status(void);
-
-/**
- * Optional, set the TCPC power mode.
- *
- * @param port Type-C port number
- * @param mode 0: off/sleep, 1: on/awake
- */
-void board_set_tcpc_power_mode(int port, int mode) __attribute__((weak));
-
-/**
- * Initialize TCPC.
- *
- * @param port Type-C port number
- */
-void tcpc_init(int port);
-
-/**
- * TCPC is asserting alert
- *
- * @param port Type-C port number
- */
-void tcpc_alert_clear(int port);
-
-/**
- * Run TCPC task once. This checks for incoming messages, processes
- * any outgoing messages, and reads CC lines.
- *
- * @param port Type-C port number
- * @param evt Event type that woke up this task
- */
-int tcpc_run(int port, int evt);
-
-/**
- * Initialize board specific TCPC functions post TCPC initialization.
- *
- * @param port Type-C port number
- *
- * @return EC_SUCCESS or error
- */
-int board_tcpc_post_init(int port) __attribute__((weak));
-
-/**
- * Turn on/off VCONN power switch in board specific code.
- *
- * @param port Type-C port number
- * @param cc_pin 0:CC pin 0, 1: CC pin 1
- * @param enabled 1: Enable VCONN, 0: Disable VCONN
- *
- */
-void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled);
-
-#endif /* __CROS_EC_USB_PD_TCPM_H */