summaryrefslogtreecommitdiff
path: root/driver/tcpm/rt1718s.c
diff options
context:
space:
mode:
authorJack Rosenthal <jrosenth@chromium.org>2021-11-04 12:11:58 -0600
committerCommit Bot <commit-bot@chromium.org>2021-11-05 04:22:34 +0000
commit252457d4b21f46889eebad61d4c0a65331919cec (patch)
tree01856c4d31d710b20e85a74c8d7b5836e35c3b98 /driver/tcpm/rt1718s.c
parent08f5a1e6fc2c9467230444ac9b582dcf4d9f0068 (diff)
downloadchrome-ec-stabilize-14526.67.B-ish.tar.gz
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/rt1718s.c')
-rw-r--r--driver/tcpm/rt1718s.c561
1 files changed, 0 insertions, 561 deletions
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, &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,
-};