diff options
author | Dtrain Hsu <dtrain_hsu@compal.corp-partner.google.com> | 2022-02-10 10:33:08 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2022-02-17 11:20:41 +0000 |
commit | 55680f70d2a1e61c193fc78ff1d51c7437803683 (patch) | |
tree | e12ef58e7b092b03ac8925f2656acd612fec4239 /board/kinox/usbc_config.c | |
parent | 7e464f4acaef417e315c1d48779c2ea67b14993d (diff) | |
download | chrome-ec-stabilize-14526.73.B-main.tar.gz |
kinox: Initial EC imagestabilize-quickfix-14526.91.B-mainstabilize-14526.89.B-mainstabilize-14526.84.B-mainstabilize-14526.73.B-mainstabilize-14526.67.B-mainstabilize-14526.57.B-mainrelease-R100-14526.B-main
Create the initial EC image for the kinox variant by copying the
brask reference board EC files into a new directory named for
the variant.
(Auto-Generated by create_initial_ec_image.sh version 1.5.0).
BUG=b:215049181
BRANCH=None
TEST=make BOARD=kinox
Signed-off-by: Dtrain Hsu <dtrain_hsu@compal.corp-partner.google.com>
Change-Id: I604216664a0efc690ba9cd2c0c071a0e4650b228
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3448054
Reviewed-by: Zhuohao Lee <zhuohao@chromium.org>
Commit-Queue: Zhuohao Lee <zhuohao@chromium.org>
Diffstat (limited to 'board/kinox/usbc_config.c')
-rw-r--r-- | board/kinox/usbc_config.c | 401 |
1 files changed, 401 insertions, 0 deletions
diff --git a/board/kinox/usbc_config.c b/board/kinox/usbc_config.c new file mode 100644 index 0000000000..a245fc96ae --- /dev/null +++ b/board/kinox/usbc_config.c @@ -0,0 +1,401 @@ +/* Copyright 2022 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. + */ + +#include <stdint.h> +#include <stdbool.h> + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/retimer/kb800x.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/rt1715.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usbc_config.h" +#include "usbc_ppc.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C2_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_NO_DEBUG_ACC_CONTROL, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + }, + [USBC_PORT_C2] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C2_TCPC, + .addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C2_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_C0_C2_PPC, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux usbc0_tcss_usb_mux = { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, +}; +static const struct usb_mux usbc1_tcss_usb_mux = { + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, +}; +static const struct usb_mux usbc2_tcss_usb_mux = { + .usb_port = USBC_PORT_C2, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, +}; + +struct kb800x_control_t kb800x_control[] = { + [USBC_PORT_C0] = { + }, + [USBC_PORT_C1] = { + .retimer_rst_gpio = GPIO_USB_C1_RT_RST_R_L, + .ss_lanes = { + [KB800X_A0] = KB800X_TX0, [KB800X_A1] = KB800X_RX0, + [KB800X_B0] = KB800X_RX1, [KB800X_B1] = KB800X_TX1, + [KB800X_C0] = KB800X_RX0, [KB800X_C1] = KB800X_TX0, + [KB800X_D0] = KB800X_TX1, [KB800X_D1] = KB800X_RX1, + } + }, + [USBC_PORT_C2] = { + }, +}; +BUILD_ASSERT(ARRAY_SIZE(kb800x_control) == USBC_PORT_COUNT); + +const struct usb_mux usb_muxes[] = { + [USBC_PORT_C0] = { + .usb_port = USBC_PORT_C0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C2_MUX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + .next_mux = &usbc0_tcss_usb_mux, + }, + [USBC_PORT_C1] = { + .usb_port = USBC_PORT_C1, + .driver = &kb800x_usb_mux_driver, + .i2c_port = I2C_PORT_USB_C1_MUX, + .i2c_addr_flags = KB800X_I2C_ADDR0_FLAGS, + .next_mux = &usbc1_tcss_usb_mux, + }, + [USBC_PORT_C2] = { + .usb_port = USBC_PORT_C2, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C2_MUX, + .i2c_addr_flags = USBC_PORT_C2_BB_RETIMER_I2C_ADDR, + .next_mux = &usbc2_tcss_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C2_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_C0_C2_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_1_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/* + * USB C0 and C2 uses burnside bridge chips and have their reset + * controlled by their respective TCPC chips acting as GPIO expanders. + * + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C2_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, + [IOEX_C2_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C2_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + enum ioex_signal rst_signal; + + if (me->usb_port == USBC_PORT_C0) { + rst_signal = IOEX_USB_C0_RT_RST_ODL; + } else if (me->usb_port == USBC_PORT_C2) { + rst_signal = IOEX_USB_C2_RT_RST_ODL; + } else { + return EC_ERROR_INVAL; + } + + /* + * We do not have a load switch for the burnside bridge chips, + * so we only need to sequence reset. + */ + + if (enable) { + /* + * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + ioex_set_level(rst_signal, 1); + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + } else { + ioex_set_level(rst_signal, 0); + msleep(1); + } + return EC_SUCCESS; +} + +__override int bb_retimer_reset(const struct usb_mux *me) +{ + /* + * TODO(b/193402306, b/195375738): Remove this once transition to + * QS Silicon is complete + */ + bb_retimer_power_enable(me, false); + msleep(5); + bb_retimer_power_enable(me, true); + msleep(25); + + return EC_SUCCESS; +} + +void board_reset_pd_mcu(void) +{ + enum gpio_signal tcpc_rst; + + tcpc_rst = GPIO_USB_C0_C2_TCPC_RST_ODL; + + /* + * TODO(b/179648104): figure out correct timing + */ + + gpio_set_level(tcpc_rst, 0); + gpio_set_level(GPIO_USB_C1_RT_RST_R_L, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + + msleep(20); + + gpio_set_level(tcpc_rst, 1); + gpio_set_level(GPIO_USB_C1_RT_RST_R_L, 1); + + /* wait for chips to come up */ + + msleep(50); +} + +static void enable_ioex(int ioex) +{ + ioex_init(ioex); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) { + board_reset_pd_mcu(); + + /* + * These IO expander pins are implemented using the + * C0/C2 TCPC, so they must be set up after the TCPC has + * been taken out of reset. + */ + enable_ioex(IOEX_C0_NCT38XX); + enable_ioex(IOEX_C2_NCT38XX); + } + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_C2_TCPC_INT_ODL); + + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_C2_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0 | PD_STATUS_TCPC_ALERT_2; + + if (gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C2) + return gpio_get_level(GPIO_USB_C2_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_C2_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C2_BC12_INT_ODL: + task_set_event(TASK_ID_USB_CHG_P2, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + case GPIO_USB_C2_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C2); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} + +__override bool board_is_tbt_usb4_port(int port) +{ + return true; +} + +__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) +{ + if (!board_is_tbt_usb4_port(port)) + return TBT_SS_RES_0; + + return TBT_SS_TBT_GEN3; +} |