summaryrefslogtreecommitdiff
path: root/baseboard/honeybuns/usbc_support.c
diff options
context:
space:
mode:
Diffstat (limited to 'baseboard/honeybuns/usbc_support.c')
-rw-r--r--baseboard/honeybuns/usbc_support.c480
1 files changed, 0 insertions, 480 deletions
diff --git a/baseboard/honeybuns/usbc_support.c b/baseboard/honeybuns/usbc_support.c
deleted file mode 100644
index 4d7049ad37..0000000000
--- a/baseboard/honeybuns/usbc_support.c
+++ /dev/null
@@ -1,480 +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.
- */
-
-/* USBC functions for RO */
-
-#include "common.h"
-#include "console.h"
-#include "driver/tcpm/tcpci.h"
-#include "driver/tcpm/ps8xxx.h"
-#include "sn5s330.h"
-#include "hooks.h"
-#include "i2c.h"
-#include "system.h"
-#include "timer.h"
-#include "usb_charge.h"
-#include "usb_pd_tcpm.h"
-#include "usb_pd.h"
-#include "usbc_ppc.h"
-#include "util.h"
-#include "registers.h"
-#include "ucpd-stm32gx.h"
-
-#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args)
-
-enum usbc_states {
- UNATTACHED_SNK,
- ATTACH_WAIT_SNK,
- ATTACHED_SNK,
-};
-
-/* Variables used to manage the simple usbc state machine */
-static int usbc_port;
-static int usbc_state;
-static int usbc_vbus;
-static enum tcpc_cc_voltage_status cc1_v;
-static enum tcpc_cc_voltage_status cc2_v;
-
-__maybe_unused static __const_data const char * const usbc_state_names[] = {
- [UNATTACHED_SNK] = "Unattached.SNK",
- [ATTACH_WAIT_SNK] = "AttachWait.SNK",
- [ATTACHED_SNK] = "Attached.SNK",
-};
-
-static int read_reg(uint8_t port, int reg, int *regval)
-{
- return i2c_read8(ppc_chips[port].i2c_port,
- ppc_chips[port].i2c_addr_flags,
- reg,
- regval);
-}
-
-static int write_reg(uint8_t port, int reg, int regval)
-{
- return i2c_write8(ppc_chips[port].i2c_port,
- ppc_chips[port].i2c_addr_flags,
- reg,
- regval);
-}
-
-static int baseboard_ppc_enable_sink_path(int port)
-{
- int regval;
- int status;
- int retries;
-
- /*
- * It seems that sometimes setting the FUNC_SET1 register fails
- * initially. Therefore, we'll retry a couple of times.
- */
- retries = 0;
- do {
- status = write_reg(port, SN5S330_FUNC_SET1, SN5S330_ILIM_3_06);
- if (status) {
- retries++;
- msleep(1);
- } else {
- break;
- }
- } while (retries < 10);
-
- /* Turn off dead battery resistors, turn on CC FETs */
- status = read_reg(port, SN5S330_FUNC_SET4, &regval);
- if (!status) {
- regval |= SN5S330_CC_EN;
- status = write_reg(port, SN5S330_FUNC_SET4, regval);
- }
- if (status) {
- return status;
- }
-
- /* Enable sink path via PP2 */
- status = read_reg(port, SN5S330_FUNC_SET3, &regval);
- if (!status) {
- regval &= ~SN5S330_PP1_EN;
- regval |= SN5S330_PP2_EN;
- status = write_reg(port, SN5S330_FUNC_SET3, regval);
- }
- if (status) {
- return status;
- }
-
- return EC_SUCCESS;
-}
-
-static void baseboard_ucpd_apply_rd(int port)
-{
- uint32_t cfgr1_reg;
- uint32_t moder_reg;
- uint32_t cr;
-
- /* Ensure that clock to UCPD is enabled */
- STM32_RCC_APB1ENR2 |= STM32_RCC_APB1ENR2_UPCD1EN;
-
- /* Make sure CC1/CC2 pins PB4/PB6 are set for analog mode */
- moder_reg = STM32_GPIO_MODER(GPIO_B);
- moder_reg |= 0x3300;
- STM32_GPIO_MODER(GPIO_B) = moder_reg;
- /*
- * CFGR1 must be written when UCPD peripheral is disabled. Note that
- * disabling ucpd causes the peripheral to quit any ongoing activity and
- * sets all ucpd registers back their default values.
- */
-
- cfgr1_reg = STM32_UCPD_CFGR1_PSC_CLK_VAL(UCPD_PSC_DIV - 1) |
- STM32_UCPD_CFGR1_TRANSWIN_VAL(UCPD_TRANSWIN_CNT - 1) |
- STM32_UCPD_CFGR1_IFRGAP_VAL(UCPD_IFRGAP_CNT - 1) |
- STM32_UCPD_CFGR1_HBITCLKD_VAL(UCPD_HBIT_DIV - 1);
- STM32_UCPD_CFGR1(port) = cfgr1_reg;
-
- /* Enable ucpd */
- STM32_UCPD_CFGR1(port) |= STM32_UCPD_CFGR1_UCPDEN;
-
- /* Apply Rd to both CC lines */
- cr = STM32_UCPD_CR(port);
- cr |= STM32_UCPD_CR_ANAMODE | STM32_UCPD_CR_CCENABLE_MASK;
- STM32_UCPD_CR(port) = cr;
-
- /*
- * After exiting reset, stm32gx will have dead battery mode enabled by
- * default which connects Rd to CC1/CC2. This should be disabled when EC
- * is powered up.
- */
- STM32_PWR_CR3 |= STM32_PWR_CR3_UCPD1_DBDIS;
-}
-
-
-static void baseboard_ucpd_get_cc(int port, enum tcpc_cc_voltage_status *cc1,
- enum tcpc_cc_voltage_status *cc2)
-{
- int vstate_cc1;
- int vstate_cc2;
- int anamode;
- uint32_t sr;
-
- /*
- * cc_voltage_status is determined from vstate_cc bit field in the
- * status register. The meaning of the value vstate_cc depends on
- * current value of ANAMODE (src/snk).
- *
- * vstate_cc maps directly to cc_state from tcpci spec when ANAMODE = 1,
- * but needs to be modified slightly for case ANAMODE = 0.
- *
- * If presenting Rp (source), then need to to a circular shift of
- * vstate_ccx value:
- * vstate_cc | cc_state
- * ------------------
- * 0 -> 1
- * 1 -> 2
- * 2 -> 0
- */
-
- /* Get vstate_ccx values and power role */
- sr = STM32_UCPD_SR(port);
- /* Get Rp or Rd active */
- anamode = !!(STM32_UCPD_CR(port) & STM32_UCPD_CR_ANAMODE);
- vstate_cc1 = (sr & STM32_UCPD_SR_VSTATE_CC1_MASK) >>
- STM32_UCPD_SR_VSTATE_CC1_SHIFT;
- vstate_cc2 = (sr & STM32_UCPD_SR_VSTATE_CC2_MASK) >>
- STM32_UCPD_SR_VSTATE_CC2_SHIFT;
-
- /* Do circular shift if port == source */
- if (anamode) {
- if (vstate_cc1 != STM32_UCPD_SR_VSTATE_RA)
- vstate_cc1 += 4;
- if (vstate_cc2 != STM32_UCPD_SR_VSTATE_RA)
- vstate_cc2 += 4;
- } else {
- if (vstate_cc1 != STM32_UCPD_SR_VSTATE_OPEN)
- vstate_cc1 = (vstate_cc1 + 1) % 3;
- if (vstate_cc2 != STM32_UCPD_SR_VSTATE_OPEN)
- vstate_cc2 = (vstate_cc2 + 1) % 3;
- }
-
- *cc1 = vstate_cc1;
- *cc2 = vstate_cc2;
-}
-
-static int baseboard_rp_is_present(enum tcpc_cc_voltage_status cc1,
- enum tcpc_cc_voltage_status cc2)
-{
- return (cc1 >= TYPEC_CC_VOLT_RP_DEF || cc2 >= TYPEC_CC_VOLT_RP_DEF);
-}
-
-static void baseboard_usbc_check_connect(void);
-DECLARE_DEFERRED(baseboard_usbc_check_connect);
-
-static void baseboard_usbc_check_connect(void)
-{
- enum tcpc_cc_voltage_status cc1;
- enum tcpc_cc_voltage_status cc2;
- int ppc_reg;
- enum usbc_states enter_state = usbc_state;
-
- /*
- * In RO, the only usbc related requirement is to enable the stm32g4
- * USB-EP to be enumerated by the host attached to C0. To prevent D+
- * being pulled high prior to VBUS presence, the EC uses GPIO_BPWR_DET
- * to signal the USB hub that VBUS is present. Therefore, we need a
- * simple usbc state machine to detect an attach (Rp and VBUS) event so
- * this GPIO signal is properly controlled in RO.
- *
- * Note that RO only runs until the RWSIG timer expires and jumps to RW,
- * and in RW, the full usb-pd stack is initialized and run.
- */
-
- /* Get current CC voltage levels */
- baseboard_ucpd_get_cc(usbc_port, &cc1, &cc2);
- /* Update VBUS state */
- if (!read_reg(usbc_port, SN5S330_INT_STATUS_REG3, &ppc_reg))
- usbc_vbus = ppc_reg & SN5S330_VBUS_GOOD;
-
- switch (usbc_state) {
- case UNATTACHED_SNK:
- /*
- * Require either CC1 or CC2 to have a valid Rp CC voltage level
- * to advance to ATTACH_WAIT_SNK.
- */
- if (baseboard_rp_is_present(cc1, cc2))
- usbc_state = ATTACH_WAIT_SNK;
- break;
- case ATTACH_WAIT_SNK:
- /*
- * This state handles debounce by ensuring the CC voltages are
- * the same between two state machine iterations. If this
- * condition is met, and VBUS is present, then advance to
- * ATTACHED_SNK and set GPIO_BPWR_DET.
- *
- * If Rp voltage is no longer detected, then return to
- * UNATTACHED_SNK.
- */
- if (usbc_vbus && cc1 == cc1_v && cc2 == cc2_v) {
- usbc_state = ATTACHED_SNK;
- gpio_set_level(GPIO_BPWR_DET, 1);
- } else if (!baseboard_rp_is_present(cc1, cc2)) {
- usbc_state = UNATTACHED_SNK;
- }
- break;
- case ATTACHED_SNK:
- /*
- * In this state, only checking for VBUS going away to indicate
- * a detach event and inform the USB hub via GPIO_BPWR_DET.
- */
- if (!usbc_vbus) {
- usbc_state = UNATTACHED_SNK;
- gpio_set_level(GPIO_BPWR_DET, 0);
- }
- break;
- }
-
- /* Save CC voltage for debounce check */
- cc1_v = cc1;
- cc2_v = cc2;
-
- if (enter_state != usbc_state)
- CPRINTS("%s: cc1 = %d, cc2 = %d vbus = %d",
- usbc_state_names[usbc_state], cc1, cc2, usbc_vbus);
-
- hook_call_deferred(&baseboard_usbc_check_connect_data,
- PD_T_TRY_CC_DEBOUNCE);
-}
-
-int baseboard_usbc_init(int port)
-{
- int rv;
-
- /* Initialize ucpd and apply Rd to CC lines */
- baseboard_ucpd_apply_rd(port);
- /* Initialize ppc to enable sink path */
- rv = baseboard_ppc_enable_sink_path(port);
- if (rv)
- CPRINTS("ppc init failed!");
- /* Save host port value */
- usbc_port = port;
- /* Start RO usbc attach state machine */
- gpio_set_level(GPIO_BPWR_DET, 0);
- /* Start simple usbc state machine */
- baseboard_usbc_check_connect();
-
- return rv;
-}
-
-#ifdef SECTION_IS_RW
-int c1_ps8805_is_vbus_present(int port)
-{
- int vbus;
-
- vbus = tcpm_check_vbus_level(port, VBUS_PRESENT);
-
- return vbus;
-}
-
-int c1_ps8805_is_sourcing_vbus(int port)
-{
- int rv;
- int level;
-
- rv = ps8805_gpio_get_level(port, PS8805_GPIO_1, &level);
- if (rv)
- return 0;
-
- return level;
-}
-
-
-int c1_ps8805_vbus_source_enable(int port, int enable)
-{
-
- return ps8805_gpio_set_level(port, PS8805_GPIO_1, enable);
-}
-
-__override bool usb_ufp_check_usb3_enable(int port)
-{
- /* USB3.1 mux should be enabled based on UFP data role */
- return port == USB_PD_PORT_HOST;
-}
-
-#ifdef GPIO_USBC_UF_ATTACHED_SRC
-static int ppc_ocp_count;
-
-static void baseboard_usb3_manage_vbus(void)
-{
- int level = gpio_get_level(GPIO_USBC_UF_ATTACHED_SRC);
-
- /*
- * GPIO_USBC_UF_MUX_VBUS_EN is an output from the PS8803 which tracks if
- * C2 is attached. When it's attached, this signal will be high. Use
- * this level to control PPC VBUS on/off.
- */
- ppc_vbus_source_enable(USB_PD_PORT_USB3, level);
- CPRINTS("C2: State = %s", level ? "Attached.SRC " : "Unattached.SRC");
-
- /* Reset OCP event counter for detach */
- if (!level) {
- ppc_ocp_count = 0;
-
-#ifdef GPIO_USB_HUB_OCP_NOTIFY
- /*
- * In the case of an OCP event on this port, the usb hub should be
- * notified via a GPIO signal. Following, an OCP, the attached.src state
- * for the usb3 only port is checked again. If it's attached, then make
- * sure the OCP notify signal is reset.
- */
- gpio_set_level(GPIO_USB_HUB_OCP_NOTIFY, 1);
-#endif
- }
-}
-DECLARE_DEFERRED(baseboard_usb3_manage_vbus);
-
-void baseboard_usb3_check_state(void)
-{
- hook_call_deferred(&baseboard_usb3_manage_vbus_data, 0);
-}
-
-void baseboard_usbc_usb3_enable_interrupts(int enable)
-{
- if (enable) {
- /* Enable VBUS control interrupt for C2 */
- gpio_enable_interrupt(GPIO_USBC_UF_ATTACHED_SRC);
- /* Enable PPC interrupt */
- gpio_enable_interrupt(GPIO_USBC_UF_PPC_INT_ODL);
- } else {
- /* Disable VBUS control interrupt for C2 */
- gpio_disable_interrupt(GPIO_USBC_UF_ATTACHED_SRC);
- /* Disable PPC interrupt */
- gpio_disable_interrupt(GPIO_USBC_UF_PPC_INT_ODL);
- }
-}
-
-int baseboard_config_usbc_usb3_ppc(void)
-{
- int rv;
-
- /*
- * This port is not usb-pd capable, but there is a ppc which must be
- * initialized, and keep the VBUS switch enabled.
- */
- rv = ppc_init(USB_PD_PORT_USB3);
- if (rv)
- return rv;
-
- /* Need to set current limit to 3A to match advertised value */
- ppc_set_vbus_source_current_limit(USB_PD_PORT_USB3, TYPEC_RP_3A0);
- /* Reset OCP event counter */
- ppc_ocp_count = 0;
-
- /* Check state at init time */
- baseboard_usb3_manage_vbus();
-
- /* Enable attached.src and PPC interrupts */
- baseboard_usbc_usb3_enable_interrupts(1);
-
- return EC_SUCCESS;
-}
-
-static void baseboard_usbc_usb3_handle_interrupt(void)
-{
- int port = USB_PD_PORT_USB3;
-
- /*
- * SN5S330's /INT pin is level, so process interrupts until it
- * deasserts if the chip has a dedicated interrupt pin.
- */
- while (gpio_get_level(GPIO_USBC_UF_PPC_INT_ODL) == 0) {
- int rise = 0;
- int fall = 0;
-
- read_reg(port, SN5S330_INT_TRIP_RISE_REG1, &rise);
- read_reg(port, SN5S330_INT_TRIP_FALL_REG1, &fall);
-
- /* Notify the system about the overcurrent event. */
- if (rise & SN5S330_ILIM_PP1_MASK) {
- CPRINTS("usb3_ppc: VBUS OC!");
- gpio_set_level(GPIO_USB_HUB_OCP_NOTIFY, 0);
- if (++ppc_ocp_count < 5)
- hook_call_deferred(&baseboard_usb3_manage_vbus_data,
- USB_HUB_OCP_RESET_MSEC);
- else
- CPRINTS("usb3_ppc: VBUS OC limit reached!");
- }
-
- /* Clear the interrupt sources. */
- write_reg(port, SN5S330_INT_TRIP_RISE_REG1, rise);
- write_reg(port, SN5S330_INT_TRIP_FALL_REG1, fall);
-
- read_reg(port, SN5S330_INT_TRIP_RISE_REG2, &rise);
- read_reg(port, SN5S330_INT_TRIP_FALL_REG2, &fall);
-
- /*
- * VCONN may be latched off due to an overcurrent. Indicate
- * when the VCONN overcurrent happens.
- */
- if (rise & SN5S330_VCONN_ILIM)
- CPRINTS("usb3_ppc: VCONN OC!");
-
- /*
- * CC overvoltage event. There is not action to take here, but
- * log the event.
- */
- if (rise & SN5S330_CC1_CON || rise & SN5S330_CC2_CON)
- CPRINTS("usb3_ppc: CC OV!");
-
- /* Clear the interrupt sources. */
- write_reg(port, SN5S330_INT_TRIP_RISE_REG2, rise);
- write_reg(port, SN5S330_INT_TRIP_FALL_REG2, fall);
-
- }
-}
-DECLARE_DEFERRED(baseboard_usbc_usb3_handle_interrupt);
-
-void baseboard_usbc_usb3_irq(void)
-{
- hook_call_deferred(&baseboard_usbc_usb3_handle_interrupt_data, 0);
-}
-
-#endif /* defined(GPIO_USBC_UF_ATTACHED_SRC) */
-#endif /* defined(SECTION_IS_RW) */
-