diff options
author | Jack Rosenthal <jrosenth@chromium.org> | 2021-11-04 12:11:58 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-11-05 04:22:34 +0000 |
commit | 252457d4b21f46889eebad61d4c0a65331919cec (patch) | |
tree | 01856c4d31d710b20e85a74c8d7b5836e35c3b98 /driver/tcpm | |
parent | 08f5a1e6fc2c9467230444ac9b582dcf4d9f0068 (diff) | |
download | chrome-ec-stabilize-14695.85.B-ish.tar.gz |
ish: Trim down the release branchstabilize-wristpin-14469.59.B-ishstabilize-voshyr-14637.B-ishstabilize-quickfix-14695.187.B-ishstabilize-quickfix-14695.124.B-ishstabilize-quickfix-14526.91.B-ishstabilize-14695.85.B-ishstabilize-14695.107.B-ishstabilize-14682.B-ishstabilize-14633.B-ishstabilize-14616.B-ishstabilize-14589.B-ishstabilize-14588.98.B-ishstabilize-14588.14.B-ishstabilize-14588.123.B-ishstabilize-14536.B-ishstabilize-14532.B-ishstabilize-14528.B-ishstabilize-14526.89.B-ishstabilize-14526.84.B-ishstabilize-14526.73.B-ishstabilize-14526.67.B-ishstabilize-14526.57.B-ishstabilize-14498.B-ishstabilize-14496.B-ishstabilize-14477.B-ishstabilize-14469.9.B-ishstabilize-14469.8.B-ishstabilize-14469.58.B-ishstabilize-14469.41.B-ishstabilize-14442.B-ishstabilize-14438.B-ishstabilize-14411.B-ishstabilize-14396.B-ishstabilize-14395.B-ishstabilize-14388.62.B-ishstabilize-14388.61.B-ishstabilize-14388.52.B-ishstabilize-14385.B-ishstabilize-14345.B-ishstabilize-14336.B-ishstabilize-14333.B-ishrelease-R99-14469.B-ishrelease-R98-14388.B-ishrelease-R102-14695.B-ishrelease-R101-14588.B-ishrelease-R100-14526.B-ishfirmware-cherry-14454.B-ishfirmware-brya-14505.B-ishfirmware-brya-14505.71.B-ishfactory-kukui-14374.B-ishfactory-guybrush-14600.B-ishfactory-cherry-14455.B-ishfactory-brya-14517.B-ish
In the interest of making long-term branch maintenance incur as little
technical debt on us as possible, we should not maintain any files on
the branch we are not actually using.
This has the added effect of making it extremely clear when merging CLs
from the main branch when changes have the possibility to affect us.
The follow-on CL adds a convenience script to actually pull updates from
the main branch and generate a CL for the update.
BUG=b:204206272
BRANCH=ish
TEST=make BOARD=arcada_ish && make BOARD=drallion_ish
Signed-off-by: Jack Rosenthal <jrosenth@chromium.org>
Change-Id: I17e4694c38219b5a0823e0a3e55a28d1348f4b18
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3262038
Reviewed-by: Jett Rink <jettrink@chromium.org>
Reviewed-by: Tom Hughes <tomhughes@chromium.org>
Diffstat (limited to 'driver/tcpm')
34 files changed, 0 insertions, 12866 deletions
diff --git a/driver/tcpm/anx7447.c b/driver/tcpm/anx7447.c deleted file mode 100644 index 9a9a3c7971..0000000000 --- a/driver/tcpm/anx7447.c +++ /dev/null @@ -1,861 +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 "tcpm/tcpci.h" -#include "tcpm/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 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_addr_flags; -}; - -struct anx_usb_mux { - int state; -}; - -static int anx7447_mux_set(const struct usb_mux *me, mux_state_t mux_state, - bool *ack_required); - -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 addresses, TCPC address and - * SPI address. The registers of TCPC address are partly compliant - * with standard USB TCPC specification, and the registers in SPI - * 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 - * address because its 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 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_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_addr_flags, - reg, val); -#ifdef CONFIG_USB_PD_TCPC_LOW_POWER - pd_device_accessed(port); -#endif - return rv; -} - -void anx7447_hpd_mode_init(int port) -{ - int reg, rv; - - rv = anx7447_reg_read(port, ANX7447_REG_HPD_CTRL_0, ®); - if (rv) - return; - - /* - * Set ANX7447_REG_HPD_MODE bit as 0, then the TCPC will generate the - * HPD pulse from internal timer (by using ANX7447_REG_HPD_IRQ0) - * instead of using the ANX7447_REG_HPD_OUT to set the HPD IRQ signal. - */ - reg &= ~(ANX7447_REG_HPD_MODE | ANX7447_REG_HPD_PLUG | - ANX7447_REG_HPD_UNPLUG); - 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, ®); - 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, ®); - if (rv) - return; - - /* - * When ANX7447_REG_HPD_MODE is 1, use ANX7447_REG_HPD_OUT - * to generate HPD event, otherwise use ANX7447_REG_HPD_UNPLUG - * and ANX7447_REG_HPD_PLUG. - */ - if (hpd_lvl) { - reg &= ~ANX7447_REG_HPD_UNPLUG; - reg |= ANX7447_REG_HPD_PLUG; - } else { - reg &= ~ANX7447_REG_HPD_PLUG; - reg |= ANX7447_REG_HPD_UNPLUG; - } - 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; - const struct usb_mux *me = &usb_muxes[port]; - bool unused; - - ASSERT(port < CONFIG_USB_PD_PORT_MAX_COUNT); - - memset(&anx[port], 0, sizeof(struct anx_state)); - - /* - * find corresponding anx7447 SPI address according to - * specified TCPC address - */ - for (i = 0; i < ARRAY_SIZE(anx7447_i2c_addrs_flags); i++) { - if (I2C_STRIP_FLAGS(tcpc_config[port].i2c_info.addr_flags) == - I2C_STRIP_FLAGS( - anx7447_i2c_addrs_flags[i].tcpc_addr_flags)) { - anx[port].i2c_addr_flags = - anx7447_i2c_addrs_flags[i].spi_addr_flags; - break; - } - } - if (!I2C_STRIP_FLAGS(anx[port].i2c_addr_flags)) { - ccprintf("TCPC I2C addr 0x%x is invalid for ANX7447\n", - I2C_STRIP_FLAGS(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, ®); - if (rv) - return rv; - reg &= ~ANX7447_REG_ENABLE_VBUS_PROTECT; - rv = tcpc_write(port, ANX7447_REG_TCPC_CTRL_2, reg); - if (rv) - return rv; - - /* - * Specifically disable voltage alarms, as VBUS_VOLTAGE_ALARM_HI may - * trigger repeatedly despite being masked (b/153989733) - */ - rv = tcpc_update16(port, TCPC_REG_POWER_CTRL, - TCPC_REG_POWER_CTRL_VBUS_VOL_MONITOR_DIS, MASK_SET); - if (rv) - return rv; - - /* ADC enable, use to monitor VBUS voltage */ - rv = tcpc_read(port, ANX7447_REG_ADC_CTRL_1, ®); - 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, ®); - 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, ®); - 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); - if (rv) - return rv; - -#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 - */ - while ((me != NULL) && (me->driver != &anx7447_usb_mux_driver)) - me = me->next_mux; - - /* - * Note that bypassing the usb_mux API is okay for internal driver calls - * since the task calling init already holds this port's mux lock. - */ - if (me != NULL && - !(me->flags & USB_MUX_FLAG_NOT_TCPC)) - rv = anx7447_mux_set(me, USB_PD_MUX_NONE, &unused); -#endif /* CONFIG_USB_PD_TCPM_MUX */ - - return rv; -} - -static int anx7447_release(int port) -{ - return EC_SUCCESS; -} - -#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) -{ - /* process and clear alert status */ - tcpci_tcpc_alert(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(const struct usb_mux *me, - mux_state_t mux_state) -{ - int reg = 0; - int port = me->usb_port; - int hpd_lvl = (mux_state & USB_PD_MUX_HPD_LVL) ? 1 : 0; - int hpd_irq = (mux_state & USB_PD_MUX_HPD_IRQ) ? 1 : 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(!(me->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); - - /* - * For generate hardware HPD IRQ, need clear bit - * ANX7447_REG_HPD_IRQ0 first, then set it. This bit is not - * write clear. - */ - anx7447_reg_read(port, ANX7447_REG_HPD_CTRL_0, ®); - reg &= ~ANX7447_REG_HPD_IRQ0; - anx7447_reg_write(port, ANX7447_REG_HPD_CTRL_0, reg); - reg |= ANX7447_REG_HPD_IRQ0; - 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(const struct usb_mux *me) -{ - int port = me->usb_port; - bool unused; - - ASSERT(port < CONFIG_USB_PD_PORT_MAX_COUNT); - - memset(&mux[port], 0, sizeof(struct anx_usb_mux)); - - /* init hpd status */ - anx7447_hpd_mode_init(port); - anx7447_set_hpd_level(port, 0); - anx7447_hpd_output_en(port); - - /* - * ANX initializes its muxes to (USB_PD_MUX_USB_ENABLED | - * USB_PD_MUX_DP_ENABLED) when reinitialized, we need to force - * initialize it to USB_PD_MUX_NONE - */ - return anx7447_mux_set(me, USB_PD_MUX_NONE, &unused); -} - -#ifdef CONFIG_USB_PD_TCPM_ANX7447_AUX_PU_PD -static void anx7447_mux_safemode(const struct usb_mux *me, int on_off) -{ - int reg; - - mux_read(me, ANX7447_REG_ANALOG_CTRL_9, ®); - - if (on_off) - reg |= ANX7447_REG_SAFE_MODE; - else - reg &= ~(ANX7447_REG_SAFE_MODE); - - mux_write(me, ANX7447_REG_ANALOG_CTRL_9, reg); - CPRINTS("C%d set mux to safemode %s, reg = 0x%x", - me->usb_port, (on_off) ? "on" : "off", reg); -} - -static inline void anx7447_configure_aux_src(const struct usb_mux *me, - int on_off) -{ - int reg; - - mux_read(me, ANX7447_REG_ANALOG_CTRL_9, ®); - - if (on_off) - reg |= ANX7447_REG_R_AUX_RES_PULL_SRC; - else - reg &= ~(ANX7447_REG_R_AUX_RES_PULL_SRC); - - mux_write(me, ANX7447_REG_ANALOG_CTRL_9, reg); - - CPRINTS("C%d set aux_src to %s, reg = 0x%x", - me->usb_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(const struct usb_mux *me, mux_state_t mux_state, - bool *ack_required) -{ - int cc_direction; - mux_state_t mux_type; - int sw_sel = 0x00, aux_sw = 0x00; - int rv; - int port = me->usb_port; - - /* This driver does not use host command ACKs */ - *ack_required = false; - - cc_direction = mux_state & USB_PD_MUX_POLARITY_INVERTED; - mux_type = mux_state & USB_PD_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 == USB_PD_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 == USB_PD_MUX_DP_ENABLED) { - /* 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 == USB_PD_MUX_USB_ENABLED) { - /* ssrxp<->b11, ssrxn<->b10, sstxp<->a2, sstxn<->a3 */ - sw_sel = 0x20; - } - } else { - /* cc2 connection */ - if (mux_type == USB_PD_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 == USB_PD_MUX_DP_ENABLED) { - /* 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 == USB_PD_MUX_USB_ENABLED) { - /* 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(me, 1); -#endif - rv = mux_write(me, ANX7447_REG_TCPC_SWITCH_0, sw_sel); - rv |= mux_write(me, ANX7447_REG_TCPC_SWITCH_1, sw_sel); - rv |= mux_write(me, 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 != USB_PD_MUX_NONE) { - anx7447_configure_aux_src(me, 1); - anx7447_mux_safemode(me, 0); - } else - anx7447_configure_aux_src(me, 0); -#endif - - return rv; -} - -/* current mux state */ -static int anx7447_mux_get(const struct usb_mux *me, mux_state_t *mux_state) -{ - int port = me->usb_port; - - *mux_state = mux[port].state; - - return EC_SUCCESS; -} -#endif /* CONFIG_USB_PD_TCPM_MUX */ - -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE -static int anx7447_tcpc_drp_toggle(int port) -{ - int rv, reg; - - rv = tcpc_read(port, ANX7447_REG_ANALOG_CTRL_10, ®); - if (rv) - return rv; - /* - * When using Look4Connection command to toggle CC under normal mode - * the CABLE_DET_DIG shall be clear first. - */ - if (reg & ANX7447_REG_CABLE_DET_DIG) { - reg &= ~ANX7447_REG_CABLE_DET_DIG; - rv = tcpc_write(port, ANX7447_REG_ANALOG_CTRL_10, reg); - if (rv) - return rv; - } - - return tcpci_tcpc_drp_toggle(port); -} -#endif - -/* Override for tcpci_tcpm_set_cc */ -static int anx7447_set_cc(int port, int pull) -{ - int rp, reg; - - rp = tcpc_read(port, ANX7447_REG_ANALOG_CTRL_10, ®); - if (rp) - return rp; - /* - * When setting CC status, should be confirm that the CC toggling - * process is stopped, the CABLE_DET_DIG shall be set to one. - */ - if ((reg & ANX7447_REG_CABLE_DET_DIG) == 0) { - reg |= ANX7447_REG_CABLE_DET_DIG; - rp = tcpc_write(port, ANX7447_REG_ANALOG_CTRL_10, reg); - if (rp) - return rp; - } - - rp = tcpci_get_cached_rp(port); - - /* Set manual control, and set both CC lines to the same pull */ - return tcpc_write(port, TCPC_REG_ROLE_CTRL, - TCPC_REG_ROLE_CTRL_SET(0, rp, pull, pull)); -} - -/* Override for tcpci_tcpm_set_polarity */ -static int anx7447_set_polarity(int port, - enum tcpc_cc_polarity polarity) -{ - return tcpc_update8(port, - TCPC_REG_TCPC_CTRL, - TCPC_REG_TCPC_CTRL_SET(1), - polarity_rm_dts(polarity) - ? MASK_SET : MASK_CLR); -} - -#ifdef CONFIG_CMD_TCPC_DUMP -static const struct tcpc_reg_dump_map anx7447_regs[] = { - { - .addr = ANX7447_REG_TCPC_SWITCH_0, - .name = "SWITCH_0", - .size = 1, - }, - { - .addr = ANX7447_REG_TCPC_SWITCH_1, - .name = "SWITCH_1", - .size = 1, - }, - { - .addr = ANX7447_REG_TCPC_AUX_SWITCH, - .name = "AUX_SWITCH", - .size = 1, - }, - { - .addr = ANX7447_REG_ADC_CTRL_1, - .name = "ADC_CTRL_1", - .size = 1, - }, - { - .addr = ANX7447_REG_ANALOG_CTRL_8, - .name = "ANALOG_CTRL_8", - .size = 1, - }, - { - .addr = ANX7447_REG_ANALOG_CTRL_10, - .name = "ANALOG_CTRL_10", - .size = 1, - }, - { - .addr = ANX7447_REG_TCPC_CTRL_2, - .name = "TCPC_CTRL_2", - .size = 1, - }, -}; - -const struct { - const char *name; - uint8_t addr; -} anx7447_alt_regs[] = { - { - .name = "HPD_CTRL_0", - .addr = ANX7447_REG_HPD_CTRL_0, - }, - { - .name = "HPD_DEGLITCH_H", - .addr = ANX7447_REG_HPD_DEGLITCH_H, - }, - { - .name = "INTP_SOURCE_0", - .addr = ANX7447_REG_INTP_SOURCE_0, - }, - { - .name = "INTP_MASK_0", - .addr = ANX7447_REG_INTP_MASK_0, - }, - { - .name = "INTP_CTRL_0", - .addr = ANX7447_REG_INTP_CTRL_0, - }, - { - .name = "PAD_INTP_CTRL", - .addr = ANX7447_REG_PAD_INTP_CTRL, - }, -}; - -/* - * Dump registers for debug command. - */ -static void anx7447_dump_registers(int port) -{ - int i, val; - - tcpc_dump_std_registers(port); - tcpc_dump_registers(port, anx7447_regs, ARRAY_SIZE(anx7447_regs)); - for (i = 0; i < ARRAY_SIZE(anx7447_alt_regs); i++) { - anx7447_reg_read(port, anx7447_alt_regs[i].addr, &val); - ccprintf(" %-26s(ALT/0x%02x) = 0x%02x\n", - anx7447_alt_regs[i].name, - anx7447_alt_regs[i].addr, (uint8_t)val); - cflush(); - } -} -#endif /* defined(CONFIG_CMD_TCPC_DUMP) */ - -/* - * ANX7447 is a TCPCI compatible port controller, with some caveats. - * It seems to require both CC lines to be set always, instead of just - * one at a time, according to TCPCI spec. Thus, now that the TCPCI - * driver more closely follows the spec, this driver requires - * overrides for set_cc and set_polarity. - */ -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 - .check_vbus_level = &tcpci_tcpm_check_vbus_level, -#endif - .select_rp_value = &tcpci_tcpm_select_rp_value, - .set_cc = &anx7447_set_cc, - .set_polarity = &anx7447_set_polarity, -#ifdef CONFIG_USB_PD_DECODE_SOP - .sop_prime_enable = &tcpci_tcpm_sop_prime_enable, -#endif - .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 = anx7447_tcpc_drp_toggle, -#endif - .get_chip_info = &tcpci_get_chip_info, -#ifdef CONFIG_USB_PD_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 - .set_bist_test_mode = &tcpci_set_bist_test_mode, -#ifdef CONFIG_CMD_TCPC_DUMP - .dump_registers = &anx7447_dump_registers, -#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 75982e6b91..0000000000 --- a/driver/tcpm/anx7447.h +++ /dev/null @@ -1,156 +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. - */ - -#include "usb_mux.h" - -/* USB Power delivery port management */ - -#ifndef __CROS_EC_USB_PD_TCPM_ANX7447_H -#define __CROS_EC_USB_PD_TCPM_ANX7447_H - -/* Registers: TCPC 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 address used */ -#define ANX7447_REG_INTP_SOURCE_0 0x67 - -#define ANX7447_REG_HPD_CTRL_0 0x7E -#define ANX7447_REG_HPD_MODE 0x01 -#define ANX7447_REG_HPD_OUT 0x02 -#define ANX7447_REG_HPD_IRQ0 0x04 -#define ANX7447_REG_HPD_PLUG 0x08 -#define ANX7447_REG_HPD_UNPLUG 0x10 - -#define ANX7447_REG_HPD_DEGLITCH_H 0x80 -#define ANX7447_REG_HPD_DETECT 0x80 -#define ANX7447_REG_HPD_OEN 0x40 - -#define ANX7447_REG_PAD_INTP_CTRL 0x85 - -#define ANX7447_REG_INTP_MASK_0 0x86 - -#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_CABLE_DET_DIG 0x40 - -#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_addr_flags; - uint16_t spi_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_clear_hpd_status(int port); -void anx7447_tcpc_update_hpd_status(const struct usb_mux *me, - mux_state_t mux_state); - -/** - * 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 567005920e..0000000000 --- a/driver/tcpm/anx74xx.c +++ /dev/null @@ -1,1210 +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 "tcpm/tcpci.h" -#include "tcpm/tcpm.h" -#include "timer.h" -#include "usb_charge.h" -#include "usb_mux.h" -#include "usb_pd.h" -#include "usb_pd_tcpc.h" -#include "usb_pd_tcpm.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 - -#if defined(CONFIG_USB_PD_REV30) -#error "ANX74xx chips were developed before PD 3.0 and aren't PD 3.0 compliant" -#error "Please undefine PD 3.0. See b/159253723 for details" -#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, ®); \ - 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]; - -#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, ®)) - 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, ®); - 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, ®); - 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(const struct usb_mux *me, - mux_state_t mux_state) -{ - int reg; - int port = me->usb_port; - int hpd_lvl = (mux_state & USB_PD_MUX_HPD_LVL) ? 1 : 0; - int hpd_irq = (mux_state & USB_PD_MUX_HPD_IRQ) ? 1 : 0; - - mux_read(me, ANX74XX_REG_HPD_CTRL_0, ®); - if (hpd_lvl) - reg |= ANX74XX_REG_HPD_OUT_DATA; - else - reg &= ~ANX74XX_REG_HPD_OUT_DATA; - mux_write(me, 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(me, ANX74XX_REG_HPD_CTRL_0, ®); - reg &= ~ANX74XX_REG_HPD_OUT_DATA; - mux_write(me, ANX74XX_REG_HPD_CTRL_0, reg); - usleep(HPD_DSTREAM_DEBOUNCE_IRQ); - reg |= ANX74XX_REG_HPD_OUT_DATA; - mux_write(me, 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 &= 0xcf; - tcpc_write(port, ANX74XX_REG_HPD_CTRL_0, reg); -} - -#ifdef CONFIG_USB_PD_TCPM_MUX -static int anx74xx_tcpm_mux_init(const struct usb_mux *me) -{ - /* Nothing to do here, ANX initializes its muxes - * as (USB_PD_MUX_USB_ENABLED | USB_PD_MUX_DP_ENABLED) - */ - anx[me->usb_port].mux_state = USB_PD_MUX_USB_ENABLED | - USB_PD_MUX_DP_ENABLED; - - return EC_SUCCESS; -} - -static int anx74xx_tcpm_mux_enter_safe_mode(int port) -{ - int reg; - const struct usb_mux *me = &usb_muxes[port]; - - if (mux_read(me, ANX74XX_REG_ANALOG_CTRL_2, ®)) - return EC_ERROR_UNKNOWN; - if (mux_write(me, 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; - const struct usb_mux *me = &usb_muxes[port]; - - if (mux_read(me, ANX74XX_REG_ANALOG_CTRL_2, ®)) - return EC_ERROR_UNKNOWN; - if (mux_write(me, 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; - const struct usb_mux *me = &usb_muxes[port]; - - /* - * Safe mode must be entered before any changes are made to the mux - * settings used to enable ALT_DP mode. This function is called either - * from anx74xx_tcpm_mux_set when USB_PD_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(me, ANX74XX_REG_ANALOG_CTRL_2, ®)) - return EC_ERROR_UNKNOWN; - if (mux_write(me, ANX74XX_REG_ANALOG_CTRL_2, reg & 0xf)) - return EC_ERROR_UNKNOWN; - - /* Clear Bit[7:0] R_SWITCH */ - if (mux_write(me, ANX74XX_REG_ANALOG_CTRL_1, 0x0)) - return EC_ERROR_UNKNOWN; - /* Clear Bit[7:4] R_SWITCH_H */ - if (mux_read(me, ANX74XX_REG_ANALOG_CTRL_5, ®)) - return EC_ERROR_UNKNOWN; - if (mux_write(me, 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; - const struct usb_mux *me = &usb_muxes[port]; - - /* - * 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(me, ANX74XX_REG_ANALOG_CTRL_2, ®)) - 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(me, ANX74XX_REG_ANALOG_CTRL_2, reg)) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -static int anx74xx_tcpm_mux_set(const struct usb_mux *me, - mux_state_t mux_state, - bool *ack_required) -{ - int ctrl5; - int ctrl1 = 0; - int rv; - int port = me->usb_port; - - /* This driver does not use host command ACKs */ - *ack_required = false; - - if (!(mux_state & ~USB_PD_MUX_POLARITY_INVERTED)) { - anx[port].mux_state = mux_state; - return anx74xx_tcpm_mux_exit(port); - } - - rv = mux_read(me, ANX74XX_REG_ANALOG_CTRL_5, &ctrl5); - if (rv) - return EC_ERROR_UNKNOWN; - ctrl5 &= 0x0f; - - if (mux_state & USB_PD_MUX_USB_ENABLED) { - /* Connect USB SS switches */ - if (mux_state & USB_PD_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 & USB_PD_MUX_DP_ENABLED) { - /* Set pin assignment D */ - if (mux_state & USB_PD_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 & USB_PD_MUX_DP_ENABLED) { - /* Set pin assignment C */ - if (mux_state & USB_PD_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(me, ANX74XX_REG_ANALOG_CTRL_1, ctrl1); - /* Write Rswitch config bits */ - rv |= mux_write(me, 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 & USB_PD_MUX_POLARITY_INVERTED, - mux_state & USB_PD_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(const struct usb_mux *me, - mux_state_t *mux_state) -{ - *mux_state = anx[me->usb_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, ®); - 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, ®); - 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, ®); - 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, ®); - 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, ®); - 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, ®); - /* 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, ®); - 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) -{ - /* Keep track of current RP value */ - tcpci_set_cached_rp(port, rp); - - /* For ANX3429 cannot get cc correctly when Rp != USB_Default */ - 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, ®); - 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, ®); - 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, ®); - 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, enum tcpc_cc_polarity polarity) -{ - int reg, mux_state, rv = EC_SUCCESS; - const struct usb_mux *me = &usb_muxes[port]; - bool unused; - - rv |= tcpc_read(port, ANX74XX_REG_CC_SOFTWARE_CTRL, ®); - if (polarity_rm_dts(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 & ~USB_PD_MUX_POLARITY_INVERTED; - if (polarity_rm_dts(polarity)) - mux_state |= USB_PD_MUX_POLARITY_INVERTED; - anx74xx_tcpm_mux_set(me, mux_state, &unused); -#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, ®); - 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, ®); - 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, ®); - 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, tcpci_get_cached_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 bool anx74xx_tcpm_check_vbus_level(int port, enum vbus_level level) -{ - int reg = 0; - - tcpc_read(port, ANX74XX_REG_ANALOG_STATUS, ®); - if (level == VBUS_PRESENT) - return ((reg & ANX74XX_REG_VBUS_STATUS) ? 1 : 0); - else - return ((reg & ANX74XX_REG_VBUS_STATUS) ? 0 : 1); -} -#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, ®)) { - 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 tcpci_msg_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 TCPCI_MSG_SOP: - case TCPCI_MSG_SOP_PRIME: - case TCPCI_MSG_SOP_PRIME_PRIME: - len = PD_HEADER_CNT(header) * 4 + 2; - ret = anx74xx_send_message(port, header, - data, type, len); - break; - case TCPCI_MSG_TX_HARD_RESET: - /* Request HARD RESET */ - tcpc_read(port, ANX74XX_REG_TX_CTRL_1, ®); - 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 TCPCI_MSG_CABLE_RESET: - /* Request CABLE RESET */ - tcpc_read(port, ANX74XX_REG_TX_CTRL_1, ®); - reg |= ANX74XX_REG_TX_CABLE_RESET_REQ; - ret = tcpc_write(port, ANX74XX_REG_TX_CTRL_1, reg); - break; - case TCPCI_MSG_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, ®); - 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, ®); - - /* 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, ®)) - ++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); - - /* Read and clear extended alert register 1 */ - reg = 0; - tcpc_read(port, ANX74XX_REG_IRQ_EXT_SOURCE_1, ®); - 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] = TCPCI_MSG_SOP; - else if (reg & ANX74XX_REG_EXT_SOP_PRIME) - msg_sop[port] = TCPCI_MSG_SOP_PRIME; -#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, ®); - 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] = TCPCI_MSG_SOP_PRIME_PRIME; -#endif - - if (reg & ANX74XX_REG_EXT_HARD_RST) { - /* hard reset received */ - task_set_event(PD_PORT_TO_TASK_ID(port), - PD_EVENT_RX_HARD_RESET); - } -} - -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, ®); - 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 &= (~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 &= (~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, ®); - 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, ®); - 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 - .check_vbus_level = &anx74xx_tcpm_check_vbus_level, -#endif - .select_rp_value = &anx74xx_tcpm_select_rp_value, - .set_cc = &anx74xx_tcpm_set_cc, - .set_polarity = &anx74xx_tcpm_set_polarity, -#ifdef CONFIG_USB_PD_DECODE_SOP - .sop_prime_enable = &tcpci_tcpm_sop_prime_enable, -#endif - .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 - .set_bist_test_mode = &tcpci_set_bist_test_mode, -}; - -#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 8d700d4d86..0000000000 --- a/driver/tcpm/anx74xx.h +++ /dev/null @@ -1,229 +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. - */ - -#include "usb_mux.h" - -/* 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_clear_hpd_status(int port); -void anx74xx_tcpc_update_hpd_status(const struct usb_mux *me, - mux_state_t mux_state); - -#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 5e37352bc5..0000000000 --- a/driver/tcpm/anx7688.c +++ /dev/null @@ -1,225 +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 "tcpm/tcpci.h" -#include "tcpm/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, ®); - 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, ®); - 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(const struct usb_mux *me, mux_state_t mux_state, - bool *ack_required) -{ - int reg = 0; - int rv, polarity; - - /* This driver does not use host command ACKs */ - *ack_required = false; - - rv = mux_read(me, TCPC_REG_CONFIG_STD_OUTPUT, ®); - if (rv != EC_SUCCESS) - return rv; - - reg &= ~TCPC_REG_CONFIG_STD_OUTPUT_MUX_MASK; - if (mux_state & USB_PD_MUX_USB_ENABLED) - reg |= TCPC_REG_CONFIG_STD_OUTPUT_MUX_USB; - if (mux_state & USB_PD_MUX_DP_ENABLED) - reg |= TCPC_REG_CONFIG_STD_OUTPUT_MUX_DP; - - /* ANX7688 needs to set bit0 */ - rv = mux_read(me, 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(me, TCPC_REG_CONFIG_STD_OUTPUT, reg); -} - -#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC -static bool anx7688_tcpm_check_vbus_level(int port, enum vbus_level level) -{ - 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, ®); - - if (level == VBUS_PRESENT) - return ((reg & 0x10) ? 1 : 0); - else - return ((reg & 0x10) ? 0 : 1); -} -#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 - .check_vbus_level = &anx7688_tcpm_check_vbus_level, -#endif - .select_rp_value = &tcpci_tcpm_select_rp_value, - .set_cc = &tcpci_tcpm_set_cc, - .set_polarity = &tcpci_tcpm_set_polarity, -#ifdef CONFIG_USB_PD_DECODE_SOP - .sop_prime_enable = &tcpci_tcpm_sop_prime_enable, -#endif - .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, - .set_bist_test_mode = &tcpci_set_bist_test_mode, -}; - -#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/ccgxxf.h b/driver/tcpm/ccgxxf.h deleted file mode 100644 index f4b3deb355..0000000000 --- a/driver/tcpm/ccgxxf.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright 2021 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 For Cypress EZ-PD CCG6DF, CCG6SF - * CCGXXF FW is designed to adapt standard TCPM driver procedures. - */ -#ifndef __CROS_EC_DRIVER_TCPM_CCGXXF_H -#define __CROS_EC_DRIVER_TCPM_CCGXXF_H - -#define CCGXXF_I2C_ADDR1_FLAGS 0x0B -#define CCGXXF_I2C_ADDR2_FLAGS 0x1B - -/* CCGXXF built in I/O expander definitions */ -#ifdef CONFIG_IO_EXPANDER_CCGXXF - -/* CCGXXF I/O ports that can be referenced in gpio.inc */ -enum ccgxxf_io_ports { - CCGXXF_PORT_0, - CCGXXF_PORT_1, - CCGXXF_PORT_2, - CCGXXF_PORT_3 -}; - -/* CCGXXF I/O pins that can be referenced in gpio.inc */ -enum ccgxxf_io_pins { - CCGXXF_IO_0, - CCGXXF_IO_1, - CCGXXF_IO_2, - CCGXXF_IO_3, - CCGXXF_IO_4, - CCGXXF_IO_5, - CCGXXF_IO_6, - CCGXXF_IO_7 -}; - -#define CCGXXF_REG_GPIO_CONTROL(port) ((port) + 0x80) -#define CCGXXF_REG_GPIO_STATUS(port) ((port) + 0x84) - -#define CCGXXF_REG_GPIO_MODE 0x88 -#define CCGXXF_GPIO_PIN_MASK_SHIFT 8 -#define CCGXXF_GPIO_PIN_MODE_SHIFT 2 -#define CCGXXF_GPIO_1P8V_SEL BIT(7) - -enum ccgxxf_gpio_mode { - CCGXXF_GPIO_MODE_HIZ_ANALOG, - CCGXXF_GPIO_MODE_HIZ_DIGITAL, - CCGXXF_GPIO_MODE_RES_UP, - CCGXXF_GPIO_MODE_RES_DWN, - CCGXXF_GPIO_MODE_OD_LOW, - CCGXXF_GPIO_MODE_OD_HIGH, - CCGXXF_GPIO_MODE_STRONG, - CCGXXF_GPIO_MODE_RES_UPDOWN -}; - -extern const struct ioexpander_drv ccgxxf_ioexpander_drv; - -#endif /* CONFIG_IO_EXPANDER_CCGXXF */ - -#endif /* __CROS_EC_DRIVER_TCPM_CCGXXF_H */ diff --git a/driver/tcpm/fusb302.c b/driver/tcpm/fusb302.c deleted file mode 100644 index 0098906d32..0000000000 --- a/driver/tcpm/fusb302.c +++ /dev/null @@ -1,1205 +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/tcpci.h" -#include "tcpm/tcpm.h" -#include "timer.h" -#include "usb_charge.h" -#include "usb_pd.h" -#include "usb_pd_tcpc.h" -#include "usb_pd_tcpm.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]; - -static struct mutex measure_lock; - -/* - * 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 |= 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, ®); - - 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; - - mutex_lock(&measure_lock); - - /* Read status register */ - tcpc_read(port, TCPC_REG_SWITCHES0, ®); - /* 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, ®); - - /* 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, ®); - - 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); - - mutex_unlock(&measure_lock); - - 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; - - mutex_lock(&measure_lock); - - /* - * Measure CC1 first. - */ - tcpc_read(port, TCPC_REG_SWITCHES0, ®); - - /* 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, ®); - - /* 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, ®); - 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); - - mutex_unlock(&measure_lock); -} - -/* 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; - - /* Keep track of current RP value */ - tcpci_set_cached_rp(port, rp); - - rv = tcpc_read(port, TCPC_REG_CONTROL0, ®); - 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 |= TCPC_REG_CONTROL3_AUTO_RETRY; - reg |= (CONFIG_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 &= ~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); - - /* 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, ®); - 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 &= ~(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 &= ~TCPC_REG_CONTROL2_TOGGLE; - tcpc_write(port, TCPC_REG_CONTROL2, reg); - - /* enable pull-downs, disable pullups */ - tcpc_read(port, TCPC_REG_SWITCHES0, ®); - - 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 &= ~TCPC_REG_CONTROL2_TOGGLE; - tcpc_write(port, TCPC_REG_CONTROL2, reg); - - /* Ensure manual switches are opened */ - tcpc_read(port, TCPC_REG_SWITCHES0, ®); - 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, enum tcpc_cc_polarity polarity) -{ - /* Port polarity : 0 => CC1 is CC line, 1 => CC2 is CC line */ - int reg; - - tcpc_read(port, TCPC_REG_SWITCHES0, ®); - - /* 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_rm_dts(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_rm_dts(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, ®); - - /* clear tx_cc bits */ - reg &= ~TCPC_REG_SWITCHES1_TXCC1_EN; - reg &= ~TCPC_REG_SWITCHES1_TXCC2_EN; - - /* set tx polarity */ - if (polarity_rm_dts(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; -} - -__maybe_unused static int fusb302_tcpm_decode_sop_prime_enable(int port, - bool enable) -{ - int reg; - - if (tcpc_read(port, TCPC_REG_CONTROL1, ®)) - return EC_ERROR_UNKNOWN; - - if (enable) - reg |= (TCPC_REG_CONTROL1_ENSOP1 | - TCPC_REG_CONTROL1_ENSOP2); - else - reg &= ~(TCPC_REG_CONTROL1_ENSOP1 | - TCPC_REG_CONTROL1_ENSOP2); - - return tcpc_write(port, TCPC_REG_CONTROL1, reg); -} - -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); - - if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) { - if (state[port].rx_enable) { - if (fusb302_tcpm_decode_sop_prime_enable(port, - true)) - return EC_ERROR_UNKNOWN; - } - } - } else { - - tcpc_read(port, TCPC_REG_SWITCHES0, ®); - - /* clear VCONN switch bits */ - reg &= ~TCPC_REG_SWITCHES0_VCONN_CC1; - reg &= ~TCPC_REG_SWITCHES0_VCONN_CC2; - - tcpc_write(port, TCPC_REG_SWITCHES0, reg); - - if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) { - if (state[port].rx_enable) { - if (fusb302_tcpm_decode_sop_prime_enable(port, - false)) - return EC_ERROR_UNKNOWN; - } - } - } - - 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 &= ~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, ®); - - /* 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, ®)) - 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, ®)) - 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, ®)) - 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 & 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, ®)) - return EC_ERROR_UNKNOWN; - - if (reg & TCPC_REG_STATUS1_RXSOP1) - *head |= PD_HEADER_SOP(TCPCI_MSG_SOP_PRIME); - else if (reg & TCPC_REG_STATUS1_RXSOP2) - *head |= PD_HEADER_SOP(TCPCI_MSG_SOP_PRIME_PRIME); - } -#endif - - return rv; -} - -static int fusb302_tcpm_transmit(int port, enum tcpci_msg_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 TCPCI_MSG_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 TCPCI_MSG_SOP_PRIME: - - /* 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_SYNC3; - buf[buf_pos++] = FUSB302_TKN_SYNC3; - - return fusb302_send_message(port, header, data, buf, buf_pos); - case TCPCI_MSG_SOP_PRIME_PRIME: - - /* 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_SYNC3; - buf[buf_pos++] = FUSB302_TKN_SYNC1; - buf[buf_pos++] = FUSB302_TKN_SYNC3; - - return fusb302_send_message(port, header, data, buf, buf_pos); - case TCPCI_MSG_TX_HARD_RESET: - /* Simply hit the SEND_HARD_RESET bit */ - tcpc_read(port, TCPC_REG_CONTROL3, ®); - reg |= TCPC_REG_CONTROL3_SEND_HARDRESET; - tcpc_write(port, TCPC_REG_CONTROL3, reg); - - break; - case TCPCI_MSG_TX_BIST_MODE_2: - /* Hit the BIST_MODE2 bit and start TX */ - tcpc_read(port, TCPC_REG_CONTROL1, ®); - reg |= TCPC_REG_CONTROL1_BIST_MODE2; - tcpc_write(port, TCPC_REG_CONTROL1, reg); - - tcpc_read(port, TCPC_REG_CONTROL0, ®); - 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 &= ~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 bool fusb302_tcpm_check_vbus_level(int port, enum vbus_level level) -{ - int reg; - - /* Read status register */ - tcpc_read(port, TCPC_REG_STATUS0, ®); - - if (level == VBUS_PRESENT) - return (reg & TCPC_REG_STATUS0_VBUSOK) ? 1 : 0; - else - return (reg & TCPC_REG_STATUS0_VBUSOK) ? 0 : 1; -} -#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); - } - - 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_check_vbus_level(port, - VBUS_PRESENT)); -#else - if (!fusb302_tcpm_check_vbus_level(port, VBUS_PRESENT)) - 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); - task_set_event(PD_PORT_TO_TASK_ID(port), - PD_EVENT_RX_HARD_RESET); - } - - 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, ®); - - /* 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_set_toggle_mode(int port, int mode) -{ - int reg, rv; - - rv = i2c_read8(tcpc_config[port].i2c_info.port, - tcpc_config[port].i2c_info.addr_flags, - TCPC_REG_CONTROL2, ®); - if (rv) - return rv; - - reg &= ~TCPC_REG_CONTROL2_MODE_MASK; - reg |= mode << TCPC_REG_CONTROL2_MODE_POS; - return i2c_write8(tcpc_config[port].i2c_info.port, - tcpc_config[port].i2c_info.addr_flags, - TCPC_REG_CONTROL2, reg); -} - -static int fusb302_tcpm_enter_low_power_mode(int port) -{ - int reg, rv, mode = TCPC_REG_CONTROL2_MODE_DRP; - - /** - * vendor's suggested LPM flow: - * - enable low power mode and set up other things - * - sleep 250 us - * - start toggling - */ - rv = i2c_write8(tcpc_config[port].i2c_info.port, - tcpc_config[port].i2c_info.addr_flags, - TCPC_REG_POWER, TCPC_REG_POWER_PWR_LOW); - if (rv) - return rv; - - switch (pd_get_dual_role(port)) { - case PD_DRP_TOGGLE_ON: - mode = TCPC_REG_CONTROL2_MODE_DRP; - break; - case PD_DRP_TOGGLE_OFF: - mode = TCPC_REG_CONTROL2_MODE_UFP; - break; - case PD_DRP_FREEZE: - mode = pd_get_power_role(port) == PD_ROLE_SINK ? - TCPC_REG_CONTROL2_MODE_UFP : - TCPC_REG_CONTROL2_MODE_DFP; - break; - case PD_DRP_FORCE_SINK: - mode = TCPC_REG_CONTROL2_MODE_UFP; - break; - case PD_DRP_FORCE_SOURCE: - mode = TCPC_REG_CONTROL2_MODE_DFP; - break; - } - rv = fusb302_set_toggle_mode(port, mode); - if (rv) - return rv; - - usleep(250); - - rv = i2c_read8(tcpc_config[port].i2c_info.port, - tcpc_config[port].i2c_info.addr_flags, - TCPC_REG_CONTROL2, ®); - if (rv) - return rv; - reg |= TCPC_REG_CONTROL2_TOGGLE; - return i2c_write8(tcpc_config[port].i2c_info.port, - tcpc_config[port].i2c_info.addr_flags, - TCPC_REG_CONTROL2, reg); -} -#endif - -/* - * Compare VBUS voltage with given mdac reference voltage. - * returns non-zero if VBUS voltage >= (mdac + 1) * 420 mV - */ -static int fusb302_compare_mdac(int port, int mdac) -{ - int orig_reg, status0; - - mutex_lock(&measure_lock); - - /* backup REG_MEASURE */ - tcpc_read(port, TCPC_REG_MEASURE, &orig_reg); - /* set reg_measure bit 0~5 to mdac, and bit6 to 1(measure vbus) */ - tcpc_write(port, TCPC_REG_MEASURE, - (mdac & TCPC_REG_MEASURE_MDAC_MASK) | TCPC_REG_MEASURE_VBUS); - - /* Wait on measurement */ - usleep(350); - - /* - * Read status register, if STATUS0_COMP=1 then vbus is higher than - * (mdac + 1) * 0.42V - */ - tcpc_read(port, TCPC_REG_STATUS0, &status0); - /* write back original value */ - tcpc_write(port, TCPC_REG_MEASURE, orig_reg); - - mutex_unlock(&measure_lock); - - return status0 & TCPC_REG_STATUS0_COMP; -} - -int tcpc_get_vbus_voltage(int port) -{ - int mdac = 0, i; - - /* - * Implement by comparing VBUS with MDAC reference voltage, and binary - * search the value of MDAC. - * - * MDAC register has 6 bits, so we can simply search 1 bit per - * iteration, from MSB to LSB. - */ - for (i = 5; i >= 0; i--) { - if (fusb302_compare_mdac(port, mdac | BIT(i))) - mdac |= BIT(i); - } - - return (mdac + 1) * 420; -} - -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 - .check_vbus_level = &fusb302_tcpm_check_vbus_level, -#endif - .select_rp_value = &fusb302_tcpm_select_rp_value, - .set_cc = &fusb302_tcpm_set_cc, - .set_polarity = &fusb302_tcpm_set_polarity, -#ifdef CONFIG_USB_PD_DECODE_SOP - .sop_prime_enable = &fusb302_tcpm_decode_sop_prime_enable, -#endif - .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 717b28df18..0000000000 --- a/driver/tcpm/fusb302.h +++ /dev/null @@ -1,211 +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 address varies by part number */ -/* FUSB302BUCX / FUSB302BMPX */ -#define FUSB302_I2C_ADDR_FLAGS 0x22 -/* FUSB302B01MPX */ -#define FUSB302_I2C_ADDR_B01_FLAGS 0x23 -/* FUSB302B10MPX */ -#define FUSB302_I2C_ADDR_B10_FLAGS 0x24 -/* FUSB302B11MPX */ -#define FUSB302_I2C_ADDR_B11_FLAGS 0x25 - -#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_MDAC_MASK 0x3F -#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_MASK (0x3<<TCPC_REG_CONTROL2_MODE_POS) -#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/fusb307.c b/driver/tcpm/fusb307.c deleted file mode 100644 index e8804a2661..0000000000 --- a/driver/tcpm/fusb307.c +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright 2020 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 Fairchild's FUSB307 */ - -#include "console.h" -#include "fusb307.h" -#include "hooks.h" -#include "task.h" -#include "tcpm/tcpci.h" -#include "tcpm/tcpm.h" -#include "timer.h" -#include "util.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -int fusb307_power_supply_reset(int port) -{ - return tcpc_write(port, TCPC_REG_COMMAND, 0x66); -} - -static int fusb307_tcpm_init(int port) -{ - int rv; - - rv = tcpci_tcpm_init(port); - - rv = tcpci_set_role_ctrl(port, TYPEC_DRP, TYPEC_RP_USB, TYPEC_CC_RD); - pd_set_dual_role(port, PD_DRP_TOGGLE_ON); - - return rv; -} - -int fusb307_tcpm_set_polarity(int port, enum tcpc_cc_polarity polarity) -{ - int rv; - enum tcpc_cc_voltage_status cc1, cc2; - - rv = tcpci_tcpm_set_polarity(port, polarity); - - tcpm_get_cc(port, &cc1, &cc2); - if (cc1) { - if (pd_get_power_role(port) == PD_ROLE_SINK) { - int role = TCPC_REG_ROLE_CTRL_SET(0, - tcpci_get_cached_rp(port), TYPEC_CC_RD, TYPEC_CC_OPEN); - - tcpc_write(port, TCPC_REG_ROLE_CTRL, role); - } else { - int role = TCPC_REG_ROLE_CTRL_SET(0, - tcpci_get_cached_rp(port), TYPEC_CC_RP, TYPEC_CC_OPEN); - - tcpc_write(port, TCPC_REG_ROLE_CTRL, role); - } - } else if (cc2) { - if (pd_get_power_role(port) == PD_ROLE_SINK) { - int role = TCPC_REG_ROLE_CTRL_SET(0, - tcpci_get_cached_rp(port), TYPEC_CC_OPEN, TYPEC_CC_RD); - - tcpc_write(port, TCPC_REG_ROLE_CTRL, role); - } else { - int role = TCPC_REG_ROLE_CTRL_SET(0, - tcpci_get_cached_rp(port), TYPEC_CC_OPEN, TYPEC_CC_RP); - - tcpc_write(port, TCPC_REG_ROLE_CTRL, role); - } - } else { - if (pd_get_power_role(port) == PD_ROLE_SINK) - tcpci_tcpm_set_cc(port, TYPEC_CC_RD); - else - tcpci_tcpm_set_cc(port, TYPEC_CC_RP); - } - - return rv; -} - -const struct tcpm_drv fusb307_tcpm_drv = { - .init = &fusb307_tcpm_init, - .release = &tcpci_tcpm_release, - .get_cc = &tcpci_tcpm_get_cc, -#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC - .check_vbus_level = &tcpci_tcpm_check_vbus_level, -#endif - .select_rp_value = &tcpci_tcpm_select_rp_value, - .set_cc = &tcpci_tcpm_set_cc, - .set_polarity = &fusb307_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, - .tcpc_enable_auto_discharge_disconnect = - &tcpci_tcpc_enable_auto_discharge_disconnect, - .get_chip_info = &tcpci_get_chip_info, -#if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) - .drp_toggle = &tcpci_tcpc_drp_toggle, -#endif - .set_bist_test_mode = &tcpci_set_bist_test_mode, -}; - diff --git a/driver/tcpm/fusb307.h b/driver/tcpm/fusb307.h deleted file mode 100644 index 3f1f12901d..0000000000 --- a/driver/tcpm/fusb307.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright 2020 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 */ -/* For Fairchild FUSB307 */ -#ifndef __CROS_EC_FUSB307_H -#define __CROS_EC_FUSB307_H - -#include "usb_pd.h" - -#define FUSB307_I2C_ADDR_FLAGS 0x50 - -#define TCPC_REG_RESET 0xA2 -#define TCPC_REG_RESET_PD_RESET BIT(1) -#define TCPC_REG_RESET_SW_RESET BIT(0) - -#define TCPC_REG_GPIO1_CFG 0xA4 -#define TCPC_REG_GPIO1_CFG_GPO1_VAL BIT(2) -#define TCPC_REG_GPIO1_CFG_GPI1_EN BIT(1) -#define TCPC_REG_GPIO1_CFG_GPO1_EN BIT(0) - -int fusb307_power_supply_reset(int port); - -extern const struct tcpm_drv fusb307_tcpm_drv; - -#endif /* __CROS_EC_FUSB307_H */ diff --git a/driver/tcpm/it83xx.c b/driver/tcpm/it83xx.c deleted file mode 100644 index 7bd2913bd7..0000000000 --- a/driver/tcpm/it83xx.c +++ /dev/null @@ -1,910 +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 "tcpm/tcpci.h" -#include "timer.h" -#include "util.h" -#include "usb_common.h" -#include "usb_pd.h" -#include "usb_pd_tcpm.h" -#include "hooks.h" - -#ifdef CONFIG_USB_PD_TCPMV1 -#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 -#endif - -#ifdef CONFIG_USB_PD_TCPMV2 -#if defined(CONFIG_USB_PD_VBUS_DETECT_TCPC) || \ - defined(CONFIG_USB_PD_DISCHARGE_TCPC) -#error "Unsupported config options of IT83xx PD driver" -#endif -#endif - -int rx_en[IT83XX_USBPD_PHY_PORT_COUNT]; -STATIC_IF(CONFIG_USB_PD_DECODE_SOP) - bool sop_prime_en[IT83XX_USBPD_PHY_PORT_COUNT]; - -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) == IT83XX_USBPD_PHY_PORT_COUNT); - -static int it83xx_tcpm_set_rx_enable(int port, int enable); -static int it83xx_tcpm_set_vconn(int port, int enable); - -/* - * Disable cc analog and pd digital module, but only left Rd_5.1K (Not - * Dead Battery) analog module alive to assert Rd on CCs. EC reset or - * calling _init() are able to re-active cc and pd. - */ -void it83xx_Rd_5_1K_only_for_hibernate(int port) -{ - /* This only apply to active 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)); - /* - * Disable CCs voltage detector, and - * connect CCs analog module (ex.UP/RD/DET/TX/RX), and - * connect CCs 5.1K to GND - */ - IT83XX_USBPD_CCCSR(port) = 0x22; - /* Disconnect CCs 5V tolerant */ - IT83XX_USBPD_CCPSR(port) |= - (USBPD_REG_MASK_DISCONNECT_POWER_CC2 | - USBPD_REG_MASK_DISCONNECT_POWER_CC1); - /* - * Select Rp reserved value for not current leakage, and - * CCs assert Rd, and - * enable CCs analog module - */ - IT83XX_USBPD_BMCSR(port) &= ~0x08; - IT83XX_USBPD_CCGCR(port) &= ~0x1f; - } -} - -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); - - if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) { - int type = USBPD_REG_GET_SOP_TYPE_RX(IT83XX_USBPD_MRSR(port)); - *head |= PD_HEADER_SOP(type); - } - /* - * 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 tcpci_msg_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 (type == TCPCI_MSG_SOP) - 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 <= CONFIG_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 > CONFIG_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 tcpci_msg_type reset_type) -{ - if (reset_type == TCPCI_MSG_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 (USBPD_IS_HARD_CABLE_RESET_TX_DONE(port)) { - IT83XX_USBPD_ISR(port) = - USBPD_REG_MASK_HARD_CABLE_RESET_TX_DONE; - return TCPC_TX_COMPLETE_SUCCESS; - } - - return TCPC_TX_COMPLETE_FAILED; -} - -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); -} - -#ifdef CONFIG_USB_PD_FRS_TCPC -static int it83xx_tcpm_set_frs_enable(int port, int enable) -{ - uint8_t mask = (USBPD_REG_FAST_SWAP_REQUEST_ENABLE | - USBPD_REG_FAST_SWAP_DETECT_ENABLE); - - if (enable) { - /* - * Disable HW auto turn off FRS requestion and detection - * when we receive soft or hard reset. - */ - IT83XX_USBPD_PDPSR(port) &= ~USBPD_REG_MASK_AUTO_FRS_DISABLE; - /* W/C status */ - IT83XX_USBPD_PD30IR(port) = 0x3f; - /* Enable FRS detection (cc to GND) interrupt */ - IT83XX_USBPD_MPD30IR(port) &= ~(USBPD_REG_MASK_PD30_ISR | - USBPD_REG_MASK_FAST_SWAP_DETECT_ISR); - /* Enable FRS detection (cc to GND) */ - IT83XX_USBPD_PDQSCR(port) = (IT83XX_USBPD_PDQSCR(port) & ~mask) - | USBPD_REG_FAST_SWAP_DETECT_ENABLE; - } else { - /* Disable FRS detection (cc to GND) interrupt */ - IT83XX_USBPD_MPD30IR(port) |= (USBPD_REG_MASK_PD30_ISR | - USBPD_REG_MASK_FAST_SWAP_DETECT_ISR); - /* Disable FRS detection and requestion */ - IT83XX_USBPD_PDQSCR(port) &= ~mask; - } - - return EC_SUCCESS; -} -#endif - -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); - /* - * According PD version set the total number of HW attempts - * (= retry count + 1) - */ - IT83XX_USBPD_BMCSR(port) = (IT83XX_USBPD_BMCSR(port) & ~0x70) | - ((CONFIG_PD_RETRY_COUNT + 1) << 4); - /* Disable Rx decode */ - it83xx_tcpm_set_rx_enable(port, 0); - if (IS_ENABLED(CONFIG_USB_PD_TCPMV1)) { - uint8_t flags = 0; - /* - * If explicit contract is set in bbram when EC boot up, then - * TCPMv1 set soft reset as first state instead of - * unattached.SNK, so we need to enable BMC PHY for tx module. - * - * NOTE: If the platform is without battery and connects to - * adapter, then cold reset EC, our Rd is always asserted on cc, - * so adapter keeps providing 5v and data in BBRAM are still - * alive. - */ - if ((pd_get_saved_port_flags(port, &flags) == EC_SUCCESS) && - (flags & PD_BBRMFLG_EXPLICIT_CONTRACT)) - USBPD_ENABLE_BMC_PHY(port); - } - /* 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_OUT_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 - /* cc connect */ - IT83XX_USBPD_CCCSR(port) = 0; - /* disable vconn */ - it83xx_tcpm_set_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); - /* - * Disconnect CCs Rd_DB from GND - * NOTE: CCs assert both Rd_5.1k and Rd_DB from USBPD_START() to - * disconnect Rd_DB about 1.5us. - */ - IT83XX_USBPD_CCPSR(port) |= (USBPD_REG_MASK_DISCONNECT_5_1K_CC2_DB | - USBPD_REG_MASK_DISCONNECT_5_1K_CC1_DB); -} - -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; - - /* Keep track of current RP value */ - tcpci_set_cached_rp(port, rp_sel); - - /* - * 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, enum tcpc_cc_polarity polarity) -{ - enum usbpd_cc_pin cc_pin = - (polarity == POLARITY_CC1 || polarity == POLARITY_CC1_DTS) ? - USBPD_CC_PIN_1 : USBPD_CC_PIN_2; - - it83xx_select_polarity(port, cc_pin); - - return EC_SUCCESS; -} - -__maybe_unused static int it83xx_tcpm_decode_sop_prime_enable(int port, - bool enable) -{ - /* Save SOP'/SOP'' enable state */ - sop_prime_en[port] = enable; - - if (rx_en[port]) { - if (enable) - IT83XX_USBPD_PDMSR(port) |= - (USBPD_REG_MASK_SOPP_ENABLE | - USBPD_REG_MASK_SOPPP_ENABLE); - else - IT83XX_USBPD_PDMSR(port) &= - ~(USBPD_REG_MASK_SOPP_ENABLE | - USBPD_REG_MASK_SOPPP_ENABLE); - } - - 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' and SOP'' packet */ - it83xx_tcpm_decode_sop_prime_enable(port, true); - /* Turn on Vconn power switch. */ - board_pd_vconn_ctrl(port, - USBPD_GET_PULL_CC_SELECTION(port) ? - USBPD_CC_PIN_2 : USBPD_CC_PIN_1, - enable); - } else { - /* - * If the pd port has previous connection and supplies - * Vconn, then RO jumping to RW reset the system, - * we never know which cc is the previous Vconn pin, - * so we always turn both cc pins off when disable - * Vconn power switch. - */ - board_pd_vconn_ctrl(port, USBPD_CC_PIN_1, enable); - board_pd_vconn_ctrl(port, USBPD_CC_PIN_2, enable); - /* Disable tcpc receive SOP' and SOP'' packet */ - if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) - it83xx_tcpm_decode_sop_prime_enable(port, - false); - /* - * Before disabling cc 5v tolerant, we need to make - * sure cc voltage detector is enabled and Vconn is - * dropped below 3.3v (>500us) to avoid the potential - * risk of voltage fed back into Vcore. - */ - usleep(IT83XX_USBPD_T_VCONN_BELOW_3_3V); - /* - * 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) -{ - /* Save rx_on */ - rx_en[port] = enable; - - if (enable) { - IT83XX_USBPD_IMR(port) &= ~USBPD_REG_MASK_MSG_RX_DONE; - IT83XX_USBPD_PDMSR(port) |= USBPD_REG_MASK_SOP_ENABLE; - IT83XX_USBPD_VDMMCSR(port) |= USBPD_REG_MASK_HARD_RESET_DECODE; - if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) - it83xx_tcpm_decode_sop_prime_enable(port, - sop_prime_en[port]); - } else { - IT83XX_USBPD_IMR(port) |= USBPD_REG_MASK_MSG_RX_DONE; - IT83XX_USBPD_PDMSR(port) &= ~(USBPD_REG_MASK_SOP_ENABLE | - USBPD_REG_MASK_SOPP_ENABLE | - USBPD_REG_MASK_SOPPP_ENABLE); - IT83XX_USBPD_VDMMCSR(port) &= ~USBPD_REG_MASK_HARD_RESET_DECODE; - } - - return EC_SUCCESS; -} - -static int it83xx_tcpm_transmit(int port, - enum tcpci_msg_type type, - uint16_t header, - const uint32_t *data) -{ - int status = TCPC_TX_COMPLETE_FAILED; - - switch (type) { - case TCPCI_MSG_SOP: - case TCPCI_MSG_SOP_PRIME: - case TCPCI_MSG_SOP_PRIME_PRIME: - case TCPCI_MSG_SOP_DEBUG_PRIME: - case TCPCI_MSG_SOP_DEBUG_PRIME_PRIME: - status = it83xx_tx_data(port, - type, - header, - data); - break; - case TCPCI_MSG_TX_BIST_MODE_2: - it83xx_send_bist_mode2_pattern(port); - status = TCPC_TX_COMPLETE_SUCCESS; - break; - case TCPCI_MSG_TX_HARD_RESET: - case TCPCI_MSG_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) -{ - chip_info->vendor_id = USB_VID_ITE; - chip_info->product_id = ((IT83XX_GCTRL_CHIPID1 << 8) | - IT83XX_GCTRL_CHIPID2); - chip_info->device_id = IT83XX_GCTRL_CHIPVER & 0xf; - chip_info->fw_version_number = 0xEC; - - return EC_SUCCESS; -} - -#ifdef CONFIG_USB_PD_TCPC_LOW_POWER -static int it83xx_tcpm_enter_low_power_mode(int port) -{ - /* - * ITE embedded TCPC SLEEP_MASK_USB_PD flag is only controlled by - * it83xx driver in set_pd_sleep_mask(), and do low power mode in - * idle_task(). - * In deep sleep mode, ITE TCPC clock is turned off, and the - * timer every 5ms to exit the mode and wakeup PD task to run - * (ex. change the CC lines termination). - */ - return EC_SUCCESS; -} -#endif - -static void it83xx_tcpm_switch_plug_out_type(int port) -{ - enum tcpc_cc_voltage_status cc1, cc2; - - /* Check what do we and partner cc assert */ - it83xx_tcpm_get_cc(port, &cc1, &cc2); - - if ((cc1 == TYPEC_CC_VOLT_RD && cc2 == TYPEC_CC_VOLT_RD) || - (cc1 == TYPEC_CC_VOLT_RA && cc2 == TYPEC_CC_VOLT_RA)) - /* We're source, switch to detect audio/debug plug out. */ - IT83XX_USBPD_TCDCR(port) = (IT83XX_USBPD_TCDCR(port) & - ~USBPD_REG_PLUG_IN_OUT_DETECT_DISABLE) | - USBPD_REG_PLUG_OUT_DETECT_TYPE_SELECT | - USBPD_REG_PLUG_OUT_SELECT; - else if (cc1 == TYPEC_CC_VOLT_RD || cc2 == TYPEC_CC_VOLT_RD) - /* We're source, switch to detect sink plug out. */ - IT83XX_USBPD_TCDCR(port) = (IT83XX_USBPD_TCDCR(port) & - ~USBPD_REG_PLUG_IN_OUT_DETECT_DISABLE & - ~USBPD_REG_PLUG_OUT_DETECT_TYPE_SELECT) | - USBPD_REG_PLUG_OUT_SELECT; - else if (cc1 >= TYPEC_CC_VOLT_RP_DEF || cc2 >= TYPEC_CC_VOLT_RP_DEF) - /* - * We're sink, disable detect interrupt, so messages on cc line - * won't trigger interrupt. - * NOTE: Plug out is detected by TCPM polling Vbus. - */ - IT83XX_USBPD_TCDCR(port) |= - USBPD_REG_PLUG_IN_OUT_DETECT_DISABLE; - /* - * If not above cases, plug in interrupt will fire again, - * and call switch_plug_out_type() to set the right state. - */ -} - -void switch_plug_out_type(enum usbpd_port port) -{ - it83xx_tcpm_switch_plug_out_type(port); -} - -void set_pd_sleep_mask(int port) -{ - int i; - bool prevent_deep_sleep = false; - - /* - * Set SLEEP_MASK_USB_PD for deep sleep mode: - * 1.Enable deep sleep mode, when all ITE ports are in Unattach.SRC/SNK - * state (HOOK_DISCONNECT called) and other ports aren't pd_capable(). - * 2.Disable deep sleep mode, when one of ITE port is in Attach.SRC/SNK - * state (HOOK_CONNECT called) or one of other ports is pd_capable(). - */ - for (i = 0; i < CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT; ++i) { - if (IT83XX_USBPD_GCR(i) & USBPD_REG_MASK_BMC_PHY) { - prevent_deep_sleep = true; - break; - } - } - - /* - * Check if any other ports have a PD port partner connected. Deep - * sleep is forbidden if any PD port partner is connected. Above, we - * only checked for the ITE ports. - */ - if (!prevent_deep_sleep) { - for (; i < board_get_usb_pd_port_count(); i++) - if (pd_capable(i)) - prevent_deep_sleep = true; - } - - if (prevent_deep_sleep) - disable_sleep(SLEEP_MASK_USB_PD); - else - enable_sleep(SLEEP_MASK_USB_PD); -} - -static void it83xx_tcpm_hook_connect(void) -{ - int port = TASK_ID_TO_PD_PORT(task_get_current()); - -#ifdef CONFIG_USB_PD_TCPMV2 - /* - * There are five cases that hook_connect() be called by TCPMv2: - * 1)AttachWait.SNK -> Attached.SNK: disable detect interrupt. - * 2)AttachWait.SRC -> Attached.SRC: enable detect plug out. - * 3)AttachWait.SNK -> Try.SRC -> TryWait.SNK -> Attached.SNK: we do - * Try.SRC fail, disable detect interrupt. - * 4)AttachWait.SNK -> Try.SRC -> Attached.SRC: we do Try.SRC - * successfully, need to switch to detect plug out. - * 5)Attached.SRC -> TryWait.SNK -> Attached.SNK: partner do Try.SRC - * successfully, disable detect interrupt. - * - * NOTE: Try.SRC and TryWait.SNK are embedded respectively in - * SRC_DISCONNECT and SNK_DISCONNECT in TCPMv1. Every time we go to - * Try.SRC/TryWait.SNK state, the plug in interrupt will be enabled and - * fire for 3), 4), 5) cases, then set correctly for the SRC detect plug - * out or the SNK disable detect, so TCPMv1 needn't this. - */ - it83xx_tcpm_switch_plug_out_type(port); -#endif - /* Enable PD PHY Tx and Rx module since type-c has connected. */ - USBPD_ENABLE_BMC_PHY(port); - set_pd_sleep_mask(port); -} - -DECLARE_HOOK(HOOK_USB_PD_CONNECT, it83xx_tcpm_hook_connect, HOOK_PRIO_DEFAULT); - -static void it83xx_tcpm_hook_disconnect(void) -{ - int port = TASK_ID_TO_PD_PORT(task_get_current()); - - if (IS_ENABLED(IT83XX_INTC_PLUG_IN_OUT_SUPPORT)) - /* - * Switch to detect plug in and enable detect plug in interrupt, - * since pd task has detected a type-c physical disconnected. - */ - IT83XX_USBPD_TCDCR(port) &= ~(USBPD_REG_PLUG_OUT_SELECT | - USBPD_REG_PLUG_IN_OUT_DETECT_DISABLE); - - /* exit BIST test data mode */ - USBPD_SW_RESET(port); - - /* - * Init rx status and disable PD PHY Tx and Rx module for better power - * consumption since type-c has disconnected. - */ - rx_en[port] = 0; - if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) - sop_prime_en[port] = 0; - USBPD_DISABLE_BMC_PHY(port); - set_pd_sleep_mask(port); -} - -DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, it83xx_tcpm_hook_disconnect, - 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, -#ifdef CONFIG_USB_PD_DECODE_SOP - .sop_prime_enable = &it83xx_tcpm_decode_sop_prime_enable, -#endif - .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, -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - .drp_toggle = NULL, -#endif - .get_chip_info = &it83xx_tcpm_get_chip_info, -#ifdef CONFIG_USB_PD_TCPC_LOW_POWER - .enter_low_power_mode = &it83xx_tcpm_enter_low_power_mode, -#endif -#ifdef CONFIG_USB_PD_FRS_TCPC - .set_frs_enable = &it83xx_tcpm_set_frs_enable, -#endif -}; diff --git a/driver/tcpm/it83xx_pd.h b/driver/tcpm/it83xx_pd.h deleted file mode 100644 index ff7c231f23..0000000000 --- a/driver/tcpm/it83xx_pd.h +++ /dev/null @@ -1,458 +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 - -#include "driver/tcpm/it8xxx2_pd_public.h" - -/* USBPD Controller */ -#if defined(CONFIG_USB_PD_TCPM_DRIVER_IT83XX) -#define IT83XX_USBPD_BASE(port) (0x00F03700 + (0x100 * (port))) - -#define IT83XX_USBPD_GCR(p) REG8(IT83XX_USBPD_BASE(p)+0x0) -#define USBPD_REG_MASK_SW_RESET_BIT BIT(7) -#define USBPD_REG_MASK_TYPE_C_DETECT_RESET BIT(6) -#define USBPD_REG_MASK_BMC_PHY BIT(4) -#define USBPD_REG_MASK_AUTO_SEND_SW_RESET BIT(3) -#define USBPD_REG_MASK_AUTO_SEND_HW_RESET BIT(2) -#define USBPD_REG_MASK_SNIFFER_MODE BIT(1) -#define USBPD_REG_MASK_GLOBAL_ENABLE BIT(0) -#define IT83XX_USBPD_PDMSR(p) REG8(IT83XX_USBPD_BASE(p)+0x01) -#define USBPD_REG_MASK_SOPPP_ENABLE BIT(7) -#define USBPD_REG_MASK_SOPP_ENABLE BIT(6) -#define USBPD_REG_MASK_SOP_ENABLE BIT(5) -#define IT83XX_USBPD_CCGCR(p) REG8(IT83XX_USBPD_BASE(p)+0x04) -#define USBPD_REG_MASK_DISABLE_CC BIT(4) -#define IT83XX_USBPD_CCCSR(p) REG8(IT83XX_USBPD_BASE(p)+0x05) -#define USBPD_REG_MASK_CC2_DISCONNECT BIT(7) -#define USBPD_REG_MASK_CC2_DISCONNECT_5_1K_TO_GND BIT(6) -#define USBPD_REG_MASK_CC1_DISCONNECT BIT(3) -#define USBPD_REG_MASK_CC1_DISCONNECT_5_1K_TO_GND BIT(2) -#ifdef IT83XX_USBPD_CC_VOLTAGE_DETECTOR_INDEPENDENT -#define USBPD_REG_MASK_DISABLE_CC_VOL_DETECTOR (BIT(5) | BIT(1)) -#else -#define USBPD_REG_MASK_DISABLE_CC_VOL_DETECTOR BIT(1) -#endif -#define IT83XX_USBPD_CCPSR(p) REG8(IT83XX_USBPD_BASE(p)+0x06) -#define USBPD_REG_MASK_DISCONNECT_5_1K_CC2_DB BIT(6) -#define USBPD_REG_MASK_DISCONNECT_POWER_CC2 BIT(5) -#define USBPD_REG_MASK_DISCONNECT_5_1K_CC1_DB BIT(2) -#define USBPD_REG_MASK_DISCONNECT_POWER_CC1 BIT(1) -#define IT83XX_USBPD_DFPVDR(p) REG8(IT83XX_USBPD_BASE(p)+0x08) -#define IT83XX_USBPD_UFPVDR(p) REG8(IT83XX_USBPD_BASE(p)+0x09) -#define IT83XX_USBPD_PDPSR(p) REG8(IT83XX_USBPD_BASE(p)+0x0B) -#define USBPD_REG_MASK_AUTO_FRS_DISABLE BIT(7) -#define IT83XX_USBPD_CCADCR(p) REG8(IT83XX_USBPD_BASE(p)+0x0C) -#define IT83XX_USBPD_ISR(p) REG8(IT83XX_USBPD_BASE(p)+0x14) -#define USBPD_REG_MASK_TYPE_C_DETECT BIT(7) -#define USBPD_REG_MASK_CABLE_RESET_DETECT BIT(6) -#define USBPD_REG_MASK_HARD_RESET_DETECT BIT(5) -#define USBPD_REG_MASK_MSG_RX_DONE BIT(4) -#define USBPD_REG_MASK_AUTO_SOFT_RESET_TX_DONE BIT(3) -#define USBPD_REG_MASK_HARD_CABLE_RESET_TX_DONE BIT(2) -#define USBPD_REG_MASK_MSG_TX_DONE BIT(1) -#define USBPD_REG_MASK_TIMER_TIMEOUT BIT(0) -#define IT83XX_USBPD_IMR(p) REG8(IT83XX_USBPD_BASE(p)+0x15) -#define IT83XX_USBPD_MTCR(p) REG8(IT83XX_USBPD_BASE(p)+0x18) -#define USBPD_REG_MASK_SW_RESET_TX_STAT BIT(3) -#define USBPD_REG_MASK_TX_BUSY_STAT BIT(2) -#define USBPD_REG_MASK_TX_DISCARD_STAT BIT(2) -#ifdef IT83XX_PD_TX_ERROR_STATUS_BIT5 -#define USBPD_REG_MASK_TX_ERR_STAT BIT(5) -#else -#define USBPD_REG_MASK_TX_ERR_STAT BIT(1) -#endif -#define USBPD_REG_MASK_TX_START BIT(0) -#define IT83XX_USBPD_MTSR0(p) REG8(IT83XX_USBPD_BASE(p)+0x19) -#define USBPD_REG_MASK_CABLE_ENABLE BIT(7) -#define USBPD_REG_MASK_SEND_HW_RESET BIT(6) -#define USBPD_REG_MASK_SEND_BIST_MODE_2 BIT(5) -#define IT83XX_USBPD_MTSR1(p) REG8(IT83XX_USBPD_BASE(p)+0x1A) -#define IT83XX_USBPD_VDMMCSR(p) REG8(IT83XX_USBPD_BASE(p)+0x1B) -#define USBPD_REG_MASK_HARD_RESET_DECODE BIT(0) -#define IT83XX_USBPD_MRSR(p) REG8(IT83XX_USBPD_BASE(p)+0x1C) -#define USBPD_REG_GET_SOP_TYPE_RX(mrsr) (((mrsr) >> 4) & 0x7) -#define USBPD_REG_MASK_RX_MSG_VALID BIT(0) -#define IT83XX_USBPD_PEFSMR(p) REG8(IT83XX_USBPD_BASE(p)+0x1D) -#define IT83XX_USBPD_PES0R(p) REG8(IT83XX_USBPD_BASE(p)+0x1E) -#define IT83XX_USBPD_PES1R(p) REG8(IT83XX_USBPD_BASE(p)+0x1F) -#define IT83XX_USBPD_TDO(p) REG32(IT83XX_USBPD_BASE(p)+0x20) -#define IT83XX_USBPD_AGTMHLR(p) REG8(IT83XX_USBPD_BASE(p)+0x3C) -#define IT83XX_USBPD_AGTMHHR(p) REG8(IT83XX_USBPD_BASE(p)+0x3D) -#define IT83XX_USBPD_TMHLR(p) REG8(IT83XX_USBPD_BASE(p)+0x3E) -#define IT83XX_USBPD_TMHHR(p) REG8(IT83XX_USBPD_BASE(p)+0x3F) -#define IT83XX_USBPD_RDO0(p) REG32(IT83XX_USBPD_BASE(p)+0x40) -#define IT83XX_USBPD_RMH(p) REG16(IT83XX_USBPD_BASE(p)+0x5E) -#define IT83XX_USBPD_CCPSR0(p) REG8(IT83XX_USBPD_BASE(p)+0x60) -#define IT83XX_USBPD_BMCSR(p) REG8(IT83XX_USBPD_BASE(p)+0x64) -#define IT83XX_USBPD_PDMHSR(p) REG8(IT83XX_USBPD_BASE(p)+0x65) -#define IT83XX_USBPD_TCDCR(p) REG8(IT83XX_USBPD_BASE(p)+0x67) -#define USBPD_REG_PLUG_OUT_DETECT_TYPE_SELECT BIT(7) -#define USBPD_REG_MASK_TYPEC_PLUG_IN_OUT_ISR BIT(4) -#define USBPD_REG_PLUG_OUT_SELECT BIT(3) -#define USBPD_REG_PLUG_IN_OUT_DETECT_DISABLE BIT(1) -#define USBPD_REG_PLUG_IN_OUT_DETECT_STAT BIT(0) -#define IT83XX_USBPD_PDQSCR(p) REG8(IT83XX_USBPD_BASE(p)+0x70) -#define USBPD_REG_FAST_SWAP_REQUEST_ENABLE BIT(1) -#define USBPD_REG_FAST_SWAP_DETECT_ENABLE BIT(0) -#define IT83XX_USBPD_PD30IR(p) REG8(IT83XX_USBPD_BASE(p)+0x78) -#define USBPD_REG_FAST_SWAP_DETECT_STAT BIT(4) -#define IT83XX_USBPD_MPD30IR(p) REG8(IT83XX_USBPD_BASE(p)+0x7A) -#define USBPD_REG_MASK_PD30_ISR BIT(7) -#define USBPD_REG_MASK_FAST_SWAP_DETECT_ISR BIT(4) - -#elif defined(CONFIG_USB_PD_TCPM_DRIVER_IT8XXX2) -#define IT83XX_USBPD_BASE(port) (0x00F03700 + (0x100 * (port) * (port))) - -#define IT83XX_USBPD_PDGCR(p) REG8(IT83XX_USBPD_BASE(p)+0x0) -#define USBPD_REG_MASK_SW_RESET_BIT BIT(7) -#define USBPD_REG_MASK_PROTOCOL_STATE_CLEAR BIT(6) -#define USBPD_REG_MASK_BIST_DATA_MODE BIT(4) -#define USBPD_REG_MASK_AUTO_BIST_RESPONSE BIT(3) -#define USBPD_REG_MASK_TX_MESSAGE_ENABLE BIT(2) -#define USBPD_REG_MASK_SNIFFER_MODE BIT(1) -#define USBPD_REG_MASK_BMC_PHY BIT(0) -#define IT83XX_USBPD_PDCSR0(p) REG8(IT83XX_USBPD_BASE(p)+0x01) -#define IT83XX_USBPD_PDMSR(p) REG8(IT83XX_USBPD_BASE(p)+0x02) -#define USBPD_REG_MASK_DISABLE_AUTO_GEN_TX_HEADER BIT(7) -#define USBPD_REG_MASK_AUTO_FRS_DISABLE BIT(6) -#define IT83XX_USBPD_PDCSR1(p) REG8(IT83XX_USBPD_BASE(p)+0x03) -#define USBPD_REG_MASK_CABLE_RESET_RX_ENABLE BIT(6) -#define USBPD_REG_MASK_HARD_RESET_RX_ENABLE BIT(5) -#define USBPD_REG_MASK_SOPPP_RX_ENABLE BIT(2) -#define USBPD_REG_MASK_SOPP_RX_ENABLE BIT(1) -#define USBPD_REG_MASK_SOP_RX_ENABLE BIT(0) -#define IT83XX_USBPD_CCGCR(p) REG8(IT83XX_USBPD_BASE(p)+0x04) -#define USBPD_REG_MASK_DISABLE_CC BIT(7) -#define USBPD_REG_MASK_DISABLE_CC_VOL_DETECTOR BIT(6) -#define USBPD_REG_MASK_CC_SELECT_RP_RESERVED (BIT(3) | BIT(2) | BIT(1)) -#define USBPD_REG_MASK_CC_SELECT_RP_DEF (BIT(3) | BIT(2)) -#define USBPD_REG_MASK_CC_SELECT_RP_1A5 BIT(3) -#define USBPD_REG_MASK_CC_SELECT_RP_3A0 BIT(2) -#define USBPD_REG_MASK_CC1_CC2_SELECTION BIT(0) -#define IT83XX_USBPD_CCCSR(p) REG8(IT83XX_USBPD_BASE(p)+0x05) -#define USBPD_REG_MASK_CC2_DISCONNECT BIT(7) -#define USBPD_REG_MASK_CC2_DISCONNECT_5_1K_TO_GND BIT(6) -#define USBPD_REG_MASK_CC1_DISCONNECT BIT(3) -#define USBPD_REG_MASK_CC1_DISCONNECT_5_1K_TO_GND BIT(2) -#ifdef IT83XX_USBPD_CC1_CC2_RESISTANCE_SEPARATE -#define USBPD_REG_MASK_CC1_CC2_RP_RD_SELECT (BIT(1) | BIT(5)) -#else -#define USBPD_REG_MASK_CC1_CC2_RP_RD_SELECT BIT(1) -#endif -#define IT83XX_USBPD_CCPSR(p) REG8(IT83XX_USBPD_BASE(p)+0x06) -#define USBPD_REG_MASK_DISCONNECT_5_1K_CC2_DB BIT(6) -#define USBPD_REG_MASK_DISCONNECT_POWER_CC2 BIT(5) -#define USBPD_REG_MASK_DISCONNECT_5_1K_CC1_DB BIT(2) -#define USBPD_REG_MASK_DISCONNECT_POWER_CC1 BIT(1) -#define IT83XX_USBPD_SRCVCRR(p) REG8(IT83XX_USBPD_BASE(p)+0x08) -#define USBPD_REG_MASK_SRC_COMPARE_CC2_VOLT_H BIT(5) -#define USBPD_REG_MASK_SRC_COMPARE_CC2_VOLT_L BIT(4) -#define USBPD_REG_MASK_SRC_COMPARE_CC1_VOLT_H BIT(1) -#define USBPD_REG_MASK_SRC_COMPARE_CC1_VOLT_L BIT(0) -#define IT83XX_USBPD_SNKVCRR(p) REG8(IT83XX_USBPD_BASE(p)+0x09) -#define USBPD_REG_MASK_SNK_COMPARE_CC2_VOLT_H BIT(6) -#define USBPD_REG_MASK_SNK_COMPARE_CC2_VOLT_M BIT(5) -#define USBPD_REG_MASK_SNK_COMPARE_CC2_VOLT_L BIT(4) -#define USBPD_REG_MASK_SNK_COMPARE_CC1_VOLT_H BIT(2) -#define USBPD_REG_MASK_SNK_COMPARE_CC1_VOLT_M BIT(1) -#define USBPD_REG_MASK_SNK_COMPARE_CC1_VOLT_L BIT(0) -#define IT83XX_USBPD_PDFSCR(p) REG8(IT83XX_USBPD_BASE(p)+0x0C) -#define USBPD_REG_FAST_SWAP_REQUEST_ENABLE BIT(1) -#define USBPD_REG_FAST_SWAP_DETECT_ENABLE BIT(0) -#define IT83XX_USBPD_IFS(p) REG8(IT83XX_USBPD_BASE(p)+0x12) -#define USBPD_REG_FAST_SWAP_DETECT_STAT BIT(4) -#define IT83XX_USBPD_MIFS(p) REG8(IT83XX_USBPD_BASE(p)+0x13) -#define USBPD_REG_MASK_FAST_SWAP_ISR BIT(7) -#define USBPD_REG_MASK_FAST_SWAP_DETECT_ISR BIT(4) -#define IT83XX_USBPD_ISR(p) REG8(IT83XX_USBPD_BASE(p)+0x14) -#define USBPD_REG_MASK_CABLE_RESET_DETECT BIT(6) -#define USBPD_REG_MASK_HARD_RESET_DETECT BIT(5) -#define USBPD_REG_MASK_MSG_RX_DONE BIT(4) -#define USBPD_REG_MASK_TX_ERROR_STAT BIT(3) -#define USBPD_REG_MASK_CABLE_RESET_TX_DONE BIT(2) -#define USBPD_REG_MASK_HARD_RESET_TX_DONE BIT(1) -#define USBPD_REG_MASK_MSG_TX_DONE BIT(0) -#define IT83XX_USBPD_IMR(p) REG8(IT83XX_USBPD_BASE(p)+0x15) -#define IT83XX_USBPD_MTCR(p) REG8(IT83XX_USBPD_BASE(p)+0x18) -#define USBPD_REG_MASK_TX_DISCARD_STAT BIT(7) -#define USBPD_REG_MASK_TX_NO_RESPONSE_STAT BIT(6) -#define USBPD_REG_MASK_TX_NOT_EN_STAT BIT(5) -#define USBPD_REG_MASK_CABLE_RESET BIT(3) -#define USBPD_REG_MASK_SEND_HW_RESET BIT(2) -#define USBPD_REG_MASK_SEND_BIST_MODE_2 BIT(1) -#define USBPD_REG_MASK_TX_START BIT(0) -#define IT83XX_USBPD_MTSR0(p) REG8(IT83XX_USBPD_BASE(p)+0x19) -#define IT83XX_USBPD_MHSR0(p) REG8(IT83XX_USBPD_BASE(p)+0x1A) -#define USBPD_REG_MASK_SOP_PORT_DATA_ROLE BIT(5) -#define IT83XX_USBPD_MHSR1(p) REG8(IT83XX_USBPD_BASE(p)+0x1B) -#define USBPD_REG_MASK_SOP_PORT_POWER_ROLE BIT(0) -#define IT83XX_USBPD_TDO(p) REG32(IT83XX_USBPD_BASE(p)+0x22) -#define IT83XX_USBPD_RMH(p) REG16(IT83XX_USBPD_BASE(p)+0x42) -#define IT83XX_USBPD_RDO(p) REG32(IT83XX_USBPD_BASE(p)+0x44) -#define IT83XX_USBPD_BMCDR0(p) REG8(IT83XX_USBPD_BASE(p)+0x61) -#define USBPD_REG_MASK_BMC_RX_THRESHOLD_SRC BIT(5) -#define USBPD_REG_MASK_BMC_RX_THRESHOLD_SNK BIT(1) -#define IT83XX_USBPD_TCDCR(p) REG8(IT83XX_USBPD_BASE(p)+0x67) -#define USBPD_REG_PLUG_OUT_DETECT_TYPE_SELECT BIT(7) -#define USBPD_REG_PLUG_OUT_SELECT BIT(6) -#define USBPD_REG_PD3_0_SNK_TX_OK_DISABLE BIT(5) -#define USBPD_REG_PD3_0_SNK_TX_NG_DISABLE BIT(3) -#define USBPD_REG_PLUG_IN_OUT_DETECT_DISABLE BIT(1) -#define USBPD_REG_PLUG_IN_OUT_DETECT_STAT BIT(0) -#define IT83XX_USBPD_CCPSR0(p) REG8(IT83XX_USBPD_BASE(p)+0x70) -#define IT83XX_USBPD_CCPSR3_RISE(p) REG8(IT83XX_USBPD_BASE(p)+0x73) -#define IT83XX_USBPD_CCPSR4_FALL(p) REG8(IT83XX_USBPD_BASE(p)+0x74) -#endif /* !defined(CONFIG_USB_PD_TCPM_DRIVER_IT83XX) */ - -/* - * 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 IT83XX_USBPD_CC_PIN_CONFIG2 0x06 - -/* - * Before disabling cc 5v tolerant, we need to make sure cc voltage - * detector is enabled and Vconn is dropped below 3.3v (>500us) to avoid - * the potential risk of voltage fed back into Vcore. - */ -#define IT83XX_USBPD_T_VCONN_BELOW_3_3V 500 /* us */ - -#ifndef CONFIG_USB_PD_TCPM_ITE_ON_CHIP -#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 0 -#endif - -#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) - -#if defined(CONFIG_USB_PD_TCPM_DRIVER_IT83XX) -/* 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) -#define USBPD_CLEAR_FRS_DETECT_STATUS(port) \ - (IT83XX_USBPD_PD30IR(port) = USBPD_REG_FAST_SWAP_DETECT_STAT) -#define USBPD_CC1_DISCONNECTED(p) \ - ((IT83XX_USBPD_CCCSR(p) | USBPD_REG_MASK_CC1_DISCONNECT) & \ - ~USBPD_REG_MASK_CC2_DISCONNECT) -#define USBPD_CC2_DISCONNECTED(p) \ - ((IT83XX_USBPD_CCCSR(p) | USBPD_REG_MASK_CC2_DISCONNECT) & \ - ~USBPD_REG_MASK_CC1_DISCONNECT) - -/* 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) - -#elif defined(CONFIG_USB_PD_TCPM_DRIVER_IT8XXX2) -/* macros for set */ -#define USBPD_SW_RESET(port) \ - SET_MASK(IT83XX_USBPD_PDGCR(port), \ - USBPD_REG_MASK_SW_RESET_BIT) -#define USBPD_ENABLE_BMC_PHY(port) \ - SET_MASK(IT83XX_USBPD_PDGCR(port), \ - USBPD_REG_MASK_BMC_PHY) -#define USBPD_DISABLE_BMC_PHY(port) \ - CLEAR_MASK(IT83XX_USBPD_PDGCR(port), \ - USBPD_REG_MASK_BMC_PHY) -#define USBPD_START(port) \ - CLEAR_MASK(IT83XX_USBPD_CCGCR(port), \ - USBPD_REG_MASK_DISABLE_CC) -#define USBPD_SEND_HARD_RESET(port) \ - SET_MASK(IT83XX_USBPD_MTCR(port), \ - USBPD_REG_MASK_SEND_HW_RESET) -#define USBPD_SEND_CABLE_RESET(port) \ - SET_MASK(IT83XX_USBPD_MTCR(port), \ - USBPD_REG_MASK_CABLE_RESET) -#define USBPD_ENABLE_SEND_BIST_MODE_2(port) \ - SET_MASK(IT83XX_USBPD_MTCR(port), \ - USBPD_REG_MASK_SEND_BIST_MODE_2) -#define USBPD_DISABLE_SEND_BIST_MODE_2(port) \ - CLEAR_MASK(IT83XX_USBPD_MTCR(port), \ - USBPD_REG_MASK_SEND_BIST_MODE_2) -#define USBPD_KICK_TX_START(port) \ - SET_MASK(IT83XX_USBPD_MTCR(port), \ - USBPD_REG_MASK_TX_START) -#define USBPD_CLEAR_FRS_DETECT_STATUS(port) \ - (IT83XX_USBPD_IFS(port) = USBPD_REG_FAST_SWAP_DETECT_STAT) -#define USBPD_CC1_DISCONNECTED(p) \ - ((IT83XX_USBPD_CCCSR(p) | USBPD_REG_MASK_CC1_DISCONNECT) & \ - ~USBPD_REG_MASK_CC2_DISCONNECT) -#define USBPD_CC2_DISCONNECTED(p) \ - ((IT83XX_USBPD_CCCSR(p) | USBPD_REG_MASK_CC2_DISCONNECT) & \ - ~USBPD_REG_MASK_CC1_DISCONNECT) - -/* macros for get */ -#define USBPD_GET_POWER_ROLE(port) \ - (IT83XX_USBPD_MHSR1(port) & BIT(0)) -#define USBPD_GET_CC1_PULL_REGISTER_SELECTION(port) \ - (IT83XX_USBPD_CCCSR(port) & BIT(1)) -#define USBPD_GET_CC2_PULL_REGISTER_SELECTION(port) \ - (IT83XX_USBPD_CCCSR(port) & BIT(1)) -#define USBPD_GET_PULL_CC_SELECTION(port) \ - (IT83XX_USBPD_CCGCR(port) & BIT(0)) -#define USBPD_GET_SNK_COMPARE_CC1_VOLT(port) \ - (IT83XX_USBPD_SNKVCRR(port) & \ - (USBPD_REG_MASK_SNK_COMPARE_CC1_VOLT_L | \ - USBPD_REG_MASK_SNK_COMPARE_CC1_VOLT_M | \ - USBPD_REG_MASK_SNK_COMPARE_CC1_VOLT_H)) -#define USBPD_GET_SNK_COMPARE_CC2_VOLT(port) \ - ((IT83XX_USBPD_SNKVCRR(port) & \ - (USBPD_REG_MASK_SNK_COMPARE_CC2_VOLT_L | \ - USBPD_REG_MASK_SNK_COMPARE_CC2_VOLT_M | \ - USBPD_REG_MASK_SNK_COMPARE_CC2_VOLT_H)) >> 4) -#define USBPD_GET_SRC_COMPARE_CC1_VOLT(port) \ - (IT83XX_USBPD_SRCVCRR(port) & \ - (USBPD_REG_MASK_SRC_COMPARE_CC1_VOLT_L | \ - USBPD_REG_MASK_SRC_COMPARE_CC1_VOLT_H)) -#define USBPD_GET_SRC_COMPARE_CC2_VOLT(port) \ - ((IT83XX_USBPD_SRCVCRR(port) & \ - (USBPD_REG_MASK_SRC_COMPARE_CC2_VOLT_L | \ - USBPD_REG_MASK_SRC_COMPARE_CC2_VOLT_H)) >> 4) - -/* macros for check */ -#define USBPD_IS_TX_ERR(port) \ - IS_MASK_SET(IT83XX_USBPD_ISR(port), USBPD_REG_MASK_TX_ERROR_STAT) -#endif /* !defined(CONFIG_USB_PD_TCPM_DRIVER_IT83XX) */ - -/* 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_HARD_CABLE_RESET_TX_DONE(port) \ - IS_MASK_SET(IT83XX_USBPD_ISR(port), \ - USBPD_REG_MASK_HARD_CABLE_RESET_TX_DONE) -#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) -#define USBPD_IS_PLUG_IN_OUT_DETECT(port)\ - IS_MASK_SET(IT83XX_USBPD_TCDCR(port), USBPD_REG_PLUG_IN_OUT_DETECT_STAT) -#define USBPD_IS_PLUG_IN(port) \ - IS_MASK_CLEAR(IT83XX_USBPD_TCDCR(port), USBPD_REG_PLUG_OUT_SELECT) -#if defined(CONFIG_USB_PD_TCPM_DRIVER_IT83XX) -#define USBPD_IS_FAST_SWAP_DETECT(port) \ - IS_MASK_SET(IT83XX_USBPD_PD30IR(port), USBPD_REG_FAST_SWAP_DETECT_STAT) -#elif defined(CONFIG_USB_PD_TCPM_DRIVER_IT8XXX2) -#define USBPD_IS_FAST_SWAP_DETECT(port) \ - IS_MASK_SET(IT83XX_USBPD_IFS(port), USBPD_REG_FAST_SWAP_DETECT_STAT) -#endif - -#if defined(CONFIG_USB_PD_TCPM_ITE_ON_CHIP) && defined(CONFIG_ZEPHYR) -/* Use the Zephyr names here. When upstreaming we can update this */ -#include <dt-bindings/interrupt-controller/ite-intc.h> - -#define IT83XX_GPIO_GPCRF4 GPCRF4 -#define IT83XX_GPIO_GPCRF5 GPCRF5 -#define IT83XX_GPIO_GPCRH1 GPCRH1 -#define IT83XX_GPIO_GPCRH2 GPCRH2 -#define IT83XX_GPIO_GPCRP0 IT8XXX2_GPIO_GPCRP0 -#define IT83XX_GPIO_GPCRP1 IT8XXX2_GPIO_GPCRP1 -#define IT83XX_IRQ_USBPD0 IT8XXX2_IRQ_USBPD0 -#define IT83XX_IRQ_USBPD1 IT8XXX2_IRQ_USBPD1 -#define IT83XX_IRQ_USBPD2 IT8XXX2_IRQ_USBPD2 -#define USB_VID_ITE 0x048d - -/* ITE chip supports PD features */ -#define IT83XX_INTC_FAST_SWAP_SUPPORT -#define IT83XX_INTC_PLUG_IN_OUT_SUPPORT -#endif - -enum usbpd_port { - USBPD_PORT_A, - USBPD_PORT_B, - USBPD_PORT_C, -}; - -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, -}; - -enum tuning_unit { - IT83XX_TX_PRE_DRIVING_TIME_DEFAULT, - IT83XX_TX_PRE_DRIVING_TIME_1_UNIT, - IT83XX_TX_PRE_DRIVING_TIME_2_UNIT, - IT83XX_TX_PRE_DRIVING_TIME_3_UNIT, -}; - -struct usbpd_ctrl_t { - volatile uint8_t *cc1; - volatile uint8_t *cc2; - uint8_t irq; -}; - -/* Data structure for board to adjust pd port rising and falling time */ -struct cc_para_t { - enum tuning_unit rising_time; - enum tuning_unit falling_time; -}; - -extern const struct usbpd_ctrl_t usbpd_ctrl_regs[]; -void it8xxx2_clear_tx_error_status(enum usbpd_port port); -void it8xxx2_get_tx_error_status(enum usbpd_port port); -void it83xx_Rd_5_1K_only_for_hibernate(int port); -void switch_plug_out_type(enum usbpd_port port); -/* - * Board-level callback function to get cc tuning parameters - * NOTE: board must define CONFIG_IT83XX_TUNE_CC_PHY - */ -const struct cc_para_t *board_get_cc_tuning_parameter(enum usbpd_port port); - -#endif /* __CROS_EC_DRIVER_TCPM_IT83XX_H */ diff --git a/driver/tcpm/it8xxx2.c b/driver/tcpm/it8xxx2.c deleted file mode 100644 index dd5d1231fc..0000000000 --- a/driver/tcpm/it8xxx2.c +++ /dev/null @@ -1,968 +0,0 @@ -/* Copyright 2020 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 on ITE chip it8xxx2 with embedded TCPC */ - -#include "common.h" -#include "config.h" -#include "console.h" -#include "it83xx_pd.h" -#include "ite_pd_intc.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" -#include "usb_common.h" -#include "usb_pd.h" -#include "usb_pd_tcpm.h" -#include "hooks.h" - -#ifdef CONFIG_USB_PD_TCPMV1 -#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 IT8xxx2 PD driver" -#endif -#endif - -#ifdef CONFIG_USB_PD_TCPMV2 -#if defined(CONFIG_USB_PD_VBUS_DETECT_TCPC) || \ - defined(CONFIG_USB_PD_DISCHARGE_TCPC) -#error "Unsupported config options of IT8xxx2 PD driver" -#endif -#endif - -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -bool rx_en[IT83XX_USBPD_PHY_PORT_COUNT]; -STATIC_IF(CONFIG_USB_PD_DECODE_SOP) - bool sop_prime_en[IT83XX_USBPD_PHY_PORT_COUNT]; -static uint8_t tx_error_status[IT83XX_USBPD_PHY_PORT_COUNT] = {0}; - -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}, - {&IT83XX_GPIO_GPCRP0, &IT83XX_GPIO_GPCRP1, IT83XX_IRQ_USBPD2}, -}; -BUILD_ASSERT(ARRAY_SIZE(usbpd_ctrl_regs) >= IT83XX_USBPD_PHY_PORT_COUNT); - -/* - * Disable cc analog and pd digital module, but only left Rd_5.1K (Not - * Rd_DB) analog module alive to assert Rd on CCs. EC reset or calling - * _init() are able to re-active cc and pd. - */ -void it83xx_Rd_5_1K_only_for_hibernate(int port) -{ - uint8_t cc_config = (port == USBPD_PORT_C ? - IT83XX_USBPD_CC_PIN_CONFIG2 : - IT83XX_USBPD_CC_PIN_CONFIG); - - /* This only apply to active PD port */ - if (*usbpd_ctrl_regs[port].cc1 == cc_config && - *usbpd_ctrl_regs[port].cc2 == cc_config) { - /* Disable PD Tx and Rx PHY */ - IT83XX_USBPD_PDGCR(port) &= ~USBPD_REG_MASK_BMC_PHY; - /* Disable CCs voltage detector */ - IT83XX_USBPD_CCGCR(port) |= - USBPD_REG_MASK_DISABLE_CC_VOL_DETECTOR; - /* Select Rp reserved value for not current leakage */ - IT83XX_USBPD_CCGCR(port) |= - USBPD_REG_MASK_CC_SELECT_RP_RESERVED; - /* - * Connect CCs analog module (ex.UP/RD/DET/TX/RX), and - * connect CCs 5.1K to GND, and - * CCs assert Rd - */ - IT83XX_USBPD_CCCSR(port) &= - ~(USBPD_REG_MASK_CC2_DISCONNECT | - USBPD_REG_MASK_CC2_DISCONNECT_5_1K_TO_GND | - USBPD_REG_MASK_CC1_DISCONNECT | - USBPD_REG_MASK_CC1_DISCONNECT_5_1K_TO_GND | - USBPD_REG_MASK_CC1_CC2_RP_RD_SELECT); - /* Disconnect CCs 5V tolerant */ - IT83XX_USBPD_CCPSR(port) |= - (USBPD_REG_MASK_DISCONNECT_POWER_CC2 | - USBPD_REG_MASK_DISCONNECT_POWER_CC1); - /* Enable CCs analog module */ - IT83XX_USBPD_CCGCR(port) &= ~USBPD_REG_MASK_DISABLE_CC; - } -} - -static enum tcpc_cc_voltage_status it8xxx2_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; - - /* - * Because the message header bit(8) field has different definition - * between SOP and SOP'/SOP'', in order to not happen misjudgement - * when we receive SOP or SOP'/SOP'', the getting power role synchronize - * with pd[port].power_role (also synchronization with tcpm_set_cc) - * instead of message header. - */ - /* Sink */ - if (pd_get_power_role(port) == PD_ROLE_SINK) { - if (cc_pin == USBPD_CC_PIN_1) - ufp_volt = USBPD_GET_SNK_COMPARE_CC1_VOLT(port); - else - ufp_volt = USBPD_GET_SNK_COMPARE_CC2_VOLT(port); - - switch (ufp_volt) { - case USBPD_UFP_STATE_SNK_DEF: - cc_state = TYPEC_CC_VOLT_RP_DEF; - break; - case USBPD_UFP_STATE_SNK_1_5: - cc_state = TYPEC_CC_VOLT_RP_1_5; - break; - case USBPD_UFP_STATE_SNK_3_0: - cc_state = TYPEC_CC_VOLT_RP_3_0; - 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 = USBPD_GET_SRC_COMPARE_CC1_VOLT(port); - else - dfp_volt = USBPD_GET_SRC_COMPARE_CC2_VOLT(port); - - 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 it8xxx2_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); - - /* - * BIT[6:4] SOP type of Rx message - * 000b=SOP, 001b=SOP', 010b=SOP", 011b=Debug SOP', 100b=Debug SOP" - * 101b=HRDRST, 110b=CBLRST - * 000b~100b is aligned to enum tcpci_msg_type. - * - */ - if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) - *head |= PD_HEADER_SOP((IT83XX_USBPD_MTSR0(port) >> 4) & 0x7); - - /* Check data message */ - if (cnt) - memcpy(buf, (uint32_t *)&IT83XX_USBPD_RDO(port), cnt * 4); - - return EC_SUCCESS; -} - -void it8xxx2_clear_tx_error_status(enum usbpd_port port) -{ - tx_error_status[port] = 0; -} - -void it8xxx2_get_tx_error_status(enum usbpd_port port) -{ - tx_error_status[port] = IT83XX_USBPD_MTCR(port) & - (USBPD_REG_MASK_TX_NOT_EN_STAT | - USBPD_REG_MASK_TX_DISCARD_STAT | - USBPD_REG_MASK_TX_NO_RESPONSE_STAT); -} - -static enum tcpc_transmit_complete it8xxx2_tx_data(enum usbpd_port port, - enum tcpci_msg_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_MHSR0(port) = (uint8_t)header; - IT83XX_USBPD_MHSR1(port) = (header >> 8); - - /* - * Bit[2:0] Tx message type - * 000b=SOP, 001b=SOP', 010b=SOP", 011b=Debug SOP', 100b=Debug SOP''. - */ - IT83XX_USBPD_MTSR0(port) = - (IT83XX_USBPD_MTSR0(port) & ~0x7) | (type & 0x7); - - /* Limited by PD_HEADER_CNT() */ - ASSERT(length <= 0x7); - - if (length) - /* Set data */ - memcpy((uint32_t *)&IT83XX_USBPD_TDO(port), buf, length * 4); - - for (r = 0; r <= CONFIG_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 error status (TCPC won't set multi tx errors at one - * time transmission): - * 1) If we doesn't enable Tx. - * 2) If discard, means HW doesn't send the msg and resend. - * 3) If port partner doesn't respond GoodCRC. - * 4) If Tx timeout. - */ - if (tx_error_status[port] || (evt & TASK_EVENT_TIMER)) { - if (tx_error_status[port] & - USBPD_REG_MASK_TX_NOT_EN_STAT) { - CPRINTS("p%d TxErr: Tx EN and resend", port); - tx_error_status[port] &= - ~USBPD_REG_MASK_TX_NOT_EN_STAT; - IT83XX_USBPD_PDGCR(port) |= - USBPD_REG_MASK_TX_MESSAGE_ENABLE; - continue; - } else if (tx_error_status[port] & - USBPD_REG_MASK_TX_DISCARD_STAT) { - CPRINTS("p%d TxErr: Discard and resend", port); - tx_error_status[port] &= - ~USBPD_REG_MASK_TX_DISCARD_STAT; - continue; - } else if (tx_error_status[port] & - USBPD_REG_MASK_TX_NO_RESPONSE_STAT) { - /* HW had automatically resent message twice */ - tx_error_status[port] &= - ~USBPD_REG_MASK_TX_NO_RESPONSE_STAT; - return TCPC_TX_COMPLETE_FAILED; - } else if (evt & TASK_EVENT_TIMER) { - CPRINTS("p%d TxErr: Timeout", port); - return TCPC_TX_UNSET; - } - } else - break; - } - - if (r > CONFIG_PD_RETRY_COUNT) - return TCPC_TX_COMPLETE_DISCARDED; - - return TCPC_TX_COMPLETE_SUCCESS; -} - -static enum tcpc_transmit_complete it8xxx2_send_hw_reset(enum usbpd_port port) -{ - /* Send hard reset */ - USBPD_SEND_HARD_RESET(port); - usleep(MSEC); - - if (!(IT83XX_USBPD_ISR(port) & USBPD_REG_MASK_HARD_RESET_TX_DONE)) - return TCPC_TX_COMPLETE_FAILED; - IT83XX_USBPD_ISR(port) = USBPD_REG_MASK_HARD_RESET_TX_DONE; - - return TCPC_TX_COMPLETE_SUCCESS; -} - -static enum tcpc_transmit_complete it8xxx2_send_cable_reset( - enum usbpd_port port) -{ - /* Send cable reset */ - USBPD_SEND_CABLE_RESET(port); - usleep(MSEC); - - if (!(IT83XX_USBPD_ISR(port) & USBPD_REG_MASK_CABLE_RESET_TX_DONE)) - return TCPC_TX_COMPLETE_FAILED; - IT83XX_USBPD_ISR(port) = USBPD_REG_MASK_CABLE_RESET_TX_DONE; - - return TCPC_TX_COMPLETE_SUCCESS; -} - -static void it8xxx2_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 it8xxx2_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 { - /* Connect cc analog module (ex.UP/RD/DET/TX/RX) */ - IT83XX_USBPD_CCCSR(port) &= ~(USBPD_REG_MASK_CC2_DISCONNECT | - USBPD_REG_MASK_CC1_DISCONNECT); - /* Disable cc 5v tolerant */ - IT83XX_USBPD_CCPSR(port) |= - (USBPD_REG_MASK_DISCONNECT_POWER_CC1 | - USBPD_REG_MASK_DISCONNECT_POWER_CC2); - } -} - -static void it8xxx2_enable_cc(enum usbpd_port port, int enable) -{ - if (enable) - IT83XX_USBPD_CCGCR(port) &= ~USBPD_REG_MASK_DISABLE_CC; - else - IT83XX_USBPD_CCGCR(port) |= USBPD_REG_MASK_DISABLE_CC; -} - -static void it8xxx2_set_power_role(enum usbpd_port port, int power_role) -{ - /* 0: PD_ROLE_SINK, 1: PD_ROLE_SOURCE */ - if (power_role == PD_ROLE_SOURCE) { - /* - * Bit[0:6] BMC Rx threshold setting - * 000 1000b: power neutral - * 010 0000b: sinking power => - * High to low Y3Rx threshold = 0.38, - * Low to high Y3Rx threshold = 0.54. - * 000 0010b: sourcing power => - * High to low Y3Rx threshold = 0.64, - * Low to high Y3Rx threshold = 0.79. - */ - IT83XX_USBPD_BMCDR0(port) = USBPD_REG_MASK_BMC_RX_THRESHOLD_SRC; - /* Bit0: source */ - IT83XX_USBPD_MHSR1(port) |= USBPD_REG_MASK_SOP_PORT_POWER_ROLE; - /* Bit1: CC1 and CC2 select Rp */ - IT83XX_USBPD_CCCSR(port) |= USBPD_REG_MASK_CC1_CC2_RP_RD_SELECT; - } else { - /* - * Bit[0:6] BMC Rx threshold setting - * 000 1000b: power neutral - * 010 0000b: sinking power => - * High to low Y3Rx threshold = 0.38, - * Low to high Y3Rx threshold = 0.54. - * 000 0010b: sourcing power => - * High to low Y3Rx threshold = 0.64, - * Low to high Y3Rx threshold = 0.79. - */ - IT83XX_USBPD_BMCDR0(port) = USBPD_REG_MASK_BMC_RX_THRESHOLD_SNK; - /* Bit0: sink */ - IT83XX_USBPD_MHSR1(port) &= ~USBPD_REG_MASK_SOP_PORT_POWER_ROLE; - /* Bit1: CC1 and CC2 select Rd */ - IT83XX_USBPD_CCCSR(port) &= - ~USBPD_REG_MASK_CC1_CC2_RP_RD_SELECT; - } -} - -static void it8xxx2_set_data_role(enum usbpd_port port, int data_role) -{ - /* 0: PD_ROLE_UFP 1: PD_ROLE_DFP */ - if (data_role == PD_ROLE_DFP) - /* Bit5: DFP */ - IT83XX_USBPD_MHSR0(port) |= USBPD_REG_MASK_SOP_PORT_DATA_ROLE; - else - /* Bit5: UFP */ - IT83XX_USBPD_MHSR0(port) &= ~USBPD_REG_MASK_SOP_PORT_DATA_ROLE; -} - -static void it8xxx2_select_polarity(enum usbpd_port port, - enum usbpd_cc_pin cc_pin) -{ - /* CC1/CC2 selection */ - if (cc_pin == USBPD_CC_PIN_1) - IT83XX_USBPD_CCGCR(port) |= USBPD_REG_MASK_CC1_CC2_SELECTION; - else - IT83XX_USBPD_CCGCR(port) &= ~USBPD_REG_MASK_CC1_CC2_SELECTION; -} - -static int it8xxx2_set_cc(enum usbpd_port port, int pull) -{ - int enable_cc = 1; - - switch (pull) { - case TYPEC_CC_RD: - it8xxx2_set_power_role(port, PD_ROLE_SINK); - break; - case TYPEC_CC_RP: - it8xxx2_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; - } - - it8xxx2_enable_cc(port, enable_cc); - return EC_SUCCESS; -} - -static int it8xxx2_tcpm_release(int port) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -static int it8xxx2_tcpm_get_cc(int port, - enum tcpc_cc_voltage_status *cc1, - enum tcpc_cc_voltage_status *cc2) -{ - *cc2 = it8xxx2_get_cc(port, USBPD_CC_PIN_2); - *cc1 = it8xxx2_get_cc(port, USBPD_CC_PIN_1); - - return EC_SUCCESS; -} - -static int it8xxx2_tcpm_select_rp_value(int port, int rp_sel) -{ - uint8_t rp; - - /* - * Bit[3-1]: CC output current (effective when Rp assert in 05h Bit[1]) - * 111: reserved - * 010: 330uA outpt (3.0A) - * 100: 180uA outpt (1.5A) - * 110: 80uA outpt (USB default) - */ - switch (rp_sel) { - case TYPEC_RP_1A5: - rp = USBPD_REG_MASK_CC_SELECT_RP_1A5; - break; - case TYPEC_RP_3A0: - rp = USBPD_REG_MASK_CC_SELECT_RP_3A0; - break; - case TYPEC_RP_USB: - default: - rp = USBPD_REG_MASK_CC_SELECT_RP_DEF; - break; - } - IT83XX_USBPD_CCGCR(port) = (IT83XX_USBPD_CCGCR(port) & ~(7 << 1)) | rp; - - return EC_SUCCESS; -} - -static int it8xxx2_tcpm_set_cc(int port, int pull) -{ - return it8xxx2_set_cc(port, pull); -} - -static int it8xxx2_tcpm_set_polarity(int port, enum tcpc_cc_polarity polarity) -{ - enum usbpd_cc_pin cc_pin = - (polarity == POLARITY_CC1 || polarity == POLARITY_CC1_DTS) ? - USBPD_CC_PIN_1 : USBPD_CC_PIN_2; - - it8xxx2_select_polarity(port, cc_pin); - - return EC_SUCCESS; -} - -__maybe_unused static int it8xxx2_tcpm_decode_sop_prime_enable(int port, - bool enable) -{ - /* Save SOP'/SOP'' enable state */ - sop_prime_en[port] = enable; - - if (!rx_en[port]) - return EC_SUCCESS; - - if (enable) - IT83XX_USBPD_PDCSR1(port) |= - (USBPD_REG_MASK_SOPP_RX_ENABLE | - USBPD_REG_MASK_SOPPP_RX_ENABLE); - else - IT83XX_USBPD_PDCSR1(port) &= - ~(USBPD_REG_MASK_SOPP_RX_ENABLE | - USBPD_REG_MASK_SOPPP_RX_ENABLE); - - return EC_SUCCESS; -} - -static int it8xxx2_tcpm_set_vconn(int port, int enable) -{ - /* - * IT8xxx2 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. - */ - it8xxx2_enable_vconn(port, enable); - if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) - /* Enable tcpc receive SOP' and SOP'' packet */ - it8xxx2_tcpm_decode_sop_prime_enable(port, - true); - /* Turn on Vconn power switch. */ - board_pd_vconn_ctrl(port, - USBPD_GET_PULL_CC_SELECTION(port) ? - USBPD_CC_PIN_2 : USBPD_CC_PIN_1, - enable); - } else { - /* - * If the pd port has previous connection and supplies - * Vconn, then RO jumping to RW reset the system, - * we never know which cc is the previous Vconn pin, - * so we always turn both cc pins off when disable - * Vconn power switch. - */ - board_pd_vconn_ctrl(port, USBPD_CC_PIN_1, enable); - board_pd_vconn_ctrl(port, USBPD_CC_PIN_2, enable); - if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) - /* Disable tcpc receive SOP' and SOP'' packet */ - it8xxx2_tcpm_decode_sop_prime_enable(port, - false); - /* - * Before disabling cc 5v tolerant, we need to make - * sure cc voltage detector is enabled and Vconn is - * dropped below 3.3v (>500us) to avoid the potential - * risk of voltage fed back into Vcore. - */ - usleep(IT83XX_USBPD_T_VCONN_BELOW_3_3V); - /* - * Since our cc are not Vconn SRC, enable cc analog - * module (ex.UP/RD/DET/Tx/Rx) and disable 5v tolerant. - */ - it8xxx2_enable_vconn(port, enable); - } - } - - return EC_SUCCESS; -} - -static int it8xxx2_tcpm_set_msg_header(int port, int power_role, int data_role) -{ - /* 0: PD_ROLE_SINK, 1: PD_ROLE_SOURCE */ - if (power_role == PD_ROLE_SOURCE) - /* Bit0: source */ - IT83XX_USBPD_MHSR1(port) |= USBPD_REG_MASK_SOP_PORT_POWER_ROLE; - else - /* Bit0: sink */ - IT83XX_USBPD_MHSR1(port) &= ~USBPD_REG_MASK_SOP_PORT_POWER_ROLE; - - it8xxx2_set_data_role(port, data_role); - - return EC_SUCCESS; -} - -static int it8xxx2_tcpm_set_rx_enable(int port, int enable) -{ - /* Save rx_on */ - rx_en[port] = !!enable; - - if (enable) { - IT83XX_USBPD_IMR(port) &= ~USBPD_REG_MASK_MSG_RX_DONE; - IT83XX_USBPD_PDCSR1(port) |= - (USBPD_REG_MASK_SOP_RX_ENABLE | - USBPD_REG_MASK_HARD_RESET_RX_ENABLE); - if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) - it8xxx2_tcpm_decode_sop_prime_enable(port, - sop_prime_en[port]); - } else { - IT83XX_USBPD_IMR(port) |= USBPD_REG_MASK_MSG_RX_DONE; - IT83XX_USBPD_PDCSR1(port) &= ~(USBPD_REG_MASK_SOP_RX_ENABLE | - USBPD_REG_MASK_SOPP_RX_ENABLE | - USBPD_REG_MASK_SOPPP_RX_ENABLE | - USBPD_REG_MASK_HARD_RESET_RX_ENABLE); - } - - return EC_SUCCESS; -} - -static int it8xxx2_tcpm_transmit(int port, - enum tcpci_msg_type type, - uint16_t header, - const uint32_t *data) -{ - int status = TCPC_TX_COMPLETE_FAILED; - - switch (type) { - case TCPCI_MSG_SOP: - case TCPCI_MSG_SOP_PRIME: - case TCPCI_MSG_SOP_PRIME_PRIME: - case TCPCI_MSG_SOP_DEBUG_PRIME: - case TCPCI_MSG_SOP_DEBUG_PRIME_PRIME: - status = it8xxx2_tx_data(port, - type, - header, - data); - break; - case TCPCI_MSG_TX_BIST_MODE_2: - it8xxx2_send_bist_mode2_pattern(port); - status = TCPC_TX_COMPLETE_SUCCESS; - break; - case TCPCI_MSG_TX_HARD_RESET: - status = it8xxx2_send_hw_reset(port); - break; - case TCPCI_MSG_CABLE_RESET: - status = it8xxx2_send_cable_reset(port); - break; - default: - status = TCPC_TX_COMPLETE_FAILED; - break; - } - pd_transmit_complete(port, status); - - return EC_SUCCESS; -} - -static int it8xxx2_tcpm_get_chip_info(int port, int live, - struct ec_response_pd_chip_info_v1 *chip_info) -{ - chip_info->vendor_id = USB_VID_ITE; - chip_info->product_id = ((IT83XX_GCTRL_CHIPID1 << 8) | - IT83XX_GCTRL_CHIPID2); - chip_info->device_id = IT83XX_GCTRL_CHIPVER & 0xf; - chip_info->fw_version_number = 0xEC; - - return EC_SUCCESS; -} - -#ifdef CONFIG_USB_PD_TCPC_LOW_POWER -static int it8xxx2_tcpm_enter_low_power_mode(int port) -{ - /* - * ITE embedded TCPC SLEEP_MASK_USB_PD flag is only controlled by - * it8xxx2 driver in it8xxx2_set_pd_sleep_mask(), and do low power - * mode in idle_task(). - * In deep sleep mode, ITE TCPC clock is turned off, and the - * timer every 5ms to exit the mode and wakeup PD task to run - * (ex. change the CC lines termination). - */ - return EC_SUCCESS; -} -#endif - -#ifdef CONFIG_USB_PD_FRS_TCPC -static int it8xxx2_tcpm_set_frs_enable(int port, int enable) -{ - uint8_t mask = (USBPD_REG_FAST_SWAP_REQUEST_ENABLE | - USBPD_REG_FAST_SWAP_DETECT_ENABLE); - - if (enable) { - /* - * Disable HW auto turn off FRS requestion and detection - * when we receive soft or hard reset. - */ - IT83XX_USBPD_PDMSR(port) &= ~USBPD_REG_MASK_AUTO_FRS_DISABLE; - /* W/C status */ - IT83XX_USBPD_IFS(port) = 0x33; - /* Enable FRS detection (cc to GND) interrupt */ - IT83XX_USBPD_MIFS(port) &= ~(USBPD_REG_MASK_FAST_SWAP_ISR | - USBPD_REG_MASK_FAST_SWAP_DETECT_ISR); - /* Enable FRS detection (cc to GND) */ - IT83XX_USBPD_PDFSCR(port) = (IT83XX_USBPD_PDFSCR(port) & ~mask) - | USBPD_REG_FAST_SWAP_DETECT_ENABLE; - /* - * TODO(b/160210457): Enable HW auto trigger - * GPH3(port0)/GPH4(port1) output H/L after we detect FRS cc - * low signal. - */ - } else { - /* Disable FRS detection (cc to GND) interrupt */ - IT83XX_USBPD_MIFS(port) |= (USBPD_REG_MASK_FAST_SWAP_ISR | - USBPD_REG_MASK_FAST_SWAP_DETECT_ISR); - /* Disable FRS detection and requestion */ - IT83XX_USBPD_PDFSCR(port) &= ~mask; - /* - * TODO(b/160210457): Disable HW auto trigger - * GPH3(port0)/GPH4(port1) output H/L after we detect FRS cc - * low signal. - */ - } - - return EC_SUCCESS; -} -#endif - -static void it8xxx2_tcpm_switch_plug_out_type(int port) -{ - enum tcpc_cc_voltage_status cc1, cc2; - - /* Check what do we and partner cc assert */ - it8xxx2_tcpm_get_cc(port, &cc1, &cc2); - - if ((cc1 == TYPEC_CC_VOLT_RD && cc2 == TYPEC_CC_VOLT_RD) || - (cc1 == TYPEC_CC_VOLT_RA && cc2 == TYPEC_CC_VOLT_RA)) - /* We're source, switch to detect audio/debug plug out. */ - IT83XX_USBPD_TCDCR(port) = (IT83XX_USBPD_TCDCR(port) & - ~USBPD_REG_PLUG_IN_OUT_DETECT_DISABLE) | - USBPD_REG_PLUG_OUT_DETECT_TYPE_SELECT | - USBPD_REG_PLUG_OUT_SELECT; - else if (cc1 == TYPEC_CC_VOLT_RD || cc2 == TYPEC_CC_VOLT_RD) - /* We're source, switch to detect sink plug out. */ - IT83XX_USBPD_TCDCR(port) = (IT83XX_USBPD_TCDCR(port) & - ~USBPD_REG_PLUG_IN_OUT_DETECT_DISABLE & - ~USBPD_REG_PLUG_OUT_DETECT_TYPE_SELECT) | - USBPD_REG_PLUG_OUT_SELECT; - else if (cc1 >= TYPEC_CC_VOLT_RP_DEF || cc2 >= TYPEC_CC_VOLT_RP_DEF) - /* - * We're sink, disable detect interrupt, so messages on cc line - * won't trigger interrupt. - * NOTE: Plug out is detected by TCPM polling Vbus. - */ - IT83XX_USBPD_TCDCR(port) |= - USBPD_REG_PLUG_IN_OUT_DETECT_DISABLE; - /* - * If not above cases, plug in interrupt will fire again, - * and call switch_plug_out_type() to set the right state. - */ -} - -void switch_plug_out_type(enum usbpd_port port) -{ - it8xxx2_tcpm_switch_plug_out_type(port); -} - -static void it8xxx2_init(enum usbpd_port port, int role) -{ - uint8_t cc_config = (port == USBPD_PORT_C ? - IT83XX_USBPD_CC_PIN_CONFIG2 : - IT83XX_USBPD_CC_PIN_CONFIG); - - if (IS_ENABLED(CONFIG_IT83XX_TUNE_CC_PHY)) { - /* Tune cc Tx pre-driving time */ - const struct cc_para_t *ptr = - board_get_cc_tuning_parameter(port); - - IT83XX_USBPD_CCPSR3_RISE(port) = ptr->rising_time; - IT83XX_USBPD_CCPSR4_FALL(port) = ptr->falling_time; - } - /* Reset and disable HW auto generate message header */ - IT83XX_USBPD_PDMSR(port) &= ~USBPD_REG_MASK_DISABLE_AUTO_GEN_TX_HEADER; - USBPD_SW_RESET(port); - /* According PD version set HW auto retry count */ - IT83XX_USBPD_PDCSR0(port) = (IT83XX_USBPD_PDCSR0(port) & ~0xC0) | - (CONFIG_PD_RETRY_COUNT << 6); - /* Disable Rx decode */ - it8xxx2_tcpm_set_rx_enable(port, 0); - if (IS_ENABLED(CONFIG_USB_PD_TCPMV1)) { - uint8_t flags = 0; - /* - * If explicit contract is set in bbram when EC boot up, then - * TCPMv1 set soft reset as first state instead of - * unattached.SNK, so we need to enable BMC PHY for tx module. - * - * NOTE: If the platform is without battery and connects to - * adapter, then cold reset EC, our Rd is always asserted on cc, - * so adapter keeps providing 5v and data in BBRAM are still - * alive. - */ - if ((pd_get_saved_port_flags(port, &flags) == EC_SUCCESS) && - (flags & PD_BBRMFLG_EXPLICIT_CONTRACT)) - USBPD_ENABLE_BMC_PHY(port); - } - /* Disable all interrupts */ - IT83XX_USBPD_IMR(port) = 0xff; - /* W/C status */ - IT83XX_USBPD_ISR(port) = 0xff; - /* Enable cc voltage detector */ - IT83XX_USBPD_CCGCR(port) &= ~USBPD_REG_MASK_DISABLE_CC_VOL_DETECTOR; - /* Select Rp value USB-DEFAULT (Rd value default connect with 5.1k) */ - it8xxx2_tcpm_select_rp_value(port, TYPEC_RP_USB); - /* Which cc pin connect in attached state. Default to cc1 */ - it8xxx2_select_polarity(port, USBPD_CC_PIN_1); - /* Change data role as the same power role */ - it8xxx2_set_data_role(port, role); - /* Set default power role and assert Rp/Rd */ - it8xxx2_set_power_role(port, role); - /* Disable vconn: connect cc analog module, disable cc 5v tolerant */ - it8xxx2_tcpm_set_vconn(port, 0); - /* Enable tx done and hard reset detect interrupt */ - IT83XX_USBPD_IMR(port) &= ~(USBPD_REG_MASK_MSG_TX_DONE | - USBPD_REG_MASK_HARD_RESET_DETECT); -#ifdef IT83XX_INTC_PLUG_IN_OUT_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 enable type-c plug-in detect interrupt. - */ - IT83XX_USBPD_TCDCR(port) = (IT83XX_USBPD_TCDCR(port) & - ~(USBPD_REG_PLUG_IN_OUT_DETECT_DISABLE | - USBPD_REG_PLUG_OUT_SELECT)) | - USBPD_REG_PLUG_IN_OUT_DETECT_STAT; -#endif - /* Set cc1/cc2 pins alternate mode */ - *usbpd_ctrl_regs[port].cc1 = cc_config; - *usbpd_ctrl_regs[port].cc2 = cc_config; - task_clear_pending_irq(usbpd_ctrl_regs[port].irq); -#ifdef CONFIG_ZEPHYR - irq_connect_dynamic(usbpd_ctrl_regs[port].irq, 0, - (void (*)(const void *))chip_pd_irq, (void *)port, 0); -#endif - task_enable_irq(usbpd_ctrl_regs[port].irq); - USBPD_START(port); - /* - * Disconnect CCs Rd_DB from GND - * NOTE: CCs assert both Rd_5.1k and Rd_DB from USBPD_START() to - * disconnect Rd_DB about 1.5us. - */ - IT83XX_USBPD_CCPSR(port) |= (USBPD_REG_MASK_DISCONNECT_5_1K_CC2_DB | - USBPD_REG_MASK_DISCONNECT_5_1K_CC1_DB); -} - -static int it8xxx2_tcpm_init(int port) -{ - /* Initialize physical layer */ - it8xxx2_init(port, PD_ROLE_DEFAULT(port)); - - return EC_SUCCESS; -} - -static void it8xxx2_set_pd_sleep_mask(int port) -{ - int i; - bool prevent_deep_sleep = false; - - /* - * Set SLEEP_MASK_USB_PD for deep sleep mode: - * 1.Enable deep sleep mode, when all ITE ports are in Unattach.SRC/SNK - * state (HOOK_DISCONNECT called) and other ports aren't pd_capable(). - * 2.Disable deep sleep mode, when one of ITE port is in Attach.SRC/SNK - * state (HOOK_CONNECT called) or one of other ports is pd_capable(). - */ - for (i = 0; i < CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT; ++i) { - if (IT83XX_USBPD_PDGCR(i) & USBPD_REG_MASK_BMC_PHY) { - prevent_deep_sleep = true; - break; - } - } - - /* - * Check if any other ports have a PD port partner connected. Deep - * sleep is forbidden if any PD port partner is connected. Above, we - * only checked for the ITE ports. - */ - if (!prevent_deep_sleep) { - for (; i < board_get_usb_pd_port_count(); i++) - if (pd_capable(i)) - prevent_deep_sleep = true; - } - - if (prevent_deep_sleep) - disable_sleep(SLEEP_MASK_USB_PD); - else - enable_sleep(SLEEP_MASK_USB_PD); -} - -static void it8xxx2_tcpm_hook_connect(void) -{ - int port = TASK_ID_TO_PD_PORT(task_get_current()); - -#ifdef CONFIG_USB_PD_TCPMV2 - /* - * There are five cases that hook_connect() be called by TCPMv2: - * 1)AttachWait.SNK -> Attached.SNK: disable detect interrupt. - * 2)AttachWait.SRC -> Attached.SRC: enable detect plug out. - * 3)AttachWait.SNK -> Try.SRC -> TryWait.SNK -> Attached.SNK: we do - * Try.SRC fail, disable detect interrupt. - * 4)AttachWait.SNK -> Try.SRC -> Attached.SRC: we do Try.SRC - * successfully, need to switch to detect plug out. - * 5)Attached.SRC -> TryWait.SNK -> Attached.SNK: partner do Try.SRC - * successfully, disable detect interrupt. - * - * NOTE: Try.SRC and TryWait.SNK are embedded respectively in - * SRC_DISCONNECT and SNK_DISCONNECT in TCPMv1. Every time we go to - * Try.SRC/TryWait.SNK state, the plug in interrupt will be enabled and - * fire for 3), 4), 5) cases, then set correctly for the SRC detect plug - * out or the SNK disable detect, so TCPMv1 needn't this. - */ - it8xxx2_tcpm_switch_plug_out_type(port); -#endif - /* Enable PD PHY Tx and Rx module since type-c has connected. */ - USBPD_ENABLE_BMC_PHY(port); - it8xxx2_set_pd_sleep_mask(port); -} - -DECLARE_HOOK(HOOK_USB_PD_CONNECT, it8xxx2_tcpm_hook_connect, HOOK_PRIO_DEFAULT); - -static void it8xxx2_tcpm_hook_disconnect(void) -{ - int port = TASK_ID_TO_PD_PORT(task_get_current()); - - if (IS_ENABLED(IT83XX_INTC_PLUG_IN_OUT_SUPPORT)) - /* - * Switch to detect plug in and enable detect plug in interrupt, - * since pd task has detected a type-c physical disconnected. - */ - IT83XX_USBPD_TCDCR(port) &= ~(USBPD_REG_PLUG_OUT_SELECT | - USBPD_REG_PLUG_IN_OUT_DETECT_DISABLE); - - /* Exit BIST test data mode */ - USBPD_SW_RESET(port); - - /* - * Init rx status and disable PD PHY Tx and Rx module for better power - * consumption since type-c has disconnected. - */ - rx_en[port] = 0; - if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) - sop_prime_en[port] = 0; - USBPD_DISABLE_BMC_PHY(port); - it8xxx2_set_pd_sleep_mask(port); -} - -DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, it8xxx2_tcpm_hook_disconnect, - HOOK_PRIO_DEFAULT); - -const struct tcpm_drv it8xxx2_tcpm_drv = { - .init = &it8xxx2_tcpm_init, - .release = &it8xxx2_tcpm_release, - .get_cc = &it8xxx2_tcpm_get_cc, - .select_rp_value = &it8xxx2_tcpm_select_rp_value, - .set_cc = &it8xxx2_tcpm_set_cc, - .set_polarity = &it8xxx2_tcpm_set_polarity, -#ifdef CONFIG_USB_PD_DECODE_SOP - .sop_prime_enable = &it8xxx2_tcpm_decode_sop_prime_enable, -#endif - .set_vconn = &it8xxx2_tcpm_set_vconn, - .set_msg_header = &it8xxx2_tcpm_set_msg_header, - .set_rx_enable = &it8xxx2_tcpm_set_rx_enable, - .get_message_raw = &it8xxx2_tcpm_get_message_raw, - .transmit = &it8xxx2_tcpm_transmit, -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - .drp_toggle = NULL, -#endif - .get_chip_info = &it8xxx2_tcpm_get_chip_info, -#ifdef CONFIG_USB_PD_TCPC_LOW_POWER - .enter_low_power_mode = &it8xxx2_tcpm_enter_low_power_mode, -#endif -#ifdef CONFIG_USB_PD_FRS_TCPC - .set_frs_enable = &it8xxx2_tcpm_set_frs_enable, -#endif -}; diff --git a/driver/tcpm/ite_pd_intc.c b/driver/tcpm/ite_pd_intc.c deleted file mode 100644 index 2b5a391dfe..0000000000 --- a/driver/tcpm/ite_pd_intc.c +++ /dev/null @@ -1,87 +0,0 @@ -/* Copyright 2021 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 "it83xx_pd.h" -#include "ite_pd_intc.h" -#include "task.h" -#include "tcpm/tcpm.h" -#include "usb_pd.h" - -void chip_pd_irq(enum usbpd_port port) -{ - task_clear_pending_irq(usbpd_ctrl_regs[port].irq); - - /* check status */ - if (IS_ENABLED(IT83XX_INTC_FAST_SWAP_SUPPORT) && - IS_ENABLED(CONFIG_USB_PD_FRS_TCPC) && - IS_ENABLED(CONFIG_USB_PD_REV30)) { - /* - * FRS detection must handle first, because we need to short - * the interrupt -> board_frs_handler latency-critical time. - */ - if (USBPD_IS_FAST_SWAP_DETECT(port)) { - /* clear detect FRS signal (cc to GND) status */ - USBPD_CLEAR_FRS_DETECT_STATUS(port); - if (board_frs_handler) - board_frs_handler(port); - /* inform TCPMv2 to change state */ - pd_got_frs_signal(port); - } - } - - if (USBPD_IS_HARD_RESET_DETECT(port)) { - /* clear interrupt */ - IT83XX_USBPD_ISR(port) = USBPD_REG_MASK_HARD_RESET_DETECT; - USBPD_SW_RESET(port); - task_set_event(PD_PORT_TO_TASK_ID(port), - PD_EVENT_RX_HARD_RESET); - } - - if (USBPD_IS_RX_DONE(port)) { - tcpm_enqueue_message(port); - /* clear RX done interrupt */ - IT83XX_USBPD_ISR(port) = USBPD_REG_MASK_MSG_RX_DONE; - } - - if (USBPD_IS_TX_DONE(port)) { -#ifdef CONFIG_USB_PD_TCPM_DRIVER_IT8XXX2 - it8xxx2_clear_tx_error_status(port); - /* check TX status, clear by TX_DONE status too */ - if (USBPD_IS_TX_ERR(port)) - it8xxx2_get_tx_error_status(port); -#endif - /* clear TX done interrupt */ - IT83XX_USBPD_ISR(port) = USBPD_REG_MASK_MSG_TX_DONE; - task_set_event(PD_PORT_TO_TASK_ID(port), - TASK_EVENT_PHY_TX_DONE); - } - - if (IS_ENABLED(IT83XX_INTC_PLUG_IN_OUT_SUPPORT)) { - if (USBPD_IS_PLUG_IN_OUT_DETECT(port)) { - if (USBPD_IS_PLUG_IN(port)) - /* - * When tcpc detect type-c plug in: - * 1)If we are sink, disable detect interrupt, - * messages on cc line won't trigger interrupt. - * 2)If we are source, then set plug out - * detection. - */ - switch_plug_out_type(port); - else - /* - * When tcpc detect type-c plug out: - * switch to detect plug in. - */ - IT83XX_USBPD_TCDCR(port) &= - ~USBPD_REG_PLUG_OUT_SELECT; - - /* clear type-c device plug in/out detect interrupt */ - IT83XX_USBPD_TCDCR(port) |= - USBPD_REG_PLUG_IN_OUT_DETECT_STAT; - task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC); - } - } -} diff --git a/driver/tcpm/ite_pd_intc.h b/driver/tcpm/ite_pd_intc.h deleted file mode 100644 index 8123e1a233..0000000000 --- a/driver/tcpm/ite_pd_intc.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright 2021 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. - */ - -/* ITE PD INTC control module */ - -#ifndef __CROS_EC_ITE_PD_INTC_H -#define __CROS_EC_ITE_PD_INTC_H - -/** - * ITE embedded PD interrupt routine - * - * NOTE: Enable ITE embedded PD that it requires CONFIG_USB_PD_TCPM_ITE_ON_CHIP - * - * @param port Type-C port number - * - * @return none - */ -void chip_pd_irq(enum usbpd_port port); - -#endif /* __CROS_EC_ITE_PD_INTC_H */ diff --git a/driver/tcpm/mt6370.c b/driver/tcpm/mt6370.c deleted file mode 100644 index 100a4d9eeb..0000000000 --- a/driver/tcpm/mt6370.c +++ /dev/null @@ -1,222 +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 "tcpm/tcpci.h" -#include "tcpm/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, enum tcpc_cc_polarity 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 - .check_vbus_level = &tcpci_tcpm_check_vbus_level, -#endif - .select_rp_value = &tcpci_tcpm_select_rp_value, - .set_cc = &mt6370_set_cc, - .set_polarity = &mt6370_set_polarity, -#ifdef CONFIG_USB_PD_DECODE_SOP - .sop_prime_enable = &tcpci_tcpm_sop_prime_enable, -#endif - .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_USB_PD_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 - .set_bist_test_mode = &tcpci_set_bist_test_mode, -}; 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 00240516e5..0000000000 --- a/driver/tcpm/nct38xx.c +++ /dev/null @@ -1,377 +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 "hooks.h" -#include "nct38xx.h" -#include "task.h" -#include "tcpm/tcpci.h" -#include "usb_common.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) - -static enum nct38xx_boot_type boot_type[CONFIG_USB_PD_PORT_MAX_COUNT]; - -enum nct38xx_boot_type nct38xx_get_boot_type(int port) -{ - return boot_type[port]; -} - -void nct38xx_reset_notify(int port) -{ - /* A full reset also resets the chip's dead battery boot status */ - boot_type[port] = NCT38XX_BOOT_UNKNOWN; -} - -static int nct38xx_init(int port) -{ - int rv; - int reg; - - /* - * Detect dead battery boot by the default role control value of 0x0A - * once per EC run - */ - if (boot_type[port] == NCT38XX_BOOT_UNKNOWN) { - RETURN_ERROR(tcpc_read(port, TCPC_REG_ROLE_CTRL, ®)); - - if (reg == NCT38XX_ROLE_CTRL_DEAD_BATTERY) - boot_type[port] = NCT38XX_BOOT_DEAD_BATTERY; - else - boot_type[port] = NCT38XX_BOOT_NORMAL; - } - - RETURN_ERROR(tcpc_read(port, TCPC_REG_POWER_STATUS, ®)); - - /* - * Set TCPC_CONTROL.DebugAccessoryControl = 1 to control by TCPM, - * not TCPC in most cases. This must be left alone if we're on a - * dead battery boot with a debug accessory. CC line detection will - * be delayed if we have booted from a dead battery with a debug - * accessory and change this bit (see b/186799392). - */ - if ((boot_type[port] == NCT38XX_BOOT_DEAD_BATTERY) && - (reg & TCPC_REG_POWER_STATUS_DEBUG_ACC_CON)) - CPRINTS("C%d: Booted in dead battery mode, not changing debug" - " control", port); - else if (tcpc_config[port].flags & TCPC_FLAGS_NO_DEBUG_ACC_CONTROL) - CPRINTS("C%d: NO_DEBUG_ACC_CONTROL", port); - else - RETURN_ERROR(tcpc_update8(port, TCPC_REG_TCPC_CTRL, - TCPC_REG_TCPC_CTRL_DEBUG_ACC_CONTROL, - MASK_SET)); - - /* - * 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_update8(port, - TCPC_REG_FAULT_CTRL, - TCPC_REG_FAULT_CTRL_VBUS_OVP_FAULT_DIS, - MASK_SET); - if (rv) - return rv; - - /* Enable VBus monitor and Disable FRS */ - rv = tcpc_update8(port, - TCPC_REG_POWER_CTRL, - (TCPC_REG_POWER_CTRL_VBUS_VOL_MONITOR_DIS | - TCPC_REG_POWER_CTRL_FRS_ENABLE), - MASK_CLR); - if (rv) - return rv; - - /* Set FRS direction for SNK detect, if FRS is enabled */ - if (IS_ENABLED(CONFIG_USB_PD_FRS_TCPC)) { - 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); - if (rv) - return rv; - - /** - * Set driver specific ALERT mask bits - * - * Wake up on faults - */ - reg = TCPC_REG_ALERT_FAULT; - - /* - * Enable the Vendor Define alert event only when the IO expander - * feature is defined - */ - if (IS_ENABLED(CONFIG_IO_EXPANDER_NCT38XX)) - reg |= TCPC_REG_ALERT_VENDOR_DEF; - - rv = tcpc_update16(port, - TCPC_REG_ALERT_MASK, - reg, - MASK_SET); - - if (rv) - return rv; - - /* Enable full VCONN protection (Over-Current and Short-Circuit) */ - reg = NCT38XX_REG_VBC_FAULT_CTL_VC_OCP_EN | - NCT38XX_REG_VBC_FAULT_CTL_VC_SCP_EN | - NCT38XX_REG_VBC_FAULT_CTL_FAULT_VC_OFF; - - rv = tcpc_update8(port, - NCT38XX_REG_VBC_FAULT_CTL, - reg, - MASK_SET); - - return rv; -} - -static int nct38xx_tcpm_init(int port) -{ - int rv; - - rv = tcpci_tcpm_init(port); - if (rv) - return rv; - - return nct38xx_init(port); -} - -static int nct38xx_tcpm_set_cc(int port, int pull) -{ - /* - * Setting the CC lines to open/open requires that the NCT CTRL_OUT - * register has sink disabled. Otherwise, when no battery is connected: - * - * 1. You set CC lines to Open/Open. This is physically happening on - * the CC line. - * 2. Since CC is now Open/Open, the internal TCPC HW state machine - * is no longer in Attached.Snk and therefore our TCPC HW - * automatically opens the sink switch (de-assert the VBSNK_EN pin) - * 3. Since sink switch is open, the TCPC VCC voltage starts to drop. - * 4. When TCPC VCC gets below ~2.7V the TCPC will reset and therefore - * it will present Rd/Rd on the CC lines. Also the VBSNK_EN pin - * after reset is Hi-Z, so the sink switch will get closed again. - * - * Disabling SNKEN makes the VBSNK_EN pin Hi-Z, so - * USB_Cx_TCPC_VBSNK_EN_L will be asserted by external - * pull-down, so only do so if already sinking, otherwise - * both source and sink switches can be closed, which should - * never happen (b/166850036). - * - * SNKEN will be re-enabled in nct38xx_init above (from tcpm_init), or - * when CC lines are set again, or when sinking is disabled. - */ - int rv; - enum mask_update_action action = - pull == TYPEC_CC_OPEN && tcpm_get_snk_ctrl(port) ? - MASK_CLR : MASK_SET; - - rv = tcpc_update8(port, - NCT38XX_REG_CTRL_OUT_EN, - NCT38XX_REG_CTRL_OUT_EN_SNKEN, - action); - if (rv) - return rv; - - return tcpci_tcpm_set_cc(port, pull); -} - -#ifdef CONFIG_USB_PD_PPC -static int nct38xx_tcpm_set_snk_ctrl(int port, int enable) -{ - int rv; - - /* - * To disable sinking, SNKEN must be enabled so that - * USB_Cx_TCPC_VBSNK_EN_L will be driven high. - */ - if (!enable) { - rv = tcpc_update8(port, - NCT38XX_REG_CTRL_OUT_EN, - NCT38XX_REG_CTRL_OUT_EN_SNKEN, - MASK_SET); - if (rv) - return rv; - } - - return tcpci_tcpm_set_snk_ctrl(port, enable); -} -#endif - -static inline int tcpc_read_alert_no_lpm_exit(int port, int *val) -{ - return tcpc_addr_read16_no_lpm_exit(port, - tcpc_config[port].i2c_info.addr_flags, - TCPC_REG_ALERT, val); -} - -/* Map Type-C port to IOEX port */ -__overridable int board_map_nct38xx_tcpc_port_to_ioex(int port) -{ - return port; -} - -static void nct38xx_tcpc_alert(int port) -{ - int alert, rv; - - /* - * The nct3808 is a dual port chip with a shared ALERT - * pin. Avoid taking a port out of LPM if it is not alerting. - * - * The nct38xx exits Idle mode when ALERT is signaled, so there - * is no need to run the TCPM LPM exit code to check the ALERT - * register bits (Ref. NCT38n7/8 Datasheet S 2.3.4 "Setting the - * I2C to * Idle"). In fact, running the TCPM LPM exit code - * causes a new CC Status ALERT which has the effect of creating - * a new ALERT as a side-effect of handing an ALERT. - */ - rv = tcpc_read_alert_no_lpm_exit(port, &alert); - if (rv == EC_SUCCESS && alert == TCPC_REG_ALERT_NONE) { - /* No ALERT on this port, return early. */ - return; - } - - /* Process normal TCPC ALERT event and clear status. */ - tcpci_tcpc_alert(port); - - /* - * If the IO expander feature is enabled, use the ALERT register - * value read before it was cleared by calling - * tcpci_tcpc_alert(). Check the Vendor Defined Alert bit to - * handle the IOEX IO's interrupt event. - */ - if (IS_ENABLED(CONFIG_IO_EXPANDER_NCT38XX) && - rv == EC_SUCCESS && (alert & TCPC_REG_ALERT_VENDOR_DEF)) { - int ioexport; - - ioexport = board_map_nct38xx_tcpc_port_to_ioex(port); - nct38xx_ioex_event_handler(ioexport); - } -} - -static int nct3807_handle_fault(int port, int fault) -{ - int rv = EC_SUCCESS; - - /* Registers are set to default, initialize for our use */ - if (fault & TCPC_REG_FAULT_STATUS_ALL_REGS_RESET) { - rv = nct38xx_init(port); - } else { - /* We don't use TCPC OVP, so just disable it */ - if (fault & TCPC_REG_FAULT_STATUS_VBUS_OVER_VOLTAGE) { - /* Disable OVP */ - rv = tcpc_update8(port, - TCPC_REG_FAULT_CTRL, - TCPC_REG_FAULT_CTRL_VBUS_OVP_FAULT_DIS, - MASK_SET); - if (rv) - return rv; - } - /* Failing AutoDischargeDisconnect should disable it */ - if (fault & TCPC_REG_FAULT_STATUS_AUTO_DISCHARGE_FAIL) - tcpm_enable_auto_discharge_disconnect(port, 0); - } - return rv; -} - -__maybe_unused static int nct38xx_set_frs_enable(int port, int enable) -{ - /* - * From b/192012189: Enabling FRS for this chip should: - * - * 1. Make sure that the sink will not disconnect if Vbus will drop - * due to the Fast Role Swap by setting VBUS_SINK_DISCONNECT_THRESHOLD - * to 0 - * 2. Enable the FRS interrupt (already done in TCPCI alert init) - * 3. Set POWER_CONTORL.FastRoleSwapEnable to 1 - */ - RETURN_ERROR(tcpc_write16(port, - TCPC_REG_VBUS_SINK_DISCONNECT_THRESH, - enable ? 0x0000 : - TCPC_REG_VBUS_SINK_DISCONNECT_THRESH_DEFAULT)); - - return tcpc_update8(port, - TCPC_REG_POWER_CTRL, - TCPC_REG_POWER_CTRL_FRS_ENABLE, - enable ? MASK_SET : MASK_CLR); -} - -const struct tcpm_drv nct38xx_tcpm_drv = { - .init = &nct38xx_tcpm_init, - .release = &tcpci_tcpm_release, - .get_cc = &tcpci_tcpm_get_cc, -#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC - .check_vbus_level = &tcpci_tcpm_check_vbus_level, -#endif - .select_rp_value = &tcpci_tcpm_select_rp_value, - .set_cc = &nct38xx_tcpm_set_cc, - .set_polarity = &tcpci_tcpm_set_polarity, -#ifdef CONFIG_USB_PD_DECODE_SOP - .sop_prime_enable = &tcpci_tcpm_sop_prime_enable, -#endif - .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 = &nct38xx_tcpc_alert, -#ifdef CONFIG_USB_PD_DISCHARGE_TCPC - .tcpc_discharge_vbus = &tcpci_tcpc_discharge_vbus, -#endif - .tcpc_enable_auto_discharge_disconnect = - &tcpci_tcpc_enable_auto_discharge_disconnect, - .debug_accessory = &tcpci_tcpc_debug_accessory, - -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - .drp_toggle = &tcpci_tcpc_drp_toggle, -#endif -#ifdef CONFIG_USB_PD_PPC - .get_snk_ctrl = &tcpci_tcpm_get_snk_ctrl, - .set_snk_ctrl = &nct38xx_tcpm_set_snk_ctrl, - .get_src_ctrl = &tcpci_tcpm_get_src_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 - .set_bist_test_mode = &tcpci_set_bist_test_mode, -#ifdef CONFIG_USB_PD_FRS_TCPC - .set_frs_enable = &nct38xx_set_frs_enable, -#endif - .handle_fault = &nct3807_handle_fault, -}; diff --git a/driver/tcpm/nct38xx.h b/driver/tcpm/nct38xx.h deleted file mode 100644 index a63a9f0808..0000000000 --- a/driver/tcpm/nct38xx.h +++ /dev/null @@ -1,149 +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 - -/* - * Default value from the ROLE_CTRL register on first boot will depend on - * whether we're coming from a dead battery state. - */ -#define NCT38XX_ROLE_CTRL_DEAD_BATTERY 0x0A -#define NCT39XX_ROLE_CTRL_GOOD_BATTERY 0x4A - -#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_REG_VBC_FAULT_CTL 0xD7 -#define NCT38XX_REG_VBC_FAULT_CTL_VC_OCP_EN (1 << 0) -#define NCT38XX_REG_VBC_FAULT_CTL_VC_SCP_EN (1 << 1) -#define NCT38XX_REG_VBC_FAULT_CTL_FAULT_VC_OFF (1 << 3) -#define NCT38XX_REG_VBC_FAULT_CTL_VB_OCP_OFF (1 << 4) -#define NCT38XX_REG_VBC_FAULT_CTL_VC_OVP_OFF (1 << 5) - -#define NCT38XX_RESET_HOLD_DELAY_MS 1 - -/* - * From the datasheet (section 4.4.2 Reset Timing) as following: - * | Min | Max | - * ----------------------+-------+-------+ - * NCT3807 (single port) | x | 1.5ms | - * ----------------------+-------+-------+ - * NCT3808 (dual port) | x | 3ms | - * ----------------------+-------+-------+ - */ -#define NCT3807_RESET_POST_DELAY_MS 2 -#define NCT3808_RESET_POST_DELAY_MS 3 - -extern const struct tcpm_drv nct38xx_tcpm_drv; - -/* - * The interrupt handler to handle Vendor Define ALERT event from IOEX chip. - * - * Normally, the Vendor Define event should be checked by the NCT38XX TCPCI - * driver's tcpc_alert function. - * This function is only included when NCT38XX TCPC driver is not included. - * (i.e. CONFIG_USB_PD_TCPM_NCT38XX is not defined) - */ -void nct38xx_ioex_handle_alert(int ioex); - -/* - * Check which IO's interrupt event is triggered. If any, call its - * registered interrupt handler. - * - * @param ioex I/O expander number - * @return EC_SUCCESS on success else error - */ -int nct38xx_ioex_event_handler(int ioex); - -/* - * Board level function to map USB-C port to IOEX port - * - * Default function assumes USB-C port number to be same as the - * I/O expander port number. If this logic differs, add an - * overridable function at the board level. - * - * @param port USB-C port number - * @return IOEX port number - */ -__override_proto int board_map_nct38xx_tcpc_port_to_ioex(int port); - -enum nct38xx_boot_type { - NCT38XX_BOOT_UNKNOWN, - NCT38XX_BOOT_DEAD_BATTERY, - NCT38XX_BOOT_NORMAL, -}; - -/** - * Collect our boot type from the driver - * - * @param port USB-C port number - * @return Returns the boot type detected for this chip - */ -enum nct38xx_boot_type nct38xx_get_boot_type(int port); - -/** - * Notify the driver that the TCPC has been reset, and any stored state from - * the chip should therefore be gathered again. This should be called when - * board_reset_pd_mcu is called after init time. - * - * @param port USB-C port number which has been reset - */ -void nct38xx_reset_notify(int port); - -extern const struct ioexpander_drv nct38xx_ioexpander_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 4643c669c0..0000000000 --- a/driver/tcpm/ps8xxx.c +++ /dev/null @@ -1,1037 +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: - * - PS8705 - * - PS8751 - * - PS8755 - * - PS8805 - * - PS8815 - */ - -#include "common.h" -#include "console.h" -#include "ps8xxx.h" -#include "tcpm/tcpci.h" -#include "tcpm/tcpm.h" -#include "timer.h" -#include "usb_mux.h" -#include "usb_pd.h" - -#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) && \ - !defined(CONFIG_USB_PD_TCPM_PS8815) -#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 - -#ifdef CONFIG_USB_PD_TCPM_PS8751 -/* PS8751 cannot run with PD 3.0 (see b/148554997 for details) */ -#if defined(CONFIG_USB_PD_REV30) -#error "PS8751 cannot run with PD 3.0. Fall back to using PD 2.0" -#endif - -#endif /* CONFIG_USB_PD_TCPM_PS8751 */ - -#ifdef CONFIG_USB_PD_TCPM_PS8751_CUSTOM_MUX_DRIVER -#if !defined(CONFIG_USB_PD_TCPM_PS8751) -#error "Custom MUX driver is available only for PS8751" -#endif - -#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 PS8XXX_I2C_RECOVERY_DELAY_MS 10 - -/* - * The product_id per ports here is expected to be set in callback function - - * .init of tcpm_drv by calling board_get_ps8xxx_product_id(). - * - * In case of CONFIG_USB_PD_TCPM_MULTI_PS8XXX enabled, board code should - * override the board_get_ps8xxx_product_id() for getting the correct id. - */ -static uint16_t product_id[CONFIG_USB_PD_PORT_MAX_COUNT]; - -/* - * Revisions A1 and A0 of the PS8815 can corrupt the transmit buffer when - * updating the transmit buffer within 1ms of writing the ROLE_CONTROL - * register. When this version of silicon is detected, add a 1ms delay before - * all writes to the transmit buffer. - * - * See b/171430855 for details. - */ -static uint8_t ps8xxx_role_control_delay_ms[CONFIG_USB_PD_PORT_MAX_COUNT]; - -/* - * b/178664884, on PS8815, firmware revision 0x10 and older can report an - * incorrect value on the the CC lines. This flag controls when to apply - * the workaround. - */ -static bool ps8815_disable_rp_detect[CONFIG_USB_PD_PORT_MAX_COUNT]; -static bool ps8815_disconnected[CONFIG_USB_PD_PORT_MAX_COUNT]; -/* - * 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 ps8xxx_wake_from_standby(const struct usb_mux *me); - -#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) -/* - * 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; -} -#endif /* CONFIG_USB_PD_TCPM_PS875[15] || CONFIG_USB_PD_TCPM_PS8[78]05 */ - -#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) -{ - int p1_addr; - int p3_addr; - int regval; - int rv; - - /* Enable access to debug pages. */ - p3_addr = tcpc_config[port].i2c_info.addr_flags; - rv = tcpc_addr_read(port, p3_addr, PS8XXX_REG_I2C_DEBUGGING_ENABLE, - ®val); - if (rv) - return rv; - - rv = tcpc_addr_write(port, p3_addr, PS8XXX_REG_I2C_DEBUGGING_ENABLE, - PS8XXX_REG_I2C_DEBUGGING_ENABLE_ON); - - /* Disable Auto DCI */ - p1_addr = PS8751_P3_TO_P1_FLAGS(p3_addr); - rv = ps8xxx_addr_dci_disable(port, p1_addr, - PS8XXX_P1_REG_MUX_USB_DCI_CFG); - - /* - * PS8705/PS8755/PS8805 will automatically re-assert bit:0 on the - * PS8XXX_REG_I2C_DEBUGGING_ENABLE register. - */ - return rv; -} -#endif /* CONFIG_USB_PD_TCPM_PS8755 || CONFIG_USB_PD_TCPM_PS8[78]05 */ - -#ifdef CONFIG_USB_PD_TCPM_PS8751 -static int ps8751_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 */ - -#ifdef CONFIG_USB_PD_TCPM_PS8815 -static int ps8815_dci_disable(int port) -{ - /* DCI is disabled on the ps8815 */ - return EC_SUCCESS; -} -#endif /* CONFIG_USB_PD_TCPM_PS8815 */ - -#ifdef CONFIG_USB_PD_TCPM_PS8805 -static int ps8805_gpio_mask[] = { - PS8805_REG_GPIO_0, - PS8805_REG_GPIO_1, - PS8805_REG_GPIO_2, -}; - -int ps8805_gpio_set_level(int port, enum ps8805_gpio signal, int level) -{ - int rv; - int regval; - int mask; - - if (signal >= PS8805_GPIO_NUM) - return EC_ERROR_INVAL; - - rv = i2c_read8(tcpc_config[port].i2c_info.port, - PS8805_VENDOR_DEFINED_I2C_ADDR, - PS8805_REG_GPIO_CONTROL, ®val); - if (rv) - return rv; - - mask = ps8805_gpio_mask[signal]; - if (level) - regval |= mask; - else - regval &= ~mask; - - return i2c_write8(tcpc_config[port].i2c_info.port, - PS8805_VENDOR_DEFINED_I2C_ADDR, - PS8805_REG_GPIO_CONTROL, regval); -} - -int ps8805_gpio_get_level(int port, enum ps8805_gpio signal, int *level) -{ - int regval; - int rv; - - if (signal >= PS8805_GPIO_NUM) - return EC_ERROR_INVAL; - - rv = i2c_read8(tcpc_config[port].i2c_info.port, - PS8805_VENDOR_DEFINED_I2C_ADDR, - PS8805_REG_GPIO_CONTROL, ®val); - if (rv) - return rv; - *level = !!(regval & ps8805_gpio_mask[signal]); - - return EC_SUCCESS; -} -#endif /* CONFIG_USB_PD_TCPM_PS8805 */ - -enum ps8xxx_variant_regs { - REG_FIRST_INDEX = 0, - /* NOTE: The rev will read as 0x00 if the FW has malfunctioned. */ - REG_FW_VER = REG_FIRST_INDEX, - REG_MAX_COUNT, -}; - -struct ps8xxx_variant_map { - int product_id; - int (*dci_disable_ptr)(int port); - int reg_map[REG_MAX_COUNT]; -}; - -/* - * variant_map here is leveraged to lookup from ps8xxx_variant_regs to i2c - * register and corresponding dci_disable function based on product_id. - */ -static struct ps8xxx_variant_map variant_map[] = { -#ifdef CONFIG_USB_PD_TCPM_PS8705 - { - PS8705_PRODUCT_ID, - ps8705_dci_disable, - { - [REG_FW_VER] = 0x82, - } - }, -#endif -#ifdef CONFIG_USB_PD_TCPM_PS8751 - { - 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, - } - }, -#endif -#ifdef CONFIG_USB_PD_TCPM_PS8805 - { - 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, - } - }, -#endif -}; - -static int get_reg_by_product(const int port, - const enum ps8xxx_variant_regs reg) -{ - int i; - - if (reg < REG_FIRST_INDEX || reg >= REG_MAX_COUNT) - return INT32_MAX; - - for (i = 0; i < ARRAY_SIZE(variant_map); i++) { - if (product_id[port] == - variant_map[i].product_id) { - return variant_map[i].reg_map[reg]; - } - } - - CPRINTS("%s: failed to get register number by product_id.", __func__); - return INT32_MAX; -} - -static int dp_set_hpd(const struct usb_mux *me, int enable) -{ - int reg; - int rv; - - rv = mux_read(me, MUX_IN_HPD_ASSERTION_REG, ®); - if (rv) - return rv; - if (enable) - reg |= IN_HPD; - else - reg &= ~IN_HPD; - return mux_write(me, MUX_IN_HPD_ASSERTION_REG, reg); -} - -static int dp_set_irq(const struct usb_mux *me, int enable) -{ - int reg; - int rv; - - rv = mux_read(me, MUX_IN_HPD_ASSERTION_REG, ®); - if (rv) - return rv; - if (enable) - reg |= HPD_IRQ; - else - reg &= ~HPD_IRQ; - return mux_write(me, MUX_IN_HPD_ASSERTION_REG, reg); -} - -__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, - * SKU ID / strappings / provisioning in the factory can be the ways. - */ - - if (IS_ENABLED(CONFIG_USB_PD_TCPM_MULTI_PS8XXX)) { - CPRINTS("%s: board should override this function.", __func__); - return 0; - } else if (IS_ENABLED(CONFIG_USB_PD_TCPM_PS8705)) { - return PS8705_PRODUCT_ID; - } else if (IS_ENABLED(CONFIG_USB_PD_TCPM_PS8751)) { - return PS8751_PRODUCT_ID; - } else if (IS_ENABLED(CONFIG_USB_PD_TCPM_PS8755)) { - return PS8755_PRODUCT_ID; - } else if (IS_ENABLED(CONFIG_USB_PD_TCPM_PS8805)) { - return PS8805_PRODUCT_ID; - } else if (IS_ENABLED(CONFIG_USB_PD_TCPM_PS8815)) { - return PS8815_PRODUCT_ID; - } - - CPRINTS("%s: Any new product id is not defined here?", __func__); - return 0; -} - -bool check_ps8755_chip(int port) -{ - int val; - int p0_addr; - int status; - bool is_ps8755 = false; - - p0_addr = PS8751_P3_TO_P0_FLAGS(tcpc_config[port].i2c_info.addr_flags); - status = tcpc_addr_read(port, p0_addr, PS8755_P0_REG_SM, &val); - if (status == EC_SUCCESS && val == PS8755_P0_REG_SM_VALUE) - is_ps8755 = true; - - return is_ps8755; -} - -void ps8xxx_tcpc_update_hpd_status(const struct usb_mux *me, - mux_state_t mux_state) -{ - int port = me->usb_port; - int hpd_lvl = (mux_state & USB_PD_MUX_HPD_LVL) ? 1 : 0; - int hpd_irq = (mux_state & USB_PD_MUX_HPD_IRQ) ? 1 : 0; - - if (IS_ENABLED(CONFIG_USB_PD_TCPM_PS8751_CUSTOM_MUX_DRIVER) && - product_id[me->usb_port] == PS8751_PRODUCT_ID && - me->flags & USB_MUX_FLAG_NOT_TCPC) - ps8xxx_wake_from_standby(me); - - dp_set_hpd(me, 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(me, 0); - usleep(HPD_DSTREAM_DEBOUNCE_IRQ); - dp_set_irq(me, 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, TCPCI_MSG_TX_BIST_MODE_2); - - return rv; -} - -static int ps8xxx_tcpm_transmit(int port, enum tcpci_msg_type type, - uint16_t header, const uint32_t *data) -{ - if (type == TCPCI_MSG_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; - int reg = get_reg_by_product(port, REG_FW_VER); - - status = tcpc_read(port, reg, &version); - if (status != 0) { - /* wait for chip to wake up */ - msleep(10); - } - - return tcpci_tcpm_release(port); -} - -static void ps8xxx_role_control_delay(int port) -{ - int delay; - - delay = ps8xxx_role_control_delay_ms[port]; - if (delay) - msleep(delay); -} - -#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) -{ - int rv; - - rv = tcpci_set_role_ctrl(port, drp, rp, pull); - - /* - * b/171430855 delay 1 ms after ROLE_CONTROL updates to prevent - * transmit buffer corruption - */ - ps8xxx_role_control_delay(port); - - return rv; -} - -static int ps8xxx_tcpc_drp_toggle(int port) -{ - int rv; - int status; - int opposite_pull; - - /* - * Workaround for PS8805/PS8815, 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) { - if (ps8815_disable_rp_detect[port]) { - CPRINTS("TCPC%d: rearm Rp disable detect on connect", - port); - ps8815_disconnected[port] = true; - } - - /* Check CC_STATUS for the current pull */ - rv = tcpc_read(port, TCPC_REG_CC_STATUS, &status); - if (status & TCPC_REG_CC_STATUS_CONNECT_RESULT_MASK) { - /* Current pull: Rd */ - opposite_pull = TYPEC_CC_RP; - } else { - /* Current pull: Rp */ - opposite_pull = TYPEC_CC_RD; - } - - /* Set auto drp toggle, starting with the opposite pull */ - rv |= ps8xxx_set_role_ctrl(port, TYPEC_DRP, TYPEC_RP_USB, - opposite_pull); - - /* Set Look4Connection command */ - rv |= tcpc_write(port, TCPC_REG_COMMAND, - TCPC_REG_COMMAND_LOOK4CONNECTION); - - return rv; - } else { - return tcpci_tcpc_drp_toggle(port); - } -} -#endif - -#ifdef CONFIG_USB_PD_TCPM_PS8805_FORCE_DID -static int ps8805_make_device_id(int port, int *id) -{ - int p0_addr; - int val; - int status; - - 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; - switch (val & 0xF0) { - case 0x00: /* A2 chip */ - *id = 1; - break; - case 0xa0: /* A3 chip */ - *id = 2; - break; - default: - return EC_ERROR_UNKNOWN; - } - return EC_SUCCESS; -} -#endif - -#ifdef CONFIG_USB_PD_TCPM_PS8815_FORCE_DID -/* - * Early ps8815 A1 firmware reports 0x0001 in the TCPCI Device ID - * registers which makes it indistinguishable from A0. This - * overrides the Device ID based if vendor specific registers - * identify the chip as A1. - * - * See b/159289062. - * - * 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) -{ - 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; - - switch (val) { - case 0x0a00: - *id = 1; - break; - case 0x0a01: - *id = 2; - break; - case 0x0a02: - *id = 3; - break; - default: - return EC_ERROR_UNKNOWN; - } - 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 - * block firmware update. When the chip is asleep, the 1st I2C - * transaction will fail but the chip will begin to wake up within 10ms - * (I2C_RECOVERY_DELAY_MS). After this delay, I2C transactions succeed, - * but the firmware is still not fully operational. The way to check if - * the firmware is ready, is to poll the firmware register for a - * non-zero value. This logic applies to all ps8xxx family members - * supported by this driver. - */ - -static int ps8xxx_lpm_recovery_delay(int port) -{ - int val; - int status; - int fw_reg; - timestamp_t deadline; - - fw_reg = get_reg_by_product(port, REG_FW_VER); - - deadline = get_time(); - deadline.val += PS8815_FW_INIT_DELAY_MS * 1000; - - val = 0; - for (;;) { - if (timestamp_expired(deadline, NULL)) - return EC_ERROR_TIMEOUT; - - status = tcpc_read(port, fw_reg, &val); - if (status != EC_SUCCESS) { - /* wait for chip to wake up */ - msleep(PS8XXX_I2C_RECOVERY_DELAY_MS); - continue; - } - if (val != 0) - break; - msleep(1); - } - - return EC_SUCCESS; -} - -static int ps8xxx_get_chip_info(int port, int live, - struct ec_response_pd_chip_info_v1 *chip_info) -{ - int val; - int reg; - int rv = tcpci_get_chip_info(port, live, chip_info); - - if (rv != EC_SUCCESS) - return rv; - - if (chip_info == NULL) - return EC_SUCCESS; - - if (!live) { - uint16_t pid; - - pid = board_get_ps8xxx_product_id(port); - if (pid == 0) - return EC_ERROR_UNKNOWN; - product_id[port] = pid; - chip_info->vendor_id = PS8XXX_VENDOR_ID; - chip_info->product_id = product_id[port]; - } - -#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); - if (rv != EC_SUCCESS) - return rv; - chip_info->device_id = val; - } -#endif -#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); - 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; - - /* 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)) - return EC_ERROR_UNKNOWN; - -#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) -{ - /* - * PS8751 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. - */ - if (product_id[port] == PS8751_PRODUCT_ID) - return EC_SUCCESS; - - return tcpci_enter_low_power_mode(port); -} -#endif - -static int ps8xxx_dci_disable(int port) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(variant_map); i++) { - if (product_id[port] == variant_map[i].product_id) - return variant_map[i].dci_disable_ptr(port); - } - - CPRINTS("%s: failed to get dci_disable function pointers.", __func__); - return EC_ERROR_INVAL; -} - -__maybe_unused static int ps8815_transmit_buffer_workaround_check(int port) -{ - int p1_addr; - int val; - int status; - - if (product_id[port] != PS8815_PRODUCT_ID) - return EC_SUCCESS; - - /* 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; - - switch (val) { - case 0x0a00: - case 0x0a01: - ps8xxx_role_control_delay_ms[port] = 1; - break; - default: - break; - } - - return EC_SUCCESS; -} - -__maybe_unused static int ps8815_disable_rp_detect_workaround_check(int port) -{ - int val; - int rv; - int reg; - - ps8815_disable_rp_detect[port] = false; - ps8815_disconnected[port] = true; - - reg = get_reg_by_product(port, REG_FW_VER); - rv = tcpc_read(port, reg, &val); - if (rv != EC_SUCCESS) - return rv; - - /* - * RP detect is a problem in firmware version 0x10 and older. - */ - if (val <= 0x10) - ps8815_disable_rp_detect[port] = true; - - return EC_SUCCESS; -} - -__overridable void board_ps8xxx_tcpc_init(int port) -{} - -static int ps8xxx_tcpm_init(int port) -{ - int status; - - product_id[port] = board_get_ps8xxx_product_id(port); - - status = ps8xxx_lpm_recovery_delay(port); - if (status != EC_SUCCESS) { - CPRINTS("C%d: init: LPM recovery failed", port); - return status; - } - - if (IS_ENABLED(CONFIG_USB_PD_TCPM_PS8815)) { - status = ps8815_transmit_buffer_workaround_check(port); - if (status != EC_SUCCESS) - return status; - status = ps8815_disable_rp_detect_workaround_check(port); - if (status != EC_SUCCESS) - return status; - } - - board_ps8xxx_tcpc_init(port); - - status = tcpci_tcpm_init(port); - if (status != EC_SUCCESS) - return status; - - return ps8xxx_dci_disable(port); -} - -#ifdef CONFIG_USB_PD_TCPM_PS8751 -/* - * TODO(twawrzynczak): Remove this workaround when no - * longer needed. See: https://issuetracker.google.com/147684491 - * - * This is a workaround for what appears to be a bug in PS8751 firmware - * version 0x44. (Does the bug exist in other PS8751 firmware versions? - * Should this workaround be limited to only 0x44?) - * - * With nothing connected to the port, sometimes after DRP is disabled, - * the CC_STATUS register reads the CC state incorrectly (reading it - * as though a port partner is detected), which ends up confusing - * our TCPM. The workaround for this seems to be a short sleep and - * then re-reading the CC state. In other words, the issue shows up - * as a short glitch or transient, which an extra read and then a short - * 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) -{ - int rv; - int status; - rv = tcpc_read(port, TCPC_REG_CC_STATUS, &status); - if (rv) - return rv; - - /* Derived empirically */ - usleep(300); - - return tcpci_tcpm_get_cc(port, cc1, cc2); -} -#endif - -static int ps8xxx_tcpm_set_cc(int port, int pull) -{ - int rv; - - /* - * b/178664884: Before presenting Rp on initial connect, disable - * internal function that checks Rp value. This is a workaround - * in the PS8815 firmware that reports an incorrect value on the CC - * lines. - * - * The PS8815 self-clears these bits. - */ - if (ps8815_disable_rp_detect[port] && ps8815_disconnected[port] && - pull == TYPEC_CC_RP) { - CPRINTS("TCPC%d: disable chip based Rp detect on connection", - port); - tcpc_write(port, PS8XXX_REG_RP_DETECT_CONTROL, - RP_DETECT_DISABLE); - ps8815_disconnected[port] = false; - } - - rv = tcpci_tcpm_set_cc(port, pull); - - /* - * b/171430855 delay 1 ms after ROLE_CONTROL updates to prevent - * transmit buffer corruption - */ - ps8xxx_role_control_delay(port); - - return rv; -} - -static int ps8xxx_tcpm_get_cc(int port, enum tcpc_cc_voltage_status *cc1, - enum tcpc_cc_voltage_status *cc2) -{ -#ifdef CONFIG_USB_PD_TCPM_PS8751 - if (product_id[port] == PS8751_PRODUCT_ID) - return ps8751_get_gcc(port, cc1, cc2); -#endif - - return tcpci_tcpm_get_cc(port, cc1, cc2); -} - -const struct tcpm_drv ps8xxx_tcpm_drv = { - .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, -#endif - .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, -#endif - .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 = ps8xxx_tcpc_drp_toggle, -#endif -#ifdef CONFIG_USB_PD_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 - .set_bist_test_mode = tcpci_set_bist_test_mode, -}; - -#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 */ - -#ifdef CONFIG_USB_PD_TCPM_PS8751_CUSTOM_MUX_DRIVER - -static int ps8xxx_mux_init(const struct usb_mux *me) -{ - RETURN_ERROR(tcpci_tcpm_mux_init(me)); - - /* If this MUX is also the TCPC, then skip init */ - if (!(me->flags & USB_MUX_FLAG_NOT_TCPC)) - return EC_SUCCESS; - - product_id[me->usb_port] = board_get_ps8xxx_product_id(me->usb_port); - - return EC_SUCCESS; -} - -/* - * PS8751 goes to standby mode automatically when both CC lines are set to RP. - * In standby mode it doesn't respond to first I2C access, but next - * transactions are working fine (until it goes to sleep again). - * - * To wake device documentation recommends read content of 0xA0 register. - */ -void ps8xxx_wake_from_standby(const struct usb_mux *me) -{ - int reg; - - /* Since we are waking up device, this call will most likely fail */ - mux_read(me, PS8XXX_REG_I2C_DEBUGGING_ENABLE, ®); - msleep(10); -} - -static int ps8xxx_mux_set(const struct usb_mux *me, mux_state_t mux_state, - bool *ack_required) -{ - if (product_id[me->usb_port] == PS8751_PRODUCT_ID && - me->flags & USB_MUX_FLAG_NOT_TCPC) { - ps8xxx_wake_from_standby(me); - - /* - * To operate properly, when working as mux only, PS8751 CC - * lines needs to be RD all the time. Changing to RP after - * 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 tcpci_tcpm_mux_set(me, mux_state, ack_required); -} - -static int ps8xxx_mux_get(const struct usb_mux *me, mux_state_t *mux_state) -{ - if (product_id[me->usb_port] == PS8751_PRODUCT_ID && - me->flags & USB_MUX_FLAG_NOT_TCPC) - ps8xxx_wake_from_standby(me); - - return tcpci_tcpm_mux_get(me, mux_state); -} - -static int ps8xxx_mux_enter_low_power(const struct usb_mux *me) -{ - /* - * Set PS8751 lines to RP. This allows device to standby - * automatically after ~2 seconds - */ - if (product_id[me->usb_port] == PS8751_PRODUCT_ID && - me->flags & USB_MUX_FLAG_NOT_TCPC) { - /* - * It may happen that this write will fail, but - * RP seems to be set correctly - */ - mux_write(me, TCPC_REG_ROLE_CTRL, - TCPC_REG_ROLE_CTRL_SET(TYPEC_NO_DRP, TYPEC_RP_USB, - TYPEC_CC_RP, TYPEC_CC_RP)); - return EC_SUCCESS; - } - - return tcpci_tcpm_mux_enter_low_power(me); -} - -const struct usb_mux_driver ps8xxx_usb_mux_driver = { - .init = ps8xxx_mux_init, - .set = ps8xxx_mux_set, - .get = ps8xxx_mux_get, - .enter_low_power_mode = ps8xxx_mux_enter_low_power, -}; - -#endif /* CONFIG_USB_PD_TCPM_PS8751_CUSTOM_MUX_DRIVER */ diff --git a/driver/tcpm/ps8xxx.h b/driver/tcpm/ps8xxx.h deleted file mode 100644 index 8458dbb7e5..0000000000 --- a/driver/tcpm/ps8xxx.h +++ /dev/null @@ -1,146 +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. - */ -#include "usb_mux.h" - -#include "driver/tcpm/ps8xxx_public.h" - -/* Parade Tech Type-C port controller */ - -#ifndef __CROS_EC_USB_PD_TCPM_PS8XXX_H -#define __CROS_EC_USB_PD_TCPM_PS8XXX_H - -#define PS8751_P3_TO_P0_FLAGS(p3_flags) ((p3_flags) - 3) -#define PS8751_P3_TO_P1_FLAGS(p3_flags) ((p3_flags) - 2) - -#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_REG_RP_DETECT_CONTROL 0x9B -#define RP_DETECT_DISABLE 0x30 - -#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 - -#define MUX_IN_HPD_ASSERTION_REG 0xD0 -#define IN_HPD BIT(0) -#define HPD_IRQ BIT(1) - -#define PS8XXX_P1_REG_MUX_USB_DCI_CFG 0x4B - -#define PS8755_P0_REG_SM 0x06 -#define PS8755_P0_REG_SM_VALUE 0x80 - -#if defined(CONFIG_USB_PD_TCPM_PS8751) -/* Vendor defined registers */ -#define PS8XXX_REG_VENDOR_ID_L 0x00 -#define PS8XXX_REG_VENDOR_ID_H 0x01 -#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 -#endif - -/* Vendor defined registers */ -#define PS8815_P1_REG_HW_REVISION 0xF0 - -/* - * Below register is defined from Parade PS8815 Register Table, - * See b:189587527 for more detail. - */ - -/* Displayport related settings */ -#define PS8815_REG_DP_EQ_SETTING 0xF8 -#define PS8815_AUTO_EQ_DISABLE BIT(7) -#define PS8815_DPEQ_LOSS_UP_21DB 0x09 -#define PS8815_DPEQ_LOSS_UP_20DB 0x08 -#define PS8815_DPEQ_LOSS_UP_19DB 0x07 -#define PS8815_DPEQ_LOSS_UP_18DB 0x06 -#define PS8815_DPEQ_LOSS_UP_17DB 0x05 -#define PS8815_DPEQ_LOSS_UP_16DB 0x04 -#define PS8815_DPEQ_LOSS_UP_13DB 0x03 -#define PS8815_DPEQ_LOSS_UP_12DB 0x02 -#define PS8815_DPEQ_LOSS_UP_10DB 0x01 -#define PS8815_DPEQ_LOSS_UP_9DB 0x00 -#define PS8815_REG_DP_EQ_COMP_SHIFT 3 -#define PS8815_AUX_INTERCEPTION_DISABLE BIT(1) - -/* - * PS8805 register to distinguish chip revision - * bit 7-4: 1010b is A3 chip, 0000b is A2 chip - */ -#define PS8805_P0_REG_CHIP_REVISION 0x62 - -/* - * PS8805 GPIO control register. Note the device I2C address of 0x1A is - * independent of the ADDR pin on the chip, and not the same address being used - * for TCPCI functions. - */ -#define PS8805_VENDOR_DEFINED_I2C_ADDR 0x1A -#define PS8805_REG_GPIO_CONTROL 0x21 -#define PS8805_REG_GPIO_0 BIT(7) -#define PS8805_REG_GPIO_1 BIT(5) -#define PS8805_REG_GPIO_2 BIT(6) - -enum ps8805_gpio { - PS8805_GPIO_0, - PS8805_GPIO_1, - PS8805_GPIO_2, - PS8805_GPIO_NUM, -}; - -/** - * Set PS8805 gpio signal to desired level - * - * @param port: The Type-C port number. - * @param signal PS8805 gpio number (0, 1, or 2) - * @param level desired level - * @return EC_SUCCESS if I2C accesses are successful - */ -int ps8805_gpio_set_level(int port, enum ps8805_gpio signal, int level); - -/** - * Get PS8805 gpio signal value - * - * @param port: The Type-C port number. - * @param signal PS8805 gpio number (0, 1, or 2) - * @param pointer location to store gpio level - * @return EC_SUCCESS if I2C accesses are successful - */ -int ps8805_gpio_get_level(int port, enum ps8805_gpio signal, int *level); - -/** - * Check if the chip is PS8755 - * - * @param port: The Type-C port number. - * @return true if hidden register sm is 0x80 - */ -bool check_ps8755_chip(int port); - -/* - * Allow boards to customize for PS8XXX initial if board has - * specific settings. - * - * @param port: The Type-C port number. - */ -__override_proto void board_ps8xxx_tcpc_init(int port); - -#endif /* defined(__CROS_EC_USB_PD_TCPM_PS8XXX_H) */ diff --git a/driver/tcpm/raa489000.c b/driver/tcpm/raa489000.c deleted file mode 100644 index c4976bab4e..0000000000 --- a/driver/tcpm/raa489000.c +++ /dev/null @@ -1,325 +0,0 @@ -/* Copyright 2020 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. - * - * Renesas RAA489000 TCPC driver - */ - -#include "charge_manager.h" -#include "charger.h" -#include "common.h" -#include "console.h" -#include "driver/charger/isl923x.h" -#include "i2c.h" -#include "raa489000.h" -#include "tcpm/tcpci.h" -#include "tcpm/tcpm.h" -#include "timer.h" - -#define DEFAULT_R_AC 20 -#define R_AC CONFIG_CHARGER_SENSE_RESISTOR_AC -#define AC_CURRENT_TO_REG(CUR) ((CUR) * R_AC / DEFAULT_R_AC) - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -static int dev_id[CONFIG_USB_PD_PORT_MAX_COUNT] = { -1 }; - -static int raa489000_enter_low_power_mode(int port) -{ - int rv; - - rv = tcpc_write16(port, RAA489000_PD_PHYSICAL_SETTING1, 0); - if (rv) - CPRINTS("RAA489000(%d): Failed to set PD PHY setting1!", port); - - rv = tcpc_write16(port, RAA489000_TCPC_SETTING1, 0); - if (rv) - CPRINTS("RAA489000(%d): Failed to set TCPC setting1!", port); - - return tcpci_enter_low_power_mode(port); -} - -/* Configure output current in the TCPC because it is controlling Vbus */ -int raa489000_set_output_current(int port, enum tcpc_rp_value rp) -{ - int regval; - int selected_cur = rp == TYPEC_RP_3A0 ? - RAA489000_VBUS_CURRENT_TARGET_3A : - RAA489000_VBUS_CURRENT_TARGET_1_5A; - - regval = AC_CURRENT_TO_REG(selected_cur) + - selected_cur % (DEFAULT_R_AC/R_AC); - - return tcpc_write16(port, RAA489000_VBUS_CURRENT_TARGET, - regval); -} - -int raa489000_init(int port) -{ - int rv; - int regval; - int device_id; - int i2c_port; - struct charge_port_info chg = { 0 }; - int vbus_mv = 0; - - /* Perform unlock sequence */ - rv = tcpc_write16(port, 0xAA, 0xDAA0); - if (rv) - CPRINTS("c%d: failed unlock step1", port); - rv = tcpc_write16(port, 0xAA, 0xACE0); - if (rv) - CPRINTS("c%d: failed unlock step2", port); - rv = tcpc_write16(port, 0xAA, 0x0D0B); - if (rv) - CPRINTS("c%d: failed unlock step3", port); - - device_id = -1; - rv = tcpc_read16(port, TCPC_REG_BCD_DEV, &device_id); - if (rv) - CPRINTS("C%d: Failed to read DEV_ID", port); - CPRINTS("%s(%d): DEVICE_ID=%d", __func__, port, device_id); - dev_id[port] = device_id; - - /* Enable the ADC */ - /* - * TODO(b:147316511) Since this register can be accessed by multiple - * tasks, we should add a mutex when modifying this register. - * - * See(b:178981107,b:178728138) When the battery does not exist, - * we must enable ADC function so that charger_get_vbus_voltage - * can get the correct voltage. - */ - i2c_port = tcpc_config[port].i2c_info.port; - rv = i2c_read16(i2c_port, ISL923X_ADDR_FLAGS, - ISL9238_REG_CONTROL3, ®val); - regval |= RAA489000_ENABLE_ADC; - rv |= i2c_write16(i2c_port, ISL923X_ADDR_FLAGS, - ISL9238_REG_CONTROL3, regval); - if (rv) - CPRINTS("c%d: failed to enable ADCs", port); - - /* Enable Vbus detection */ - rv = tcpc_write(port, TCPC_REG_COMMAND, - TCPC_REG_COMMAND_ENABLE_VBUS_DETECT); - if (rv) - CPRINTS("c%d: failed to enable vbus detect cmd", port); - - - /* - * If VBUS is present, start sinking from it if we haven't already - * chosen a charge port and no battery is connected. This is - * *kinda hacky* doing it here, but we must start sinking VBUS now, - * otherwise the board may die (See b/150702984, b/178728138). This - * works as this part is a combined charger IC and TCPC. - */ - usleep(853); - charger_get_vbus_voltage(port, &vbus_mv); - - /* - * Disable the ADC - * - * See(b:178356507) 9mW is reduced on S0iX power consumption - * by clearing 'Enable ADC' bit. - */ - if (IS_ENABLED(CONFIG_OCPC) && (port != 0)) { - i2c_port = tcpc_config[port].i2c_info.port; - rv = i2c_read16(i2c_port, ISL923X_ADDR_FLAGS, - ISL9238_REG_CONTROL3, ®val); - regval &= ~RAA489000_ENABLE_ADC; - rv |= i2c_write16(i2c_port, ISL923X_ADDR_FLAGS, - ISL9238_REG_CONTROL3, regval); - if (rv) - CPRINTS("c%d: failed to disable ADCs", port); - } - - if ((vbus_mv > 3900) && - charge_manager_get_active_charge_port() == CHARGE_PORT_NONE && - !pd_is_battery_capable()) { - chg.current = 500; - chg.voltage = 5000; - charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, port, &chg); - board_set_active_charge_port(port); - } - - if (device_id > 1) { - /* - * A1 silicon has a DEVICE_ID of 1. For B0 and newer, we need - * allow the TCPC to control VBUS in order to start VBUS ADC - * sampling. This is a requirement to clear the TCPC - * initialization status but in POWER_STATUS. Otherwise, the - * common TCPCI init will fail. (See b/154191301) - */ - rv = tcpc_read16(port, RAA489000_TCPC_SETTING1, ®val); - regval |= RAA489000_TCPC_PWR_CNTRL; - rv = tcpc_write16(port, RAA489000_TCPC_SETTING1, regval); - if (rv) - CPRINTS("C%d: failed to set TCPC power control", port); - } - - /* Note: registers may not be ready until TCPCI init succeeds */ - rv = tcpci_tcpm_init(port); - if (rv) - return rv; - - /* - * Set some vendor defined registers to enable the CC comparators and - * remove the dead battery resistors. This only needs to be done on - * early silicon versions. - */ - if (device_id <= 1) { - rv = tcpc_write16(port, RAA489000_TYPEC_SETTING1, - RAA489000_SETTING1_RDOE | - RAA489000_SETTING1_CC2_CMP3_EN | - RAA489000_SETTING1_CC2_CMP2_EN | - RAA489000_SETTING1_CC2_CMP1_EN | - RAA489000_SETTING1_CC1_CMP3_EN | - RAA489000_SETTING1_CC1_CMP2_EN | - RAA489000_SETTING1_CC1_CMP1_EN | - RAA489000_SETTING1_CC_DB_EN); - if (rv) - CPRINTS("c%d: failed to enable CC comparators", port); - } - - /* Set Rx enable for receiver comparator */ - rv = tcpc_read16(port, RAA489000_PD_PHYSICAL_SETTING1, ®val); - regval |= RAA489000_PD_PHY_SETTING1_RECEIVER_EN | - RAA489000_PD_PHY_SETTING1_SQUELCH_EN | - RAA489000_PD_PHY_SETTING1_TX_LDO11_EN; - rv |= tcpc_write16(port, RAA489000_PD_PHYSICAL_SETTING1, regval); - if (rv) - CPRINTS("c%d: failed to set PD PHY setting1", port); - - /* - * Disable VBUS auto discharge, we'll turn it on later as its needed to - * goodcrc. - */ - rv = tcpc_read(port, TCPC_REG_POWER_CTRL, ®val); - regval &= ~TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT; - rv |= tcpc_write(port, TCPC_REG_POWER_CTRL, regval); - if (rv) - CPRINTS("c%d: failed to set auto discharge", port); - - if (device_id <= 1) { - /* The vendor says to set this setting. */ - rv = tcpc_write16(port, RAA489000_PD_PHYSICAL_PARAMETER1, - 0x6C07); - if (rv) - CPRINTS("c%d: failed to set PD PHY PARAM1", port); - } - - /* Enable the correct TCPCI interface version */ - rv = tcpc_read16(port, RAA489000_TCPC_SETTING1, ®val); - if (!(tcpc_config[port].flags & TCPC_FLAGS_TCPCI_REV2_0)) - regval |= RAA489000_TCPCV1_0_EN; - else - regval &= ~RAA489000_TCPCV1_0_EN; - - if (device_id <= 1) { - /* Allow the TCPC to control VBUS. */ - regval |= RAA489000_TCPC_PWR_CNTRL; - } - - rv = tcpc_write16(port, RAA489000_TCPC_SETTING1, regval); - if (rv) - CPRINTS("c%d: failed to set TCPCIv1.0 mode", port); - - /* - * Set Vbus OCP UV here, PD tasks will set target current - */ - rv = tcpc_write16(port, RAA489000_VBUS_OCP_UV_THRESHOLD, - RAA489000_OCP_THRESHOLD_VALUE); - if (rv) - CPRINTS("c%d: failed to set OCP threshold", port); - - /* Set Vbus Target Voltage */ - rv = tcpc_write16(port, RAA489000_VBUS_VOLTAGE_TARGET, - RAA489000_VBUS_VOLTAGE_TARGET_5160MV); - if (rv) - CPRINTS("c%d: failed to set Vbus Target Voltage", port); - - return rv; -} - -int raa489000_tcpm_set_cc(int port, int pull) -{ - int rv; - - rv = tcpci_tcpm_set_cc(port, pull); - if (dev_id[port] > 1 || rv) - return rv; - - /* Older silicon needs the TCPM to set RDOE to 1 after setting Rp */ - if (pull == TYPEC_CC_RP) - rv = tcpc_update16(port, RAA489000_TYPEC_SETTING1, - RAA489000_SETTING1_RDOE, MASK_SET); - - return rv; -} - -int raa489000_debug_detach(int port) -{ - int rv; - int power_status; - - /* - * Force RAA489000 to see debug detach by running: - * - * 1. Set POWER_CONTROL. AutoDischargeDisconnect=1 - * 2. Set ROLE_CONTROL=0x0F(OPEN,OPEN) - * 3. Set POWER_CONTROL. AutoDischargeDisconnect=0 - * - * Only if we have sufficient battery or are not sinking. Otherwise, - * we would risk brown-out during the CC open set. - */ - RETURN_ERROR(tcpc_read(port, TCPC_REG_POWER_STATUS, &power_status)); - - if (!pd_is_battery_capable() && - (power_status & TCPC_REG_POWER_STATUS_SINKING_VBUS)) - return EC_SUCCESS; - - tcpci_tcpc_enable_auto_discharge_disconnect(port, 1); - - rv = tcpci_tcpm_set_cc(port, TYPEC_CC_OPEN); - - tcpci_tcpc_enable_auto_discharge_disconnect(port, 0); - - return rv; -} - -/* RAA489000 is a TCPCI compatible port controller */ -const struct tcpm_drv raa489000_tcpm_drv = { - .init = &raa489000_init, - .release = &tcpci_tcpm_release, - .get_cc = &tcpci_tcpm_get_cc, -#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC - .check_vbus_level = &tcpci_tcpm_check_vbus_level, -#endif - .select_rp_value = &tcpci_tcpm_select_rp_value, - .set_cc = &raa489000_tcpm_set_cc, - .set_polarity = &tcpci_tcpm_set_polarity, -#ifdef CONFIG_USB_PD_DECODE_SOP - .sop_prime_enable = &tcpci_tcpm_sop_prime_enable, -#endif - .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_USB_PD_TCPC_LOW_POWER - .enter_low_power_mode = &raa489000_enter_low_power_mode, -#endif - .set_bist_test_mode = &tcpci_set_bist_test_mode, - .tcpc_enable_auto_discharge_disconnect = - &tcpci_tcpc_enable_auto_discharge_disconnect, - .debug_detach = &raa489000_debug_detach, -}; diff --git a/driver/tcpm/raa489000.h b/driver/tcpm/raa489000.h deleted file mode 100644 index 2a4c7c6b3d..0000000000 --- a/driver/tcpm/raa489000.h +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright 2020 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. - * - * TCPC driver for Renesas RAA489000 Buck-boost charger with TCPC - */ - -#include "compile_time_macros.h" -#include "usb_pd_tcpm.h" - -#ifndef __CROS_EC_USB_PD_TCPM_RAA489000_H -#define __CROS_EC_USB_PD_TCPM_RAA489000_H - -#define RAA489000_TCPC0_I2C_FLAGS 0x22 -#define RAA489000_TCPC1_I2C_FLAGS 0x23 -#define RAA489000_TCPC2_I2C_FLAGS 0x24 -#define RAA489000_TCPC3_I2C_FLAGS 0x25 - -/* Vendor registers */ -#define RAA489000_TCPC_SETTING1 0x80 -#define RAA489000_VBUS_VOLTAGE_TARGET 0x90 -#define RAA489000_VBUS_CURRENT_TARGET 0x92 -#define RAA489000_VBUS_OCP_UV_THRESHOLD 0x94 -#define RAA489000_TYPEC_SETTING1 0xC0 -#define RAA489000_PD_PHYSICAL_SETTING1 0xE0 -#define RAA489000_PD_PHYSICAL_PARAMETER1 0xE8 - -/* TCPC_SETTING_1 */ -#define RAA489000_TCPCV1_0_EN BIT(0) -#define RAA489000_TCPC_PWR_CNTRL BIT(4) - -/* VBUS_CURRENT_TARGET */ -#define RAA489000_VBUS_CURRENT_TARGET_3A 0x66 /* 3.0A + iOvershoot */ -#define RAA489000_VBUS_CURRENT_TARGET_1_5A 0x38 /* 1.5A + iOvershoot */ - -/* VBUS_VOLTAGE_TARGET */ -#define RAA489000_VBUS_VOLTAGE_TARGET_5160MV 0x102 /* 5.16V */ -#define RAA489000_VBUS_VOLTAGE_TARGET_5220MV 0x105 /* 5.22V */ - -/* VBUS_OCP_UV_THRESHOLD */ -/* Detect voltage level of overcurrent protection during Sourcing VBUS */ -#define RAA489000_OCP_THRESHOLD_VALUE 0x00BE /* 4.75V */ - -/* TYPEC_SETTING1 - only older silicon */ -/* Enables for reverse current protection */ -#define RAA489000_SETTING1_IP2_EN BIT(9) -#define RAA489000_SETTING1_IP1_EN BIT(8) - -/* Switches from dead-battery Rd */ -#define RAA489000_SETTING1_RDOE BIT(7) - -/* CC comparator enables */ -#define RAA489000_SETTING1_CC2_CMP3_EN BIT(6) -#define RAA489000_SETTING1_CC2_CMP2_EN BIT(5) -#define RAA489000_SETTING1_CC2_CMP1_EN BIT(4) -#define RAA489000_SETTING1_CC1_CMP3_EN BIT(3) -#define RAA489000_SETTING1_CC1_CMP2_EN BIT(2) -#define RAA489000_SETTING1_CC1_CMP1_EN BIT(1) - -/* CC debounce enable */ -#define RAA489000_SETTING1_CC_DB_EN BIT(0) - -/* PD_PHYSICAL_SETTING_1 */ -#define RAA489000_PD_PHY_SETTING1_RECEIVER_EN BIT(9) -#define RAA489000_PD_PHY_SETTING1_SQUELCH_EN BIT(8) -#define RAA489000_PD_PHY_SETTING1_TX_LDO11_EN BIT(0) - -/* PD_PHYSICAL_PARMETER_1 */ -#define PD_PHY_PARAM1_NOISE_FILTER_CNT_MASK (GENMASK(4, 0)) - -/** - * - * Set output current limit on the TCPC. Note, this chip also offers an OTG - * current level register in the charger i2c page but we must use the TCPC - * current limit because the TCPC is controlling Vbus. - * - * @param port USB-C port number - * @param rp Rp value for current limit (either 1.5A or 3A) - * - * @return Zero if the current limit set was successful, non-zero otherwise - */ -int raa489000_set_output_current(int port, enum tcpc_rp_value rp); - -extern const struct tcpm_drv raa489000_tcpm_drv; - -#endif diff --git a/driver/tcpm/rt1715.c b/driver/tcpm/rt1715.c deleted file mode 100644 index ed3d283bc9..0000000000 --- a/driver/tcpm/rt1715.c +++ /dev/null @@ -1,263 +0,0 @@ -/* Copyright 2021 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. - */ -/* Richtek RT1715 Type-C port controller */ - -#include "common.h" -#include "rt1715.h" -#include "tcpm/tcpci.h" -#include "tcpm/tcpm.h" -#include "timer.h" -#include "usb_pd.h" -#include "usb_pd_tcpm.h" - -#ifndef CONFIG_USB_PD_TCPM_TCPCI -#error "RT1715 is using a standard TCPCI interface" -#error "Please upgrade your board configuration" -#endif - -static int rt1715_polarity[CONFIG_USB_PD_PORT_MAX_COUNT]; -static bool rt1715_initialized[CONFIG_USB_PD_PORT_MAX_COUNT]; - - -static int rt1715_enable_ext_messages(int port, int enable) -{ - return tcpc_update8(port, RT1715_REG_VENDOR_5, - RT1715_REG_VENDOR_5_ENEXTMSG, - enable ? MASK_SET : MASK_CLR); -} - -static int rt1715_tcpci_tcpm_init(int port) -{ - int rv; - /* - * Do not fully reinitialize the registers when leaving low-power mode. - * TODO(b/179234089): Generalize this concept in the tcpm_drv API. - */ - - /* Only do soft-reset on first init. */ - if (!(rt1715_initialized[port])) { - /* RT1715 has a vendor-defined register reset */ - rv = tcpc_update8(port, RT1715_REG_VENDOR_7, - RT1715_REG_VENDOR_7_SOFT_RESET, MASK_SET); - if (rv) - return rv; - rt1715_initialized[port] = true; - msleep(10); - } - - rv = tcpc_update8(port, RT1715_REG_VENDOR_5, - RT1715_REG_VENDOR_5_SHUTDOWN_OFF, MASK_SET); - if (rv) - return rv; - - if (IS_ENABLED(CONFIG_USB_PD_REV30)) - rt1715_enable_ext_messages(port, 1); - - rv = tcpc_write(port, RT1715_REG_I2CRST_CTRL, - (RT1715_REG_I2CRST_CTRL_EN | - RT1715_REG_I2CRST_CTRL_TOUT_200MS)); - if (rv) - return rv; - - /* Unmask interrupt for LPM wakeup */ - rv = tcpc_write(port, RT1715_REG_RT_MASK, RT1715_REG_RT_MASK_M_WAKEUP); - if (rv) - return rv; - - /* - * Set tTCPCFilter (CC debounce time) to 400 us - * (min 250 us, max 500 us). - */ - rv = tcpc_write(port, RT1715_REG_TTCPC_FILTER, - RT1715_REG_TTCPC_FILTER_400US); - if (rv) - return rv; - - rv = tcpc_write(port, RT1715_REG_DRP_TOGGLE_CYCLE, - RT1715_REG_DRP_TOGGLE_CYCLE_76MS); - if (rv) - return rv; - - /* PHY control */ - /* Set PHY control registers to Richtek recommended values */ - rv = tcpc_write(port, RT1715_REG_PHY_CTRL1, - (RT1715_REG_PHY_CTRL1_ENRETRY | - RT1715_REG_PHY_CTRL1_TRANSCNT_7 | - RT1715_REG_PHY_CTRL1_TRXFILTER_125NS)); - if (rv) - return rv; - - /* Set PHY control registers to Richtek recommended values */ - rv = tcpc_write(port, RT1715_REG_PHY_CTRL2, - RT1715_REG_PHY_CTRL2_CDRTHRESH_2_58US); - if (rv) - return rv; - - return tcpci_tcpm_init(port); -} - -/* - * Selects the CC PHY noise filter voltage level according to the current - * CC voltage level. - * - * @param cc_level The CC voltage level for the port's current role - * @return EC_SUCCESS if writes succeed; failure code otherwise - */ -static inline int rt1715_init_cc_params(int port, int cc_level) -{ - int rv, en, sel; - - if (cc_level == TYPEC_CC_VOLT_RP_DEF) { - /* RXCC threshold : 0.55V */ - en = RT1715_REG_BMCIO_RXDZEN_DISABLE; - - sel = RT1715_REG_BMCIO_RXDZSEL_OCCTRL_600MA - | RT1715_REG_BMCIO_RXDZSEL_SEL; - } else { - /* RD threshold : 0.35V & RP threshold : 0.75V */ - en = RT1715_REG_BMCIO_RXDZEN_ENABLE; - - sel = RT1715_REG_BMCIO_RXDZSEL_OCCTRL_600MA - | RT1715_REG_BMCIO_RXDZSEL_SEL; - } - - rv = tcpc_write(port, RT1715_REG_BMCIO_RXDZEN, en); - if (!rv) - rv = tcpc_write(port, RT1715_REG_BMCIO_RXDZSEL, sel); - - return rv; -} - -static int rt1715_get_cc(int port, enum tcpc_cc_voltage_status *cc1, - enum tcpc_cc_voltage_status *cc2) -{ - int rv; - - rv = tcpci_tcpm_get_cc(port, cc1, cc2); - if (rv) - return rv; - - return rt1715_init_cc_params(port, rt1715_polarity[port] ? *cc2 : *cc1); -} - -/* - * See b/179256608#comment26 for explanation. - * Disable 24MHz oscillator and enable LPM. Upon exit from LPM, the LPEN will be - * reset to 0. - * - * The exit condition for LPM is CC status change, and the wakeup interrupt will - * be set. - */ -#ifdef CONFIG_USB_PD_TCPC_LOW_POWER -static int rt1715_enter_low_power_mode(int port) -{ - int regval; - int rv; - - rv = tcpc_read(port, RT1715_REG_PWR, ®val); - if (rv) - return rv; - - regval |= RT1715_REG_PWR_BMCIO_LPEN; - regval &= ~RT1715_REG_PWR_BMCIO_OSCEN; - rv = tcpc_write(port, RT1715_REG_PWR, regval); - if (rv) - return rv; - - return tcpci_enter_low_power_mode(port); -} -#endif - -static int rt1715_set_vconn(int port, int enable) -{ - int rv; - int regval; - - /* - * Auto-idle cannot be used while sourcing Vconn. - * See b/179256608#comment26 for explanation. - */ - rv = tcpc_read(port, RT1715_REG_VENDOR_5, ®val); - if (rv) - return rv; - - if (enable) - regval &= ~RT1715_REG_VENDOR_5_AUTOIDLE_EN; - else - regval |= RT1715_REG_VENDOR_5_AUTOIDLE_EN; - - rv = tcpc_write(port, RT1715_REG_VENDOR_5, regval); - if (rv) - return rv; - - return tcpci_tcpm_set_vconn(port, enable); -} - -static int rt1715_set_polarity(int port, enum tcpc_cc_polarity polarity) -{ - int rv; - enum tcpc_cc_voltage_status cc1, cc2; - - rt1715_polarity[port] = polarity; - - rv = tcpci_tcpm_get_cc(port, &cc1, &cc2); - if (rv) - return rv; - - rv = rt1715_init_cc_params(port, polarity ? cc2 : cc1); - if (rv) - return rv; - - return tcpci_tcpm_set_polarity(port, polarity); -} - -static void rt1715_alert(int port) -{ - /* - * Make sure the wakeup interrupt is cleared. This bit is set on wakeup - * from LPM. See b/179256608#comment16 for explanation. - */ - tcpc_write(port, RT1715_REG_RT_INT, RT1715_REG_RT_INT_WAKEUP); - - tcpci_tcpc_alert(port); -} - -const struct tcpm_drv rt1715_tcpm_drv = { - .init = &rt1715_tcpci_tcpm_init, - .release = &tcpci_tcpm_release, - .get_cc = &rt1715_get_cc, -#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC - .check_vbus_level = &tcpci_tcpm_check_vbus_level, -#endif - .select_rp_value = &tcpci_tcpm_select_rp_value, - .set_cc = &tcpci_tcpm_set_cc, - .set_polarity = &rt1715_set_polarity, -#ifdef CONFIG_USB_PD_DECODE_SOP - .sop_prime_enable = &tcpci_tcpm_sop_prime_enable, -#endif - .set_vconn = &rt1715_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 = &rt1715_alert, -#ifdef CONFIG_USB_PD_DISCHARGE_TCPC - .tcpc_discharge_vbus = &tcpci_tcpc_discharge_vbus, -#endif - .tcpc_enable_auto_discharge_disconnect = - &tcpci_tcpc_enable_auto_discharge_disconnect, -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - .drp_toggle = &tcpci_tcpc_drp_toggle, -#endif -#ifdef CONFIG_USB_PD_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 = &rt1715_enter_low_power_mode, -#endif - .set_bist_test_mode = &tcpci_set_bist_test_mode, -}; diff --git a/driver/tcpm/rt1715.h b/driver/tcpm/rt1715.h deleted file mode 100644 index dcf2aa28d4..0000000000 --- a/driver/tcpm/rt1715.h +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright 2021 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. - */ -/* Richtek RT1715 Type-C port controller */ -#ifndef __CROS_EC_USB_PD_TCPM_RT1715_H -#define __CROS_EC_USB_PD_TCPM_RT1715_H - -/* I2C interface */ -#define RT1715_I2C_ADDR_FLAGS 0x4E - -#define RT1715_VENDOR_ID 0x29CF - -#define RT1715_REG_VENDOR_7 0xA0 -#define RT1715_REG_VENDOR_7_SOFT_RESET BIT(0) - -#define RT1715_REG_PHY_CTRL1 0x80 -/* Wait for tReceive before retrying transmit in response to a bad GoodCRC */ -#define RT1715_REG_PHY_CTRL1_ENRETRY BIT(7) -/* - * Bit 6:4 <TRANSCNT>: Consider CC to be idle if there are 7 or fewer BMC - * transients observed in <46.67us> - */ -#define RT1715_REG_PHY_CTRL1_TRANSCNT_7 0x70 -/* - * Bit 1:0 <TRXFilter>: RX filter to make sure the stable received PD message. - * default value is 01b - * The debounce time is (register value + 2) * 41.67ns - */ -#define RT1715_REG_PHY_CTRL1_TRXFILTER_125NS 0x01 -#define RT1715_REG_PHY_CTRL2 0x81 -/* - * Decrease the time that the PHY will wait for a second transition to detect - * a BMC-encoded 1 bit from 2.67 us to 2.25 us. - * Timeout = register value * .04167 us. - */ -#define RT1715_REG_PHY_CTRL2_CDRTHRESH_2_25US 54 -#define RT1715_REG_PHY_CTRL2_CDRTHRESH_2_5US 60 -#define RT1715_REG_PHY_CTRL2_CDRTHRESH_2_58US 62 - -#define RT1715_REG_PWR 0x90 -#define RT1715_REG_PWR_BMCIO_LPEN BIT(3) -#define RT1715_REG_PWR_VBUS_DETEN BIT(1) -#define RT1715_REG_PWR_BMCIO_OSCEN BIT(0) - -#define RT1715_REG_BMCIO_RXDZSEL 0x93 -#define RT1715_REG_BMCIO_RXDZSEL_OCCTRL_600MA BIT(7) -#define RT1715_REG_BMCIO_RXDZSEL_SEL BIT(0) - -#define RT1715_REG_RT_INT 0x98 -#define RT1715_REG_RT_INT_WAKEUP BIT(0) - -#define RT1715_REG_RT_MASK 0x99 -#define RT1715_REG_RT_MASK_M_WAKEUP BIT(0) - -#define RT1715_REG_VENDOR_5 0x9B -#define RT1715_REG_VENDOR_5_SHUTDOWN_OFF BIT(5) -#define RT1715_REG_VENDOR_5_ENEXTMSG BIT(4) -#define RT1715_REG_VENDOR_5_AUTOIDLE_EN BIT(3) - -#define RT1715_REG_I2CRST_CTRL 0x9E -/* I2C reset : (val + 1) * 12.5ms */ -#define RT1715_REG_I2CRST_CTRL_TOUT_200MS 0x0F -#define RT1715_REG_I2CRST_CTRL_TOUT_150MS 0x0B -#define RT1715_REG_I2CRST_CTRL_TOUT_100MS 0x07 -#define RT1715_REG_I2CRST_CTRL_EN BIT(7) - - -#define RT1715_REG_TTCPC_FILTER 0xA1 -#define RT1715_REG_TTCPC_FILTER_400US 0x0F - -#define RT1715_REG_DRP_TOGGLE_CYCLE 0xA2 -/* DRP Duty : (51.2 + 6.4 * val) ms */ -#define RT1715_REG_DRP_TOGGLE_CYCLE_76MS 0x04 - -#define RT1715_REG_DRP_DUTY_CTRL 0xA3 -#define RT1715_REG_DRP_DUTY_CTRL_40PERCENT 400 - -#define RT1715_REG_BMCIO_RXDZEN 0xAF -#define RT1715_REG_BMCIO_RXDZEN_ENABLE 0x01 -#define RT1715_REG_BMCIO_RXDZEN_DISABLE 0x00 - -extern const struct tcpm_drv rt1715_tcpm_drv; - -#endif /* defined(__CROS_EC_USB_PD_TCPM_RT1715_H) */ diff --git a/driver/tcpm/rt1718s.c b/driver/tcpm/rt1718s.c deleted file mode 100644 index 9d5a8895ad..0000000000 --- a/driver/tcpm/rt1718s.c +++ /dev/null @@ -1,561 +0,0 @@ -/* Copyright 2021 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. - */ - -/* - * RT1718S TCPC Driver - */ - -#include "console.h" -#include "driver/tcpm/rt1718s.h" -#include "driver/tcpm/tcpci.h" -#include "driver/tcpm/tcpm.h" -#include "stdint.h" -#include "system.h" -#include "task.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 RT1718S_SW_RESET_DELAY_MS 2 - -/* i2c_write function which won't wake TCPC from low power mode. */ -static int rt1718s_write(int port, int reg, int val, int len) -{ - if (reg > 0xFF) { - return i2c_write_offset16( - tcpc_config[port].i2c_info.port, - tcpc_config[port].i2c_info.addr_flags, - reg, val, len); - } else if (len == 1) { - return tcpc_write(port, reg, val); - } else { - return tcpc_write16(port, reg, val); - } -} - -static int rt1718s_read(int port, int reg, int *val, int len) -{ - if (reg > 0xFF) { - return i2c_read_offset16( - tcpc_config[port].i2c_info.port, - tcpc_config[port].i2c_info.addr_flags, - reg, val, len); - } else if (len == 1) { - return tcpc_read(port, reg, val); - } else { - return tcpc_read16(port, reg, val); - } -} - -int rt1718s_write8(int port, int reg, int val) -{ - return rt1718s_write(port, reg, val, 1); -} - -int rt1718s_read8(int port, int reg, int *val) -{ - return rt1718s_read(port, reg, val, 1); -} - -int rt1718s_update_bits8(int port, int reg, int mask, int val) -{ - int reg_val; - - if (mask == 0xFF) - return rt1718s_write8(port, reg, val); - - RETURN_ERROR(rt1718s_read8(port, reg, ®_val)); - - reg_val &= (~mask); - reg_val |= (mask & val); - return rt1718s_write8(port, reg, reg_val); -} - -int rt1718s_write16(int port, int reg, int val) -{ - return rt1718s_write(port, reg, val, 2); -} - -int rt1718s_read16(int port, int reg, int *val) -{ - return rt1718s_read(port, reg, val, 2); -} - - -static int rt1718s_sw_reset(int port) -{ - int rv; - - rv = rt1718s_update_bits8(port, RT1718S_SYS_CTRL3, - RT1718S_SWRESET_MASK, 0xFF); - - msleep(RT1718S_SW_RESET_DELAY_MS); - - return rv; -} - -/* enable bc 1.2 sink function */ -static int rt1718s_enable_bc12_sink(int port, bool en) -{ - return rt1718s_update_bits8(port, RT1718S_RT2_BC12_SNK_FUNC, - RT1718S_RT2_BC12_SNK_FUNC_BC12_SNK_EN, - en ? 0xFF : 0); -} - -static int rt1718s_set_bc12_sink_spec_ta(int port, bool en) -{ - return rt1718s_update_bits8(port, - RT1718S_RT2_BC12_SNK_FUNC, - RT1718S_RT2_BC12_SNK_FUNC_SPEC_TA_EN, en ? 0xFF : 0); -} - -static int rt1718s_set_bc12_sink_dcdt_sel(int port, uint8_t dcdt_sel) -{ - return rt1718s_update_bits8(port, - RT1718S_RT2_BC12_SNK_FUNC, - RT1718S_RT2_BC12_SNK_FUNC_DCDT_SEL_MASK, dcdt_sel); -} - -static int rt1718s_set_bc12_sink_vlgc_option(int port, bool en) -{ - return rt1718s_update_bits8(port, - RT1718S_RT2_BC12_SNK_FUNC, - RT1718S_RT2_BC12_SNK_FUNC_VLGC_OPT, en ? 0xFF : 0); -} - -static int rt1718s_set_bc12_sink_vport_sel(int port, uint8_t sel) -{ - return rt1718s_update_bits8(port, - RT1718S_RT2_DPDM_CTR1_DPDM_SET, - RT1718S_RT2_DPDM_CTR1_DPDM_SET_DPDM_VSRC_SEL_MASK, sel); -} - -static int rt1718s_set_bc12_sink_wait_vbus(int port, bool en) -{ - return rt1718s_update_bits8(port, - RT1718S_RT2_BC12_SNK_FUNC, - RT1718S_RT2_BC12_SNK_FUNC_BC12_WAIT_VBUS, - en ? 0xFF : 0); -} - -/* - * rt1718s BC12 function initial - */ -static int rt1718s_bc12_init(int port) -{ - /* Enable vendor defined BC12 function */ - RETURN_ERROR(rt1718s_write8(port, RT1718S_RT_MASK6, - RT1718S_RT_MASK6_M_BC12_SNK_DONE | - RT1718S_RT_MASK6_M_BC12_TA_CHG)); - - RETURN_ERROR(rt1718s_write8(port, RT1718S_RT2_SBU_CTRL_01, - RT1718S_RT2_SBU_CTRL_01_DPDM_VIEN | - RT1718S_RT2_SBU_CTRL_01_DM_SWEN | - RT1718S_RT2_SBU_CTRL_01_DP_SWEN)); - - /* Disable 2.7v mode */ - RETURN_ERROR(rt1718s_set_bc12_sink_spec_ta(port, false)); - - /* DCDT select 600ms timeout */ - RETURN_ERROR(rt1718s_set_bc12_sink_dcdt_sel(port, - RT1718S_RT2_BC12_SNK_FUNC_DCDT_SEL_600MS)); - - /* Disable vlgc option */ - RETURN_ERROR(rt1718s_set_bc12_sink_vlgc_option(port, false)); - - /* DPDM voltage selection */ - RETURN_ERROR(rt1718s_set_bc12_sink_vport_sel(port, - RT1718S_RT2_DPDM_CTR1_DPDM_SET_DPDM_VSRC_SEL_0_65V)); - - /* Disable sink wait vbus */ - RETURN_ERROR(rt1718s_set_bc12_sink_wait_vbus(port, false)); - - return EC_SUCCESS; -} - -static int rt1718s_workaround(int port) -{ - int device_id; - - RETURN_ERROR(tcpc_read16(port, RT1718S_DEVICE_ID, &device_id)); - - switch (device_id) { - case RT1718S_DEVICE_ID_ES1: - RETURN_ERROR(rt1718s_update_bits8(port, RT1718S_VCONN_CONTROL_3, - RT1718S_VCONN_CONTROL_3_VCONN_OVP_DEG, - 0xFF)); - /* fallthrough */ - case RT1718S_DEVICE_ID_ES2: - RETURN_ERROR(rt1718s_update_bits8(port, TCPC_REG_FAULT_CTRL, - TCPC_REG_FAULT_CTRL_VBUS_OCP_FAULT_DIS, - 0xFF)); - RETURN_ERROR(rt1718s_update_bits8(port, RT1718S_VCON_CTRL4, - RT1718S_VCON_CTRL4_UVP_CP_EN | - RT1718S_VCON_CTRL4_OVP_CP_EN, - 0)); - RETURN_ERROR(rt1718s_update_bits8(port, RT1718S_VCONN_CONTROL_2, - RT1718S_VCONN_CONTROL_2_OVP_EN_CC1 | - RT1718S_VCONN_CONTROL_2_OVP_EN_CC2, - 0xFF)); - break; - default: - /* do nothing */ - break; - } - - return EC_SUCCESS; -} - -static int rt1718s_init(int port) -{ - static bool need_sw_reset = true; - - if (!system_jumped_late() && need_sw_reset) { - RETURN_ERROR(rt1718s_sw_reset(port)); - need_sw_reset = false; - } - - RETURN_ERROR(rt1718s_bc12_init(port)); - - /* Set VBUS_VOL_SEL to 20V */ - RETURN_ERROR(rt1718s_update_bits8(port, RT1718S_RT2_VBUS_VOL_CTRL, - RT1718S_RT2_VBUS_VOL_CTRL_VOL_SEL, - RT1718S_VBUS_VOL_TO_REG(20))); - - /* Disable FOD function */ - RETURN_ERROR(rt1718s_update_bits8(port, 0xCF, 0x40, 0x00)); - - /* Tcpc connect invalid disabled. Exit shipping mode */ - RETURN_ERROR(rt1718s_update_bits8(port, RT1718S_SYS_CTRL1, - RT1718S_SYS_CTRL1_TCPC_CONN_INVALID, 0x00)); - RETURN_ERROR(rt1718s_update_bits8(port, RT1718S_SYS_CTRL1, - RT1718S_SYS_CTRL1_SHIPPING_OFF, 0xFF)); - - /* Clear alert and fault */ - RETURN_ERROR(rt1718s_write8(port, TCPC_REG_FAULT_STATUS, 0xFF)); - RETURN_ERROR(tcpc_write16(port, TCPC_REG_ALERT, 0xFFFF)); - - RETURN_ERROR(tcpci_tcpm_init(port)); - - RETURN_ERROR(rt1718s_workaround(port)); - /* - * Set vendor defined alert unmasked, this must be done after - * tcpci_tcpm_init. - */ - RETURN_ERROR(tcpc_update16(port, TCPC_REG_ALERT_MASK, - TCPC_REG_ALERT_MASK_VENDOR_DEF, - MASK_SET)); - - RETURN_ERROR(board_rt1718s_init(port)); - - return EC_SUCCESS; -} - -__overridable int board_rt1718s_init(int port) -{ - return EC_SUCCESS; -} - -static enum charge_supplier rt1718s_get_bc12_type(int port) -{ - int data; - - if (rt1718s_read8(port, RT1718S_RT2_BC12_STAT, &data)) - return CHARGE_SUPPLIER_OTHER; - - switch (data & RT1718S_RT2_BC12_STAT_PORT_STATUS_MASK) { - case RT1718S_RT2_BC12_STAT_PORT_STATUS_NONE: - return CHARGE_SUPPLIER_NONE; - case RT1718S_RT2_BC12_STAT_PORT_STATUS_SDP: - return CHARGE_SUPPLIER_BC12_SDP; - case RT1718S_RT2_BC12_STAT_PORT_STATUS_CDP: - return CHARGE_SUPPLIER_BC12_CDP; - case RT1718S_RT2_BC12_STAT_PORT_STATUS_DCP: - return CHARGE_SUPPLIER_BC12_DCP; - } - - return CHARGE_SUPPLIER_OTHER; -} - -static int rt1718s_get_bc12_ilim(enum charge_supplier supplier) -{ - switch (supplier) { - case CHARGE_SUPPLIER_BC12_DCP: - case CHARGE_SUPPLIER_BC12_CDP: - return USB_CHARGER_MAX_CURR_MA; - case CHARGE_SUPPLIER_BC12_SDP: - default: - return USB_CHARGER_MIN_CURR_MA; - } -} - -static void rt1718s_update_charge_manager(int port, - enum charge_supplier new_bc12_type) -{ - static enum charge_supplier current_bc12_type = CHARGE_SUPPLIER_NONE; - - if (new_bc12_type != current_bc12_type) { - if (current_bc12_type != CHARGE_SUPPLIER_NONE) - charge_manager_update_charge(current_bc12_type, port, - NULL); - - if (new_bc12_type != CHARGE_SUPPLIER_NONE) { - struct charge_port_info chg = { - .current = rt1718s_get_bc12_ilim(new_bc12_type), - .voltage = USB_CHARGER_VOLTAGE_MV, - }; - - charge_manager_update_charge(new_bc12_type, port, &chg); - } - - current_bc12_type = new_bc12_type; - } -} - -static void rt1718s_bc12_usb_charger_task(const int port) -{ - rt1718s_enable_bc12_sink(port, false); - - while (1) { - uint32_t evt = task_wait_event(-1); - - if (evt & USB_CHG_EVENT_VBUS) { - if (pd_snk_is_vbus_provided(port)) - rt1718s_enable_bc12_sink(port, true); - else - rt1718s_update_charge_manager( - port, CHARGE_SUPPLIER_NONE); - } - - /* detection done, update charge_manager and stop detection */ - if (evt & USB_CHG_EVENT_BC12) { - int type = rt1718s_get_bc12_type(port); - - rt1718s_update_charge_manager( - port, type); - rt1718s_enable_bc12_sink(port, false); - } - } -} - -void rt1718s_vendor_defined_alert(int port) -{ - int rv, value; - - if (IS_ENABLED(CONFIG_USB_PD_FRS_PPC) && - IS_ENABLED(CONFIG_USBC_PPC_RT1718S)) { - int int1; - - rv = rt1718s_read8(port, RT1718S_RT_INT1, &int1); - if (rv) - return; - rv = rt1718s_write8(port, RT1718S_RT_INT1, int1); - if (rv) - return; - - if ((int1 & RT1718S_RT_INT1_INT_RX_FRS)) { - pd_got_frs_signal(port); - - tcpc_write16(port, TCPC_REG_ALERT, - TCPC_REG_ALERT_VENDOR_DEF); - /* ignore other interrupts for faster frs handling */ - return; - } - } - - /* Process BC12 alert */ - rv = rt1718s_read8(port, RT1718S_RT_INT6, &value); - if (rv) - return; - - /* clear BC12 alert */ - rv = rt1718s_write8(port, RT1718S_RT_INT6, value); - if (rv) - return; - - /* check snk done */ - if (value & RT1718S_RT_INT6_INT_BC12_SNK_DONE) - task_set_event(USB_CHG_PORT_TO_TASK_ID(port), - USB_CHG_EVENT_BC12); - - /* clear the alerts from rt1718s_workaround() */ - rv = rt1718s_write8(port, RT1718S_RT_INT2, 0xFF); - if (rv) - return; - /* ES1 workaround: disable Vconn discharge */ - rv = rt1718s_update_bits8(port, RT1718S_SYS_CTRL2, - RT1718S_SYS_CTRL2_VCONN_DISCHARGE_EN, - 0); - if (rv) - return; - - tcpc_write16(port, TCPC_REG_ALERT, TCPC_REG_ALERT_VENDOR_DEF); -} - -static void rt1718s_alert(int port) -{ - int alert; - - tcpc_read16(port, TCPC_REG_ALERT, &alert); - if (alert & TCPC_REG_ALERT_VENDOR_DEF) - rt1718s_vendor_defined_alert(port); - - if (alert & ~TCPC_REG_ALERT_VENDOR_DEF) - tcpci_tcpc_alert(port); -} - -#ifdef CONFIG_USB_PD_TCPC_LOW_POWER -static int rt1718s_enter_low_power_mode(int port) -{ - /* enter low power mode */ - RETURN_ERROR(rt1718s_update_bits8(port, RT1718S_SYS_CTRL2, - RT1718S_SYS_CTRL2_LPWR_EN, 0xFF)); - RETURN_ERROR(rt1718s_update_bits8(port, RT1718S_SYS_CTRL2, - RT1718S_SYS_CTRL2_BMCIO_OSC_EN, 0)); - - /* disable DP/DM/SBU swtiches */ - RETURN_ERROR(rt1718s_write8(port, RT1718S_RT2_SBU_CTRL_01, 0)); - - return tcpci_enter_low_power_mode(port); -} -#endif - -int rt1718s_get_adc(int port, enum rt1718s_adc_channel channel, int *adc_val) -{ - static struct mutex adc_lock; - int rv; - const int max_wait_times = 30; - - if (in_interrupt_context()) { - CPRINTS("Err: use ADC in IRQ"); - return EC_ERROR_INVAL; - } - - mutex_lock(&adc_lock); - - /* Start ADC conversation */ - rv = rt1718s_write16(port, RT1718S_ADC_CTRL_01, BIT(channel)); - if (rv) - goto out; - - /* - * The expected conversion time is 85.3us * number of enabled channels. - * Polling for 3ms should be long enough. - */ - for (int i = 0; i < max_wait_times; i++) { - int adc_done; - - usleep(100); - rv = rt1718s_read8(port, RT1718S_RT_INT6, &adc_done); - if (rv) - goto out; - if (adc_done & RT1718S_RT_INT6_INT_ADC_DONE) - break; - if (i == max_wait_times - 1) { - CPRINTS("conversion fail channel=%d", channel); - rv = EC_ERROR_TIMEOUT; - goto out; - } - } - - /* Read ADC data */ - rv = rt1718s_read16(port, RT1718S_ADC_CHX_VOL_L(channel), adc_val); - if (rv) - goto out; - - /* - * The resolution of VBUS1 ADC is 12.5mV, - * other channels are 4mV. - */ - if (channel == RT1718S_ADC_VBUS1) - *adc_val = *adc_val * 125 / 10; - else - *adc_val *= 4; - -out: - /* Cleanup: disable adc and clear interrupt. Error ignored. */ - rt1718s_write16(port, RT1718S_ADC_CTRL_01, 0); - rt1718s_write8(port, RT1718S_RT_INT6, RT1718S_RT_INT6_INT_ADC_DONE); - - mutex_unlock(&adc_lock); - return rv; -} - -void rt1718s_gpio_set_flags(int port, enum rt1718s_gpio signal, uint32_t flags) -{ - int val = 0; - - if (!(flags & GPIO_OPEN_DRAIN)) - val |= RT1718S_GPIO_CTRL_OD_N; - if (flags & GPIO_PULL_UP) - val |= RT1718S_GPIO_CTRL_PU; - if (flags & GPIO_PULL_DOWN) - val |= RT1718S_GPIO_CTRL_PD; - if (flags & GPIO_HIGH) - val |= RT1718S_GPIO_CTRL_O; - if (flags & GPIO_OUTPUT) - val |= RT1718S_GPIO_CTRL_OE; - - rt1718s_write8(port, RT1718S_GPIO_CTRL(signal), val); -} - -void rt1718s_gpio_set_level(int port, enum rt1718s_gpio signal, int value) -{ - rt1718s_update_bits8(port, RT1718S_GPIO_CTRL(signal), - RT1718S_GPIO_CTRL_O, - value ? 0xFF : 0); -} - -int rt1718s_gpio_get_level(int port, enum rt1718s_gpio signal) -{ - int val; - - rt1718s_read8(port, RT1718S_GPIO_CTRL(signal), &val); - return !!(val & RT1718S_GPIO_CTRL_I); -} - -/* RT1718S is a TCPCI compatible port controller */ -const struct tcpm_drv rt1718s_tcpm_drv = { - .init = &rt1718s_init, - .release = &tcpci_tcpm_release, - .get_cc = &tcpci_tcpm_get_cc, -#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC - .check_vbus_level = &tcpci_tcpm_check_vbus_level, -#endif - .select_rp_value = &tcpci_tcpm_select_rp_value, - .set_cc = &tcpci_tcpm_set_cc, - .set_polarity = &tcpci_tcpm_set_polarity, -#ifdef CONFIG_USB_PD_DECODE_SOP - .sop_prime_enable = &tcpci_tcpm_sop_prime_enable, -#endif - .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 = &rt1718s_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_USB_PD_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 = &rt1718s_enter_low_power_mode, -#endif -}; - -const struct bc12_drv rt1718s_bc12_drv = { - .usb_charger_task = rt1718s_bc12_usb_charger_task, -}; diff --git a/driver/tcpm/rt1718s.h b/driver/tcpm/rt1718s.h deleted file mode 100644 index 07c3ed3f82..0000000000 --- a/driver/tcpm/rt1718s.h +++ /dev/null @@ -1,245 +0,0 @@ -/* Copyright 2021 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_PD_TCPM_RT1718S_H -#define __CROS_EC_USB_PD_TCPM_RT1718S_H - -#include "util.h" -#include "usb_charge.h" -#include "usb_pd_tcpm.h" - -/* RT1718S Private RegMap */ -#define RT1718S_I2C_ADDR_FLAGS 0x43 - -#define RT1718S_VID 0x29CF -#define RT1718S_PID 0x1718 - -#define RT1718S_DEVICE_ID 0x04 -#define RT1718S_DEVICE_ID_ES1 0x4511 -#define RT1718S_DEVICE_ID_ES2 0x4513 - -#define RT1718S_PHYCTRL1 0x80 -#define RT1718S_PHYCTRL2 0x81 -#define RT1718S_PHYCTRL3 0x82 -#define RT1718S_PHYCTRL7 0x86 -#define RT1718S_VCON_CTRL1 0x8A -#define RT1718S_VCON_CTRL3 0x8C -#define RT1718S_SYS_CTRL1 0x8F -#define RT1718S_SYS_CTRL1_TCPC_CONN_INVALID BIT(6) -#define RT1718S_SYS_CTRL1_SHIPPING_OFF BIT(5) -#define RT1718S_SYS_CTRL2 0x90 -#define RT1718S_SYS_CTRL2_BMCIO_OSC_EN BIT(0) -#define RT1718S_SYS_CTRL2_LPWR_EN BIT(3) - -#define RT1718S_VCONN_CONTROL_2 0x8B -#define RT1718S_VCONN_CONTROL_2_OVP_EN_CC1 BIT(7) -#define RT1718S_VCONN_CONTROL_2_OVP_EN_CC2 BIT(6) -#define RT1718S_VCONN_CONTROL_3 0x8C -#define RT1718S_VCONN_CONTROL_3_VCONN_OVP_DEG BIT(1) - -#define RT1718S_SYS_CTRL2 0x90 -#define RT1718S_SYS_CTRL2_VCONN_DISCHARGE_EN BIT(5) - -#define RT1718S_RT_MASK1 0x91 -#define RT1718S_RT_MASK1_M_VBUS_FRS_LOW BIT(7) -#define RT1718S_RT_MASK1_M_RX_FRS BIT(6) -#define RT1718S_RT_MASK2 0x92 -#define RT1718S_RT_MASK3 0x93 -#define RT1718S_RT_MASK4 0x94 -#define RT1718S_RT_MASK5 0x95 -#define RT1718S_RT_MASK6 0x96 -#define RT1718S_RT_MASK6_M_BC12_SNK_DONE BIT(7) -#define RT1718S_RT_MASK6_M_HVDCP_CHK_DONE BIT(6) -#define RT1718S_RT_MASK6_M_BC12_TA_CHG BIT(5) -#define RT1718S_RT_MASK7 0x97 - -#define RT1718S_RT_INT1 0x98 -#define RT1718S_RT_INT1_INT_VBUS_FRS_LOW BIT(7) -#define RT1718S_RT_INT1_INT_RX_FRS BIT(6) -#define RT1718S_RT_INT2 0x99 -#define RT1718S_RT_INT6 0x9D -#define RT1718S_RT_INT6_INT_BC12_SNK_DONE BIT(7) -#define RT1718S_RT_INT6_INT_HVDCP_CHK_DONE BIT(6) -#define RT1718S_RT_INT6_INT_BC12_TA_CHG BIT(5) -#define RT1718S_RT_INT6_INT_ADC_DONE BIT(0) - -#define RT1718S_RT_ST6 0xA4 -#define RT1718S_RT_ST6_BC12_SNK_DONE BIT(7) -#define RT1718S_RT_ST6_HVDCP_CHK_DONE BIT(6) -#define RT1718S_RT_ST6_BC12_TA_CHG BIT(5) - -#define RT1718S_PHYCTRL9 0xAC - -#define RT1718S_SYS_CTRL3 0xB0 -#define RT1718S_TCPC_CTRL1 0xB1 -#define RT1718S_TCPC_CTRL2 0xB2 -#define RT1718S_TCPC_CTRL3 0xB3 -#define RT1718S_SWRESET_MASK BIT(0) -#define RT1718S_TCPC_CTRL4 0xB4 -#define RT1718S_SYS_CTRL4 0xB8 -#define RT1718S_WATCHDOG_CTRL 0xBE -#define RT1718S_I2C_RST_CTRL 0xBF - -#define RT1718S_HILO_CTRL9 0xC8 -#define RT1718S_SHILED_CTRL1 0xCA -#define RT1718S_FRS_CTRL1 0xCB -#define RT1718S_FRS_CTRL1_FRSWAPRX_MASK 0xF0 -#define RT1718S_FRS_CTRL2 0xCC -#define RT1718S_FRS_CTRL2_RX_FRS_EN BIT(6) -#define RT1718S_FRS_CTRL2_FR_VBUS_SELECT BIT(4) -#define RT1718S_FRS_CTRL2_VBUS_FRS_EN BIT(3) -#define RT1718S_FRS_CTRL3 0xCE -#define RT1718S_FRS_CTRL3_FRS_RX_WAIT_GPIO2 BIT(3) -#define RT1718S_FRS_CTRL3_FRS_RX_WAIT_GPIO1 BIT(2) - -#define RT1718S_DIS_SRC_VBUS_CTRL 0xE0 -#define RT1718S_ENA_SRC_VBUS_CTRL 0xE1 -#define RT1718S_FAULT_OC1_VBUS_CTRL 0xE3 -#define RT1718S_GPIO1_VBUS_CTRL 0xEA -#define RT1718S_GPIO1_VBUS_CTRL_FRS_RX_VBUS BIT(6) -#define RT1718S_GPIO2_VBUS_CTRL 0xEB -#define RT1718S_GPIO2_VBUS_CTRL_FRS_RX_VBUS BIT(6) -#define RT1718S_VBUS_CTRL_EN 0xEC -#define RT1718S_VBUS_CTRL_EN_GPIO2_VBUS_PATH_EN BIT(7) -#define RT1718S_VBUS_CTRL_EN_GPIO1_VBUS_PATH_EN BIT(6) - -#define RT1718S_GPIO_CTRL(n) (0xED + (n)) -#define RT1718S_GPIO_CTRL_PU BIT(5) -#define RT1718S_GPIO_CTRL_PD BIT(4) -#define RT1718S_GPIO_CTRL_OD_N BIT(3) -#define RT1718S_GPIO_CTRL_OE BIT(2) -#define RT1718S_GPIO_CTRL_O BIT(1) -#define RT1718S_GPIO_CTRL_I BIT(0) - -#define RT1718S_UNLOCK_PW_2 0xF0 -#define RT1718S_UNLOCK_PW_1 0xF1 - -#define RT1718S_RT2_SYS_CTRL5 0xF210 - -#define RT1718S_VBUS_VOL_TO_REG(_vol) (CLAMP(_vol, 5, 20) - 5) -#define RT1718S_VBUS_PCT_TO_REG(_pct) (CLAMP(_pct, 5, 20) \ - / 5 - 1) -#define RT1718S_RT2_VBUS_VOL_CTRL 0xF213 -#define RT1718S_RT2_VBUS_VOL_CTRL_OVP_SEL (BIT(5) | BIT(4)) -#define RT1718S_RT2_VBUS_VOL_CTRL_VOL_SEL 0x0F - -#define RT1718S_VCON_CTRL4 0xF211 -#define RT1718S_VCON_CTRL4_UVP_CP_EN BIT(5) -#define RT1718S_VCON_CTRL4_OVP_CP_EN BIT(4) - -#define RT1718S_RT2_VBUS_OCRC_EN 0xF214 -#define RT1718S_RT2_VBUS_OCRC_EN_VBUS_OCP1_EN BIT(0) -#define RT1718S_RT2_VBUS_OCP_CTRL1 0xF216 -#define RT1718S_RT2_VBUS_OCP_CTRL4 0xF219 - -#define RT1718S_RT2_SBU_CTRL_01 0xF23A -#define RT1718S_RT2_SBU_CTRL_01_SBU_VIEN BIT(7) -#define RT1718S_RT2_SBU_CTRL_01_DPDM_VIEN BIT(6) -#define RT1718S_RT2_SBU_CTRL_01_SBU2_SWEN BIT(3) -#define RT1718S_RT2_SBU_CTRL_01_SBU1_SWEN BIT(2) -#define RT1718S_RT2_SBU_CTRL_01_DM_SWEN BIT(1) -#define RT1718S_RT2_SBU_CTRL_01_DP_SWEN BIT(0) - -#define RT1718S_RT2_BC12_SNK_FUNC 0xF260 -#define RT1718S_RT2_BC12_SNK_FUNC_BC12_SNK_EN BIT(7) -#define RT1718S_RT2_BC12_SNK_FUNC_SPEC_TA_EN BIT(6) -#define RT1718S_RT2_BC12_SNK_FUNC_DCDT_SEL_MASK 0x30 -#define RT1718S_RT2_BC12_SNK_FUNC_DCDT_SEL_DISABLE 0x00 -#define RT1718S_RT2_BC12_SNK_FUNC_DCDT_SEL_300MS 0x10 -#define RT1718S_RT2_BC12_SNK_FUNC_DCDT_SEL_600MS 0x20 -#define RT1718S_RT2_BC12_SNK_FUNC_DCDT_SEL_WAIT_DATA 0x30 -#define RT1718S_RT2_BC12_SNK_FUNC_VLGC_OPT BIT(3) -#define RT1718S_RT2_BC12_SNK_FUNC_VPORT_SEL BIT(2) -#define RT1718S_RT2_BC12_SNK_FUNC_BC12_WAIT_VBUS BIT(1) - -#define RT1718S_RT2_BC12_STAT 0xF261 -#define RT1718S_RT2_BC12_STAT_DCDT BIT(4) -#define RT1718S_RT2_BC12_STAT_PORT_STATUS_MASK 0x0F -#define RT1718S_RT2_BC12_STAT_PORT_STATUS_NONE 0x00 -#define RT1718S_RT2_BC12_STAT_PORT_STATUS_SDP 0x0D -#define RT1718S_RT2_BC12_STAT_PORT_STATUS_CDP 0x0E -#define RT1718S_RT2_BC12_STAT_PORT_STATUS_DCP 0x0F - - -#define RT1718S_RT2_DPDM_CTR1_DPDM_SET 0xF263 -#define RT1718S_RT2_DPDM_CTR1_DPDM_SET_DPDM_VSRC_SEL_MASK 0x03 -#define RT1718S_RT2_DPDM_CTR1_DPDM_SET_DPDM_VSRC_SEL_0_55V 0x00 -#define RT1718S_RT2_DPDM_CTR1_DPDM_SET_DPDM_VSRC_SEL_0_60V 0x01 -#define RT1718S_RT2_DPDM_CTR1_DPDM_SET_DPDM_VSRC_SEL_0_65V 0x02 -#define RT1718S_RT2_DPDM_CTR1_DPDM_SET_DPDM_VSRC_SEL_0_70V 0x03 - -#define RT1718S_RT2_BC12_SRC_FUNC 0xF26D -#define RT1718S_RT2_BC12_SRC_FUNC_BC12_SRC_EN BIT(7) -#define RT1718S_RT2_BC12_SRC_FUNC_SRC_MODE_SEL_MASK 0x70 -#define RT1718S_RT2_BC12_SRC_FUNC_SRC_MODE_SEL_BC12_SDP 0x00 -#define RT1718S_RT2_BC12_SRC_FUNC_SRC_MODE_SEL_BC12_CDP 0x10 -#define RT1718S_RT2_BC12_SRC_FUNC_SRC_MODE_SEL_BC12_DCP 0x20 -#define RT1718S_RT2_BC12_SRC_FUNC_WAIT_VBUS_ON BIT(0) - -#define RT1718S_ADC_CTRL_01 0xF2A0 -#define RT1718S_ADC_CTRL_02 0xF2A1 -#define RT1718S_ADC_CHX_VOL_L(ch) (0xF2A6 + (ch) * 2) -#define RT1718S_ADC_CHX_VOL_H(ch) (0xF2A7 + (ch) * 2) - -extern const struct tcpm_drv rt1718s_tcpm_drv; -extern const struct bc12_drv rt1718s_bc12_drv; - -int rt1718s_write8(int port, int reg, int val); -int rt1718s_read8(int port, int reg, int *val); -int rt1718s_update_bits8(int port, int reg, int mask, int val); -int rt1718s_write16(int port, int reg, int val); -int rt1718s_read16(int port, int reg, int *val); -__override_proto int board_rt1718s_init(int port); - -enum rt1718s_adc_channel { - RT1718S_ADC_VBUS1 = 0, - RT1718S_ADC_VBUS2, - RT1718S_ADC_VDC, - RT1718S_ADC_VBUS_CURRENT, - RT1718S_ADC_CC1, - RT1718S_ADC_CC2, - RT1718S_ADC_SBU1, - RT1718S_ADC_SBU2, - RT1718S_ADC_DP, - RT1718S_ADC_DM, - RT1718S_ADC_CH10, - RT1718S_ADC_CH11, -}; - -int rt1718s_get_adc(int port, enum rt1718s_adc_channel channel, int *adc_val); - -enum rt1718s_gpio { - RT1718S_GPIO1 = 0, - RT1718S_GPIO2, - RT1718S_GPIO3, -}; - -/** - * Set flags for GPIO - * - * @param port rt1718s I2C port - * @param signal gpio pin name in enum rt1718s_gpio - * @param flags GPIO_* flags defined in include/gpio.h - */ -void rt1718s_gpio_set_flags(int port, enum rt1718s_gpio signal, uint32_t flags); - -/** - * Set the value of a signal - * - * @param port rt1718s I2C port - * @param signal gpio pin name in enum rt1718s_gpio - * @param value New value for signal (0 = low, non-zero = high) - */ -void rt1718s_gpio_set_level(int port, enum rt1718s_gpio signal, int value); - -/** - * Get the current value of a signal. - * - * @param port rt1718s I2C port - * @param signal gpio pin name in enum rt1718s_gpio - * @return 0 if low, 1 if high. - */ -int rt1718s_gpio_get_level(int port, enum rt1718s_gpio signal); - -#endif /* __CROS_EC_USB_PD_TCPM_MT6370_H */ diff --git a/driver/tcpm/stm32gx.c b/driver/tcpm/stm32gx.c deleted file mode 100644 index 359c7c1108..0000000000 --- a/driver/tcpm/stm32gx.c +++ /dev/null @@ -1,186 +0,0 @@ -/* Copyright 2020 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 STM32Gx UCPD module */ - -#include "chip/stm32/ucpd-stm32gx.h" -#include "common.h" -#include "config.h" -#include "console.h" -#include "registers.h" -#include "stm32gx.h" -#include "system.h" -#include "task.h" -#include "tcpm/tcpci.h" -#include "timer.h" -#include "util.h" -#include "usb_pd.h" -#include "usb_pd_tcpm.h" -#include "hooks.h" - -/* - * STM32G4 UCPD peripheral does not have the ability to detect VBUS, but - * CONFIG_USB_PD_VBUS_DETECT_TCPC maybe still be defined for another port on the - * same board which uses a TCPC that does have this feature. Therefore, this - * config option is not considered an error. - */ -#if defined(CONFIG_USB_PD_TCPC_LOW_POWER) -#error "Unsupported config options of Stm32gx PD driver" -#endif - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -/* Wait time for vconn power switch to turn off. */ -#ifndef PD_STM32GX_VCONN_TURN_OFF_DELAY_US -#define PD_STM32GX_VCONN_TURN_OFF_DELAY_US 500 -#endif - -static int cached_rp[CONFIG_USB_PD_PORT_MAX_COUNT]; - - -static int stm32gx_tcpm_get_message_raw(int port, uint32_t *buf, int *head) -{ - return stm32gx_ucpd_get_message_raw(port, buf, head); -} - -static int stm32gx_tcpm_init(int port) -{ - return stm32gx_ucpd_init(port); -} - -static int stm32gx_tcpm_release(int port) -{ - return stm32gx_ucpd_release(port); -} - -static int stm32gx_tcpm_get_cc(int port, enum tcpc_cc_voltage_status *cc1, - enum tcpc_cc_voltage_status *cc2) -{ - /* Get cc_state value for each CC line */ - stm32gx_ucpd_get_cc(port, cc1, cc2); - - return EC_SUCCESS; -} - -static int stm32gx_tcpm_select_rp_value(int port, int rp_sel) -{ - cached_rp[port] = rp_sel; - - return EC_SUCCESS; -} - -static int stm32gx_tcpm_set_cc(int port, int pull) -{ - return stm32gx_ucpd_set_cc(port, pull, cached_rp[port]); -} - -static int stm32gx_tcpm_set_polarity(int port, enum tcpc_cc_polarity polarity) -{ - return stm32gx_ucpd_set_polarity(port, polarity); -} - -static int stm32gx_tcpm_set_vconn(int port, int enable) -{ - stm32gx_ucpd_vconn_disc_rp(port, enable); - - if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) - stm32gx_ucpd_sop_prime_enable(port, enable); - - return EC_SUCCESS; -} - -static int stm32gx_tcpm_set_msg_header(int port, int power_role, int data_role) -{ - return stm32gx_ucpd_set_msg_header(port, power_role, data_role); -} - -static int stm32gx_tcpm_set_rx_enable(int port, int enable) -{ - return stm32gx_ucpd_set_rx_enable(port, enable); -} - -static int stm32gx_tcpm_transmit(int port, - enum tcpci_msg_type type, - uint16_t header, - const uint32_t *data) -{ - return stm32gx_ucpd_transmit(port, type, header, data); -} - -static int stm32gx_tcpm_sop_prime_enable(int port, bool enable) -{ - return stm32gx_ucpd_sop_prime_enable(port, enable); -} - - -static int stm32gx_tcpm_get_chip_info(int port, int live, - struct ec_response_pd_chip_info_v1 *chip_info) -{ - return stm32gx_ucpd_get_chip_info(port, live, chip_info); -} - -static void stm32gx_tcpm_sw_reset(void) -{ - /* - * TODO(b/167601672): Not sure if this hook is required for UCPD as - * opposed to TCPCI compliant TCPC. Leaving this a placeholder so I - * don't forget to pull this back in, if required. - */ -} -DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, stm32gx_tcpm_sw_reset, HOOK_PRIO_DEFAULT); - -static int stm32gx_tcpm_reset_bist_type_2(int port) -{ - /* - * The UCPD peripheral must be disabled, then enabled, to recover from - * starting BIST type-2 mode. Call the init method to accomplish - * this. Then, need to send a hard reset to port partner. - */ - stm32gx_ucpd_init(port); - pd_execute_hard_reset(port); - task_set_event(PD_PORT_TO_TASK_ID(port), TASK_EVENT_WAKE); - - return EC_SUCCESS; -} - -enum ec_error_list stm32gx_tcpm_set_bist_test_mode(const int port, - const bool enable) -{ - return stm32gx_ucpd_set_bist_test_mode(port, enable); -} - -bool stm32gx_tcpm_check_vbus_level(int port, enum vbus_level level) -{ - /* - * UCPD peripheral can't detect VBUS, so always return 0. Any port which - * uses the stm32g4 UCPD peripheral for its TCPC would also have a PPC - * that will handle VBUS detection. However, there may be products which - * don't have a PPC on some ports that will rely on a TCPC to do VBUS - * detection. - */ - return 0; -} - -const struct tcpm_drv stm32gx_tcpm_drv = { - .init = &stm32gx_tcpm_init, - .release = &stm32gx_tcpm_release, - .get_cc = &stm32gx_tcpm_get_cc, - .check_vbus_level = &stm32gx_tcpm_check_vbus_level, - .select_rp_value = &stm32gx_tcpm_select_rp_value, - .set_cc = &stm32gx_tcpm_set_cc, - .set_polarity = &stm32gx_tcpm_set_polarity, -#ifdef CONFIG_USB_PD_DECODE_SOP - .sop_prime_enable = &stm32gx_tcpm_sop_prime_enable, -#endif - .set_vconn = &stm32gx_tcpm_set_vconn, - .set_msg_header = &stm32gx_tcpm_set_msg_header, - .set_rx_enable = &stm32gx_tcpm_set_rx_enable, - .get_message_raw = &stm32gx_tcpm_get_message_raw, - .transmit = &stm32gx_tcpm_transmit, - .get_chip_info = &stm32gx_tcpm_get_chip_info, - .reset_bist_type_2 = &stm32gx_tcpm_reset_bist_type_2, - .set_bist_test_mode = &stm32gx_tcpm_set_bist_test_mode, -}; diff --git a/driver/tcpm/stm32gx.h b/driver/tcpm/stm32gx.h deleted file mode 100644 index de6a803d52..0000000000 --- a/driver/tcpm/stm32gx.h +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright 2020 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_STM32GX_H -#define __CROS_EC_DRIVER_TCPM_STM32GX_H - - -extern const struct tcpm_drv stm32gx_tcpm_drv; - - -#endif /* __CROS_EC_DRIVER_TCPM_STM32GX_H */ diff --git a/driver/tcpm/stub.c b/driver/tcpm/stub.c deleted file mode 100644 index 863a88c044..0000000000 --- a/driver/tcpm/stub.c +++ /dev/null @@ -1,159 +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 "tcpm/tcpci.h" -#include "tcpm/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, enum tcpc_cc_polarity polarity) -{ - return tcpc_set_polarity(port, polarity_rm_dts(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); -} - -void tcpm_enable_auto_discharge_disconnect(int port, int 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 tcpci_msg_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); - } - 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 */ - task_set_event(PD_PORT_TO_TASK_ID(port), - PD_EVENT_RX_HARD_RESET); - } - 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 1e08e0967d..0000000000 --- a/driver/tcpm/tcpci.c +++ /dev/null @@ -1,1838 +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 "hooks.h" -#include "i2c.h" -#include "ps8xxx.h" -#include "task.h" -#include "tcpm/tcpci.h" -#include "tcpm/tcpm.h" -#include "timer.h" -#include "usb_charge.h" -#include "usb_common.h" -#include "usb_mux.h" -#include "usb_pd.h" -#include "usb_pd_flags.h" -#include "usb_pd_tcpc.h" -#include "usb_pd_tcpm.h" -#include "util.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -STATIC_IF(CONFIG_USB_PD_DECODE_SOP) - bool sop_prime_en[CONFIG_USB_PD_PORT_MAX_COUNT]; -STATIC_IF(CONFIG_USB_PD_DECODE_SOP) - int rx_en[CONFIG_USB_PD_PORT_MAX_COUNT]; - -#define TCPC_FLAGS_VSAFE0V(_flags) \ - ((_flags & TCPC_FLAGS_TCPCI_REV2_0) && \ - !(_flags & TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V)) - -/**************************************************************************** - * TCPCI DEBUG Helpers - */ - -/* TCPCI FAULT-0x01 is an invalid I2C operation was performed. This tends - * to have to do with the state of registers and the last write operation. - * Defining DEBUG_I2C_FAULT_LAST_WRITE_OP will track the write operations, - * excluding XFER and BlockWrites, in an attempt to give clues as to what - * was written to the TCPCI that caused the issue. - */ -#undef DEBUG_I2C_FAULT_LAST_WRITE_OP - -struct i2c_wrt_op { - int addr; - int reg; - int val; - int mask; -}; -STATIC_IF(DEBUG_I2C_FAULT_LAST_WRITE_OP) - struct i2c_wrt_op last_write_op[CONFIG_USB_PD_PORT_MAX_COUNT]; - -/* - * AutoDischargeDisconnect has caused a number of issues with the - * feature not being correctly enabled/disabled. Defining - * DEBUG_AUTO_DISCHARGE_DISCONNECT will output a line for each enable - * and disable to help better understand any AutoDischargeDisconnect - * issues. - */ -#undef DEBUG_AUTO_DISCHARGE_DISCONNECT - -/* - * ForcedDischarge debug to help coordinate with AutoDischarge. - * Defining DEBUG_FORCED_DISCHARGE will output a line for each enable - * and disable to help better understand any Discharge issues. - */ -#undef DEBUG_FORCED_DISCHARGE - -/* - * Seeing the CC Status and ROLE Control registers as well as the - * CC that is being determined from this information can be - * helpful. Defining DEBUG_GET_CC will output a line that gives - * this useful information - */ -#undef DEBUG_GET_CC - -struct get_cc_values { - int cc1; - int cc2; - int cc_sts; - int role; -}; -STATIC_IF(DEBUG_GET_CC) - struct get_cc_values last_get_cc[CONFIG_USB_PD_PORT_MAX_COUNT]; - -/* - * Seeing RoleCtrl updates can help determine why GetCC is not - * working as it should be. - */ -#undef DEBUG_ROLE_CTRL_UPDATES - -/****************************************************************************/ - -/* - * Last reported VBus Level - * - * BIT(VBUS_SAFE0V) will indicate if in SAFE0V - * BIT(VBUS_PRESENT) will indicate if in PRESENT in the TCPCI POWER_STATUS - * - * Note that VBUS_REMOVED cannot be distinguished from !VBUS_PRESENT with - * this interface, but the trigger thresholds for Vbus Present should allow the - * same bit to be used safely for both. - * - * TODO(b/149530538): Some TCPCs may be able to implement - * VBUS_SINK_DISCONNECT_THRESHOLD to support vSinkDisconnectPD - */ -static int tcpc_vbus[CONFIG_USB_PD_PORT_MAX_COUNT]; - -/* Cached RP role values */ -static int cached_rp[CONFIG_USB_PD_PORT_MAX_COUNT]; - -/* Cache our Device Capabilities at init for later reference */ -static int dev_cap_1[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); - - if (IS_ENABLED(DEBUG_I2C_FAULT_LAST_WRITE_OP)) { - last_write_op[port].addr = i2c_addr; - last_write_op[port].reg = reg; - last_write_op[port].val = val & 0xFF; - last_write_op[port].mask = 0; - } - - rv = i2c_write8(tcpc_config[port].i2c_info.port, - i2c_addr, reg, val); - - pd_device_accessed(port); - return rv; -} - -int tcpc_addr_write16(int port, int i2c_addr, int reg, int val) -{ - int rv; - - pd_wait_exit_low_power(port); - - if (IS_ENABLED(DEBUG_I2C_FAULT_LAST_WRITE_OP)) { - last_write_op[port].addr = i2c_addr; - last_write_op[port].reg = reg; - last_write_op[port].val = val & 0xFFFF; - last_write_op[port].mask = 0; - } - - rv = i2c_write16(tcpc_config[port].i2c_info.port, - i2c_addr, 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_addr_read16(int port, int i2c_addr, int reg, int *val) -{ - pd_wait_exit_low_power(port); - - return tcpc_addr_read16_no_lpm_exit(port, i2c_addr, reg, val); -} - -int tcpc_addr_read16_no_lpm_exit(int port, int i2c_addr, int reg, int *val) -{ - int rv; - - rv = i2c_read16(tcpc_config[port].i2c_info.port, - i2c_addr, 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; -} - -int tcpc_update8(int port, int reg, - uint8_t mask, - enum mask_update_action action) -{ - int rv; - const int i2c_addr = tcpc_config[port].i2c_info.addr_flags; - - pd_wait_exit_low_power(port); - - if (IS_ENABLED(DEBUG_I2C_FAULT_LAST_WRITE_OP)) { - last_write_op[port].addr = i2c_addr; - last_write_op[port].reg = reg; - last_write_op[port].val = 0; - last_write_op[port].mask = (mask & 0xFF) | (action << 16); - } - - rv = i2c_update8(tcpc_config[port].i2c_info.port, - i2c_addr, reg, mask, action); - - pd_device_accessed(port); - return rv; -} - -int tcpc_update16(int port, int reg, - uint16_t mask, - enum mask_update_action action) -{ - int rv; - const int i2c_addr = tcpc_config[port].i2c_info.addr_flags; - - pd_wait_exit_low_power(port); - - if (IS_ENABLED(DEBUG_I2C_FAULT_LAST_WRITE_OP)) { - last_write_op[port].addr = i2c_addr; - last_write_op[port].reg = reg; - last_write_op[port].val = 0; - last_write_op[port].mask = (mask & 0xFFFF) | (action << 16); - } - - rv = i2c_update16(tcpc_config[port].i2c_info.port, - i2c_addr, reg, mask, action); - - pd_device_accessed(port); - return rv; -} - -#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */ - -/* - * TCPCI maintains and uses cached values for the RP and - * last used PULL values. Since TCPC drivers are allowed - * to use some of the TCPCI functionality, these global - * cached values need to be maintained in case part of the - * used TCPCI functionality relies on these values - */ -void tcpci_set_cached_rp(int port, int rp) -{ - cached_rp[port] = rp; -} - -int tcpci_get_cached_rp(int port) -{ - return cached_rp[port]; -} - -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. - */ - if (get_usb_pd_vbus_detect() == USB_PD_VBUS_DETECT_TCPC) { - 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 | - TCPC_REG_ALERT_FAULT - | TCPC_REG_ALERT_POWER_STATUS - ; - } else { - 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 | - TCPC_REG_ALERT_FAULT - ; - } - - /* TCPCI Rev2 includes SAFE0V alerts */ - if (TCPC_FLAGS_VSAFE0V(tcpc_config[port].flags)) - mask |= TCPC_REG_ALERT_EXT_STATUS; - - if (IS_ENABLED(CONFIG_USB_PD_FRS_TCPC)) - mask |= TCPC_REG_ALERT_ALERT_EXT; - - /* Set the alert mask in TCPC */ - rv = tcpc_write16(port, TCPC_REG_ALERT_MASK, mask); - - if (IS_ENABLED(CONFIG_USB_PD_FRS_TCPC)) { - if (rv) - return rv; - - /* Sink FRS allowed */ - mask = TCPC_REG_ALERT_EXT_SNK_FRS; - rv = tcpc_write(port, TCPC_REG_ALERT_EXTENDED_MASK, 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; - - if (get_usb_pd_vbus_detect() == USB_PD_VBUS_DETECT_TCPC) - mask = TCPC_REG_POWER_STATUS_VBUS_PRES; - else - mask = 0; - - 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); -} - -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) -{ - /* Keep track of current RP value */ - tcpci_set_cached_rp(port, rp); - - return EC_SUCCESS; -} - -void tcpci_tcpc_discharge_vbus(int port, int enable) -{ - if (IS_ENABLED(DEBUG_FORCED_DISCHARGE)) - CPRINTS("C%d: ForceDischarge %sABLED", - port, enable ? "EN" : "DIS"); - - tcpc_update8(port, - TCPC_REG_POWER_CTRL, - TCPC_REG_POWER_CTRL_FORCE_DISCHARGE, - (enable) ? MASK_SET : MASK_CLR); -} - -/* - * Auto Discharge Disconnect is supposed to be enabled when we - * are connected and disabled after we are disconnected and - * VBus is at SafeV0 - */ -void tcpci_tcpc_enable_auto_discharge_disconnect(int port, int enable) -{ - if (IS_ENABLED(DEBUG_AUTO_DISCHARGE_DISCONNECT)) - CPRINTS("C%d: AutoDischargeDisconnect %sABLED", - port, enable ? "EN" : "DIS"); - - tcpc_update8(port, - TCPC_REG_POWER_CTRL, - TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT, - (enable) ? MASK_SET : MASK_CLR); -} - -int tcpci_tcpc_debug_accessory(int port, bool enable) -{ - return tcpc_update8(port, TCPC_REG_CONFIG_STD_OUTPUT, - TCPC_REG_CONFIG_STD_OUTPUT_DBG_ACC_CONN_N, - enable ? MASK_CLR : MASK_SET); -} - -int tcpci_tcpm_get_cc(int port, enum tcpc_cc_voltage_status *cc1, - enum tcpc_cc_voltage_status *cc2) -{ - int role; - int status; - int cc1_present_rd, cc2_present_rd; - int rv; - - /* errors will return CC as open */ - *cc1 = TYPEC_CC_VOLT_OPEN; - *cc2 = TYPEC_CC_VOLT_OPEN; - - /* Get the ROLE CONTROL and CC STATUS values */ - rv = tcpc_read(port, TCPC_REG_ROLE_CTRL, &role); - if (rv) - return rv; - - rv = tcpc_read(port, TCPC_REG_CC_STATUS, &status); - if (rv) - return rv; - - /* Get the current CC values from the CC STATUS */ - *cc1 = TCPC_REG_CC_STATUS_CC1(status); - *cc2 = TCPC_REG_CC_STATUS_CC2(status); - - /* Determine if we are presenting Rd */ - cc1_present_rd = 0; - cc2_present_rd = 0; - if (role & TCPC_REG_ROLE_CTRL_DRP_MASK) { - /* - * We are doing DRP. We will use the CC STATUS - * ConnectResult to determine if we are presenting - * Rd or Rp. - */ - int term; - - term = TCPC_REG_CC_STATUS_TERM(status); - - if (*cc1 != TYPEC_CC_VOLT_OPEN) - cc1_present_rd = term; - if (*cc2 != TYPEC_CC_VOLT_OPEN) - cc2_present_rd = term; - } else { - /* - * We are not doing DRP. We will use the ROLE CONTROL - * CC values to determine if we are presenting Rd or Rp. - */ - int role_cc1, role_cc2; - - role_cc1 = TCPC_REG_ROLE_CTRL_CC1(role); - role_cc2 = TCPC_REG_ROLE_CTRL_CC2(role); - - if (*cc1 != TYPEC_CC_VOLT_OPEN) - cc1_present_rd = !!(role_cc1 == TYPEC_CC_RD); - if (*cc2 != TYPEC_CC_VOLT_OPEN) - cc2_present_rd = !!(role_cc2 == TYPEC_CC_RD); - } - *cc1 |= cc1_present_rd << 2; - *cc2 |= cc2_present_rd << 2; - - if (IS_ENABLED(DEBUG_GET_CC) && - (last_get_cc[port].cc1 != *cc1 || - last_get_cc[port].cc2 != *cc2 || - last_get_cc[port].cc_sts != status || - last_get_cc[port].role != role)) { - - CPRINTS("C%d: GET_CC cc1=%d cc2=%d cc_sts=0x%X role=0x%X", - port, *cc1, *cc2, status, role); - - last_get_cc[port].cc1 = *cc1; - last_get_cc[port].cc2 = *cc2; - last_get_cc[port].cc_sts = status; - last_get_cc[port].role = role; - } - return rv; -} - -int tcpci_tcpm_set_cc(int port, int pull) -{ - int role = TCPC_REG_ROLE_CTRL_SET(TYPEC_NO_DRP, - tcpci_get_cached_rp(port), - pull, pull); - - if (IS_ENABLED(DEBUG_ROLE_CTRL_UPDATES)) - CPRINTS("C%d: SET_CC pull=%d role=0x%X", port, pull, role); - - return tcpc_write(port, TCPC_REG_ROLE_CTRL, role); -} - -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE -int tcpci_set_role_ctrl(int port, enum tcpc_drp drp, enum tcpc_rp_value rp, - enum tcpc_cc_pull pull) -{ - int role = TCPC_REG_ROLE_CTRL_SET(drp, rp, pull, pull); - - if (IS_ENABLED(DEBUG_ROLE_CTRL_UPDATES)) - CPRINTS("C%d: SET_ROLE_CTRL drp=%d rp=%d pull=%d role=0x%X", - port, drp, rp, pull, role); - - return tcpc_write(port, TCPC_REG_ROLE_CTRL, role); -} - -int tcpci_tcpc_drp_toggle(int port) -{ - int rv; - enum tcpc_cc_pull pull; - - /* - * Set auto drp toggle - * - * Set RC.DRP=1b (DRP) - * Set RC.RpValue=00b (smallest Rp to save power) - * Set RC.CC1=(Rp) or (Rd) - * Set RC.CC2=(Rp) or (Rd) - * - * TCPCI r1 wants both lines to be set to Rd - * TCPCI r2 wants both lines to be set to Rp - * - * Set the Rp Value to be the minimal to save power - */ - pull = (tcpc_config[port].flags & TCPC_FLAGS_TCPCI_REV2_0) - ? TYPEC_CC_RP : TYPEC_CC_RD; - - rv = tcpci_set_role_ctrl(port, TYPEC_DRP, TYPEC_RP_USB, pull); - if (rv) - return rv; - - /* Set up to catch LOOK4CONNECTION alerts */ - rv = tcpc_update8(port, - TCPC_REG_TCPC_CTRL, - TCPC_REG_TCPC_CTRL_EN_LOOK4CONNECTION_ALERT, - MASK_SET); - if (rv) - return rv; - - /* 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, enum tcpc_cc_polarity polarity) -{ - return tcpc_update8(port, - TCPC_REG_TCPC_CTRL, - TCPC_REG_TCPC_CTRL_SET(1), - polarity_rm_dts(polarity) - ? MASK_SET : MASK_CLR); -} - -#ifdef CONFIG_USB_PD_PPC -bool tcpci_tcpm_get_snk_ctrl(int port) -{ - int rv; - int pwr_sts; - - rv = tcpci_tcpm_get_power_status(port, &pwr_sts); - - return rv == EC_SUCCESS && - pwr_sts & TCPC_REG_POWER_STATUS_SINKING_VBUS; -} - -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); -} - -bool tcpci_tcpm_get_src_ctrl(int port) -{ - int rv; - int pwr_sts; - - rv = tcpci_tcpm_get_power_status(port, &pwr_sts); - - return rv == EC_SUCCESS && - pwr_sts & TCPC_REG_POWER_STATUS_SOURCING_VBUS; -} - -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 - -__maybe_unused int tcpci_tcpm_sop_prime_enable(int port, bool enable) -{ - /* save SOP'/SOP'' enable state */ - sop_prime_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; - } - - return tcpc_write(port, TCPC_REG_RX_DETECT, detect_sop_en); - } - - return EC_SUCCESS; -} - -int tcpci_tcpm_set_vconn(int port, int enable) -{ - int reg, rv; - - rv = tcpc_read(port, TCPC_REG_POWER_CTRL, ®); - if (rv) - return rv; - - reg &= ~TCPC_REG_POWER_CTRL_VCONN(1); - reg |= TCPC_REG_POWER_CTRL_VCONN(enable); - - /* - * Add delay of writing TCPC_REG_POWER_CTRL makes - * CC status being judged correctly when disable VCONN. - * This may be a PS8XXX firmware issue, Parade is still trying. - * https://partnerissuetracker.corp.google.com/issues/185202064 - */ - if (!enable) - msleep(PS8XXX_VCONN_TURN_OFF_DELAY_US); - - 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); -} - -static int tcpm_ext_status(int port, int *ext_status) -{ - /* Read TCPC Extended Status register */ - return tcpc_read(port, TCPC_REG_EXT_STATUS, ext_status); -} - -int tcpci_tcpm_set_rx_enable(int port, int enable) -{ - int detect_sop_en = 0; - - if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) { - /* save rx_on */ - rx_en[port] = enable; - } - - - if (enable) { - detect_sop_en = TCPC_REG_RX_DETECT_SOP_HRST_MASK; - - if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP) && - sop_prime_en[port]) { - /* - * Only the VCONN Source is allowed to communicate - * with the Cable Plugs. - */ - detect_sop_en = - TCPC_REG_RX_DETECT_SOP_SOPP_SOPPP_HRST_MASK; - } - } - - /* If enable, then set RX detect for SOP and HRST */ - return tcpc_write(port, TCPC_REG_RX_DETECT, detect_sop_en); -} - -#ifdef CONFIG_USB_PD_FRS_TCPC -int tcpci_tcpc_fast_role_swap_enable(int port, int enable) -{ - return tcpc_update8(port, - TCPC_REG_POWER_CTRL, - TCPC_REG_POWER_CTRL_FRS_ENABLE, - (enable) ? MASK_SET : MASK_CLR); -} -#endif - -#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC -bool tcpci_tcpm_check_vbus_level(int port, enum vbus_level level) -{ - if (level == VBUS_SAFE0V) - return !!(tcpc_vbus[port] & BIT(VBUS_SAFE0V)); - else if (level == VBUS_PRESENT) - return !!(tcpc_vbus[port] & BIT(VBUS_PRESENT)); - else - return !(tcpc_vbus[port] & BIT(VBUS_PRESENT)); -} -#endif - -struct cached_tcpm_message { - uint32_t header; - uint32_t payload[7]; -}; - -static int tcpci_rev2_0_tcpm_get_message_raw(int port, uint32_t *payload, - int *head) -{ - int rv = 0, cnt, reg = TCPC_REG_RX_BUFFER; - int frm; - uint8_t tmp[2]; - /* - * Register 0x30 is Readable Byte Count, Buffer frame type, and RX buf - * byte X. - */ - tcpc_lock(port, 1); - rv = tcpc_xfer_unlocked(port, (uint8_t *)®, 1, tmp, 2, - I2C_XFER_START); - if (rv) { - rv = EC_ERROR_UNKNOWN; - goto clear; - } - cnt = tmp[0]; - frm = tmp[1]; - - /* - * READABLE_BYTE_COUNT includes 3 bytes for frame type and header, and - * may be 0 if the TCPC saw a disconnect before the message read - */ - cnt -= 3; - if ((cnt < 0) || - (cnt > member_size(struct cached_tcpm_message, payload))) { - /* Continue to send the stop bit with the header read */ - rv = EC_ERROR_UNKNOWN; - cnt = 0; - } - - /* The next two bytes are the header */ - rv |= tcpc_xfer_unlocked(port, NULL, 0, (uint8_t *)head, 2, - cnt ? 0 : I2C_XFER_STOP); - - /* Encode message address in bits 31 to 28 */ - *head &= 0x0000ffff; - *head |= PD_HEADER_SOP(frm); - - /* Execute read and I2C_XFER_STOP, even if header read failed */ - if (cnt > 0) { - tcpc_xfer_unlocked(port, NULL, 0, (uint8_t *)payload, cnt, - I2C_XFER_STOP); - } - -clear: - tcpc_lock(port, 0); - /* Read complete, clear RX status alert bit */ - tcpc_write16(port, TCPC_REG_ALERT, TCPC_REG_ALERT_RX_STATUS); - - if (rv) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -static int tcpci_rev1_0_tcpm_get_message_raw(int port, uint32_t *payload, - int *head) -{ - int rv, cnt, reg = TCPC_REG_RX_DATA; - int frm; - - 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; - } - - if (IS_ENABLED(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; - } - } - - rv = tcpc_read16(port, TCPC_REG_RX_HDR, (int *)head); - - if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) { - /* Encode message address in bits 31 to 28 */ - *head &= 0x0000ffff; - *head |= PD_HEADER_SOP(frm); - } - - 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; -} - -int tcpci_tcpm_get_message_raw(int port, uint32_t *payload, int *head) -{ - if (tcpc_config[port].flags & TCPC_FLAGS_TCPCI_REV2_0) - return tcpci_rev2_0_tcpm_get_message_raw(port, payload, head); - - return tcpci_rev1_0_tcpm_get_message_raw(port, payload, head); -} - -/* Cache depth needs to be power of 2 */ -/* TODO: Keep track of the high water mark */ -#define CACHE_DEPTH BIT(3) -#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); - - 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 tcpci_msg_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)); - } - - if (tcpc_config[port].flags & TCPC_FLAGS_TCPCI_REV2_0) { - /* - * In TCPCI Rev 2.0, TX_BYTE_CNT and TX_BUF_BYTE_X are the same - * register. - */ - reg = TCPC_REG_TX_BUFFER; - /* TX_BYTE_CNT includes extra bytes for message header */ - cnt += sizeof(header); - tcpc_lock(port, 1); - rv = tcpc_xfer_unlocked(port, (uint8_t *)®, 1, NULL, 0, - I2C_XFER_START); - rv |= tcpc_xfer_unlocked(port, (uint8_t *)&cnt, 1, NULL, 0, 0); - if (cnt > sizeof(header)) { - rv |= tcpc_xfer_unlocked(port, (uint8_t *)&header, - sizeof(header), NULL, 0, 0); - rv |= tcpc_xfer_unlocked(port, (uint8_t *)data, - cnt-sizeof(header), NULL, 0, - I2C_XFER_STOP); - } else { - rv |= tcpc_xfer_unlocked(port, (uint8_t *)&header, - sizeof(header), NULL, 0, I2C_XFER_STOP); - } - tcpc_lock(port, 0); - - /* If tcpc write fails, return error */ - if (rv) - return rv; - } else { - /* 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 write fails, return error */ - if (rv) - return rv; - - if (cnt > 0) { - rv = tcpc_write_block(port, reg, (const uint8_t *)data, - cnt); - - /* If tcpc write fails, return error */ - if (rv) - return rv; - } - } - - /* - * We always retry in TCPC hardware since the TCPM is too slow to - * respond within tRetry (~195 usec). - * - * The retry count used is dependent on the maximum PD revision - * supported at build time. - */ - return tcpc_write(port, TCPC_REG_TRANSMIT, - TCPC_REG_TRANSMIT_SET_WITH_RETRY( - pd_get_retry_count(port, type), type)); -} - -/* - * Returns true if TCPC has reset based on reading mask registers. - */ -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; -} - -static int tcpci_get_fault(int port, int *fault) -{ - return tcpc_read(port, TCPC_REG_FAULT_STATUS, fault); -} - -static int tcpci_handle_fault(int port, int fault) -{ - int rv = EC_SUCCESS; - - CPRINTS("C%d FAULT 0x%02X detected", port, fault); - - if (IS_ENABLED(DEBUG_I2C_FAULT_LAST_WRITE_OP) && - fault & TCPC_REG_FAULT_STATUS_I2C_INTERFACE_ERR) { - if (last_write_op[port].mask == 0) - CPRINTS("C%d I2C WR 0x%02X 0x%02X value=0x%X", - port, - last_write_op[port].addr, - last_write_op[port].reg, - last_write_op[port].val); - else - CPRINTS("C%d I2C UP 0x%02X 0x%02X op=%d mask=0x%X", - port, - last_write_op[port].addr, - last_write_op[port].reg, - last_write_op[port].mask >> 16, - last_write_op[port].mask & 0xFFFF); - } - - /* Report overcurrent to the OCP module if enabled */ - if ((dev_cap_1[port] & TCPC_REG_DEV_CAP_1_VBUS_OCP_REPORTING) && - IS_ENABLED(CONFIG_USBC_OCP) && - (fault & TCPC_REG_FAULT_STATUS_VBUS_OVER_CURRENT)) - pd_handle_overcurrent(port); - - if (tcpc_config[port].drv->handle_fault) - rv = tcpc_config[port].drv->handle_fault(port, fault); - - return rv; -} - -enum ec_error_list tcpci_set_bist_test_mode(const int port, - const bool enable) -{ - int rv; - - rv = tcpc_update8(port, TCPC_REG_TCPC_CTRL, - TCPC_REG_TCPC_CTRL_BIST_TEST_MODE, - enable ? MASK_SET : MASK_CLR); - rv |= tcpc_update16(port, TCPC_REG_ALERT_MASK, - TCPC_REG_ALERT_RX_STATUS, enable ? MASK_CLR : MASK_SET); - return rv; -} - -static int tcpci_clear_fault(int port, int fault) -{ - int rv; - - rv = tcpc_write(port, TCPC_REG_FAULT_STATUS, fault); - if (rv) - return rv; - - return tcpc_write16(port, TCPC_REG_ALERT, TCPC_REG_ALERT_FAULT); -} - -static void tcpci_check_vbus_changed(int port, int alert, uint32_t *pd_event) -{ - /* - * Check for VBus change - */ - /* TCPCI Rev2 includes Safe0V detection */ - if (TCPC_FLAGS_VSAFE0V(tcpc_config[port].flags) && - (alert & TCPC_REG_ALERT_EXT_STATUS)) { - int ext_status = 0; - - /* Determine if Safe0V was detected */ - tcpm_ext_status(port, &ext_status); - if (ext_status & TCPC_REG_EXT_STATUS_SAFE0V) - /* Safe0V=1 and Present=0 */ - tcpc_vbus[port] = BIT(VBUS_SAFE0V); - } - - if (alert & TCPC_REG_ALERT_POWER_STATUS) { - int pwr_status = 0; - - /* Determine reason for power status change */ - tcpci_tcpm_get_power_status(port, &pwr_status); - if (pwr_status & TCPC_REG_POWER_STATUS_VBUS_PRES) - /* Safe0V=0 and Present=1 */ - tcpc_vbus[port] = BIT(VBUS_PRESENT); - else if (TCPC_FLAGS_VSAFE0V(tcpc_config[port].flags)) - /* TCPCI Rev2 detects Safe0V, so Present=0 */ - tcpc_vbus[port] &= ~BIT(VBUS_PRESENT); - else { - /* - * TCPCI Rev1 can not detect Safe0V, so treat this - * like a Safe0V detection. - * - * Safe0V=1 and Present=0 - */ - tcpc_vbus[port] = BIT(VBUS_SAFE0V); - } - - if ((get_usb_pd_vbus_detect() == USB_PD_VBUS_DETECT_TCPC) && - IS_ENABLED(CONFIG_USB_CHARGER)) { - /* Update charge manager with new VBUS state */ - usb_charger_vbus_change(port, - !!(tcpc_vbus[port] & BIT(VBUS_PRESENT))); - - if (pd_event) - *pd_event |= TASK_EVENT_WAKE; - } - } -} - -/* - * 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 alert = 0; - int alert_ext = 0; - int failed_attempts; - uint32_t pd_event = 0; - int retval = 0; - - /* Read the Alert register from the TCPC */ - if (tcpm_alert_status(port, &alert)) { - CPRINTS("C%d: Failed to read alert register", port); - return; - } - - /* Get Extended Alert register if needed */ - if (alert & TCPC_REG_ALERT_ALERT_EXT) - tcpm_alert_ext_status(port, &alert_ext); - - /* Clear any pending faults */ - if (alert & TCPC_REG_ALERT_FAULT) { - int fault; - - if (tcpci_get_fault(port, &fault) == EC_SUCCESS && - fault != 0 && - tcpci_handle_fault(port, fault) == EC_SUCCESS && - tcpci_clear_fault(port, fault) == EC_SUCCESS) - CPRINTS("C%d FAULT 0x%02X handled", port, fault); - } - - /* - * 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 (alert & TCPC_REG_ALERT_TX_COMPLETE) - pd_transmit_complete(port, alert & 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 (alert & TCPC_REG_ALERT_RX_STATUS) { - retval = tcpm_enqueue_message(port); - if (retval) - ++failed_attempts; - if (tcpm_alert_status(port, &alert)) - ++failed_attempts; - - - /* - * EC RX FIFO is full. Deassert ALERT# line to exit interrupt - * handler by discarding pending message from TCPC RX FIFO. - */ - if (retval == EC_ERROR_OVERFLOW) { - CPRINTS("C%d: PD RX OVF!", port); - tcpc_write16(port, TCPC_REG_ALERT, - TCPC_REG_ALERT_RX_STATUS | - TCPC_REG_ALERT_RX_BUF_OVF); - } - - /* 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. Ext first because ALERT.AlertExtended - * is set if any bit of ALERT_EXTENDED is set. - */ - if (alert_ext) - tcpc_write(port, TCPC_REG_ALERT_EXT, alert_ext); - if (alert) - tcpc_write16(port, TCPC_REG_ALERT, alert); - - if (alert & TCPC_REG_ALERT_CC_STATUS) { - if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE)) { - enum tcpc_cc_voltage_status cc1; - enum tcpc_cc_voltage_status cc2; - - /* - * Some TCPCs generate CC Alerts when - * drp auto toggle is active and nothing - * is connected to the port. So, get the - * CC line status and only generate a - * PD_EVENT_CC if something is connected. - */ - tcpci_tcpm_get_cc(port, &cc1, &cc2); - if (cc1 != TYPEC_CC_VOLT_OPEN || - cc2 != TYPEC_CC_VOLT_OPEN) - /* CC status cchanged, wake task */ - pd_event |= PD_EVENT_CC; - } else { - /* CC status changed, wake task */ - pd_event |= PD_EVENT_CC; - } - } - - tcpci_check_vbus_changed(port, alert, &pd_event); - - /* Check for Hard Reset received */ - if (alert & TCPC_REG_ALERT_RX_HARD_RST) { - /* hard reset received */ - CPRINTS("C%d Hard Reset received", port); - pd_event |= PD_EVENT_RX_HARD_RESET; - } - - /* USB TCPCI Spec R2 V1.1 Section 4.7.3 Step 2 - * - * The TCPC asserts both ALERT.TransmitSOP*MessageSuccessful and - * ALERT.TransmitSOP*MessageFailed regardless of the outcome of the - * transmission and asserts the Alert# pin. - */ - if (alert & TCPC_REG_ALERT_TX_SUCCESS && - alert & TCPC_REG_ALERT_TX_FAILED) - CPRINTS("C%d Hard Reset sent", port); - - if (IS_ENABLED(CONFIG_USB_PD_FRS_TCPC) - && (alert_ext & TCPC_REG_ALERT_EXT_SNK_FRS)) - pd_got_frs_signal(port); - - /* - * Check registers to see if we can tell that the TCPC has reset. If - * so, perform a tcpc_init. - */ - if (register_mask_reset(port)) - pd_event |= PD_EVENT_TCPC_RESET; - - /* - * 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); -} - -/* - * 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 - cached_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 = &cached_info[port]; - - - /* If already cached && live data is not asked, return cached value */ - if (i->vendor_id && !live) { - /* - * If chip_info is NULL, chip info will be stored in cache and - * can be read later by another call. - */ - if (chip_info) - memcpy(chip_info, i, sizeof(*i)); - - 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; - - /* Copy the cached value to return if chip_info is not NULL */ - if (chip_info) - memcpy(chip_info, i, sizeof(*i)); - - 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 = tcpci_tcpm_get_power_status(port, &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); - } - - /* - * For TCPCI Rev 2.0, unless the TCPM sets - * TCPC_CONTROL.EnableLooking4ConnectionAlert bit, TCPC by default masks - * Alert assertion when CC_STATUS.Looking4Connection changes state. - */ - if (tcpc_config[port].flags & TCPC_FLAGS_TCPCI_REV2_0) { - error = tcpc_update8(port, TCPC_REG_TCPC_CTRL, - TCPC_REG_TCPC_CTRL_EN_LOOK4CONNECTION_ALERT, - MASK_SET); - if (error) - CPRINTS("C%d: Failed to init TCPC_CTRL!", port); - } - - /* - * Handle and clear any alerts, since we might be coming out of low - * power mode in response to an alert interrupt from the TCPC. - */ - tcpc_alert(port); - /* Initialize power_status_mask */ - init_power_status_mask(port); - - if (TCPC_FLAGS_VSAFE0V(tcpc_config[port].flags)) { - int ext_status = 0; - - /* Read Extended Status register */ - tcpm_ext_status(port, &ext_status); - /* Initial level, set appropriately */ - if (power_status & TCPC_REG_POWER_STATUS_VBUS_PRES) - tcpc_vbus[port] = BIT(VBUS_PRESENT); - else if (ext_status & TCPC_REG_EXT_STATUS_SAFE0V) - tcpc_vbus[port] = BIT(VBUS_SAFE0V); - else - tcpc_vbus[port] = 0; - } else { - /* Initial level, set appropriately */ - tcpc_vbus[port] = (power_status & - TCPC_REG_POWER_STATUS_VBUS_PRES) - ? BIT(VBUS_PRESENT) - : BIT(VBUS_SAFE0V); - } - - /* - * Force an update to the VBUS status in case the TCPC doesn't send a - * power status changed interrupt later. - */ - tcpci_check_vbus_changed(port, - TCPC_REG_ALERT_POWER_STATUS | TCPC_REG_ALERT_EXT_STATUS, - NULL); - - 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); - - /* Cache our device capabilities for future reference */ - tcpc_read16(port, TCPC_REG_DEV_CAP_1, &dev_cap_1[port]); - - 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(const struct usb_mux *me) -{ - int error; - int power_status; - int tries = TCPM_INIT_TRIES; - - /* If this MUX is also the TCPC, then skip init */ - if (!(me->flags & USB_MUX_FLAG_NOT_TCPC)) - return EC_SUCCESS; - - /* Wait for the device to exit low power state */ - while (1) { - error = mux_read(me, 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(me, TCPC_REG_ALERT_MASK, 0); - error |= mux_write16(me, TCPC_REG_ALERT, 0xffff); - - return error ? EC_ERROR_UNKNOWN : EC_SUCCESS; -} - -int tcpci_tcpm_mux_enter_low_power(const struct usb_mux *me) -{ - /* If this MUX is also the TCPC, then skip low power */ - if (!(me->flags & USB_MUX_FLAG_NOT_TCPC)) - return EC_SUCCESS; - - return mux_write(me, TCPC_REG_COMMAND, TCPC_REG_COMMAND_I2CIDLE); -} - -int tcpci_tcpm_mux_set(const struct usb_mux *me, mux_state_t mux_state, - bool *ack_required) -{ - int rv; - int reg = 0; - - /* This driver does not use host command ACKs */ - *ack_required = false; - - /* Parameter is port only */ - rv = mux_read(me, TCPC_REG_CONFIG_STD_OUTPUT, ®); - if (rv != EC_SUCCESS) - return rv; - - reg &= ~(TCPC_REG_CONFIG_STD_OUTPUT_MUX_MASK | - TCPC_REG_CONFIG_STD_OUTPUT_CONNECTOR_FLIPPED); - if (mux_state & USB_PD_MUX_USB_ENABLED) - reg |= TCPC_REG_CONFIG_STD_OUTPUT_MUX_USB; - if (mux_state & USB_PD_MUX_DP_ENABLED) - reg |= TCPC_REG_CONFIG_STD_OUTPUT_MUX_DP; - if (mux_state & USB_PD_MUX_POLARITY_INVERTED) - reg |= TCPC_REG_CONFIG_STD_OUTPUT_CONNECTOR_FLIPPED; - - /* Parameter is port only */ - return mux_write(me, TCPC_REG_CONFIG_STD_OUTPUT, reg); -} - -/* Reads control register and updates mux_state accordingly */ -int tcpci_tcpm_mux_get(const struct usb_mux *me, mux_state_t *mux_state) -{ - int rv; - int reg = 0; - - *mux_state = 0; - - /* Parameter is port only */ - rv = mux_read(me, TCPC_REG_CONFIG_STD_OUTPUT, ®); - if (rv != EC_SUCCESS) - return rv; - - if (reg & TCPC_REG_CONFIG_STD_OUTPUT_MUX_USB) - *mux_state |= USB_PD_MUX_USB_ENABLED; - if (reg & TCPC_REG_CONFIG_STD_OUTPUT_MUX_DP) - *mux_state |= USB_PD_MUX_DP_ENABLED; - if (reg & TCPC_REG_CONFIG_STD_OUTPUT_CONNECTOR_FLIPPED) - *mux_state |= USB_PD_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 */ - -#ifdef CONFIG_CMD_TCPC_DUMP -static const struct tcpc_reg_dump_map tcpc_regs[] = { - { - .addr = TCPC_REG_VENDOR_ID, - .name = "VENDOR_ID", - .size = 2, - }, - { - .addr = TCPC_REG_PRODUCT_ID, - .name = "PRODUCT_ID", - .size = 2, - }, - { - .addr = TCPC_REG_BCD_DEV, - .name = "BCD_DEV", - .size = 2, - }, - { - .addr = TCPC_REG_TC_REV, - .name = "TC_REV", - .size = 2, - }, - { - .addr = TCPC_REG_PD_REV, - .name = "PD_REV", - .size = 2, - }, - { - .addr = TCPC_REG_PD_INT_REV, - .name = "PD_INT_REV", - .size = 2, - }, - { - .addr = TCPC_REG_ALERT, - .name = "ALERT", - .size = 2, - }, - { - .addr = TCPC_REG_ALERT_MASK, - .name = "ALERT_MASK", - .size = 2, - }, - { - .addr = TCPC_REG_POWER_STATUS_MASK, - .name = "POWER_STATUS_MASK", - .size = 1, - }, - { - .addr = TCPC_REG_FAULT_STATUS_MASK, - .name = "FAULT_STATUS_MASK", - .size = 1, - }, - { - .addr = TCPC_REG_EXT_STATUS_MASK, - .name = "EXT_STATUS_MASK", - .size = 1 - }, - { - .addr = TCPC_REG_ALERT_EXTENDED_MASK, - .name = "ALERT_EXTENDED_MASK", - .size = 1, - }, - { - .addr = TCPC_REG_CONFIG_STD_OUTPUT, - .name = "CONFIG_STD_OUTPUT", - .size = 1, - }, - { - .addr = TCPC_REG_TCPC_CTRL, - .name = "TCPC_CTRL", - .size = 1, - }, - { - .addr = TCPC_REG_ROLE_CTRL, - .name = "ROLE_CTRL", - .size = 1, - }, - { - .addr = TCPC_REG_FAULT_CTRL, - .name = "FAULT_CTRL", - .size = 1, - }, - { - .addr = TCPC_REG_POWER_CTRL, - .name = "POWER_CTRL", - .size = 1, - }, - { - .addr = TCPC_REG_CC_STATUS, - .name = "CC_STATUS", - .size = 1, - }, - { - .addr = TCPC_REG_POWER_STATUS, - .name = "POWER_STATUS", - .size = 1, - }, - { - .addr = TCPC_REG_FAULT_STATUS, - .name = "FAULT_STATUS", - .size = 1, - }, - { - .addr = TCPC_REG_EXT_STATUS, - .name = "EXT_STATUS", - .size = 1, - }, - { - .addr = TCPC_REG_ALERT_EXT, - .name = "ALERT_EXT", - .size = 1, - }, - { - .addr = TCPC_REG_DEV_CAP_1, - .name = "DEV_CAP_1", - .size = 2, - }, - { - .addr = TCPC_REG_DEV_CAP_2, - .name = "DEV_CAP_2", - .size = 2, - }, - { - .addr = TCPC_REG_STD_INPUT_CAP, - .name = "STD_INPUT_CAP", - .size = 1, - }, - { - .addr = TCPC_REG_STD_OUTPUT_CAP, - .name = "STD_OUTPUT_CAP", - .size = 1, - }, - { - .addr = TCPC_REG_CONFIG_EXT_1, - .name = "CONFIG_EXT_1", - .size = 1, - }, - { - .addr = TCPC_REG_MSG_HDR_INFO, - .name = "MSG_HDR_INFO", - .size = 1, - }, - { - .addr = TCPC_REG_RX_DETECT, - .name = "RX_DETECT", - .size = 1, - }, - { - .addr = TCPC_REG_RX_BYTE_CNT, - .name = "RX_BYTE_CNT", - .size = 1, - }, - { - .addr = TCPC_REG_RX_BUF_FRAME_TYPE, - .name = "RX_BUF_FRAME_TYPE", - .size = 1, - }, - { - .addr = TCPC_REG_TRANSMIT, - .name = "TRANSMIT", - .size = 1, - }, - { - .addr = TCPC_REG_VBUS_VOLTAGE, - .name = "VBUS_VOLTAGE", - .size = 2, - }, - { - .addr = TCPC_REG_VBUS_SINK_DISCONNECT_THRESH, - .name = "VBUS_SINK_DISCONNECT_THRESH", - .size = 2, - }, - { - .addr = TCPC_REG_VBUS_STOP_DISCHARGE_THRESH, - .name = "VBUS_STOP_DISCHARGE_THRESH", - .size = 2, - }, - { - .addr = TCPC_REG_VBUS_VOLTAGE_ALARM_HI_CFG, - .name = "VBUS_VOLTAGE_ALARM_HI_CFG", - .size = 2, - }, - { - .addr = TCPC_REG_VBUS_VOLTAGE_ALARM_LO_CFG, - .name = "VBUS_VOLTAGE_ALARM_LO_CFG", - .size = 2, - }, -}; - -/* - * Dump standard TCPC registers. - */ -void tcpc_dump_std_registers(int port) -{ - tcpc_dump_registers(port, tcpc_regs, ARRAY_SIZE(tcpc_regs)); -} -#endif - -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 - .check_vbus_level = &tcpci_tcpm_check_vbus_level, -#endif - .select_rp_value = &tcpci_tcpm_select_rp_value, - .set_cc = &tcpci_tcpm_set_cc, - .set_polarity = &tcpci_tcpm_set_polarity, -#ifdef CONFIG_USB_PD_DECODE_SOP - .sop_prime_enable = &tcpci_tcpm_sop_prime_enable, -#endif - .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 - .tcpc_enable_auto_discharge_disconnect = - &tcpci_tcpc_enable_auto_discharge_disconnect, -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - .drp_toggle = &tcpci_tcpc_drp_toggle, -#endif - .get_chip_info = &tcpci_get_chip_info, -#ifdef CONFIG_USB_PD_PPC - .get_snk_ctrl = &tcpci_tcpm_get_snk_ctrl, - .set_snk_ctrl = &tcpci_tcpm_set_snk_ctrl, - .get_src_ctrl = &tcpci_tcpm_get_src_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 - .set_bist_test_mode = &tcpci_set_bist_test_mode, -#ifdef CONFIG_CMD_TCPC_DUMP - .dump_registers = &tcpc_dump_std_registers, -#endif -}; diff --git a/driver/tcpm/tusb422.c b/driver/tcpm/tusb422.c deleted file mode 100644 index f2a4ec2fb3..0000000000 --- a/driver/tcpm/tusb422.c +++ /dev/null @@ -1,195 +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 "tcpm/tcpci.h" -#include "tcpm/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 - -#if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && \ - !defined(CONFIG_USB_PD_TCPC_LOW_POWER) -#error "TUSB422 driver requires CONFIG_USB_PD_TCPC_LOW_POWER if " \ - "CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE is enabled" -#endif - -#if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && \ - defined(CONFIG_USB_PD_DISCHARGE_TCPC) -#error "TUSB422 must disable TCPC discharge to support enabling Auto " \ - "Discharge Disconnect all the time." -#endif - -enum tusb422_reg_addr { - TUSB422_REG_VBUS_AND_VCONN_CONTROL = 0x98, -}; - -enum vbus_and_vconn_control_mask { - INT_VCONNDIS_DISABLE = BIT(1), - INT_VBUSDIS_DISABLE = BIT(2), -}; - -/* The TUSB422 cannot drive an FRS GPIO, but can detect FRS */ -static int tusb422_set_frs_enable(int port, int enable) -{ - return tcpc_update8(port, TUSB422_REG_PHY_BMC_RX_CTRL, - TUSB422_REG_PHY_BMC_RX_CTRL_FRS_RX_EN, - enable ? MASK_SET : MASK_CLR); -} - -static int tusb422_tcpci_tcpm_init(int port) -{ - int rv; - - /* - * Do not perform TCPC soft reset while waking from Low Power Mode, - * because it makes DRP incapable of looking for connection correctly - * (see b/176986511) and probably breaks firmware_PDTrySrc test - * (see b/179234089). - * - * TODO(b/179234089): Consider implementing function that performs - * only necessary things when leaving Low Power Mode, so we can perform - * TCPC soft reset here. - */ - - rv = tcpci_tcpm_init(port); - if (rv) - return rv; - - if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE)) { - /* - * When dual role auto toggle is enabled, the TUSB422 needs - * auto discharge disconnect enabled so that the CC state - * is detected correctly. - * Without this, the CC lines get stuck in the SRC.Open state - * after updating the ROLE Control register on a device connect. - */ - tusb422_tcpm_drv.tcpc_enable_auto_discharge_disconnect(port, 1); - - /* - * Disable internal VBUS discharge. AutoDischargeDisconnect must - * generally remain enabled to keep TUSB422 in active mode. - * However, this will interfere with FRS by default by - * discharging at inappropriate times. Mitigate this by - * disabling internal VBUS discharge. The TUSB422 must rely on - * external VBUS discharge. See TUSB422 datasheet, 7.4.2 Active - * Mode. - */ - tcpc_write(port, TUSB422_REG_VBUS_AND_VCONN_CONTROL, - INT_VBUSDIS_DISABLE); - } - if (IS_ENABLED(CONFIG_USB_PD_FRS_TCPC)) { - /* Disable FRS detection, and enable the FRS detection alert */ - tusb422_set_frs_enable(port, 0); - tcpc_update16(port, TCPC_REG_ALERT_MASK, - TCPC_REG_ALERT_MASK_VENDOR_DEF, MASK_SET); - tcpc_update8(port, TUSB422_REG_VENDOR_INTERRUPTS_MASK, - TUSB422_REG_VENDOR_INTERRUPTS_MASK_FRS_RX, - MASK_SET); - } - /* - * 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, - TCPC_REG_COMMAND_ENABLE_VBUS_DETECT); -} - -static int tusb422_tcpm_set_cc(int port, int pull) -{ - /* - * Enable AutoDischargeDisconnect to keep TUSB422 in active mode through - * this transition. Note that the configuration keeps the TCPC from - * actually discharging VBUS in this case. - */ - if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE)) - tusb422_tcpm_drv.tcpc_enable_auto_discharge_disconnect(port, 1); - - return tcpci_tcpm_set_cc(port, pull); -} - -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE -static int tusb422_tcpc_drp_toggle(int port) -{ - /* - * The TUSB422 requires auto discharge disconnect to be enabled for - * active mode (not unattached) operation. Make sure it is disabled - * before enabling DRP toggling. - * - * USB Type-C Port Controller Interface Specification revision 2.0, - * Figure 4-21 Source Disconnect and Figure 4-22 Sink Disconnect - */ - tusb422_tcpm_drv.tcpc_enable_auto_discharge_disconnect(port, 0); - - return tcpci_tcpc_drp_toggle(port); -} -#endif - -static void tusb422_tcpci_tcpc_alert(int port) -{ - if (IS_ENABLED(CONFIG_USB_PD_FRS_TCPC)) { - int regval; - - /* FRS detection is a vendor defined alert */ - tcpc_read(port, TUSB422_REG_VENDOR_INTERRUPTS_STATUS, ®val); - if (regval & TUSB422_REG_VENDOR_INTERRUPTS_STATUS_FRS_RX) { - tusb422_set_frs_enable(port, 0); - tcpc_write(port, TUSB422_REG_VENDOR_INTERRUPTS_STATUS, - regval); - pd_got_frs_signal(port); - } - } - tcpci_tcpc_alert(port); -} - -const struct tcpm_drv tusb422_tcpm_drv = { - .init = &tusb422_tcpci_tcpm_init, - .release = &tcpci_tcpm_release, - .get_cc = &tcpci_tcpm_get_cc, -#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC - .check_vbus_level = &tcpci_tcpm_check_vbus_level, -#endif - .select_rp_value = &tcpci_tcpm_select_rp_value, - .set_cc = &tusb422_tcpm_set_cc, - .set_polarity = &tcpci_tcpm_set_polarity, -#ifdef CONFIG_USB_PD_DECODE_SOP - .sop_prime_enable = &tcpci_tcpm_sop_prime_enable, -#endif - .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 = &tusb422_tcpci_tcpc_alert, -#ifdef CONFIG_USB_PD_DISCHARGE_TCPC - .tcpc_discharge_vbus = &tcpci_tcpc_discharge_vbus, -#endif - .tcpc_enable_auto_discharge_disconnect = - &tcpci_tcpc_enable_auto_discharge_disconnect, -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - .drp_toggle = &tusb422_tcpc_drp_toggle, -#endif -#ifdef CONFIG_USB_PD_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 - .set_bist_test_mode = &tcpci_set_bist_test_mode, -#ifdef CONFIG_USB_PD_FRS_TCPC - .set_frs_enable = &tusb422_set_frs_enable, -#endif -}; diff --git a/driver/tcpm/tusb422.h b/driver/tcpm/tusb422.h deleted file mode 100644 index f39939b184..0000000000 --- a/driver/tcpm/tusb422.h +++ /dev/null @@ -1,22 +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 - -#include "driver/tcpm/tusb422_public.h" - -#define TUSB422_REG_VENDOR_INTERRUPTS_STATUS 0x90 -#define TUSB422_REG_VENDOR_INTERRUPTS_STATUS_FRS_RX BIT(0) - -#define TUSB422_REG_VENDOR_INTERRUPTS_MASK 0x92 -#define TUSB422_REG_VENDOR_INTERRUPTS_MASK_FRS_RX BIT(0) - -#define TUSB422_REG_PHY_BMC_RX_CTRL 0x96 -#define TUSB422_REG_PHY_BMC_RX_CTRL_FRS_RX_EN BIT(3) - -#endif /* defined(__CROS_EC_USB_PD_TCPM_TUSB422_H) */ |