summaryrefslogtreecommitdiff
path: root/driver/tcpm/nct38xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/tcpm/nct38xx.c')
-rw-r--r--driver/tcpm/nct38xx.c377
1 files changed, 0 insertions, 377 deletions
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, &reg));
-
- 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, &reg));
-
- /*
- * 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,
-};