diff options
author | Ting Shen <phoenixshen@google.com> | 2021-01-20 14:21:35 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-06-01 10:19:48 +0000 |
commit | 6634ab0f08a6cf6bdd6cfe6031b2831811e84124 (patch) | |
tree | 3b7ce472e234c177454ea32c7e56d47cdabea212 | |
parent | 1fba349593d112073a911ff3a9962f5cee7615ec (diff) | |
download | chrome-ec-6634ab0f08a6cf6bdd6cfe6031b2831811e84124.tar.gz |
driver/tcpc: implement rt1718s tcpc/ppc driver
BUG=b:177391887
TEST=none
BRANCH=main
Signed-off-by: Ting Shen <phoenixshen@google.com>
Change-Id: I8f017e21b74c1e27ca7f257b76b0ef74fd0343f2
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2639734
Reviewed-by: Eric Yilun Lin <yllin@google.com>
Tested-by: Ting Shen <phoenixshen@chromium.org>
Commit-Queue: Ting Shen <phoenixshen@chromium.org>
-rw-r--r-- | driver/build.mk | 2 | ||||
-rw-r--r-- | driver/ppc/rt1718s.c | 172 | ||||
-rw-r--r-- | driver/ppc/rt1718s.h | 17 | ||||
-rw-r--r-- | driver/tcpm/rt1718s.c | 152 | ||||
-rw-r--r-- | driver/tcpm/rt1718s.h | 75 | ||||
-rw-r--r-- | include/config.h | 2 |
6 files changed, 420 insertions, 0 deletions
diff --git a/driver/build.mk b/driver/build.mk index 93536b76f7..dd57ef69e4 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -154,6 +154,7 @@ driver-$(CONFIG_USB_PD_TCPM_PS8805)+=tcpm/ps8xxx.o driver-$(CONFIG_USB_PD_TCPM_PS8815)+=tcpm/ps8xxx.o driver-$(CONFIG_USB_PD_TCPM_TUSB422)+=tcpm/tusb422.o driver-$(CONFIG_USB_PD_TCPM_RT1715)+=tcpm/rt1715.o +driver-$(CONFIG_USB_PD_TCPM_RT1718S)+=tcpm/rt1718s.o driver-$(CONFIG_USB_PD_TCPM_NCT38XX)+=tcpm/nct38xx.o driver-$(CONFIG_USB_PD_TCPM_RAA489000)+=tcpm/raa489000.o driver-$(CONFIG_USB_PD_TCPM_FUSB307)+=tcpm/fusb307.o @@ -192,6 +193,7 @@ driver-$(CONFIG_USB_HUB_GL3590)+=gl3590.o # Type-C Power Path Controllers (PPC) driver-$(CONFIG_USBC_PPC_AOZ1380)+=ppc/aoz1380.o +driver-$(CONFIG_USBC_PPC_RT1718S)+=ppc/rt1718s.o driver-$(CONFIG_USBC_PPC_SN5S330)+=ppc/sn5s330.o ifeq ($(CONFIG_USBC_PPC_NX20P3481)$(CONFIG_USBC_PPC_NX20P3483),y) driver-y += ppc/nx20p348x.o diff --git a/driver/ppc/rt1718s.c b/driver/ppc/rt1718s.c new file mode 100644 index 0000000000..3701eaf27e --- /dev/null +++ b/driver/ppc/rt1718s.c @@ -0,0 +1,172 @@ +/* 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 RT1718S USB-C Power Path Controller */ +#include "atomic.h" +#include "common.h" +#include "config.h" +#include "console.h" +#include "driver/ppc/rt1718s.h" +#include "driver/tcpm/tcpci.h" +#include "usbc_ppc.h" +#include "util.h" + + +#define RT1718S_FLAGS_SOURCE_ENABLED BIT(0) +static atomic_t flags[CONFIG_USB_PD_PORT_MAX_COUNT]; + +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) + +static int read_reg(uint8_t port, int reg, int *val) +{ + if (reg > 0xFF) { + return i2c_read_offset16( + ppc_chips[port].i2c_port, + ppc_chips[port].i2c_addr_flags, + reg, val, 1); + } else { + return i2c_read8( + ppc_chips[port].i2c_port, + ppc_chips[port].i2c_addr_flags, + reg, val); + } +} + +static int write_reg(uint8_t port, int reg, int val) +{ + if (reg > 0xFF) { + return i2c_write_offset16( + ppc_chips[port].i2c_port, + ppc_chips[port].i2c_addr_flags, + reg, val, 1); + } else { + return i2c_write8( + ppc_chips[port].i2c_port, + ppc_chips[port].i2c_addr_flags, + reg, val); + } +} + +static int update_bits(int port, int reg, int mask, int val) +{ + int reg_val; + + if (mask == 0xFF) + return write_reg(port, reg, val); + + RETURN_ERROR(read_reg(port, reg, ®_val)); + + reg_val &= (~mask); + reg_val |= (mask & val); + return write_reg(port, reg, reg_val); +} + +static int rt1718s_is_sourcing_vbus(int port) +{ + return (flags[port] & RT1718S_FLAGS_SOURCE_ENABLED); +} + +static int rt1718s_vbus_source_enable(int port, int enable) +{ + if (enable) + atomic_or(&flags[port], RT1718S_FLAGS_SOURCE_ENABLED); + else + atomic_clear_bits(&flags[port], RT1718S_FLAGS_SOURCE_ENABLED); + + return tcpm_set_src_ctrl(port, enable); +} + +static int rt1718s_vbus_sink_enable(int port, int enable) +{ + return tcpm_set_snk_ctrl(port, enable); +} + +static int rt1718s_discharge_vbus(int port, int enable) +{ + return update_bits(port, + TCPC_REG_POWER_CTRL, + TCPC_REG_POWER_CTRL_FORCE_DISCHARGE, + enable ? 0xFF : 0x00); +} + +#ifdef CONFIG_CMD_PPC_DUMP +static int rt1718s_dump(int port) +{ + for (int i = 0; i <= 0xEF; i++) { + int val = 0; + int rt = read_reg(port, i, &val); + + if (i % 16 == 0) + CPRINTF("%02X: ", i); + if (rt) + CPRINTF("-- "); + else + CPRINTF("%02X ", val); + if (i % 16 == 15) + CPRINTF("\n"); + } + for (int i = 0xF200; i <= 0xF2CF; i++) { + int val = 0; + int rt = read_reg(port, i, &val); + + if (i % 16 == 0) + CPRINTF("%04X: ", i); + if (rt) + CPRINTF("-- "); + else + CPRINTF("%02X ", val); + if (i % 16 == 15) + CPRINTF("\n"); + } + + return EC_SUCCESS; +} +#endif /* defined(CONFIG_CMD_PPC_DUMP) */ + +#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC +static int rt1718s_is_vbus_present(int port) +{ + int status; + int rv = read_reg(port, TCPC_REG_POWER_STATUS, &status); + + return (rv == 0) && (status & TCPC_REG_POWER_STATUS_VBUS_PRES); +} +#endif + +static int rt1718s_init(int port) +{ + atomic_clear(&flags[port]); + + return EC_SUCCESS; +} + +#ifdef CONFIG_USBC_PPC_POLARITY +static int rt1718s_set_polarity(int port, int polarity) +{ + return tcpci_tcpm_set_polarity(port, polarity); +} +#endif + +const struct ppc_drv rt1718s_ppc_drv = { + .init = &rt1718s_init, + .is_sourcing_vbus = &rt1718s_is_sourcing_vbus, + .vbus_sink_enable = &rt1718s_vbus_sink_enable, + .vbus_source_enable = &rt1718s_vbus_source_enable, +#ifdef CONFIG_CMD_PPC_DUMP + .reg_dump = &rt1718s_dump, +#endif /* defined(CONFIG_CMD_PPC_DUMP) */ + +#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC + .is_vbus_present = &rt1718s_is_vbus_present, +#endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */ + .discharge_vbus = &rt1718s_discharge_vbus, +#ifdef CONFIG_USBC_PPC_POLARITY + .set_polarity = &rt1718s_set_polarity, +#endif +#ifdef CONFIG_USBC_PPC_VCONN + .set_vconn = &tcpci_tcpm_set_vconn, +#endif +}; diff --git a/driver/ppc/rt1718s.h b/driver/ppc/rt1718s.h new file mode 100644 index 0000000000..f692bf3dd4 --- /dev/null +++ b/driver/ppc/rt1718s.h @@ -0,0 +1,17 @@ +/* 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 RT1718S Type-C Power Path Controller */ + +#ifndef __CROS_EC_PPC_RT1718S_H +#define __CROS_EC_PPC_RT1718S_H + +#include "driver/tcpm/rt1718s.h" +#include "usbc_ppc.h" + +extern const struct ppc_drv rt1718s_ppc_drv; + +#endif /* defined(__CROS_EC_PPC_RT1718S_H) */ + diff --git a/driver/tcpm/rt1718s.c b/driver/tcpm/rt1718s.c new file mode 100644 index 0000000000..3c2e6e6c0b --- /dev/null +++ b/driver/tcpm/rt1718s.c @@ -0,0 +1,152 @@ +/* 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. */ +int rt1718s_write8(int port, int reg, int val) +{ + if (reg > 0xFF) { + return i2c_write_offset16( + tcpc_config[port].i2c_info.port, + tcpc_config[port].i2c_info.addr_flags, + reg, val, 1); + } + return tcpc_write(port, reg, val); +} + +int rt1718s_read8(int port, int reg, int *val) +{ + if (reg > 0xFF) { + return i2c_read_offset16( + tcpc_config[port].i2c_info.port, + tcpc_config[port].i2c_info.addr_flags, + reg, val, 1); + } + return tcpc_read(port, reg, val); +} + +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); +} + +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; +} + +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; + } + + if (IS_ENABLED(CONFIG_USB_PD_FRS_TCPC)) + /* Set vbus frs low unmasked, Rx frs unmasked */ + RETURN_ERROR(rt1718s_update_bits8(port, RT1718S_RT_MASK1, + RT1718S_RT_MASK1_M_VBUS_FRS_LOW | + RT1718S_RT_MASK1_M_RX_FRS, + 0xFF)); + + + /* 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(board_rt1718s_init(port)); + + return EC_SUCCESS; +} + +__overridable int board_rt1718s_init(int port) +{ + return EC_SUCCESS; +} + +/* 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 = &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 = &tcpci_enter_low_power_mode, +#endif +}; diff --git a/driver/tcpm/rt1718s.h b/driver/tcpm/rt1718s.h new file mode 100644 index 0000000000..0f868f0598 --- /dev/null +++ b/driver/tcpm/rt1718s.h @@ -0,0 +1,75 @@ +/* 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 "usb_pd_tcpm.h" + +/* RT1718S Private RegMap */ +#define RT1718S_SLAVE_ADDR_FLAGS 0x43 + +#define RT1718S_VID 0x29CF +#define RT1718S_PID 0x1718 + +#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_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_MASK7 0x97 + +#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_DIS_SRC_VBUS_CTRL 0xE0 +#define RT1718S_ENA_SRC_VBUS_CTRL 0xE1 +#define RT1718S_FAULT_OC1_VBUS_CTRL 0xE3 +#define RT1718S_GPIO2_VBUS_CTRL 0xEB +#define RT1718S_GPIO1_CTRL 0xED +#define RT1718S_GPIO2_CTRL 0xEE + +#define RT1718S_UNLOCK_PW_2 0xF0 +#define RT1718S_UNLOCK_PW_1 0xF1 + +#define RT1718S_RT2_SYS_CTRL5 0xF210 +#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 + +extern const struct tcpm_drv rt1718s_tcpm_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); +__override_proto int board_rt1718s_init(int port); + +#endif /* __CROS_EC_USB_PD_TCPM_MT6370_H */ diff --git a/include/config.h b/include/config.h index e0d7edc32b..5a1e3336a4 100644 --- a/include/config.h +++ b/include/config.h @@ -4453,6 +4453,7 @@ #undef CONFIG_USB_PD_TCPM_TUSB422 #undef CONFIG_USB_PD_TCPM_RAA489000 #undef CONFIG_USB_PD_TCPM_RT1715 +#undef CONFIG_USB_PD_TCPM_RT1718S #undef CONFIG_USB_PD_TCPM_FUSB307 #undef CONFIG_USB_PD_TCPM_STM32GX #undef CONFIG_USB_PD_TCPM_CCGXXF @@ -4671,6 +4672,7 @@ #undef CONFIG_USBC_PPC_AOZ1380 #undef CONFIG_USBC_PPC_NX20P3481 #undef CONFIG_USBC_PPC_NX20P3483 +#undef CONFIG_USBC_PPC_RT1718S #undef CONFIG_USBC_PPC_SN5S330 #undef CONFIG_USBC_PPC_SYV682C #undef CONFIG_USBC_PPC_SYV682X |