summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDtrain Hsu <dtrain_hsu@compal.corp-partner.google.com>2022-02-10 10:33:08 +0800
committerCommit Bot <commit-bot@chromium.org>2022-02-17 11:20:41 +0000
commit55680f70d2a1e61c193fc78ff1d51c7437803683 (patch)
treee12ef58e7b092b03ac8925f2656acd612fec4239
parent7e464f4acaef417e315c1d48779c2ea67b14993d (diff)
downloadchrome-ec-stabilize-14526.89.B-main.tar.gz
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>
-rw-r--r--board/kinox/board.c199
-rw-r--r--board/kinox/board.h216
-rw-r--r--board/kinox/build.mk21
-rw-r--r--board/kinox/ec.tasklist28
-rw-r--r--board/kinox/fans.c50
-rw-r--r--board/kinox/gpio.inc182
-rw-r--r--board/kinox/i2c.c78
-rw-r--r--board/kinox/led.c252
-rw-r--r--board/kinox/pwm.c45
-rw-r--r--board/kinox/sensors.c115
-rw-r--r--board/kinox/usbc_config.c401
-rw-r--r--board/kinox/usbc_config.h20
-rw-r--r--board/kinox/vif_override.xml3
13 files changed, 1610 insertions, 0 deletions
diff --git a/board/kinox/board.c b/board/kinox/board.c
new file mode 100644
index 0000000000..0349ea2cf3
--- /dev/null
+++ b/board/kinox/board.c
@@ -0,0 +1,199 @@
+/* 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 "assert.h"
+#include "button.h"
+#include "charge_manager.h"
+#include "charge_state_v2.h"
+#include "common.h"
+#include "compile_time_macros.h"
+#include "console.h"
+#include "cros_board_info.h"
+#include "gpio.h"
+#include "gpio_signal.h"
+#include "power_button.h"
+#include "hooks.h"
+#include "power.h"
+#include "switch.h"
+#include "throttle_ap.h"
+#include "usbc_config.h"
+
+#include "gpio_list.h" /* Must come after other header files. */
+
+/* Console output macros */
+#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args)
+
+/******************************************************************************/
+/* USB-A charging control */
+
+const int usb_port_enable[USB_PORT_COUNT] = {
+ GPIO_EN_PP5000_USBA,
+};
+BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT);
+
+/******************************************************************************/
+
+int board_set_active_charge_port(int port)
+{
+ CPRINTS("Requested charge port change to %d", port);
+
+ /*
+ * The charge manager may ask us to switch to no charger if we're
+ * running off USB-C only but upstream doesn't support PD. It requires
+ * that we accept this switch otherwise it triggers an assert and EC
+ * reset; it's not possible to boot the AP anyway, but we want to avoid
+ * resetting the EC so we can continue to do the "low power" LED blink.
+ */
+ if (port == CHARGE_PORT_NONE)
+ return EC_SUCCESS;
+
+ if (port < 0 || CHARGE_PORT_COUNT <= port)
+ return EC_ERROR_INVAL;
+
+ if (port == charge_manager_get_active_charge_port())
+ return EC_SUCCESS;
+
+ /* Don't charge from a source port */
+ if (board_vbus_source_enabled(port))
+ return EC_ERROR_INVAL;
+
+ if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) {
+ int bj_active, bj_requested;
+
+ if (charge_manager_get_active_charge_port() != CHARGE_PORT_NONE)
+ /* Change is only permitted while the system is off */
+ return EC_ERROR_INVAL;
+
+ /*
+ * Current setting is no charge port but the AP is on, so the
+ * charge manager is out of sync (probably because we're
+ * reinitializing after sysjump). Reject requests that aren't
+ * in sync with our outputs.
+ */
+ bj_active = !gpio_get_level(GPIO_EN_PPVAR_BJ_ADP_L);
+ bj_requested = port == CHARGE_PORT_BARRELJACK;
+ if (bj_active != bj_requested)
+ return EC_ERROR_INVAL;
+ }
+
+ CPRINTS("New charger p%d", port);
+
+ switch (port) {
+ case CHARGE_PORT_TYPEC0:
+ case CHARGE_PORT_TYPEC1:
+ case CHARGE_PORT_TYPEC2:
+ gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 1);
+ break;
+ case CHARGE_PORT_BARRELJACK:
+ /* Make sure BJ adapter is sourcing power */
+ if (gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL))
+ return EC_ERROR_INVAL;
+ gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 0);
+ break;
+ default:
+ return EC_ERROR_INVAL;
+ }
+
+ return EC_SUCCESS;
+}
+
+void board_set_charge_limit(int port, int supplier, int charge_ma,
+ int max_ma, int charge_mv)
+{
+}
+
+/******************************************************************************/
+/*
+ * Barrel jack power supply handling
+ *
+ * EN_PPVAR_BJ_ADP_L must default active to ensure we can power on when the
+ * barrel jack is connected, and the USB-C port can bring the EC up fine in
+ * dead-battery mode. Both the USB-C and barrel jack switches do reverse
+ * protection, so we're safe to turn one on then the other off- but we should
+ * only do that if the system is off since it might still brown out.
+ */
+
+/*
+ * Barrel-jack power adapter ratings.
+ */
+static const struct {
+ int voltage;
+ int current;
+} bj_power[] = {
+ { /* 0 - 135W (also default) */
+ .voltage = 19500,
+ .current = 6920
+ },
+ { /* 1 - 230W */
+ .voltage = 19500,
+ .current = 11800
+ },
+};
+
+static unsigned int ec_config_get_bj_power(void)
+{
+ uint32_t fw_config;
+ unsigned int bj;
+
+ cbi_get_fw_config(&fw_config);
+ bj = (fw_config & EC_CFG_BJ_POWER_MASK) >> EC_CFG_BJ_POWER_L;
+ /* Out of range value defaults to 0 */
+ if (bj >= ARRAY_SIZE(bj_power))
+ bj = 0;
+ return bj;
+}
+
+#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */
+/* Debounced connection state of the barrel jack */
+static int8_t adp_connected = -1;
+static void adp_connect_deferred(void)
+{
+ struct charge_port_info pi = { 0 };
+ int connected = !gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL);
+
+ /* Debounce */
+ if (connected == adp_connected)
+ return;
+ if (connected) {
+ unsigned int bj = ec_config_get_bj_power();
+
+ pi.voltage = bj_power[bj].voltage;
+ pi.current = bj_power[bj].current;
+ }
+ charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED,
+ DEDICATED_CHARGE_PORT, &pi);
+ adp_connected = connected;
+}
+DECLARE_DEFERRED(adp_connect_deferred);
+
+/* IRQ for BJ plug/unplug. It shouldn't be called if BJ is the power source. */
+void adp_connect_interrupt(enum gpio_signal signal)
+{
+ hook_call_deferred(&adp_connect_deferred_data, ADP_DEBOUNCE_MS * MSEC);
+}
+
+static void adp_state_init(void)
+{
+ ASSERT(CHARGE_PORT_ENUM_COUNT == CHARGE_PORT_COUNT);
+ /*
+ * Initialize all charge suppliers to 0. The charge manager waits until
+ * all ports have reported in before doing anything.
+ */
+ for (int i = 0; i < CHARGE_PORT_COUNT; i++) {
+ for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++)
+ charge_manager_update_charge(j, i, NULL);
+ }
+
+ /* Report charge state from the barrel jack. */
+ adp_connect_deferred();
+}
+DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_CHARGE_MANAGER_INIT + 1);
+
+static void board_init(void)
+{
+ gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT_ODL);
+}
+DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
diff --git a/board/kinox/board.h b/board/kinox/board.h
new file mode 100644
index 0000000000..9bc5af7abe
--- /dev/null
+++ b/board/kinox/board.h
@@ -0,0 +1,216 @@
+/* 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.
+ */
+
+/* Brask board configuration */
+
+#ifndef __CROS_EC_BOARD_H
+#define __CROS_EC_BOARD_H
+
+#include "compile_time_macros.h"
+
+/* Baseboard features */
+#include "baseboard.h"
+
+#define CONFIG_MP2964
+
+/* Barrel Jack */
+#define DEDICATED_CHARGE_PORT 3
+
+/* HDMI CEC */
+#define CONFIG_CEC
+#define CEC_GPIO_OUT GPIO_HDMI_CEC_OUT
+#define CEC_GPIO_IN GPIO_HDMI_CEC_IN
+#define CEC_GPIO_PULL_UP GPIO_HDMI_CEC_PULL_UP
+
+/* USB Type A Features */
+#define USB_PORT_COUNT 4
+#define CONFIG_USB_PORT_POWER_DUMB
+
+/* USB Type C and USB PD defines */
+#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY
+
+#define CONFIG_IO_EXPANDER
+#define CONFIG_IO_EXPANDER_NCT38XX
+#define CONFIG_IO_EXPANDER_PORT_COUNT 2
+
+#define CONFIG_USB_PD_PPC
+#define CONFIG_USB_PD_TCPM_RT1715
+#define CONFIG_USBC_RETIMER_INTEL_BB
+
+#define CONFIG_USBC_RETIMER_KB800X
+#define CONFIG_KB800X_CUSTOM_XBAR
+#define CONFIG_USBC_PPC_SYV682X
+#undef CONFIG_SYV682X_HV_ILIM
+#define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50
+
+/* TODO: b/177608416 - measure and check these values on brya */
+#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */
+#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */
+#define PD_VCONN_SWAP_DELAY 5000 /* us */
+
+/* The design should support up to 100W. */
+/* TODO(b/197702356): Set the max PD to 60W now and change it
+ * to 100W after we verify it.
+ */
+#define PD_OPERATING_POWER_MW CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON
+#define PD_MAX_POWER_MW 100000
+#define PD_MAX_CURRENT_MA 5000
+#define PD_MAX_VOLTAGE_MV 20000
+
+/*
+ * Macros for GPIO signals used in common code that don't match the
+ * schematic names. Signal names in gpio.inc match the schematic and are
+ * then redefined here to so it's more clear which signal is being used for
+ * which purpose.
+ */
+#define GPIO_AC_PRESENT GPIO_ACOK_OD
+#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL
+#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL
+#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW
+#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE
+#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL
+#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L
+#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST
+#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L
+#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L
+#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK
+
+/*
+ * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup
+ * signal.
+ */
+#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL
+#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG
+#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK
+#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL
+#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL
+#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL
+#define GPIO_WP_L GPIO_EC_WP_ODL
+#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_OD
+#define GPIO_RECOVERY_L_2 GPIO_GSC_EC_RECOVERY_BTN_OD
+
+/* I2C Bus Configuration */
+
+#define I2C_PORT_DP_REDRIVER NPCX_I2C_PORT0_0
+
+#define I2C_PORT_USB_C0_C2_TCPC NPCX_I2C_PORT1_0
+#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1
+
+#define I2C_PORT_USB_C0_C2_PPC NPCX_I2C_PORT2_0
+#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT6_1
+
+#define I2C_PORT_USB_C0_C2_BC12 NPCX_I2C_PORT2_0
+#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT6_1
+
+#define I2C_PORT_USB_C0_C2_MUX NPCX_I2C_PORT3_0
+#define I2C_PORT_USB_C1_MUX NPCX_I2C_PORT6_1
+
+#define I2C_PORT_QI NPCX_I2C_PORT5_0
+#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0
+#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0
+
+#define I2C_ADDR_EEPROM_FLAGS 0x50
+
+#define I2C_ADDR_MP2964_FLAGS 0x20
+
+#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x58
+#define USBC_PORT_C2_BB_RETIMER_I2C_ADDR 0x59
+
+/* Enabling Thunderbolt-compatible mode */
+#define CONFIG_USB_PD_TBT_COMPAT_MODE
+
+/* Enabling USB4 mode */
+#define CONFIG_USB_PD_USB4
+
+/* Retimer */
+#define CONFIG_USBC_RETIMER_FW_UPDATE
+
+/* Thermal features */
+#define CONFIG_THERMISTOR
+#define CONFIG_TEMP_SENSOR
+#define CONFIG_TEMP_SENSOR_POWER
+#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B
+
+/* ADC */
+#define CONFIG_ADC
+
+/*
+ * TODO(b/197478860): Enable the fan control. We need
+ * to check the sensor value and adjust the fan speed.
+ */
+ #define CONFIG_FANS FAN_CH_COUNT
+
+/* Include math_util for bitmask_uint64 used in pd_timers */
+#define CONFIG_MATH_UTIL
+
+#ifndef __ASSEMBLER__
+
+#include "gpio_signal.h" /* needed by registers.h */
+#include "registers.h"
+#include "usbc_config.h"
+
+enum charge_port {
+ CHARGE_PORT_TYPEC0,
+ CHARGE_PORT_TYPEC1,
+ CHARGE_PORT_TYPEC2,
+ CHARGE_PORT_BARRELJACK,
+ CHARGE_PORT_ENUM_COUNT
+};
+
+enum adc_channel {
+ ADC_TEMP_SENSOR_1_CPU,
+ ADC_TEMP_SENSOR_2_CPU_VR,
+ ADC_TEMP_SENSOR_3_WIFI,
+ ADC_TEMP_SENSOR_4_DIMM,
+ ADC_VBUS,
+ ADC_CH_COUNT
+};
+
+enum temp_sensor_id {
+ TEMP_SENSOR_1_CPU,
+ TEMP_SENSOR_2_CPU_VR,
+ TEMP_SENSOR_3_WIFI,
+ TEMP_SENSOR_4_DIMM,
+ TEMP_SENSOR_COUNT
+};
+
+enum ioex_port {
+ IOEX_C0_NCT38XX = 0,
+ IOEX_C2_NCT38XX,
+ IOEX_PORT_COUNT
+};
+
+enum pwm_channel {
+ PWM_CH_LED_GREEN, /* PWM0 */
+ PWM_CH_FAN, /* PWM5 */
+ PWM_CH_LED_RED, /* PWM2 */
+ PWM_CH_COUNT
+};
+
+enum fan_channel {
+ FAN_CH_0 = 0,
+ FAN_CH_COUNT
+};
+
+enum mft_channel {
+ MFT_CH_0 = 0,
+ MFT_CH_COUNT
+};
+
+/*
+ * firmware config fields
+ */
+/*
+ * Barrel-jack power (4 bits).
+ */
+#define EC_CFG_BJ_POWER_L 0
+#define EC_CFG_BJ_POWER_H 3
+#define EC_CFG_BJ_POWER_MASK GENMASK(EC_CFG_BJ_POWER_H, EC_CFG_BJ_POWER_L)
+
+extern void adp_connect_interrupt(enum gpio_signal signal);
+
+#endif /* !__ASSEMBLER__ */
+
+#endif /* __CROS_EC_BOARD_H */
diff --git a/board/kinox/build.mk b/board/kinox/build.mk
new file mode 100644
index 0000000000..00fc2723cd
--- /dev/null
+++ b/board/kinox/build.mk
@@ -0,0 +1,21 @@
+# -*- makefile -*-
+# 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.
+#
+# Brask board specific files build
+#
+
+CHIP:=npcx
+CHIP_FAMILY:=npcx9
+CHIP_VARIANT:=npcx9m3f
+BASEBOARD:=brask
+
+board-y=
+board-y+=board.o
+board-y+=fans.o
+board-y+=i2c.o
+board-y+=led.o
+board-y+=pwm.o
+board-y+=sensors.o
+board-y+=usbc_config.o
diff --git a/board/kinox/ec.tasklist b/board/kinox/ec.tasklist
new file mode 100644
index 0000000000..ebabe8ef51
--- /dev/null
+++ b/board/kinox/ec.tasklist
@@ -0,0 +1,28 @@
+/* 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.
+ */
+
+/*
+ * See CONFIG_TASK_LIST in config.h for details.
+ *
+ * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)).
+ * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x))
+ */
+
+#define CONFIG_TASK_LIST \
+ TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \
+ TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \
+ TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \
+ TASK_ALWAYS(USB_CHG_P2, usb_charger_task, 0, TASK_STACK_SIZE) \
+ TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \
+ TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \
+ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \
+ TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \
+ TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \
+ TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \
+ TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \
+ TASK_ALWAYS(PD_C2, pd_task, NULL, VENTI_TASK_STACK_SIZE) \
+ TASK_ALWAYS(PD_INT_C0, pd_shared_alert_task, (BIT(2) | BIT(0)), LARGER_TASK_STACK_SIZE) \
+ TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, LARGER_TASK_STACK_SIZE) \
+ TASK_ALWAYS(CEC, cec_task, NULL, LARGER_TASK_STACK_SIZE)
diff --git a/board/kinox/fans.c b/board/kinox/fans.c
new file mode 100644
index 0000000000..f2a70636d0
--- /dev/null
+++ b/board/kinox/fans.c
@@ -0,0 +1,50 @@
+/* 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.
+ */
+
+/* Physical fans. These are logically separate from pwm_channels. */
+
+#include "common.h"
+#include "compile_time_macros.h"
+#include "console.h"
+#include "fan_chip.h"
+#include "fan.h"
+#include "hooks.h"
+#include "pwm.h"
+
+/* MFT channels. These are logically separate from pwm_channels. */
+const struct mft_t mft_channels[] = {
+ [MFT_CH_0] = {
+ .module = NPCX_MFT_MODULE_2,
+ .clk_src = TCKC_LFCLK,
+ .pwm_id = PWM_CH_FAN,
+ },
+};
+BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT);
+
+static const struct fan_conf fan_conf_0 = {
+ .flags = FAN_USE_RPM_MODE,
+ .ch = MFT_CH_0, /* Use MFT id to control fan */
+ .pgood_gpio = -1,
+ .enable_gpio = GPIO_EN_PP5000_FAN,
+};
+
+/*
+ * TOOD(b/197478860): need to update for real fan
+ *
+ * Prototype fan spins at about 7200 RPM at 100% PWM.
+ * Set minimum at around 30% PWM.
+ */
+static const struct fan_rpm fan_rpm_0 = {
+ .rpm_min = 2200,
+ .rpm_start = 2200,
+ .rpm_max = 7200,
+};
+
+const struct fan_t fans[FAN_CH_COUNT] = {
+ [FAN_CH_0] = {
+ .conf = &fan_conf_0,
+ .rpm = &fan_rpm_0,
+ },
+};
diff --git a/board/kinox/gpio.inc b/board/kinox/gpio.inc
new file mode 100644
index 0000000000..85ec312dde
--- /dev/null
+++ b/board/kinox/gpio.inc
@@ -0,0 +1,182 @@
+/* -*- mode:c -*-
+ *
+ * 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.
+ */
+
+/* INTERRUPT GPIOs: */
+GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt)
+GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt)
+GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt)
+GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt)
+GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt)
+GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt)
+GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt)
+GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt)
+GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt)
+GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt)
+GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt)
+GPIO_INT(USB_C0_C2_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event)
+GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt)
+GPIO_INT(USB_C0_RT_INT_ODL, PIN(B, 1), GPIO_INT_FALLING, retimer_interrupt)
+GPIO_INT(USB_C1_BC12_INT_ODL, PIN(5, 0), GPIO_INT_FALLING, bc12_interrupt)
+GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt)
+GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event)
+GPIO_INT(USB_C2_BC12_INT_ODL, PIN(8, 3), GPIO_INT_FALLING, bc12_interrupt)
+GPIO_INT(USB_C2_PPC_INT_ODL, PIN(7, 0), GPIO_INT_FALLING, ppc_interrupt)
+GPIO_INT(USB_C2_RT_INT_ODL, PIN(4, 1), GPIO_INT_FALLING, retimer_interrupt)
+GPIO_INT(BJ_ADP_PRESENT_ODL, PIN(8, 2), GPIO_INT_BOTH | GPIO_PULL_UP, adp_connect_interrupt)
+GPIO_INT(EC_RECOVERY_BTN_OD, PIN(2, 3), GPIO_INT_BOTH, button_interrupt)
+
+/* CCD */
+GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT)
+
+/* Security */
+GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW)
+GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW)
+
+/* Fan */
+GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH)
+
+/* ADC, need to check the usage */
+GPIO(ANALOG_PPVAR_PWR_IN_IMON_EC, PIN(4, 2), GPIO_INPUT)
+
+/* Display */
+GPIO(DP_CONN_OC_ODL, PIN(2, 5), GPIO_INPUT)
+GPIO(HDMI_CONN_OC_ODL, PIN(2, 4), GPIO_INPUT)
+
+/* BarrelJack */
+GPIO(EN_PPVAR_BJ_ADP_L, PIN(0, 7), GPIO_OUT_LOW)
+
+/* Chipset PCH */
+GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT)
+GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH)
+GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW)
+GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW)
+GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW)
+GPIO(EC_PCH_WAKE_ODL, PIN(C, 0), GPIO_ODR_HIGH)
+GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH)
+GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW)
+GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW)
+GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH)
+GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW)
+GPIO(IMVP9_VRRDY_OD, PIN(6, 0), GPIO_INPUT)
+GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT)
+
+/* Button */
+GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH)
+GPIO(GSC_EC_RECOVERY_BTN_OD, PIN(2, 2), GPIO_INPUT)
+
+/* NFC */
+/* TODO(b/194068530): Enable NFC */
+GPIO(NFC_COIL_ACT_L, PIN(D, 4), GPIO_INPUT)
+GPIO(NFC_LOW_POWER_MODE, PIN(9, 5), GPIO_OUT_HIGH)
+GPIO(NFC_CARD_DET_L, PIN(A, 3), GPIO_INPUT)
+GPIO(EN_NFC_BUZZER, PIN(0, 5), GPIO_OUT_LOW)
+
+/* Wireless Charger */
+/* TODO(b/191418683): Implement Qi Driver */
+GPIO(EC_QI_PWR, PIN(D, 2), GPIO_OUT_HIGH)
+GPIO(EC_I2C_QI_RESET_L, PIN(9, 3), GPIO_OUT_HIGH)
+GPIO(EC_I2C_QI_INT_ODL, PIN(9, 6), GPIO_INPUT)
+
+/* HDMI CEC */
+/* TODO(b/197474873): Enable HDMI CEC */
+GPIO(HDMI_CEC_IN, PIN(4, 0), GPIO_INPUT)
+GPIO(HDMI_CEC_OUT, PIN(D, 3), GPIO_OUT_HIGH | GPIO_OPEN_DRAIN)
+GPIO(HDMI_CEC_PULL_UP, PIN(C, 2), GPIO_OUT_HIGH)
+
+/* I2C SCL/SDA */
+GPIO(EC_I2C_QI_SCL, PIN(3, 3), GPIO_INPUT)
+GPIO(EC_I2C_QI_SDA, PIN(3, 6), GPIO_INPUT)
+GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT)
+GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT)
+GPIO(EC_I2C_DP_SCL, PIN(B, 5), GPIO_INPUT)
+GPIO(EC_I2C_DP_SDA, PIN(B, 4), GPIO_INPUT)
+GPIO(EC_I2C_USB_C0_C2_PPC_SCL, PIN(9, 2), GPIO_INPUT)
+GPIO(EC_I2C_USB_C0_C2_PPC_SDA, PIN(9, 1), GPIO_INPUT)
+GPIO(EC_I2C_USB_C0_C2_RT_SCL, PIN(D, 1), GPIO_INPUT)
+GPIO(EC_I2C_USB_C0_C2_RT_SDA, PIN(D, 0), GPIO_INPUT)
+GPIO(EC_I2C_USB_C0_C2_TCPC_SCL, PIN(9, 0), GPIO_INPUT)
+GPIO(EC_I2C_USB_C0_C2_TCPC_SDA, PIN(8, 7), GPIO_INPUT)
+GPIO(EC_I2C_USB_C1_MIX_SCL, PIN(E, 4), GPIO_INPUT)
+GPIO(EC_I2C_USB_C1_MIX_SDA, PIN(E, 3), GPIO_INPUT)
+GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(F, 3), GPIO_INPUT)
+GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(F, 2), GPIO_INPUT)
+
+/* USBA */
+GPIO(EN_PP5000_USBA, PIN(D, 7), GPIO_OUT_LOW)
+GPIO(USB_A0_OC_ODL, PIN(3, 1), GPIO_INPUT | GPIO_PULL_UP)
+GPIO(USB_A1_OC_ODL, PIN(3, 0), GPIO_INPUT | GPIO_PULL_UP)
+GPIO(USB_A2_OC_ODL, PIN(2, 7), GPIO_INPUT | GPIO_PULL_UP)
+GPIO(USB_A3_OC_ODL, PIN(2, 6), GPIO_INPUT | GPIO_PULL_UP)
+GPIO(USB_A0_STATUS_L, PIN(2, 1), GPIO_INPUT)
+GPIO(USB_A1_STATUS_L, PIN(2, 0), GPIO_INPUT)
+GPIO(USB_A2_STATUS_L, PIN(1, 7), GPIO_INPUT)
+GPIO(USB_A3_STATUS_L, PIN(1, 6), GPIO_INPUT)
+GPIO(USB_A_LOW_PWR0_OD, PIN(1, 5), GPIO_INPUT | GPIO_PULL_DOWN)
+GPIO(USB_A_LOW_PWR1_OD, PIN(1, 4), GPIO_INPUT | GPIO_PULL_DOWN)
+GPIO(USB_A_LOW_PWR2_OD, PIN(1, 1), GPIO_INPUT | GPIO_PULL_DOWN)
+GPIO(USB_A_LOW_PWR3_OD, PIN(1, 0), GPIO_INPUT | GPIO_PULL_DOWN)
+GPIO(USB_A_OC_SOC_L, PIN(8, 0), GPIO_OUT_HIGH)
+
+/* LED */
+/* TODO(b/197471359): LED implementation */
+GPIO(LED_GREEN_L, PIN(C, 3), GPIO_OUT_LOW)
+GPIO(LED_RED_L, PIN(C, 4), GPIO_OUT_LOW)
+
+/* USBC */
+GPIO(USB_C0_C2_TCPC_RST_ODL, PIN(A, 7), GPIO_ODR_LOW)
+GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW)
+GPIO(USB_C1_RT_INT_ODL, PIN(A, 0), GPIO_INPUT)
+GPIO(USB_C1_RT_RST_R_L, PIN(0, 2), GPIO_OUT_LOW)
+
+/* GPIO02_P2 to PU */
+/* GPIO03_P2 to PU */
+IOEX(USB_C0_OC_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 4), GPIO_ODR_HIGH)
+IOEX(USB_C0_FRS_EN, EXPIN(IOEX_C0_NCT38XX, 0, 6), GPIO_LOW)
+IOEX(USB_C0_RT_RST_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 7), GPIO_ODR_LOW)
+
+IOEX(USB_C2_RT_RST_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 2), GPIO_ODR_LOW)
+IOEX(USB_C1_OC_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 3), GPIO_ODR_HIGH)
+IOEX(USB_C2_OC_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 4), GPIO_ODR_HIGH)
+IOEX(USB_C2_FRS_EN, EXPIN(IOEX_C2_NCT38XX, 0, 6), GPIO_LOW)
+/* GPIO07_P2 to PU */
+
+/* UART alternate functions */
+ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */
+
+/* I2C alternate functions */
+ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */
+ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */
+ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */
+ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */
+ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, 0) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */
+ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */
+ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */
+ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */
+
+/* PWM alternate functions */
+ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* GPIO73/TA2 */
+ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */
+ALTERNATE(PIN_MASK(C, 0x18), 0, MODULE_PWM, 0) /* GPIOC4/PWM2, GPIOC3/PWM0 */
+
+/* ADC alternate functions */
+ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */
+ALTERNATE(PIN_MASK(4, 0x38), 0, MODULE_ADC, 0) /* GPIO45/ADC0, GPIO44/ADC1, GPIO43/ADC2 */
+ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */
+
+/* Unused Pins */
+UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */
+UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */
+UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */
+UNUSED(PIN(6, 6)) /* GPIO66 */
+UNUSED(PIN(8, 1)) /* GPIO81/PECI_DATA */
+UNUSED(PIN(5, 6)) /* GPIO56/CLKRUN# */
+UNUSED(PIN(9, 7)) /* GPIO97 */
+UNUSED(PIN(8, 6)) /* GPIO86/TXD/CR_SOUT2 */
+UNUSED(PIN(1, 3)) /* KSO06/GPO13/GP_SEL# */
+UNUSED(PIN(1, 2)) /* KSO07/GPO12/JEN# */
+UNUSED(PIN(0, 6)) /* KSO11/GPIO06/P80_CLK */
+UNUSED(PIN(0, 4)) /* KSO13/GPIO04 */ \ No newline at end of file
diff --git a/board/kinox/i2c.c b/board/kinox/i2c.c
new file mode 100644
index 0000000000..9c92852461
--- /dev/null
+++ b/board/kinox/i2c.c
@@ -0,0 +1,78 @@
+/* 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 "common.h"
+#include "compile_time_macros.h"
+
+#include "i2c.h"
+
+/* I2C port map configuration */
+const struct i2c_port_t i2c_ports[] = {
+ {
+ /* I2C0 */
+ .name = "dp_redriver",
+ .port = I2C_PORT_DP_REDRIVER,
+ .kbps = 400,
+ .scl = GPIO_EC_I2C_DP_SCL,
+ .sda = GPIO_EC_I2C_DP_SDA,
+ },
+ {
+ /* I2C1 */
+ .name = "tcpc0,2",
+ .port = I2C_PORT_USB_C0_C2_TCPC,
+ .kbps = 1000,
+ .scl = GPIO_EC_I2C_USB_C0_C2_TCPC_SCL,
+ .sda = GPIO_EC_I2C_USB_C0_C2_TCPC_SDA,
+ },
+ {
+ /* I2C2 */
+ .name = "ppc0,2",
+ .port = I2C_PORT_USB_C0_C2_PPC,
+ .kbps = 1000,
+ .scl = GPIO_EC_I2C_USB_C0_C2_PPC_SCL,
+ .sda = GPIO_EC_I2C_USB_C0_C2_PPC_SDA,
+ },
+ {
+ /* I2C3 */
+ .name = "retimer0,2",
+ .port = I2C_PORT_USB_C0_C2_MUX,
+ .kbps = 1000,
+ .scl = GPIO_EC_I2C_USB_C0_C2_RT_SCL,
+ .sda = GPIO_EC_I2C_USB_C0_C2_RT_SDA,
+ },
+ {
+ /* I2C4 C1 TCPC */
+ .name = "tcpc1",
+ .port = I2C_PORT_USB_C1_TCPC,
+ .kbps = 400,
+ .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL,
+ .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA,
+ },
+ {
+ /* I2C5 */
+ .name = "wireless_charger",
+ .port = I2C_PORT_QI,
+ .kbps = 400,
+ .scl = GPIO_EC_I2C_QI_SCL,
+ .sda = GPIO_EC_I2C_QI_SDA,
+ },
+ {
+ /* I2C6 */
+ .name = "ppc1",
+ .port = I2C_PORT_USB_C1_PPC,
+ .kbps = 1000,
+ .scl = GPIO_EC_I2C_USB_C1_MIX_SCL,
+ .sda = GPIO_EC_I2C_USB_C1_MIX_SDA,
+ },
+ {
+ /* I2C7 */
+ .name = "eeprom",
+ .port = I2C_PORT_EEPROM,
+ .kbps = 400,
+ .scl = GPIO_EC_I2C_MISC_SCL_R,
+ .sda = GPIO_EC_I2C_MISC_SDA_R,
+ },
+};
+const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
diff --git a/board/kinox/led.c b/board/kinox/led.c
new file mode 100644
index 0000000000..636804c7a6
--- /dev/null
+++ b/board/kinox/led.c
@@ -0,0 +1,252 @@
+/* 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.
+ *
+ * Power LED control for Brask.
+ * Solid green - active power
+ * Green flashing - suspended
+ * Red flashing - alert
+ * Solid red - critical
+ */
+
+#include "chipset.h"
+#include "console.h"
+#include "ec_commands.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "led_common.h"
+#include "pwm.h"
+#include "timer.h"
+#include "util.h"
+
+#define CPRINTS(format, args...) cprints(CC_GPIO, format, ## args)
+
+/*
+ * Due to the CSME-Lite processing, upon startup the CPU transitions through
+ * S0->S3->S5->S3->S0, causing the LED to turn on/off/on, so
+ * delay turning off the LED during suspend/shutdown.
+ */
+#define LED_CPU_DELAY_MS (2000 * MSEC)
+
+const enum ec_led_id supported_led_ids[] = {EC_LED_ID_POWER_LED};
+const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids);
+
+enum led_color {
+ LED_OFF = 0,
+ LED_RED,
+ LED_GREEN,
+
+ /* Number of colors, not a color itself */
+ LED_COLOR_COUNT
+};
+
+static int set_color_power(enum led_color color, int duty)
+{
+ int green = 0;
+ int red = 0;
+
+ if (duty < 0 || 100 < duty)
+ return EC_ERROR_UNKNOWN;
+
+ switch (color) {
+ case LED_OFF:
+ break;
+ case LED_GREEN:
+ green = 1;
+ break;
+ case LED_RED:
+ red = 1;
+ break;
+ default:
+ return EC_ERROR_UNKNOWN;
+ }
+
+ if (red)
+ pwm_set_duty(PWM_CH_LED_RED, duty);
+ else
+ pwm_set_duty(PWM_CH_LED_RED, 0);
+
+ if (green)
+ pwm_set_duty(PWM_CH_LED_GREEN, duty);
+ else
+ pwm_set_duty(PWM_CH_LED_GREEN, 0);
+
+ return EC_SUCCESS;
+}
+
+static int set_color(enum ec_led_id id, enum led_color color, int duty)
+{
+ switch (id) {
+ case EC_LED_ID_POWER_LED:
+ return set_color_power(color, duty);
+ default:
+ return EC_ERROR_UNKNOWN;
+ }
+}
+
+#define LED_PULSE_US (2 * SECOND)
+/* 40 msec for nice and smooth transition. */
+#define LED_PULSE_TICK_US (40 * MSEC)
+
+/*
+ * When pulsing is enabled, brightness is incremented by <duty_inc> every
+ * <interval> usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented
+ * likewise in LED_PULSE_US usec.
+ */
+static struct {
+ uint32_t interval;
+ int duty_inc;
+ enum led_color color;
+ int duty;
+} led_pulse;
+
+#define CONFIG_TICK(interval, color) \
+ config_tick((interval), 100 / (LED_PULSE_US / (interval)), (color))
+
+static void config_tick(uint32_t interval, int duty_inc, enum led_color color)
+{
+ led_pulse.interval = interval;
+ led_pulse.duty_inc = duty_inc;
+ led_pulse.color = color;
+ led_pulse.duty = 0;
+}
+
+static void pulse_power_led(enum led_color color)
+{
+ set_color(EC_LED_ID_POWER_LED, color, led_pulse.duty);
+ if (led_pulse.duty + led_pulse.duty_inc > 100)
+ led_pulse.duty_inc = led_pulse.duty_inc * -1;
+ else if (led_pulse.duty + led_pulse.duty_inc < 0)
+ led_pulse.duty_inc = led_pulse.duty_inc * -1;
+ led_pulse.duty += led_pulse.duty_inc;
+}
+
+static void led_tick(void);
+DECLARE_DEFERRED(led_tick);
+static void led_tick(void)
+{
+ uint32_t elapsed;
+ uint32_t next = 0;
+ uint32_t start = get_time().le.lo;
+
+ if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED))
+ pulse_power_led(led_pulse.color);
+ elapsed = get_time().le.lo - start;
+ next = led_pulse.interval > elapsed ? led_pulse.interval - elapsed : 0;
+ hook_call_deferred(&led_tick_data, next);
+}
+
+static void led_suspend(void)
+{
+ CONFIG_TICK(LED_PULSE_TICK_US, LED_GREEN);
+ led_tick();
+}
+DECLARE_DEFERRED(led_suspend);
+
+static void led_shutdown(void)
+{
+ if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED))
+ set_color(EC_LED_ID_POWER_LED, LED_OFF, 0);
+}
+DECLARE_DEFERRED(led_shutdown);
+
+static void led_shutdown_hook(void)
+{
+ hook_call_deferred(&led_tick_data, -1);
+ hook_call_deferred(&led_suspend_data, -1);
+ hook_call_deferred(&led_shutdown_data, LED_CPU_DELAY_MS);
+}
+DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, led_shutdown_hook, HOOK_PRIO_DEFAULT);
+
+static void led_suspend_hook(void)
+{
+ hook_call_deferred(&led_shutdown_data, -1);
+ hook_call_deferred(&led_suspend_data, LED_CPU_DELAY_MS);
+}
+DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, led_suspend_hook, HOOK_PRIO_DEFAULT);
+
+static void led_resume(void)
+{
+ /*
+ * Assume there is no race condition with led_tick, which also
+ * runs in hook_task.
+ */
+ hook_call_deferred(&led_tick_data, -1);
+ /*
+ * Avoid invoking the suspend/shutdown delayed hooks.
+ */
+ hook_call_deferred(&led_suspend_data, -1);
+ hook_call_deferred(&led_shutdown_data, -1);
+ if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED))
+ set_color(EC_LED_ID_POWER_LED, LED_GREEN, 100);
+}
+DECLARE_HOOK(HOOK_CHIPSET_RESUME, led_resume, HOOK_PRIO_DEFAULT);
+
+void led_alert(int enable)
+{
+ if (enable) {
+ /* Overwrite the current signal */
+ config_tick(1 * SECOND, 100, LED_RED);
+ led_tick();
+ } else {
+ /* Restore the previous signal */
+ if (chipset_in_state(CHIPSET_STATE_ON))
+ led_resume();
+ else if (chipset_in_state(CHIPSET_STATE_SUSPEND))
+ led_suspend_hook();
+ else if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
+ led_shutdown_hook();
+ }
+}
+
+void show_critical_error(void)
+{
+ hook_call_deferred(&led_tick_data, -1);
+ if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED))
+ set_color(EC_LED_ID_POWER_LED, LED_RED, 100);
+}
+
+static int command_led(int argc, char **argv)
+{
+ enum ec_led_id id = EC_LED_ID_POWER_LED;
+
+ if (argc < 2)
+ return EC_ERROR_PARAM_COUNT;
+
+ if (!strcasecmp(argv[1], "debug")) {
+ led_auto_control(id, !led_auto_control_is_enabled(id));
+ ccprintf("o%s\n", led_auto_control_is_enabled(id) ? "ff" : "n");
+ } else if (!strcasecmp(argv[1], "off")) {
+ set_color(id, LED_OFF, 0);
+ } else if (!strcasecmp(argv[1], "red")) {
+ set_color(id, LED_RED, 100);
+ } else if (!strcasecmp(argv[1], "green")) {
+ set_color(id, LED_GREEN, 100);
+ } else if (!strcasecmp(argv[1], "alert")) {
+ led_alert(1);
+ } else if (!strcasecmp(argv[1], "crit")) {
+ show_critical_error();
+ } else {
+ return EC_ERROR_PARAM1;
+ }
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(led, command_led,
+ "[debug|red|green|off|alert|crit]",
+ "Turn on/off LED.");
+
+void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range)
+{
+ brightness_range[EC_LED_COLOR_RED] = 100;
+ brightness_range[EC_LED_COLOR_GREEN] = 100;
+}
+
+int led_set_brightness(enum ec_led_id id, const uint8_t *brightness)
+{
+ if (brightness[EC_LED_COLOR_RED])
+ return set_color(id, LED_RED, brightness[EC_LED_COLOR_RED]);
+ else if (brightness[EC_LED_COLOR_GREEN])
+ return set_color(id, LED_GREEN, brightness[EC_LED_COLOR_GREEN]);
+ else
+ return set_color(id, LED_OFF, 0);
+}
diff --git a/board/kinox/pwm.c b/board/kinox/pwm.c
new file mode 100644
index 0000000000..125d507a82
--- /dev/null
+++ b/board/kinox/pwm.c
@@ -0,0 +1,45 @@
+/* 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 "common.h"
+
+#include "compile_time_macros.h"
+#include "hooks.h"
+#include "pwm.h"
+#include "pwm_chip.h"
+
+const struct pwm_t pwm_channels[] = {
+ [PWM_CH_LED_GREEN] = {
+ .channel = 0,
+ .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP,
+ .freq = 2000
+ },
+ [PWM_CH_FAN] = {
+ .channel = 5,
+ .flags = PWM_CONFIG_OPEN_DRAIN | PWM_CONFIG_DSLEEP,
+ .freq = 1000
+ },
+ [PWM_CH_LED_RED] = {
+ .channel = 2,
+ .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP,
+ .freq = 2000
+ },
+};
+BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT);
+
+static void board_pwm_init(void)
+{
+ /*
+ * TODO(b/197478860): Turn on the fan at 100% by default
+ * We need to find tune the fan speed according to the
+ * thermal sensor value.
+ */
+ pwm_enable(PWM_CH_FAN, 1);
+ pwm_set_duty(PWM_CH_FAN, 100);
+
+ pwm_enable(PWM_CH_LED_RED, 1);
+ pwm_enable(PWM_CH_LED_GREEN, 1);
+}
+DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT);
diff --git a/board/kinox/sensors.c b/board/kinox/sensors.c
new file mode 100644
index 0000000000..b3a492b61a
--- /dev/null
+++ b/board/kinox/sensors.c
@@ -0,0 +1,115 @@
+/* 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 "common.h"
+#include "adc_chip.h"
+#include "hooks.h"
+#include "temp_sensor.h"
+#include "thermal.h"
+#include "temp_sensor/thermistor.h"
+
+/* ADC configuration */
+const struct adc_t adc_channels[] = {
+ [ADC_TEMP_SENSOR_1_CPU] = {
+ .name = "TEMP_CPU",
+ .input_ch = NPCX_ADC_CH0,
+ .factor_mul = ADC_MAX_VOLT,
+ .factor_div = ADC_READ_MAX + 1,
+ .shift = 0,
+ },
+ [ADC_TEMP_SENSOR_2_CPU_VR] = {
+ .name = "TEMP_CPU_VR",
+ .input_ch = NPCX_ADC_CH1,
+ .factor_mul = ADC_MAX_VOLT,
+ .factor_div = ADC_READ_MAX + 1,
+ .shift = 0,
+ },
+ [ADC_TEMP_SENSOR_3_WIFI] = {
+ .name = "TEMP_WIFI",
+ .input_ch = NPCX_ADC_CH6,
+ .factor_mul = ADC_MAX_VOLT,
+ .factor_div = ADC_READ_MAX + 1,
+ .shift = 0,
+ },
+ [ADC_TEMP_SENSOR_4_DIMM] = {
+ .name = "TEMP_DIMM",
+ .input_ch = NPCX_ADC_CH7,
+ .factor_mul = ADC_MAX_VOLT,
+ .factor_div = ADC_READ_MAX + 1,
+ .shift = 0,
+ },
+ [ADC_VBUS] = { /* 5/39 voltage divider */
+ .name = "VBUS",
+ .input_ch = NPCX_ADC_CH2,
+ .factor_mul = ADC_MAX_VOLT * 39,
+ .factor_div = (ADC_READ_MAX + 1) * 5,
+ },
+};
+BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT);
+
+/* Temperature sensor configuration */
+const struct temp_sensor_t temp_sensors[] = {
+ [TEMP_SENSOR_1_CPU] = {
+ .name = "CPU",
+ .type = TEMP_SENSOR_TYPE_BOARD,
+ .read = get_temp_3v3_30k9_47k_4050b,
+ .idx = ADC_TEMP_SENSOR_1_CPU
+ },
+ [TEMP_SENSOR_2_CPU_VR] = {
+ .name = "CPU VR",
+ .type = TEMP_SENSOR_TYPE_BOARD,
+ .read = get_temp_3v3_30k9_47k_4050b,
+ .idx = ADC_TEMP_SENSOR_2_CPU_VR
+ },
+ [TEMP_SENSOR_3_WIFI] = {
+ .name = "WIFI",
+ .type = TEMP_SENSOR_TYPE_BOARD,
+ .read = get_temp_3v3_30k9_47k_4050b,
+ .idx = ADC_TEMP_SENSOR_3_WIFI
+ },
+ [TEMP_SENSOR_4_DIMM] = {
+ .name = "DIMM",
+ .type = TEMP_SENSOR_TYPE_BOARD,
+ .read = get_temp_3v3_30k9_47k_4050b,
+ .idx = ADC_TEMP_SENSOR_4_DIMM
+ },
+};
+BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT);
+
+/*
+ * TODO(b/180681346): update for Alder Lake/brya
+ *
+ * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at
+ * 130 C. However, sensor is located next to DDR, so we need to use the lower
+ * DDR temperature limit (85 C)
+ */
+/*
+ * TODO(b/202062363): Remove when clang is fixed.
+ */
+#define THERMAL_CPU \
+ { \
+ .temp_host = { \
+ [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \
+ [EC_TEMP_THRESH_HALT] = C_TO_K(80), \
+ }, \
+ .temp_host_release = { \
+ [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \
+ }, \
+ .temp_fan_off = C_TO_K(35), \
+ .temp_fan_max = C_TO_K(50), \
+ }
+__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU;
+
+/*
+ * TODO(b/197478860): add the thermal sensor setting
+ */
+/* this should really be "const" */
+struct ec_thermal_config thermal_params[] = {
+ [TEMP_SENSOR_1_CPU] = THERMAL_CPU,
+ [TEMP_SENSOR_2_CPU_VR] = THERMAL_CPU,
+ [TEMP_SENSOR_3_WIFI] = THERMAL_CPU,
+ [TEMP_SENSOR_4_DIMM] = THERMAL_CPU,
+};
+BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT);
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;
+}
diff --git a/board/kinox/usbc_config.h b/board/kinox/usbc_config.h
new file mode 100644
index 0000000000..1ccb5f0a71
--- /dev/null
+++ b/board/kinox/usbc_config.h
@@ -0,0 +1,20 @@
+/* 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.
+ */
+
+/* Brya board-specific USB-C configuration */
+
+#ifndef __CROS_EC_USBC_CONFIG_H
+#define __CROS_EC_USBC_CONFIG_H
+
+#define CONFIG_USB_PD_PORT_MAX_COUNT 3
+
+enum usbc_port {
+ USBC_PORT_C0 = 0,
+ USBC_PORT_C1,
+ USBC_PORT_C2,
+ USBC_PORT_COUNT
+};
+
+#endif /* __CROS_EC_USBC_CONFIG_H */
diff --git a/board/kinox/vif_override.xml b/board/kinox/vif_override.xml
new file mode 100644
index 0000000000..32736caf64
--- /dev/null
+++ b/board/kinox/vif_override.xml
@@ -0,0 +1,3 @@
+<!-- Add VIF field overrides here. See genvif.c and the Vendor Info File
+ Definition from the USB-IF.
+-->