summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTing Shen <phoenixshen@google.com>2021-01-20 14:21:35 +0800
committerCommit Bot <commit-bot@chromium.org>2021-06-01 10:19:48 +0000
commit6634ab0f08a6cf6bdd6cfe6031b2831811e84124 (patch)
tree3b7ce472e234c177454ea32c7e56d47cdabea212
parent1fba349593d112073a911ff3a9962f5cee7615ec (diff)
downloadchrome-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.mk2
-rw-r--r--driver/ppc/rt1718s.c172
-rw-r--r--driver/ppc/rt1718s.h17
-rw-r--r--driver/tcpm/rt1718s.c152
-rw-r--r--driver/tcpm/rt1718s.h75
-rw-r--r--include/config.h2
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, &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, &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