diff options
author | Scott Collyer <scollyer@google.com> | 2022-07-30 17:04:09 -0700 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-08-04 16:07:58 +0000 |
commit | fd17e4661220def8023e64d62d3d052da1ccb835 (patch) | |
tree | 3794536d0fc08d5d90da5f7c915c079ebd83105b | |
parent | 42d2e470451d10420f70cb263377cc5ebaab02f9 (diff) | |
download | chrome-ec-fd17e4661220def8023e64d62d3d052da1ccb835.tar.gz |
rex: Add support for battery/charging/USBC port 0
This CL adds config options and dts info for battery and charging. In
addition, this CL adds support for USBC port 0.
Charging depends on battery and there is also a dependency on USBC
support, so this blocks must be added together.
BRANCH=none
BUG=b:240434243
TEST=zmake build rex
Signed-off-by: Scott Collyer <scollyer@google.com>
Change-Id: I180dd01f4b1b6e05a83677c9e5adc59829035c5c
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3803584
Reviewed-by: Fabio Baltieri <fabiobaltieri@google.com>
Commit-Queue: Scott Collyer <scollyer@chromium.org>
Tested-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Vijay P Hiremath <vijay.p.hiremath@intel.com>
-rw-r--r-- | zephyr/projects/rex/BUILD.py | 2 | ||||
-rw-r--r-- | zephyr/projects/rex/CMakeLists.txt | 3 | ||||
-rw-r--r-- | zephyr/projects/rex/battery.dts | 12 | ||||
-rw-r--r-- | zephyr/projects/rex/generated.dts | 3 | ||||
-rw-r--r-- | zephyr/projects/rex/interrupts.dts | 20 | ||||
-rw-r--r-- | zephyr/projects/rex/prj.conf | 46 | ||||
-rw-r--r-- | zephyr/projects/rex/rex.dts | 64 | ||||
-rw-r--r-- | zephyr/projects/rex/src/usb_pd_policy.c | 77 | ||||
-rw-r--r-- | zephyr/projects/rex/src/usbc_config.c | 287 | ||||
-rw-r--r-- | zephyr/projects/rex/usbc.dts | 51 |
10 files changed, 556 insertions, 9 deletions
diff --git a/zephyr/projects/rex/BUILD.py b/zephyr/projects/rex/BUILD.py index 10abc7d3be..e19e46fc49 100644 --- a/zephyr/projects/rex/BUILD.py +++ b/zephyr/projects/rex/BUILD.py @@ -33,6 +33,8 @@ register_variant( here / "generated.dts", here / "interrupts.dts", here / "power_signals.dts", + here / "battery.dts", + here / "usbc.dts", ], extra_kconfig_files=[here / "prj_rex.conf"], ) diff --git a/zephyr/projects/rex/CMakeLists.txt b/zephyr/projects/rex/CMakeLists.txt index b724145961..469d8c918c 100644 --- a/zephyr/projects/rex/CMakeLists.txt +++ b/zephyr/projects/rex/CMakeLists.txt @@ -8,4 +8,5 @@ project(rex) zephyr_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include") zephyr_library_sources_ifdef(CONFIG_AP_PWRSEQ "src/board_power.c") - +zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_USBC "src/usbc_config.c") +zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_USBC "src/usb_pd_policy.c") diff --git a/zephyr/projects/rex/battery.dts b/zephyr/projects/rex/battery.dts new file mode 100644 index 0000000000..5dee2e4578 --- /dev/null +++ b/zephyr/projects/rex/battery.dts @@ -0,0 +1,12 @@ +/* Copyright 2022 The ChromiumOS Authors. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/ { + batteries { + default_battery: batgqa05l22 { + compatible = "powertech,batgqa05l22", "battery-smart"; + }; + }; +}; diff --git a/zephyr/projects/rex/generated.dts b/zephyr/projects/rex/generated.dts index c156892565..5d1c6e3eb8 100644 --- a/zephyr/projects/rex/generated.dts +++ b/zephyr/projects/rex/generated.dts @@ -156,9 +156,11 @@ }; gpio_usb_c0_bc12_int_odl: usb_c0_bc12_int_odl { gpios = <&gpioc 6 GPIO_INPUT>; + enum-name = "GPIO_USB_C0_BC12_INT_ODL"; }; gpio_usb_c0_ppc_int_odl: usb_c0_ppc_int_odl { gpios = <&gpio6 2 GPIO_INPUT>; + enum-name = "GPIO_USB_C0_PPC_INT_ODL"; }; gpio_usb_c0_rt_3p3_sx_en: usb_c0_rt_3p3_sx_en { gpios = <&gpio0 3 GPIO_ODR_HIGH>; @@ -168,6 +170,7 @@ }; gpio_usb_c0_tcpc_int_odl: usb_c0_tcpc_int_odl { gpios = <&gpioe 0 GPIO_INPUT>; + enum-name = "GPIO_USB_C0_TCPC_INT_ODL"; }; gpio_usb_c0_tcpc_rst_odl: usb_c0_tcpc_rst_odl { gpios = <&gpio6 7 GPIO_ODR_LOW>; diff --git a/zephyr/projects/rex/interrupts.dts b/zephyr/projects/rex/interrupts.dts index ae05c51335..5444bcfd06 100644 --- a/zephyr/projects/rex/interrupts.dts +++ b/zephyr/projects/rex/interrupts.dts @@ -22,6 +22,26 @@ flags = <GPIO_INT_EDGE_BOTH>; handler = "lid_interrupt"; }; + int_usb_c0_sbu_fault: c0_sbu_fault { + irq-pin = <&ioex_usb_c0_sbu_fault_odl>; + flags = <GPIO_INT_EDGE_FALLING>; + handler = "sbu_fault_interrupt"; + }; + int_usb_c0_tcpc: usb_c0_tcpc { + irq-pin = <&gpio_usb_c0_tcpc_int_odl>; + flags = <GPIO_INT_EDGE_FALLING>; + handler = "tcpc_alert_event"; + }; + int_usb_c0_ppc: usb_c0_ppc { + irq-pin = <&gpio_usb_c0_ppc_int_odl>; + flags = <GPIO_INT_EDGE_FALLING>; + handler = "ppc_interrupt"; + }; + int_usb_c0_bc12: usb_c0_bc12 { + irq-pin = <&gpio_usb_c0_bc12_int_odl>; + flags = <GPIO_INT_EDGE_FALLING>; + handler = "bc12_interrupt"; + }; }; }; diff --git a/zephyr/projects/rex/prj.conf b/zephyr/projects/rex/prj.conf index f7f00a82d3..116272ba5d 100644 --- a/zephyr/projects/rex/prj.conf +++ b/zephyr/projects/rex/prj.conf @@ -53,6 +53,52 @@ CONFIG_ADC=y # I2C CONFIG_I2C=y +# Battery +CONFIG_PLATFORM_EC_BATTERY=y +CONFIG_PLATFORM_EC_BATTERY_SMART=y +CONFIG_PLATFORM_EC_BATTERY_FUEL_GAUGE=y +CONFIG_PLATFORM_EC_BATTERY_CUT_OFF=y +CONFIG_PLATFORM_EC_BATTERY_PRESENT_GPIO=y +CONFIG_PLATFORM_EC_BATTERY_REVIVE_DISCONNECT=y + +# Charger +CONFIG_PLATFORM_EC_CHARGER_DISCHARGE_ON_AC=y +CONFIG_PLATFORM_EC_CHARGER_INPUT_CURRENT=512 +CONFIG_PLATFORM_EC_CHARGER_ISL9241=y +CONFIG_PLATFORM_EC_CHARGER_SENSE_RESISTOR=5 +CONFIG_PLATFORM_EC_CHARGER_SENSE_RESISTOR_AC=10 +CONFIG_PLATFORM_EC_CHARGER_MIN_POWER_MW_FOR_POWER_ON=30000 +CONFIG_PLATFORM_EC_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT=15000 + +# USBC +CONFIG_PLATFORM_EC_USBC_PPC=y +CONFIG_PLATFORM_EC_USBC_PPC_SYV682X=y +CONFIG_PLATFORM_EC_USBC_PPC_SYV682C=y + +CONFIG_PLATFORM_EC_USB_DRP_ACC_TRYSRC=y +CONFIG_PLATFORM_EC_USB_PD_VBUS_DETECT_TCPC=y +CONFIG_PLATFORM_EC_USB_PD_DISCHARGE_PPC=y +CONFIG_PLATFORM_EC_USB_PD_DISCHARGE_TCPC=y +CONFIG_PLATFORM_EC_USB_PD_FRS=y +CONFIG_PLATFORM_EC_USB_PD_TCPC_LOW_POWER=y +CONFIG_PLATFORM_EC_USB_PD_TCPM_TCPCI=y +CONFIG_PLATFORM_EC_USB_PD_TCPM_NCT38XX=y +CONFIG_PLATFORM_EC_USB_PD_TRY_SRC=y +CONFIG_PLATFORM_EC_USB_PD_TCPM_SBU=y +CONFIG_PLATFORM_EC_USB_PD_DUAL_ROLE_AUTO_TOGGLE=y +CONFIG_PLATFORM_EC_USBC_RETIMER_INTEL_HB=y +CONFIG_PLATFORM_EC_USBC_VCONN=y +CONFIG_PLATFORM_EC_USB_PD_TBT_COMPAT_MODE=y +CONFIG_PLATFORM_EC_USB_PD_VBUS_MEASURE_CHARGER=y +CONFIG_PLATFORM_EC_USB_PID=0x504D + +# BC 1.2 +CONFIG_PLATFORM_EC_BC12_DETECT_PI3USB9201=y + +#USB Mux +CONFIG_PLATFORM_EC_USB_MUX_VIRTUAL=y +CONFIG_PLATFORM_EC_USB_MUX_TASK=y + # External power CONFIG_PLATFORM_EC_EXTPOWER_GPIO=y diff --git a/zephyr/projects/rex/rex.dts b/zephyr/projects/rex/rex.dts index cc5a4d8efe..6876113731 100644 --- a/zephyr/projects/rex/rex.dts +++ b/zephyr/projects/rex/rex.dts @@ -14,10 +14,16 @@ ec_wp_l: write-protect { gpios = <&gpioa 0 GPIO_INPUT>; }; - gpio_ec_entering_rw: ec_entering_rw { enum-name = "GPIO_ENTERING_RW"; }; + + ioex_usb_c0_sbu_fault_odl: usb_c0_sbu_fault_odl { + gpios = <&ioex_c0_port1 2 GPIO_INPUT>; + }; + ioex_usb_c0_rt_rst_ls_l: usb_c0_rt_rst_ls_l { + gpios = <&ioex_c0_port0 7 GPIO_OUTPUT>; + }; }; }; @@ -52,15 +58,57 @@ }; &i2c1_0 { - label = "I2C_PORT_USB_C0_TCPC"; + label = "I2C_USB_C0_TCPC"; clock-frequency = <I2C_BITRATE_FAST>; pinctrl-0 = <&i2c1_0_sda_scl_gp87_90>; pinctrl-names = "default"; + + bc12_port0: pi3usb9201@5f { + compatible = "pericom,pi3usb9201"; + status = "okay"; + reg = <0x5f>; + irq = <&int_usb_c0_bc12>; + }; + + nct3807_C0:nct3807_C0@70 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nuvoton,nct38xx-gpio"; + reg = <0x70>; + label = "NCT3807_C0"; + + ioex_c0_port0:gpio@0 { + compatible = "nuvoton,nct38xx-gpio-port"; + reg = <0x0>; + label = "NCT3807_C0_GPIO0"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + pin_mask = <0xff>; + pinmux_mask = <0xf7>; + }; + ioex_c0_port1:gpio@1 { + compatible = "nuvoton,nct38xx-gpio-port"; + reg = <0x1>; + label = "NCT3807_C0_GPIO1"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + pin_mask = <0xff>; + }; + }; + + nct3808_alert_0 { + compatible = "nuvoton,nct38xx-gpio-alert"; + irq-gpios = <&gpioe 0 GPIO_ACTIVE_LOW>; + nct38xx-dev = <&nct3807_C0>; + label = "NCT3807_ALERT_0"; + }; }; &i2c2_0 { - label = "I2C_PORT_PPC0"; + label = "I2C_PPC0"; clock-frequency = <I2C_BITRATE_FAST>; pinctrl-0 = <&i2c2_0_sda_scl_gp91_92>; @@ -68,7 +116,7 @@ }; &i2c3_0 { - label = "I2C_PORT_USB_C0_C2_MUX"; + label = "I2C_USB_C0_C2_MUX"; clock-frequency = <I2C_BITRATE_FAST>; pinctrl-0 = <&i2c3_0_sda_scl_gpd0_d1>; @@ -76,7 +124,7 @@ }; &i2c4_1 { - label = "I2C_PORT_USB_C1_TCPC"; + label = "I2_USB_C1_TCPC"; clock-frequency = <I2C_BITRATE_FAST>; pinctrl-0 = <&i2c4_1_sda_scl_gpf2_f3>; @@ -84,7 +132,7 @@ }; &i2c5_0 { - label = "I2C_PORT_BATTERY"; + label = "I2C__BATTERY"; clock-frequency = <I2C_BITRATE_FAST>; pinctrl-0 = <&i2c5_0_sda_scl_gp33_36>; @@ -92,7 +140,7 @@ }; &i2c6_1 { - label = "I2C_PORT_USB_1_MIX"; + label = "I2C_USB_1_MIX"; clock-frequency = <I2C_BITRATE_FAST>; pinctrl-0 = <&i2c6_1_sda_scl_gpe3_e4>; @@ -100,7 +148,7 @@ }; &i2c7_0 { - label = "I2C_PORT_CHARGER"; + label = "I2C_CHARGER"; clock-frequency = <I2C_BITRATE_FAST>; pinctrl-0 = <&i2c7_0_sda_scl_gpb2_b3>; diff --git a/zephyr/projects/rex/src/usb_pd_policy.c b/zephyr/projects/rex/src/usb_pd_policy.c new file mode 100644 index 0000000000..b61fcd6b70 --- /dev/null +++ b/zephyr/projects/rex/src/usb_pd_policy.c @@ -0,0 +1,77 @@ +/* Copyright 2022 The ChromiumOS Authors. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Shared USB-C policy for Rex boards */ + +#include <zephyr/drivers/gpio.h> + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "ec_commands.h" +#include "ioexpander.h" +#include "system.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on. */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS. */ + ppc_vbus_source_enable(port, 0); + + /* Enable discharge if we were previously sourcing 5V */ + if (IS_ENABLED(CONFIG_USB_PD_DISCHARGE)) + pd_set_vbus_discharge(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + /* Disable charging. */ + rv = ppc_vbus_sink_enable(port, 0); + if (rv) + return rv; + + if (IS_ENABLED(CONFIG_USB_PD_DISCHARGE)) { + pd_set_vbus_discharge(port, 0); + } + + /* Provide Vbus. */ + rv = ppc_vbus_source_enable(port, 1); + if (rv) { + return rv; + } + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +/* Used by Vbus discharge common code with CONFIG_USB_PD_DISCHARGE */ +int board_vbus_source_enabled(int port) +{ + return tcpm_get_src_ctrl(port); +} + +/* Used by USB charger task with CONFIG_USB_PD_5V_EN_CUSTOM */ +int board_is_sourcing_vbus(int port) +{ + return board_vbus_source_enabled(port); +} diff --git a/zephyr/projects/rex/src/usbc_config.c b/zephyr/projects/rex/src/usbc_config.c new file mode 100644 index 0000000000..358beea385 --- /dev/null +++ b/zephyr/projects/rex/src/usbc_config.c @@ -0,0 +1,287 @@ +/* Copyright 2022 The ChromiumOS Authors. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <zephyr/drivers/gpio.h> + +#include "battery_fuel_gauge.h" +#include "charger.h" +#include "charge_manager.h" +#include "charge_ramp.h" +#include "charge_state_v2.h" +#include "charge_state.h" +#include "charger.h" +#include "driver/charger/isl9241.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/tcpci.h" +#include "gpio/gpio_int.h" +#include "hooks.h" +#include "i2c.h" +#include "ioexpander.h" +#include "ppc/syv682x_public.h" +#include "system.h" +#include "task.h" +#include "usb_mux.h" +#include "usbc_ppc.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/*******************************************************************/ +/* USB-C Configuration Start */ +#define GPIO_USB_C0_TCPC_INT_NODE \ + GPIO_DT_FROM_NODELABEL(gpio_usb_c0_tcpc_int_odl) +#define GPIO_USB_C0_TCPC_RST_NODE \ + GPIO_DT_FROM_NODELABEL(gpio_usb_c0_tcpc_rst_odl) + +/* USB-C ports */ +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_COUNT }; +BUILD_ASSERT(USBC_PORT_COUNT == CONFIG_USB_PD_PORT_MAX_COUNT); + +static void usbc_interrupt_init(void) +{ + /* Enable PPC interrupts. */ + gpio_enable_dt_interrupt(GPIO_INT_FROM_NODELABEL(int_usb_c0_ppc)); + + /* Enable TCPC interrupts. */ + gpio_enable_dt_interrupt(GPIO_INT_FROM_NODELABEL(int_usb_c0_tcpc)); + + /* Enable BC 1.2 interrupts */ + gpio_enable_dt_interrupt(GPIO_INT_FROM_NODELABEL(int_usb_c0_bc12)); + + /* Enable SBU fault interrupts */ + gpio_enable_dt_interrupt(GPIO_INT_FROM_NODELABEL(int_usb_c0_sbu_fault)); +} +DECLARE_HOOK(HOOK_INIT, usbc_interrupt_init, HOOK_PRIO_POST_I2C); + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* + * TODO: Meteorlake PCH does not use Physical GPIO for over current + * error, hence Send 'Over Current Virtual Wire' eSPI signal. + */ +} + +void sbu_fault_interrupt(enum gpio_signal signal) +{ + int port = USBC_PORT_C0; + + CPRINTSUSB("C%d: SBU fault", port); + pd_handle_overcurrent(port); +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + int port; + + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + port = 0; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} + +static void reset_nct38xx_port(int port) +{ + const struct gpio_dt_spec *reset_gpio_l; + const struct device *ioex_port0, *ioex_port1; + + /* TODO(b/225189538): Save and restore ioex signals */ + if (port == USBC_PORT_C0) { + reset_gpio_l = GPIO_DT_FROM_NODELABEL(gpio_usb_c0_tcpc_rst_odl); + ioex_port0 = DEVICE_DT_GET(DT_NODELABEL(ioex_c0_port0)); + ioex_port1 = DEVICE_DT_GET(DT_NODELABEL(ioex_c0_port1)); + } else { + /* Invalid port: do nothing */ + return; + } + + gpio_pin_set_dt(reset_gpio_l, 0); + msleep(NCT38XX_RESET_HOLD_DELAY_MS); + gpio_pin_set_dt(reset_gpio_l, 1); + nct38xx_reset_notify(port); + if (NCT3807_RESET_POST_DELAY_MS != 0) { + msleep(NCT3807_RESET_POST_DELAY_MS); + } + + /* Re-enable the IO expander pins */ + gpio_reset_port(ioex_port0); + gpio_reset_port(ioex_port1); +} + +void board_reset_pd_mcu(void) +{ + /* Reset TCPC0 */ + reset_nct38xx_port(USBC_PORT_C0); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + /* + * Check which port has the ALERT line set and ignore if that TCPC has + * its reset line active. + */ + if (!GPIO_USB_C0_TCPC_INT_NODE && GPIO_USB_C0_TCPC_RST_NODE) { + status |= PD_STATUS_TCPC_ALERT_0; + } + + return status; +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + + default: + break; + } +} + +void board_set_charge_limit(int port, int supplier, int charge_ma, int max_ma, + int charge_mv) +{ + charge_set_input_current_limit( + MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT), charge_mv); +} + +static void board_disable_charger_ports(void) +{ + int i; + + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * If this port had booted in dead battery mode, go + * ahead and reset it so EN_SNK responds properly. + */ + if (nct38xx_get_boot_type(i) == NCT38XX_BOOT_DEAD_BATTERY) { + reset_nct38xx_port(i); + pd_set_error_recovery(i); + } + + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) { + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + } +} + +int board_set_active_charge_port(int port) +{ + int is_valid_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + int rv; + + if (port == CHARGE_PORT_NONE) { + board_disable_charger_ports(); + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* + * Check if we can reset any ports in dead battery mode + * + * The NCT3807 may continue to keep EN_SNK low on the dead battery port + * and allow a dangerous level of voltage to pass through to the initial + * charge port (see b/183660105). We must reset the ports if we have + * sufficient battery to do so, which will bring EN_SNK back under + * normal control. + */ + rv = EC_SUCCESS; + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + if (nct38xx_get_boot_type(i) != NCT38XX_BOOT_DEAD_BATTERY) { + continue; + } + + /* Handle dead battery boot case */ + CPRINTSUSB("Found dead battery on %d", i); + /* + * If we have battery, get this port reset ASAP. + * This means temporarily rejecting charge manager + * sets to it. + */ + if (pd_is_battery_capable()) { + reset_nct38xx_port(i); + pd_set_error_recovery(i); + + if (port == i) { + rv = EC_ERROR_INVAL; + } + } else if (port != i) { + /* + * If other port is selected and in dead battery + * mode, reset this port. Otherwise, reject + * change because we'll brown out. + */ + if (nct38xx_get_boot_type(port) == + NCT38XX_BOOT_DEAD_BATTERY) { + reset_nct38xx_port(i); + pd_set_error_recovery(i); + } else { + rv = EC_ERROR_INVAL; + } + } + } + + if (rv != EC_SUCCESS) { + return rv; + } + + /* Check if the port is sourcing VBUS. */ + if (tcpm_get_src_ctrl(port)) { + CPRINTSUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) { + continue; + } + if (ppc_vbus_sink_enable(i, 0)) { + CPRINTSUSB("C%d: sink path disable failed.", i); + } + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/zephyr/projects/rex/usbc.dts b/zephyr/projects/rex/usbc.dts new file mode 100644 index 0000000000..2657fc81b7 --- /dev/null +++ b/zephyr/projects/rex/usbc.dts @@ -0,0 +1,51 @@ +/* Copyright 2022 The ChromiumOS Authors. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + #include <dt-bindings/usb_pd_tcpm.h> + +/ { + usbc { + #address-cells = <1>; + #size-cells = <0>; + + usbc_port0: port0@0 { + compatible = "named-usbc-port"; + reg = <0>; + bc12 = <&i2c_ec_i2c_usb_c0_ppc_b>; + ppc_port0_syv: ppc-port0 { + compatible = "silergy,syv682x"; + status = "okay"; + port = <&i2c_ec_i2c_usb_c0_ppc_b>; + i2c-addr-flags = "SYV682X_ADDR1_FLAGS"; + }; + tcpc { + compatible = "nuvoton,nct38xx"; + gpio-dev = <&nct3807_C0>; + port = <&i2c_ec_i2c_usb_c0_tcp>; + i2c-addr-flags = "NCT38XX_I2C_ADDR1_4_FLAGS"; + tcpc-flags = <(TCPC_FLAGS_TCPCI_REV2_0)>; + }; + chg { + compatible = "intersil,isl9241"; + status = "okay"; + port = <&i2c_ec_i2c_mi>; + }; + usb-muxes = <&usb_c0_hb_retimer &virtual_mux_c0>; + }; + port0-muxes { + usb_c0_hb_retimer: jhl8040r-c0 { + compatible = "intel,jhl8040r"; + port = <&i2c_ec_i2c_usb_c0_rt>; + i2c-addr-flags = <0x56>; + ls-en-pin = <&gpio_usb_c0_rt_3p3_sx_en>; + int-pin = <&gpio_usb_c0_rt_int_odl>; + reset-pin = <&ioex_usb_c0_rt_rst_ls_l>; + }; + virtual_mux_c0: virtual-mux-c0 { + compatible = "cros-ec,usbc-mux-virtual"; + }; + }; + }; +}; |