diff options
author | Tom Hughes <tomhughes@chromium.org> | 2022-09-21 14:08:36 -0700 |
---|---|---|
committer | Tom Hughes <tomhughes@chromium.org> | 2022-09-22 12:59:38 -0700 |
commit | c453fd704268ef72de871b0c5ac7a989de662334 (patch) | |
tree | fcf6ce5810f9ff9e3c8cce434812dd75492269ed /driver/tcpm/ps8xxx.c | |
parent | 6c1587ca70f558b4f96b3f0b18ad8b027d3ba99d (diff) | |
parent | 28712dae9d7ed1e694f7622cc083afa71090d4d5 (diff) | |
download | chrome-ec-firmware-fpmcu-dartmonkey-release.tar.gz |
Merge remote-tracking branch cros/main into firmware-fpmcu-dartmonkey-releasefirmware-fpmcu-dartmonkey-release
Generated by: ./util/update_release_branch.py --board dartmonkey --relevant_paths_file
./util/fingerprint-relevant-paths.txt firmware-fpmcu-dartmonkey-release
Relevant changes:
git log --oneline 6c1587ca70..28712dae9d -- board/nocturne_fp
board/dartmonkey common/fpsensor docs/fingerprint driver/fingerprint
util/getversion.sh
ded9307b79 util/getversion.sh: Fix version when not in a git repo
956055e692 board: change Google USB vendor info
71b2ef709d Update license boilerplate text in source code files
33e11afda0 Revert "fpsensor: Build fpsensor source file with C++"
c8d0360723 fpsensor: Build fpsensor source file with C++
bc113abd53 fpsensor: Fix g++ compiler error
150a58a0dc fpsensor: Fix fp_set_sensor_mode return type
b33b5ce85b fpsensor: Remove nested designators for C++ compatibility
2e864b2539 tree-wide: const-ify argv for console commands
56d8b360f9 test: Add test for get ikm failure when seed not set
3a3d6c3690 test: Add test for fpsensor trivial key failure
233e6bbd08 fpsensor_crypto: Abstract calls to hmac_SHA256
0a041b285b docs/fingerprint: Typo correction
c03fab67e2 docs/fingerprint: Fix the path of fputils.py
0b5d4baf5a util/getversion.sh: Fix empty file list handling
6e128fe760 FPMCU dev board environment with Satlab
3eb29b6aa5 builtin: Move ssize_t to sys/types.h
345d62ebd1 docs/fingerprint: Update power numbers for latest dartmonkey release
c25ffdb316 common: Conditionally support printf %l and %i modifiers
9a3c514b45 test: Add a test to check if the debugger is connected
54e603413f Move standard library tests to their own file
43fa6b4bf8 docs/fingerprint: Update power numbers for latest bloonchipper release
25536f9a84 driver/fingerprint/fpc/bep/fpc_sensor_spi.c: Format with clang-format
4face99efd driver/fingerprint/fpc/libfp/fpc_sensor_pal.h: Format with clang-format
738de2b575 trng: Rename rand to trng_rand
14b8270edd docs/fingerprint: Update dragonclaw power numbers
0b268f93d1 driver/fingerprint/fpc/libfp/fpc_private.c: Format with clang-format
f80da163f2 driver/fingerprint/fpc/libfp/fpc_private.h: Format with clang-format
a0751778f4 board/nocturne_fp/ro_workarounds.c: Format with clang-format
5e9c85c9b1 driver/fingerprint/fpc/libfp/fpc_sensor_pal.c: Format with clang-format
c1f9dd3cf8 driver/fingerprint/fpc/libfp/fpc_bio_algorithm.h: Format with clang-format
eb1e1bed8d driver/fingerprint/fpc/libfp/fpc1145_private.h: Format with clang-format
6e7b611821 driver/fingerprint/fpc/bep/fpc_bio_algorithm.h: Format with clang-format
e0589cd5e2 driver/fingerprint/fpc/bep/fpc1035_private.h: Format with clang-format
58f0246dbe board/nocturne_fp/board_ro.c: Format with clang-format
7905e556a0 common/fpsensor/fpsensor_crypto.c: Format with clang-format
21289d170c driver/fingerprint/fpc/bep/fpc1025_private.h: Format with clang-format
98a20f937e common/fpsensor/fpsensor_state.c: Format with clang-format
a2d255d8af common/fpsensor/fpsensor.c: Format with clang-format
84e53a65da board/nocturne_fp/board.h: Format with clang-format
73055eeb3f driver/fingerprint/fpc/bep/fpc_private.c: Format with clang-format
0f7b5cb509 common/fpsensor/fpsensor_private.h: Format with clang-format
1ceade6e65 driver/fingerprint/fpc/bep/fpc_private.h: Format with clang-format
dca9d74321 Revert "trng: Rename rand to trng_rand"
a6b0b3554f trng: Rename rand to trng_rand
28d0b75b70 third_party/boringssl: Remove unused header
BRANCH=None
BUG=b:244387210 b:242720240 b:215613183 b:242720910 b:236386294
BUG=b:234181908 b:244781166 b:234781655 b:234143158 b:234181908
BUG=b:237344361 b:236025198 b:234181908 b:180945056 chromium:1098010
BUG=b:246424843 b:234181908 b:131913998
TEST=`make -j buildall`
TEST=./util/run_device_tests.py --board dartmonkey
Test "aes": PASSED
Test "cec": PASSED
Test "cortexm_fpu": PASSED
Test "crc": PASSED
Test "flash_physical": PASSED
Test "flash_write_protect": PASSED
Test "fpsensor_hw": PASSED
Test "fpsensor_spi_ro": PASSED
Test "fpsensor_spi_rw": PASSED
Test "fpsensor_uart_ro": PASSED
Test "fpsensor_uart_rw": PASSED
Test "mpu_ro": PASSED
Test "mpu_rw": PASSED
Test "mutex": PASSED
Test "pingpong": PASSED
Test "printf": PASSED
Test "queue": PASSED
Test "rollback_region0": PASSED
Test "rollback_region1": PASSED
Test "rollback_entropy": PASSED
Test "rtc": PASSED
Test "sha256": PASSED
Test "sha256_unrolled": PASSED
Test "static_if": PASSED
Test "stdlib": PASSED
Test "system_is_locked_wp_on": PASSED
Test "system_is_locked_wp_off": PASSED
Test "timer_dos": PASSED
Test "utils": PASSED
Test "utils_str": PASSED
Test "panic_data_dartmonkey_v2.0.2887": PASSED
Test "panic_data_nocturne_fp_v2.2.64": PASSED
Test "panic_data_nami_fp_v2.2.144": PASSED
Force-Relevant-Builds: all
Signed-off-by: Tom Hughes <tomhughes@chromium.org>
Change-Id: I2c312583a709fedae8fe11d92c22328c3b634bc7
Diffstat (limited to 'driver/tcpm/ps8xxx.c')
-rw-r--r-- | driver/tcpm/ps8xxx.c | 352 |
1 files changed, 217 insertions, 135 deletions
diff --git a/driver/tcpm/ps8xxx.c b/driver/tcpm/ps8xxx.c index 212a7f10dd..9eb3b40b2b 100644 --- a/driver/tcpm/ps8xxx.c +++ b/driver/tcpm/ps8xxx.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,6 +8,7 @@ * * Supported TCPCs: * - PS8705 + * - PS8745 * - PS8751 * - PS8755 * - PS8805 @@ -23,7 +24,8 @@ #include "usb_mux.h" #include "usb_pd.h" -#if !defined(CONFIG_USB_PD_TCPM_PS8705) && \ +#if !defined(CONFIG_USB_PD_TCPM_PS8705) && \ + !defined(CONFIG_USB_PD_TCPM_PS8745) && \ !defined(CONFIG_USB_PD_TCPM_PS8751) && \ !defined(CONFIG_USB_PD_TCPM_PS8755) && \ !defined(CONFIG_USB_PD_TCPM_PS8805) && \ @@ -31,8 +33,7 @@ #error "Unsupported PS8xxx TCPC." #endif -#if !defined(CONFIG_USB_PD_TCPM_TCPCI) || \ - !defined(CONFIG_USB_PD_TCPM_MUX) || \ +#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" @@ -55,10 +56,10 @@ #endif /* CONFIG_USB_PD_TCPM_PS8751_CUSTOM_MUX_DRIVER */ -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) -#define PS8XXX_I2C_RECOVERY_DELAY_MS 10 +#define PS8XXX_I2C_RECOVERY_DELAY_MS 10 /* * The product_id per ports here is expected to be set in callback function - @@ -94,7 +95,7 @@ static uint64_t hpd_deadline[CONFIG_USB_PD_PORT_MAX_COUNT]; void ps8xxx_wake_from_standby(const struct usb_mux *me); -#if defined(CONFIG_USB_PD_TCPM_PS8705) || \ +#if defined(CONFIG_USB_PD_TCPM_PS8705) || \ defined(CONFIG_USB_PD_TCPM_PS8751) || \ defined(CONFIG_USB_PD_TCPM_PS8755) || \ defined(CONFIG_USB_PD_TCPM_PS8805) @@ -122,7 +123,7 @@ static int ps8xxx_addr_dci_disable(int port, int i2c_addr, int i2c_reg) } #endif /* CONFIG_USB_PD_TCPM_PS875[15] || CONFIG_USB_PD_TCPM_PS8[78]05 */ -#if defined(CONFIG_USB_PD_TCPM_PS8705) || \ +#if defined(CONFIG_USB_PD_TCPM_PS8705) || \ defined(CONFIG_USB_PD_TCPM_PS8755) || \ defined(CONFIG_USB_PD_TCPM_PS8805) static int ps8705_dci_disable(int port) @@ -166,13 +167,13 @@ static int ps8751_dci_disable(int port) } #endif /* CONFIG_USB_PD_TCPM_PS8751 */ -#ifdef CONFIG_USB_PD_TCPM_PS8815 +#if defined(CONFIG_USB_PD_TCPM_PS8815) || defined(CONFIG_USB_PD_TCPM_PS8745) static int ps8815_dci_disable(int port) { - /* DCI is disabled on the ps8815 */ + /* DCI is disabled on the ps8815 and ps8745 */ return EC_SUCCESS; } -#endif /* CONFIG_USB_PD_TCPM_PS8815 */ +#endif /* CONFIG_USB_PD_TCPM_PS8815 || CONFIG_USB_PD_TCPM_PS8745 */ #ifdef CONFIG_USB_PD_TCPM_PS8805 static int ps8805_gpio_mask[] = { @@ -191,8 +192,8 @@ int ps8805_gpio_set_level(int port, enum ps8805_gpio signal, int level) return EC_ERROR_INVAL; rv = i2c_read8(tcpc_config[port].i2c_info.port, - PS8805_VENDOR_DEFINED_I2C_ADDR, - PS8805_REG_GPIO_CONTROL, ®val); + PS8805_VENDOR_DEFINED_I2C_ADDR, PS8805_REG_GPIO_CONTROL, + ®val); if (rv) return rv; @@ -203,8 +204,8 @@ int ps8805_gpio_set_level(int port, enum ps8805_gpio signal, int level) regval &= ~mask; return i2c_write8(tcpc_config[port].i2c_info.port, - PS8805_VENDOR_DEFINED_I2C_ADDR, - PS8805_REG_GPIO_CONTROL, regval); + PS8805_VENDOR_DEFINED_I2C_ADDR, + PS8805_REG_GPIO_CONTROL, regval); } int ps8805_gpio_get_level(int port, enum ps8805_gpio signal, int *level) @@ -216,8 +217,8 @@ int ps8805_gpio_get_level(int port, enum ps8805_gpio signal, int *level) return EC_ERROR_INVAL; rv = i2c_read8(tcpc_config[port].i2c_info.port, - PS8805_VENDOR_DEFINED_I2C_ADDR, - PS8805_REG_GPIO_CONTROL, ®val); + PS8805_VENDOR_DEFINED_I2C_ADDR, PS8805_REG_GPIO_CONTROL, + ®val); if (rv) return rv; *level = !!(regval & ps8805_gpio_mask[signal]); @@ -245,49 +246,42 @@ struct ps8xxx_variant_map { */ static struct ps8xxx_variant_map variant_map[] = { #ifdef CONFIG_USB_PD_TCPM_PS8705 - { - PS8705_PRODUCT_ID, - ps8705_dci_disable, - { - [REG_FW_VER] = 0x82, - } - }, + { PS8705_PRODUCT_ID, + ps8705_dci_disable, + { + [REG_FW_VER] = 0x82, + } }, +#endif +#ifdef CONFIG_USB_PD_TCPM_PS8745 + { PS8745_PRODUCT_ID, ps8815_dci_disable, { [REG_FW_VER] = 0x82 } }, #endif #ifdef CONFIG_USB_PD_TCPM_PS8751 - { - PS8751_PRODUCT_ID, - ps8751_dci_disable, - { - [REG_FW_VER] = 0x90, - } - }, + { PS8751_PRODUCT_ID, + ps8751_dci_disable, + { + [REG_FW_VER] = 0x90, + } }, #endif #ifdef CONFIG_USB_PD_TCPM_PS8755 - { - PS8755_PRODUCT_ID, - ps8705_dci_disable, - { - [REG_FW_VER] = 0x82, - } - }, + { PS8755_PRODUCT_ID, + ps8705_dci_disable, + { + [REG_FW_VER] = 0x82, + } }, #endif #ifdef CONFIG_USB_PD_TCPM_PS8805 - { - PS8805_PRODUCT_ID, - ps8705_dci_disable, - { - [REG_FW_VER] = 0x82, - } - }, + { PS8805_PRODUCT_ID, + ps8705_dci_disable, + { + [REG_FW_VER] = 0x82, + } }, #endif #ifdef CONFIG_USB_PD_TCPM_PS8815 - { - PS8815_PRODUCT_ID, - ps8815_dci_disable, - { - [REG_FW_VER] = 0x82, - } - }, + { PS8815_PRODUCT_ID, + ps8815_dci_disable, + { + [REG_FW_VER] = 0x82, + } }, #endif }; @@ -300,8 +294,7 @@ static int get_reg_by_product(const int port, return INT32_MAX; for (i = 0; i < ARRAY_SIZE(variant_map); i++) { - if (product_id[port] == - variant_map[i].product_id) { + if (product_id[port] == variant_map[i].product_id) { return variant_map[i].reg_map[reg]; } } @@ -341,8 +334,7 @@ static int dp_set_irq(const struct usb_mux *me, int enable) } /* LCOV_EXCL_START */ -__overridable -uint16_t board_get_ps8xxx_product_id(int port) +__overridable uint16_t board_get_ps8xxx_product_id(int port) { /* Board supporting multiple chip sources in ps8xxx.c MUST override this * function to judge the real chip source for this board. For example, @@ -354,6 +346,8 @@ uint16_t board_get_ps8xxx_product_id(int port) return 0; } else if (IS_ENABLED(CONFIG_USB_PD_TCPM_PS8705)) { return PS8705_PRODUCT_ID; + } else if (IS_ENABLED(CONFIG_USB_PD_TCPM_PS8745)) { + return PS8745_PRODUCT_ID; } else if (IS_ENABLED(CONFIG_USB_PD_TCPM_PS8751)) { return PS8751_PRODUCT_ID; } else if (IS_ENABLED(CONFIG_USB_PD_TCPM_PS8755)) { @@ -385,8 +379,7 @@ bool check_ps8755_chip(int port) } void ps8xxx_tcpc_update_hpd_status(const struct usb_mux *me, - mux_state_t mux_state, - bool *ack_required) + mux_state_t mux_state, bool *ack_required) { int port = me->usb_port; int hpd_lvl = (mux_state & USB_PD_MUX_HPD_LVL) ? 1 : 0; @@ -421,12 +414,12 @@ 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); + 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); @@ -438,7 +431,7 @@ static int ps8xxx_tcpc_bist_mode_2(int port) } static int ps8xxx_tcpm_transmit(int port, enum tcpci_msg_type type, - uint16_t header, const uint32_t *data) + uint16_t header, const uint32_t *data) { if (type == TCPCI_MSG_TX_BIST_MODE_2) return ps8xxx_tcpc_bist_mode_2(port); @@ -472,7 +465,7 @@ static void ps8xxx_role_control_delay(int port) #ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE static int ps8xxx_set_role_ctrl(int port, enum tcpc_drp drp, - enum tcpc_rp_value rp, enum tcpc_cc_pull pull) + enum tcpc_rp_value rp, enum tcpc_cc_pull pull) { int rv; @@ -494,12 +487,13 @@ static int ps8xxx_tcpc_drp_toggle(int port) int opposite_pull; /* - * Workaround for PS8805/PS8815, which can't restart Connection + * Workaround for PS8805/PS8815/PS8745, which can't restart Connection * Detection if the partner already presents pull. Now starts with * the opposite pull. Check b/149570002. */ if (product_id[port] == PS8805_PRODUCT_ID || - product_id[port] == PS8815_PRODUCT_ID) { + product_id[port] == PS8815_PRODUCT_ID || + product_id[port] == PS8745_PRODUCT_ID) { if (ps8815_disable_rp_detect[port]) { CPRINTS("TCPC%d: rearm Rp disable detect on connect", port); @@ -518,7 +512,7 @@ static int ps8xxx_tcpc_drp_toggle(int port) /* Set auto drp toggle, starting with the opposite pull */ rv |= ps8xxx_set_role_ctrl(port, TYPEC_DRP, TYPEC_RP_USB, - opposite_pull); + opposite_pull); /* Set Look4Connection command */ rv |= tcpc_write(port, TCPC_REG_COMMAND, @@ -532,19 +526,26 @@ static int ps8xxx_tcpc_drp_toggle(int port) #endif #ifdef CONFIG_USB_PD_TCPM_PS8805_FORCE_DID -static int ps8805_make_device_id(int port, int *id) +static int ps8805_make_device_id(int port, int *id, int live) { + static int cached_chip_revision[CONFIG_USB_PD_PORT_MAX_COUNT]; + static bool cache_valid[CONFIG_USB_PD_PORT_MAX_COUNT]; int p0_addr; int val; int status; - p0_addr = PS8751_P3_TO_P0_FLAGS(tcpc_config[port].i2c_info.addr_flags); + if (live || !cache_valid[port]) { + p0_addr = PS8751_P3_TO_P0_FLAGS( + tcpc_config[port].i2c_info.addr_flags); + status = tcpc_addr_read(port, p0_addr, + PS8805_P0_REG_CHIP_REVISION, &val); + if (status != EC_SUCCESS) + return status; + cached_chip_revision[port] = val; + cache_valid[port] = true; + } - status = tcpc_addr_read(port, p0_addr, PS8805_P0_REG_CHIP_REVISION, - &val); - if (status != EC_SUCCESS) - return status; - switch (val & 0xF0) { + switch (cached_chip_revision[port] & 0xF0) { case 0x00: /* A2 chip */ *id = 1; break; @@ -570,21 +571,27 @@ static int ps8805_make_device_id(int port, int *id) * The ps8815 A2 reports device ID 0x0001 instead of 0x0003 when the * firmware is bad (mis-programmed). */ -static int ps8815_make_device_id(int port, int *id) +static int ps8815_make_device_id(int port, int *id, int live) { + static int cached_hw_revision[CONFIG_USB_PD_PORT_MAX_COUNT]; + static bool cache_valid[CONFIG_USB_PD_PORT_MAX_COUNT]; int p1_addr; int val; int status; - /* P1 registers are always accessible on PS8815 */ - p1_addr = PS8751_P3_TO_P1_FLAGS(tcpc_config[port].i2c_info.addr_flags); - - status = tcpc_addr_read16(port, p1_addr, PS8815_P1_REG_HW_REVISION, - &val); - if (status != EC_SUCCESS) - return status; + if (live || !cache_valid[port]) { + /* P1 registers are always accessible on PS8815 */ + p1_addr = PS8751_P3_TO_P1_FLAGS( + tcpc_config[port].i2c_info.addr_flags); + status = tcpc_addr_read16(port, p1_addr, + PS8815_P1_REG_HW_REVISION, &val); + if (status != EC_SUCCESS) + return status; + cached_hw_revision[port] = val; + cache_valid[port] = true; + } - switch (val) { + switch (cached_hw_revision[port]) { case 0x0a00: *id = 1; break; @@ -601,6 +608,52 @@ static int ps8815_make_device_id(int port, int *id) } #endif +#ifdef CONFIG_USB_PD_TCPM_PS8745_FORCE_ID +/* + * Some PS8745 firmwares report the same product/device ID and chip rev as + * PS8815-A2. This function probes vendor-specific registers to determine + * whether the device is a PS8815 or PS8745 and updates the IDs pointed to by + * the parameters to be the correct IDs for the detected chip. + * + * See b/236761058 and the PS8xxx TCPC Family Chip Revision Guide (v0.2) + */ +static int ps8745_make_device_id(int port, uint16_t *pid, uint16_t *did, + int live) +{ + static int cached_reg_id[CONFIG_USB_PD_PORT_MAX_COUNT]; + static bool cache_valid[CONFIG_USB_PD_PORT_MAX_COUNT]; + int status; + int val; + + if (live || !cache_valid[port]) { + status = tcpc_addr_read( + port, + PS8751_P3_TO_P0_FLAGS( + tcpc_config[port].i2c_info.addr_flags), + PS8815_P0_REG_ID, &val); + if (status != EC_SUCCESS) + return status; + cached_reg_id[port] = val; + cache_valid[port] = true; + } + + if (*pid == PS8815_PRODUCT_ID && (cached_reg_id[port] & BIT(1)) != 0) { + /* PS8815 with this bit set is actually PS8745 */ + *pid = PS8745_PRODUCT_ID; + } + + if (*pid == PS8745_PRODUCT_ID && *did == 0x0003) { + /* + * Some versions report the correct product ID but the + * device ID is still for PS8815-A2. + */ + *did = 0x0006; + } + + return EC_SUCCESS; +} +#endif + /* * The ps8815 can take up to 50ms (FW_INIT_DELAY_MS) to fully wake up * from sleep/low power mode - specially when it contains an application @@ -645,8 +698,10 @@ static int ps8xxx_lpm_recovery_delay(int port) } static int ps8xxx_get_chip_info(int port, int live, - struct ec_response_pd_chip_info_v1 *chip_info) + struct ec_response_pd_chip_info_v1 *chip_info) { + static int cached_fw_version[CONFIG_USB_PD_PORT_MAX_COUNT]; + static bool cache_valid[CONFIG_USB_PD_PORT_MAX_COUNT]; int val; int reg; int rv = tcpci_get_chip_info(port, live, chip_info); @@ -668,10 +723,24 @@ static int ps8xxx_get_chip_info(int port, int live, chip_info->product_id = product_id[port]; } +#ifdef CONFIG_USB_PD_TCPM_PS8745_FORCE_ID + /* device ID 3 is PS8815 and might be misreported */ + if (chip_info->product_id == PS8815_PRODUCT_ID || + chip_info->device_id == 0x0003) { + uint16_t pid = chip_info->product_id; + uint16_t did = chip_info->device_id; + + rv = ps8745_make_device_id(port, &pid, &did, live); + chip_info->product_id = pid; + chip_info->device_id = did; + if (rv != EC_SUCCESS) + return rv; + } +#endif #ifdef CONFIG_USB_PD_TCPM_PS8805_FORCE_DID if (chip_info->product_id == PS8805_PRODUCT_ID && chip_info->device_id == 0x0001) { - rv = ps8805_make_device_id(port, &val); + rv = ps8805_make_device_id(port, &val, live); if (rv != EC_SUCCESS) return rv; chip_info->device_id = val; @@ -680,24 +749,28 @@ static int ps8xxx_get_chip_info(int port, int live, #ifdef CONFIG_USB_PD_TCPM_PS8815_FORCE_DID if (chip_info->product_id == PS8815_PRODUCT_ID && chip_info->device_id == 0x0001) { - rv = ps8815_make_device_id(port, &val); + rv = ps8815_make_device_id(port, &val, live); if (rv != EC_SUCCESS) return rv; chip_info->device_id = val; } #endif - reg = get_reg_by_product(port, REG_FW_VER); - rv = tcpc_read(port, reg, &val); - if (rv != EC_SUCCESS) - return rv; - chip_info->fw_version_number = val; + if (live || !cache_valid[port]) { + reg = get_reg_by_product(port, REG_FW_VER); + rv = tcpc_read(port, reg, &val); + if (rv != EC_SUCCESS) + return rv; + cached_fw_version[port] = val; + cache_valid[port] = true; + } + chip_info->fw_version_number = cached_fw_version[port]; /* Treat unexpected values as error (FW not initiated from reset) */ - if (live && ( - chip_info->vendor_id != PS8XXX_VENDOR_ID || - chip_info->product_id != board_get_ps8xxx_product_id(port) || - chip_info->fw_version_number == 0)) + if (live && + (chip_info->vendor_id != PS8XXX_VENDOR_ID || + chip_info->product_id != board_get_ps8xxx_product_id(port) || + chip_info->fw_version_number == 0)) return EC_ERROR_UNKNOWN; #if defined(CONFIG_USB_PD_TCPM_PS8751) && \ @@ -716,12 +789,13 @@ static int ps8xxx_get_chip_info(int port, int live, static int ps8xxx_enter_low_power_mode(int port) { /* - * PS8751/PS8815 has the auto sleep function that enters + * PS8751/PS8815/PS8745 has the auto sleep function that enters * low power mode on its own in ~2 seconds. Other chips * don't have it. Stub it out for PS8751/PS8815. */ if (product_id[port] == PS8751_PRODUCT_ID || - product_id[port] == PS8815_PRODUCT_ID) + product_id[port] == PS8815_PRODUCT_ID || + product_id[port] == PS8745_PRODUCT_ID) return EC_SUCCESS; return tcpci_enter_low_power_mode(port); @@ -736,8 +810,7 @@ __maybe_unused static int ps8815_tcpc_fast_role_swap_enable(int port, if (!tcpm_tcpc_has_frs_control(port)) return EC_SUCCESS; - status = tcpc_update8(port, - PS8815_REG_RESERVED_F4, + status = tcpc_update8(port, PS8815_REG_RESERVED_F4, PS8815_REG_RESERVED_F4_FRS_EN, enable ? MASK_SET : MASK_CLR); if (status != EC_SUCCESS) @@ -816,7 +889,8 @@ __maybe_unused static int ps8815_disable_rp_detect_workaround_check(int port) } __overridable void board_ps8xxx_tcpc_init(int port) -{} +{ +} static int ps8xxx_tcpm_init(int port) { @@ -837,7 +911,10 @@ static int ps8xxx_tcpm_init(int port) status = ps8815_disable_rp_detect_workaround_check(port); if (status != EC_SUCCESS) return status; + } + if (IS_ENABLED(CONFIG_USB_PD_TCPM_PS8745) || + IS_ENABLED(CONFIG_USB_PD_TCPM_PS8815)) { /* * NOTE(b/183127346): Enable FRS sequence: * @@ -848,8 +925,7 @@ static int ps8xxx_tcpm_init(int port) * set reg 0xf4.FRS_EN (drive FRS GPIO to PPC) */ if (tcpm_tcpc_has_frs_control(port)) { - status = tcpc_update8(port, - PS8815_REG_RESERVED_D1, + status = tcpc_update8(port, PS8815_REG_RESERVED_D1, PS8815_REG_RESERVED_D1_FRS_EN, MASK_SET); if (status != EC_SUCCESS) @@ -884,7 +960,7 @@ static int ps8xxx_tcpm_init(int port) * delay will allow the transient to disappear. */ static int ps8751_get_gcc(int port, enum tcpc_cc_voltage_status *cc1, - enum tcpc_cc_voltage_status *cc2) + enum tcpc_cc_voltage_status *cc2) { int rv; int status; @@ -932,7 +1008,7 @@ static int ps8xxx_tcpm_set_cc(int port, int pull) } static int ps8xxx_tcpm_get_cc(int port, enum tcpc_cc_voltage_status *cc1, - enum tcpc_cc_voltage_status *cc2) + enum tcpc_cc_voltage_status *cc2) { #ifdef CONFIG_USB_PD_TCPM_PS8751 if (product_id[port] == PS8751_PRODUCT_ID) @@ -957,39 +1033,41 @@ static int ps8xxx_tcpm_set_vconn(int port, int enable) } const struct tcpm_drv ps8xxx_tcpm_drv = { - .init = ps8xxx_tcpm_init, - .release = ps8xxx_tcpm_release, - .get_cc = ps8xxx_tcpm_get_cc, + .init = ps8xxx_tcpm_init, + .release = ps8xxx_tcpm_release, + .get_cc = ps8xxx_tcpm_get_cc, #ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC - .check_vbus_level = tcpci_tcpm_check_vbus_level, + .check_vbus_level = tcpci_tcpm_check_vbus_level, #endif - .select_rp_value = tcpci_tcpm_select_rp_value, - .set_cc = ps8xxx_tcpm_set_cc, - .set_polarity = tcpci_tcpm_set_polarity, + .select_rp_value = tcpci_tcpm_select_rp_value, + .set_cc = ps8xxx_tcpm_set_cc, + .set_polarity = tcpci_tcpm_set_polarity, #ifdef CONFIG_USB_PD_DECODE_SOP - .sop_prime_enable = tcpci_tcpm_sop_prime_enable, + .sop_prime_enable = tcpci_tcpm_sop_prime_enable, #endif - .set_vconn = ps8xxx_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, + .set_vconn = ps8xxx_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, + .tcpc_discharge_vbus = tcpci_tcpc_discharge_vbus, #endif #ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - .drp_toggle = ps8xxx_tcpc_drp_toggle, + .drp_toggle = ps8xxx_tcpc_drp_toggle, #endif - .get_chip_info = ps8xxx_get_chip_info, - .set_snk_ctrl = tcpci_tcpm_set_snk_ctrl, - .set_src_ctrl = tcpci_tcpm_set_src_ctrl, + .get_chip_info = ps8xxx_get_chip_info, + .set_snk_ctrl = tcpci_tcpm_set_snk_ctrl, + .set_src_ctrl = tcpci_tcpm_set_src_ctrl, #ifdef CONFIG_USB_PD_TCPC_LOW_POWER - .enter_low_power_mode = ps8xxx_enter_low_power_mode, + .enter_low_power_mode = ps8xxx_enter_low_power_mode, #endif - .set_bist_test_mode = tcpci_set_bist_test_mode, -#if defined(CONFIG_USB_PD_FRS) && defined(CONFIG_USB_PD_TCPM_PS8815) - .set_frs_enable = ps8815_tcpc_fast_role_swap_enable, + .set_bist_test_mode = tcpci_set_bist_test_mode, + .get_bist_test_mode = &tcpci_get_bist_test_mode, +#if defined(CONFIG_USB_PD_FRS) && (defined(CONFIG_USB_PD_TCPM_PS8815) || \ + defined(CONFIG_USB_PD_TCPM_PS8745)) + .set_frs_enable = ps8815_tcpc_fast_role_swap_enable, #endif }; @@ -1039,6 +1117,10 @@ void ps8xxx_wake_from_standby(const struct usb_mux *me) static int ps8xxx_mux_set(const struct usb_mux *me, mux_state_t mux_state, bool *ack_required) { + /* This driver treats safe mode as none */ + if (mux_state == USB_PD_MUX_SAFE_MODE) + mux_state = USB_PD_MUX_NONE; + if (product_id[me->usb_port] == PS8751_PRODUCT_ID && me->flags & USB_MUX_FLAG_NOT_TCPC) { ps8xxx_wake_from_standby(me); @@ -1049,11 +1131,11 @@ static int ps8xxx_mux_set(const struct usb_mux *me, mux_state_t mux_state, * setting mux breaks SuperSpeed connection. */ if (mux_state != USB_PD_MUX_NONE) - RETURN_ERROR(mux_write(me, TCPC_REG_ROLE_CTRL, - TCPC_REG_ROLE_CTRL_SET(TYPEC_NO_DRP, - TYPEC_RP_USB, - TYPEC_CC_RD, - TYPEC_CC_RD))); + RETURN_ERROR( + mux_write(me, TCPC_REG_ROLE_CTRL, + TCPC_REG_ROLE_CTRL_SET( + TYPEC_NO_DRP, TYPEC_RP_USB, + TYPEC_CC_RD, TYPEC_CC_RD))); } return tcpci_tcpm_mux_set(me, mux_state, ack_required); |