summaryrefslogtreecommitdiff
path: root/zephyr/projects/trogdor/lazor
diff options
context:
space:
mode:
Diffstat (limited to 'zephyr/projects/trogdor/lazor')
-rw-r--r--zephyr/projects/trogdor/lazor/BUILD.py25
-rw-r--r--zephyr/projects/trogdor/lazor/CMakeLists.txt23
-rw-r--r--zephyr/projects/trogdor/lazor/adc.dts48
-rw-r--r--zephyr/projects/trogdor/lazor/battery.dts24
-rw-r--r--zephyr/projects/trogdor/lazor/default_gpio_pinctrl.dts43
-rw-r--r--zephyr/projects/trogdor/lazor/display.dts18
-rw-r--r--zephyr/projects/trogdor/lazor/gpio.dts320
-rw-r--r--zephyr/projects/trogdor/lazor/gpio_led.dts33
-rw-r--r--zephyr/projects/trogdor/lazor/host_interface_npcx.dts12
-rw-r--r--zephyr/projects/trogdor/lazor/i2c.dts145
-rw-r--r--zephyr/projects/trogdor/lazor/include/sku.h17
-rw-r--r--zephyr/projects/trogdor/lazor/interrupts.dts140
-rw-r--r--zephyr/projects/trogdor/lazor/keyboard.dts38
-rw-r--r--zephyr/projects/trogdor/lazor/led.dts90
-rw-r--r--zephyr/projects/trogdor/lazor/motionsense.dts181
-rw-r--r--zephyr/projects/trogdor/lazor/prj.conf164
-rw-r--r--zephyr/projects/trogdor/lazor/pwm_led.dts59
-rw-r--r--zephyr/projects/trogdor/lazor/src/hibernate.c48
-rw-r--r--zephyr/projects/trogdor/lazor/src/i2c.c17
-rw-r--r--zephyr/projects/trogdor/lazor/src/power.c58
-rw-r--r--zephyr/projects/trogdor/lazor/src/sku.c92
-rw-r--r--zephyr/projects/trogdor/lazor/src/switchcap.c128
-rw-r--r--zephyr/projects/trogdor/lazor/src/usb_pd_policy.c261
-rw-r--r--zephyr/projects/trogdor/lazor/src/usbc_config.c335
-rw-r--r--zephyr/projects/trogdor/lazor/usbc.dts36
25 files changed, 2355 insertions, 0 deletions
diff --git a/zephyr/projects/trogdor/lazor/BUILD.py b/zephyr/projects/trogdor/lazor/BUILD.py
new file mode 100644
index 0000000000..ca1a26bdcf
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/BUILD.py
@@ -0,0 +1,25 @@
+# Copyright 2021 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Define zmake projects for lazor."""
+
+register_npcx_project(
+ project_name="lazor",
+ zephyr_board="npcx7",
+ dts_overlays=[
+ "adc.dts",
+ "battery.dts",
+ "display.dts",
+ "gpio.dts",
+ "i2c.dts",
+ "host_interface_npcx.dts",
+ "interrupts.dts",
+ "keyboard.dts",
+ "led.dts",
+ "motionsense.dts",
+ "pwm_led.dts",
+ "usbc.dts",
+ "default_gpio_pinctrl.dts",
+ ],
+)
diff --git a/zephyr/projects/trogdor/lazor/CMakeLists.txt b/zephyr/projects/trogdor/lazor/CMakeLists.txt
new file mode 100644
index 0000000000..b6d5024707
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/CMakeLists.txt
@@ -0,0 +1,23 @@
+# Copyright 2021 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+cmake_minimum_required(VERSION 3.13.1)
+
+find_package(Zephyr REQUIRED HINTS "${ZEPHYR_BASE}")
+project(lazor)
+
+cros_ec_library_include_directories(include)
+
+zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_USBC
+ "src/power.c"
+ "src/usb_pd_policy.c"
+ "src/usbc_config.c")
+
+zephyr_library_sources(
+ "src/sku.c"
+ "src/switchcap.c")
+
+# Board specific implementation
+zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_I2C
+ "src/i2c.c")
diff --git a/zephyr/projects/trogdor/lazor/adc.dts b/zephyr/projects/trogdor/lazor/adc.dts
new file mode 100644
index 0000000000..b834001587
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/adc.dts
@@ -0,0 +1,48 @@
+/* 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/dt-bindings/adc/adc.h>
+
+/ {
+ named-adc-channels {
+ compatible = "named-adc-channels";
+
+ vbus {
+ enum-name = "ADC_VBUS";
+ io-channels = <&adc0 1>;
+ /* Measure VBUS through a 1/10 voltage divider */
+ mul = <10>;
+ };
+ amon_bmon {
+ enum-name = "ADC_AMON_BMON";
+ io-channels = <&adc0 2>;
+ /*
+ * Adapter current output or battery charging/
+ * discharging current (uV) 18x amplification on
+ * charger side.
+ */
+ mul = <1000>;
+ div = <18>;
+ };
+ psys {
+ enum-name = "ADC_PSYS";
+ io-channels = <&adc0 3>;
+ /*
+ * ISL9238 PSYS output is 1.44 uA/W over 5.6K resistor,
+ * to read 0.8V @ 99 W, i.e. 124000 uW/mV.
+ */
+ mul = <124000>;
+ };
+ };
+
+};
+
+&adc0 {
+ status = "okay";
+ pinctrl-0 = <&adc0_chan1_gp44
+ &adc0_chan2_gp43
+ &adc0_chan3_gp42>;
+ pinctrl-names = "default";
+};
diff --git a/zephyr/projects/trogdor/lazor/battery.dts b/zephyr/projects/trogdor/lazor/battery.dts
new file mode 100644
index 0000000000..2b17dd4761
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/battery.dts
@@ -0,0 +1,24 @@
+/* Copyright 2021 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: ap16l5j {
+ compatible = "panasonic,ap16l5j", "battery-smart";
+ };
+ ap16l5j_009 {
+ compatible = "panasonic,ap16l5j-009", "battery-smart";
+ };
+ ap16l8j {
+ compatible = "lgc,ap16l8j", "battery-smart";
+ };
+ lgc_ap18c8k {
+ compatible = "lgc,ap18c8k", "battery-smart";
+ };
+ murata_ap18c4k {
+ compatible = "murata,ap18c4k", "battery-smart";
+ };
+ };
+};
diff --git a/zephyr/projects/trogdor/lazor/default_gpio_pinctrl.dts b/zephyr/projects/trogdor/lazor/default_gpio_pinctrl.dts
new file mode 100644
index 0000000000..1819bdbc3e
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/default_gpio_pinctrl.dts
@@ -0,0 +1,43 @@
+/* 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.
+ */
+
+/* Adds the &alt1_no_lpc_espi setting over the NPCX7 default setting. */
+&{/def-io-conf-list} {
+ pinmux = <&alt0_gpio_no_spip
+ &alt0_gpio_no_fpip
+ &alt1_no_pwrgd
+ &alt1_no_lpc_espi
+ &alta_no_peci_en
+ &altd_npsl_in1_sl
+ &altd_npsl_in2_sl
+ &altd_psl_in3_sl
+ &altd_psl_in4_sl
+ &alt7_no_ksi0_sl
+ &alt7_no_ksi1_sl
+ &alt7_no_ksi2_sl
+ &alt7_no_ksi3_sl
+ &alt7_no_ksi4_sl
+ &alt7_no_ksi5_sl
+ &alt7_no_ksi6_sl
+ &alt7_no_ksi7_sl
+ &alt8_no_kso00_sl
+ &alt8_no_kso01_sl
+ &alt8_no_kso02_sl
+ &alt8_no_kso03_sl
+ &alt8_no_kso04_sl
+ &alt8_no_kso05_sl
+ &alt8_no_kso06_sl
+ &alt8_no_kso07_sl
+ &alt9_no_kso08_sl
+ &alt9_no_kso09_sl
+ &alt9_no_kso10_sl
+ &alt9_no_kso11_sl
+ &alt9_no_kso12_sl
+ &alt9_no_kso13_sl
+ &alt9_no_kso14_sl
+ &alt9_no_kso15_sl
+ &alta_no_kso16_sl
+ &alta_no_kso17_sl >;
+};
diff --git a/zephyr/projects/trogdor/lazor/display.dts b/zephyr/projects/trogdor/lazor/display.dts
new file mode 100644
index 0000000000..65d3a2d91b
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/display.dts
@@ -0,0 +1,18 @@
+/* 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.
+ */
+
+/ {
+ displight {
+ compatible = "cros-ec,displight";
+ pwms = <&pwm5 0 PWM_HZ(4800) PWM_POLARITY_NORMAL>;
+ generic-pwm-channel = <1>;
+ };
+};
+
+&pwm5 {
+ status = "okay";
+ pinctrl-0 = <&pwm5_gpb7>;
+ pinctrl-names = "default";
+};
diff --git a/zephyr/projects/trogdor/lazor/gpio.dts b/zephyr/projects/trogdor/lazor/gpio.dts
new file mode 100644
index 0000000000..a047d7e2f2
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/gpio.dts
@@ -0,0 +1,320 @@
+/* Copyright 2021 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/wake_mask_event_defines.h>
+
+/ {
+ aliases {
+ gpio-wp = &gpio_ec_wp_odl;
+ gpio-kbd-kso2 = &gpio_ec_kso_02_inv;
+ };
+
+ named-gpios {
+ compatible = "named-gpios";
+
+ gpio_usb_c0_pd_int_odl: usb_c0_pd_int_odl {
+ gpios = <&gpioe 0 GPIO_INPUT>;
+ enum-name = "GPIO_USB_C0_PD_INT_ODL";
+ };
+ gpio_usb_c1_pd_int_odl: usb_c1_pd_int_odl {
+ gpios = <&gpiof 5 GPIO_INPUT>;
+ enum-name = "GPIO_USB_C1_PD_INT_ODL";
+ };
+ gpio_usb_c0_swctl_int_odl: usb_c0_swctl_int_odl {
+ gpios = <&gpio0 3 GPIO_INPUT>;
+ enum-name = "GPIO_USB_C0_SWCTL_INT_ODL";
+ };
+ gpio_usb_c1_swctl_int_odl: usb_c1_swctl_int_odl {
+ gpios = <&gpio4 0 GPIO_INPUT>;
+ enum-name = "GPIO_USB_C1_SWCTL_INT_ODL";
+ };
+ gpio_usb_c0_bc12_int_l: usb_c0_bc12_int_l {
+ gpios = <&gpio6 1 GPIO_INPUT_PULL_UP>;
+ };
+ gpio_usb_c1_bc12_int_l: usb_c1_bc12_int_l {
+ gpios = <&gpio8 2 GPIO_INPUT_PULL_UP>;
+ };
+ gpio_usb_a0_oc_odl: usb_a0_oc_odl {
+ gpios = <&gpiod 1 GPIO_INPUT_PULL_UP>;
+ };
+ gpio_acok_od: acok_od {
+ gpios = <&gpio0 0 GPIO_INPUT>;
+ enum-name = "GPIO_AC_PRESENT";
+ };
+ gpio_ccd_mode_odl: ccd_mode_odl {
+ gpios = <&gpioe 3 GPIO_INPUT>;
+ enum-name = "GPIO_CCD_MODE_ODL";
+ };
+ gpio_ec_pwr_btn_odl: ec_pwr_btn_odl {
+ gpios = <&gpio0 1 GPIO_INPUT>;
+ enum-name = "GPIO_POWER_BUTTON_L";
+ };
+ gpio_ec_voldn_btn_odl: ec_voldn_btn_odl {
+ gpios = <&gpio7 0 GPIO_INPUT_PULL_UP>;
+ enum-name = "GPIO_VOLUME_DOWN_L";
+ };
+ gpio_ec_volup_btn_odl: ec_volup_btn_odl {
+ gpios = <&gpiof 2 GPIO_INPUT_PULL_UP>;
+ enum-name = "GPIO_VOLUME_UP_L";
+ };
+ gpio_ec_wp_odl: ec_wp_odl {
+ gpios = <&gpioa 1 (GPIO_INPUT | GPIO_ACTIVE_LOW)>;
+ };
+ gpio_lid_open_ec: lid_open_ec {
+ gpios = <&gpiod 2 GPIO_INPUT>;
+ enum-name = "GPIO_LID_OPEN";
+ };
+ gpio_ap_rst_l: ap_rst_l {
+ gpios = <&gpioc 1 (GPIO_INPUT | GPIO_VOLTAGE_1P8)>;
+ enum-name = "GPIO_AP_RST_L";
+ };
+ gpio_ps_hold: ps_hold {
+ gpios = <&gpioa 4 GPIO_INPUT_PULL_DOWN>;
+ enum-name = "GPIO_PS_HOLD";
+ };
+ gpio_ap_suspend: ap_suspend {
+ gpios = <&gpio5 7 GPIO_INPUT>;
+ enum-name = "GPIO_AP_SUSPEND";
+ };
+ gpio_deprecated_ap_rst_req: deprecated_ap_rst_req {
+ gpios = <&gpioc 2 (GPIO_INPUT_PULL_DOWN | GPIO_VOLTAGE_1P8)>;
+ enum-name = "GPIO_DEPRECATED_AP_RST_REQ";
+ };
+ gpio_power_good: power_good {
+ gpios = <&gpio5 4 GPIO_INPUT_PULL_DOWN>;
+ enum-name = "GPIO_POWER_GOOD";
+ };
+ gpio_warm_reset_l: warm_reset_l {
+ gpios = <&gpiof 4 (GPIO_INPUT | GPIO_VOLTAGE_1P8)>;
+ enum-name = "GPIO_WARM_RESET_L";
+ };
+ ap_ec_spi_cs_l {
+ gpios = <&gpio5 3 GPIO_INPUT_PULL_DOWN>;
+ };
+ gpio_tablet_mode_l: tablet_mode_l {
+ gpios = <&gpioc 6 GPIO_INPUT>;
+ enum-name = "GPIO_TABLET_MODE_L";
+ };
+ gpio_accel_gyro_int_l: accel_gyro_int_l {
+ gpios = <&gpioa 0 GPIO_INPUT>;
+ };
+ gpio_da9313_gpio0: da9313_gpio0 {
+ gpios = <&gpioe 2 GPIO_INPUT>;
+ enum-name = "GPIO_DA9313_GPIO0";
+ };
+ /*
+ * Active low input
+ */
+ gpio_switchcap_pg_int_l: switchcap_pg_int_l {
+ gpios = <&gpioe 2 (GPIO_ACTIVE_LOW | GPIO_INPUT)>;
+ };
+ gpio_ec_rst_odl: ec_rst_odl {
+ gpios = <&gpio0 2 GPIO_INPUT>;
+ };
+ ec_entering_rw {
+ gpios = <&gpioe 1 GPIO_OUTPUT_LOW>;
+ enum-name = "GPIO_ENTERING_RW";
+ };
+ ec_batt_pres_odl {
+ gpios = <&gpioe 5 GPIO_INPUT>;
+ enum-name = "GPIO_BATT_PRES_ODL";
+ };
+ pm845_resin_l {
+ gpios = <&gpio3 2 GPIO_ODR_HIGH>;
+ enum-name = "GPIO_PMIC_RESIN_L";
+ };
+ pmic_kpd_pwr_odl {
+ gpios = <&gpiod 6 GPIO_ODR_HIGH>;
+ enum-name = "GPIO_PMIC_KPD_PWR_ODL";
+ };
+ ec_int_l {
+ gpios = <&gpioa 2 GPIO_ODR_HIGH>;
+ enum-name = "GPIO_EC_INT_L";
+ };
+ qsip_on {
+ gpios = <&gpio5 0 GPIO_OUTPUT_LOW>;
+ };
+ gpio_hibernate_l: hibernate_l {
+ gpios = <&gpio5 2 GPIO_OUTPUT_HIGH>;
+ };
+ gpio_switchcap_on: switchcap_on {
+ gpios = <&gpiod 5 GPIO_OUTPUT_LOW>;
+ enum-name = "GPIO_SWITCHCAP_ON";
+ };
+ gpio_vbob_en: vbob_en {
+ gpios = <&gpiod 3 GPIO_OUTPUT_LOW>;
+ enum-name = "GPIO_VBOB_EN";
+ };
+ gpio_en_pp3300_a: en_pp3300_a {
+ gpios = <&gpioa 6 GPIO_OUTPUT_LOW>;
+ enum-name = "GPIO_EN_PP3300_A";
+ };
+ gpio_en_pp5000_a: en_pp5000_a {
+ gpios = <&gpio6 7 GPIO_OUTPUT_LOW>;
+ enum-name = "GPIO_EN_PP5000";
+ };
+ ec_bl_disable_l {
+ gpios = <&gpiob 6 GPIO_OUTPUT_LOW>;
+ enum-name = "GPIO_ENABLE_BACKLIGHT";
+ };
+ gpio_lid_accel_int_l: lid_accel_int_l {
+ gpios = <&gpio5 6 GPIO_INPUT>;
+ };
+ trackpad_int_gate {
+ gpios = <&gpio7 4 GPIO_OUTPUT_LOW>;
+ };
+ gpio_usb_c0_pd_rst_l: usb_c0_pd_rst_l {
+ gpios = <&gpiof 1 GPIO_ODR_HIGH>;
+ };
+ gpio_usb_c1_pd_rst_l: usb_c1_pd_rst_l {
+ gpios = <&gpioe 4 GPIO_ODR_HIGH>;
+ };
+ gpio_dp_mux_oe_l: dp_mux_oe_l {
+ gpios = <&gpio9 6 GPIO_ODR_HIGH>;
+ };
+ gpio_dp_mux_sel: dp_mux_sel {
+ gpios = <&gpio4 5 GPIO_OUTPUT_LOW>;
+ };
+ gpio_dp_hot_plug_det: dp_hot_plug_det {
+ gpios = <&gpio9 5 GPIO_OUTPUT_LOW>;
+ };
+ gpio_en_usb_a_5v: en_usb_a_5v {
+ gpios = <&gpio8 6 GPIO_OUTPUT_LOW>;
+ enum-name = "GPIO_EN_USB_A_5V";
+ };
+ usb_a_cdp_ilim_en {
+ gpios = <&gpio7 5 GPIO_OUTPUT_HIGH>;
+ };
+ gpio_ec_chg_led_y_c1: ec_chg_led_y_c1 {
+ #led-pin-cells = <1>;
+ gpios = <&gpioc 3 GPIO_OUTPUT_LOW>;
+ };
+ gpio_ec_chg_led_b_c1: ec_chg_led_b_c1 {
+ #led-pin-cells = <1>;
+ gpios = <&gpioc 4 GPIO_OUTPUT_LOW>;
+ };
+ gpio_brd_id0: brd_id0 {
+ gpios = <&gpioc 7 GPIO_INPUT>;
+ enum-name = "GPIO_BOARD_VERSION1";
+ };
+ gpio_brd_id1: brd_id1 {
+ gpios = <&gpio9 3 GPIO_INPUT>;
+ enum-name = "GPIO_BOARD_VERSION2";
+ };
+ gpio_brd_id2: brd_id2 {
+ gpios = <&gpio6 3 GPIO_INPUT>;
+ enum-name = "GPIO_BOARD_VERSION3";
+ };
+ gpio_sku_id0: sku_id0 {
+ gpios = <&gpiof 0 GPIO_INPUT>;
+ };
+ gpio_sku_id1: sku_id1 {
+ gpios = <&gpio4 1 GPIO_INPUT>;
+ };
+ gpio_sku_id2: sku_id2 {
+ gpios = <&gpiod 4 GPIO_INPUT>;
+ };
+ arm_x86 {
+ gpios = <&gpio6 6 GPIO_OUTPUT_LOW>;
+ };
+ ec-i2c-sensor-scl {
+ gpios = <&gpiob 3 (GPIO_INPUT | GPIO_VOLTAGE_1P8)>;
+ };
+ ec-i2c-sensor-sda {
+ gpios = <&gpiob 2 (GPIO_INPUT | GPIO_VOLTAGE_1P8)>;
+ };
+ gpio_ec_kso_02_inv: ec_kso_02_inv {
+ gpios = <&gpio1 7 (GPIO_OUTPUT_LOW | GPIO_ACTIVE_LOW)>;
+ };
+ };
+
+ usba-port-enable-list {
+ compatible = "cros-ec,usba-port-enable-pins";
+ enable-pins = <&gpio_en_usb_a_5v>;
+ };
+
+ hibernate-wake-pins {
+ compatible = "cros-ec,hibernate-wake-pins";
+ wakeup-irqs = <
+ &int_ac_present
+ &int_power_button
+ &int_lid_open
+ &int_ec_rst
+ >;
+ };
+
+ ec-mkbp-host-event-wakeup-mask {
+ compatible = "ec-wake-mask-event";
+ wakeup-mask = <(
+ HOST_EVENT_LID_OPEN |
+ HOST_EVENT_POWER_BUTTON |
+ HOST_EVENT_AC_CONNECTED |
+ HOST_EVENT_AC_DISCONNECTED |
+ HOST_EVENT_HANG_DETECT |
+ HOST_EVENT_RTC |
+ HOST_EVENT_MODE_CHANGE |
+ HOST_EVENT_DEVICE)>;
+ };
+
+ ec-mkbp-event-wakeup-mask {
+ compatible = "ec-wake-mask-event";
+ wakeup-mask = <(MKBP_EVENT_KEY_MATRIX |
+ MKBP_EVENT_HOST_EVENT |
+ MKBP_EVENT_SENSOR_FIFO)>;
+ };
+
+ sku {
+ compatible = "cros-ec,gpio-id";
+
+ bits = <
+ &gpio_sku_id0
+ &gpio_sku_id1
+ &gpio_sku_id2
+ >;
+
+ system = "binary";
+ };
+
+ board {
+ compatible = "cros-ec,gpio-id";
+
+ bits = <
+ &gpio_brd_id0
+ &gpio_brd_id1
+ &gpio_brd_id2
+ >;
+
+ system = "binary_first_base3";
+ };
+
+ unused-pins {
+ compatible = "unused-gpios";
+ unused-gpios =
+ <&gpio5 1 0>,
+ <&gpiod 0 0>,
+ <&gpiof 3 0>,
+ <&gpio0 4 0>,
+ <&gpioc 0 0>,
+ <&gpioa 7 0>,
+ <&gpio8 3 0>,
+ <&gpio8 1 0>,
+ <&gpio3 7 0>,
+ <&gpio7 6 0>,
+ <&gpio3 4 0>,
+ <&gpioc 5 0>,
+ <&gpioa 3 0>,
+ <&gpio7 3 0>,
+ <&gpiod 7 0>,
+ <&gpioa 5 0>,
+ <&gpiob 0 0>,
+ <&gpio9 4 0>,
+ <&gpiob 1 0>,
+ <&gpio6 2 0>,
+ <&gpio3 5 0>,
+ <&gpio9 7 0>,
+ <&gpio6 0 0>,
+ <&gpio7 2 0>;
+ };
+};
diff --git a/zephyr/projects/trogdor/lazor/gpio_led.dts b/zephyr/projects/trogdor/lazor/gpio_led.dts
new file mode 100644
index 0000000000..c8c026506b
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/gpio_led.dts
@@ -0,0 +1,33 @@
+/* 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.
+ */
+
+/ {
+ gpio-led-pins {
+ compatible = "cros-ec,gpio-led-pins";
+
+ color_off: color-off {
+ led-color = "LED_OFF";
+ led-id = "EC_LED_ID_BATTERY_LED";
+ led-pins = <&gpio_ec_chg_led_y_c1 0>,
+ <&gpio_ec_chg_led_b_c1 0>;
+ };
+
+ color_amber: color-amber {
+ led-color = "LED_AMBER";
+ led-id = "EC_LED_ID_BATTERY_LED";
+ br-color = "EC_LED_COLOR_AMBER";
+ led-pins = <&gpio_ec_chg_led_y_c1 1>,
+ <&gpio_ec_chg_led_b_c1 0>;
+ };
+
+ color_blue: color-blue {
+ led-color = "LED_BLUE";
+ led-id = "EC_LED_ID_BATTERY_LED";
+ br-color = "EC_LED_COLOR_BLUE";
+ led-pins = <&gpio_ec_chg_led_y_c1 0>,
+ <&gpio_ec_chg_led_b_c1 1>;
+ };
+ };
+};
diff --git a/zephyr/projects/trogdor/lazor/host_interface_npcx.dts b/zephyr/projects/trogdor/lazor/host_interface_npcx.dts
new file mode 100644
index 0000000000..14efa3c6b2
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/host_interface_npcx.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.
+ */
+
+/* host interface */
+&shi {
+ status = "okay";
+ pinctrl-0 = <&shi_gp46_47_53_55>;
+ pinctrl-1 = <&shi_gpio_gp46_47_53_55>;
+ pinctrl-names = "default", "sleep";
+};
diff --git a/zephyr/projects/trogdor/lazor/i2c.dts b/zephyr/projects/trogdor/lazor/i2c.dts
new file mode 100644
index 0000000000..e19ad224a9
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/i2c.dts
@@ -0,0 +1,145 @@
+/* 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.
+ */
+
+/ {
+ named-i2c-ports {
+ compatible = "named-i2c-ports";
+
+ i2c_power: power {
+ i2c-port = <&i2c0_0>;
+ remote-port = <0>;
+ enum-names = "I2C_PORT_POWER",
+ "I2C_PORT_BATTERY",
+ "I2C_PORT_VIRTUAL_BATTERY",
+ "I2C_PORT_CHARGER";
+ };
+ i2c_tcpc0: tcpc0 {
+ i2c-port = <&i2c1_0>;
+ enum-names = "I2C_PORT_TCPC0";
+ };
+ i2c_tcpc1: tcpc1 {
+ i2c-port = <&i2c2_0>;
+ enum-names = "I2C_PORT_TCPC1";
+ };
+ i2c_eeprom: eeprom {
+ i2c-port = <&i2c5_0>;
+ enum-names = "I2C_PORT_EEPROM";
+ };
+ i2c_sensor: sensor {
+ i2c-port = <&i2c7_0>;
+ enum-names = "I2C_PORT_SENSOR",
+ "I2C_PORT_ACCEL";
+ };
+ };
+
+};
+
+&i2c0_0 {
+ status = "okay";
+ clock-frequency = <I2C_BITRATE_STANDARD>;
+ pinctrl-0 = <&i2c0_0_sda_scl_gpb4_b5>;
+ pinctrl-names = "default";
+
+ bc12_port0: pi3usb9201@5f {
+ compatible = "pericom,pi3usb9201";
+ status = "okay";
+ reg = <0x5f>;
+ irq = <&int_usb_c0_bc12>;
+ };
+
+ charger: isl923x@9 {
+ compatible = "intersil,isl923x";
+ status = "okay";
+ reg = <0x9>;
+ };
+};
+
+&i2c_ctrl0 {
+ status = "okay";
+};
+
+&i2c1_0 {
+ status = "okay";
+ clock-frequency = <I2C_BITRATE_FAST_PLUS>;
+ pinctrl-0 = <&i2c1_0_sda_scl_gp87_90>;
+ pinctrl-names = "default";
+
+ ppc_port0: sn5s330@40 {
+ compatible = "ti,sn5s330";
+ status = "okay";
+ reg = <0x40>;
+ };
+
+ tcpc_port0: ps8xxx@b {
+ compatible = "parade,ps8xxx";
+ status = "okay";
+ reg = <0xb>;
+ };
+};
+
+&i2c_ctrl1 {
+ status = "okay";
+};
+
+&i2c2_0 {
+ status = "okay";
+ clock-frequency = <I2C_BITRATE_FAST_PLUS>;
+ pinctrl-0 = <&i2c2_0_sda_scl_gp91_92>;
+ pinctrl-names = "default";
+
+ ppc_port1: sn5s330@40{
+ compatible = "ti,sn5s330";
+ status = "okay";
+ reg = <0x40>;
+ };
+
+ tcpc_port1: ps8xxx@b {
+ compatible = "parade,ps8xxx";
+ status = "okay";
+ reg = <0xb>;
+ };
+};
+
+&i2c_ctrl2 {
+ status = "okay";
+};
+
+&i2c3_0 {
+ /* Not used as no WLC connected */
+ clock-frequency = <I2C_BITRATE_FAST>;
+};
+
+&i2c_ctrl3 {
+ status = "okay";
+};
+
+&i2c5_0 {
+ status = "okay";
+ clock-frequency = <I2C_BITRATE_FAST>;
+ pinctrl-0 = <&i2c5_0_sda_scl_gp33_36>;
+ pinctrl-names = "default";
+
+ bc12_port1: pi3usb9201@5f {
+ compatible = "pericom,pi3usb9201";
+ status = "okay";
+ reg = <0x5f>;
+ irq = <&int_usb_c1_bc12>;
+ };
+};
+
+&i2c_ctrl5 {
+ status = "okay";
+};
+
+&i2c7_0 {
+ status = "okay";
+ clock-frequency = <I2C_BITRATE_FAST>;
+ pinctrl-0 = <&i2c7_0_sda_scl_gpb2_b3>;
+ pinctrl-names = "default";
+};
+
+&i2c_ctrl7 {
+ status = "okay";
+};
diff --git a/zephyr/projects/trogdor/lazor/include/sku.h b/zephyr/projects/trogdor/lazor/include/sku.h
new file mode 100644
index 0000000000..76825bbba1
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/include/sku.h
@@ -0,0 +1,17 @@
+/* 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.
+ */
+
+/* Lazor board-specific SKU configuration */
+
+#ifndef __ZEPHYR_LAZOR_SKU_H
+#define __ZEPHYR_LAZOR_SKU_H
+
+int board_get_version(void);
+int board_is_clamshell(void);
+int board_has_da9313(void);
+int board_has_ln9310(void);
+int board_has_buck_ic(void);
+
+#endif /* __ZEPHYR_LAZOR_SKU_H */
diff --git a/zephyr/projects/trogdor/lazor/interrupts.dts b/zephyr/projects/trogdor/lazor/interrupts.dts
new file mode 100644
index 0000000000..5c2ed35e90
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/interrupts.dts
@@ -0,0 +1,140 @@
+/* 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.
+ */
+
+/ {
+ aliases {
+ int-wp = &int_wp;
+ };
+
+ gpio-interrupts {
+ compatible = "cros-ec,gpio-interrupts";
+
+ int_ac_present: ac_present {
+ irq-pin = <&gpio_acok_od>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "extpower_interrupt";
+ };
+ int_lid_open: lid_open {
+ irq-pin = <&gpio_lid_open_ec>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "lid_interrupt";
+ };
+ int_wp: wp {
+ irq-pin = <&gpio_ec_wp_odl>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "switch_interrupt";
+ };
+ int_power_button: power_button {
+ irq-pin = <&gpio_ec_pwr_btn_odl>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "power_button_interrupt";
+ };
+ int_volume_up: volume_up {
+ irq-pin = <&gpio_ec_volup_btn_odl>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "button_interrupt";
+ };
+ int_volume_down: volume_down {
+ irq-pin = <&gpio_ec_voldn_btn_odl>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "button_interrupt";
+ };
+ /*
+ * Note this is an active low input, so
+ * the direction is from logical low to
+ * logical high.
+ */
+ int_switchcap_pg: switchcap_pg {
+ irq-pin = <&gpio_switchcap_pg_int_l>;
+ flags = <GPIO_INT_EDGE_RISING>;
+ handler = "ln9310_interrupt";
+ };
+ int_ap_rst: ap_rst {
+ irq-pin = <&gpio_ap_rst_l>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "chipset_ap_rst_interrupt";
+ };
+ int_ap_suspend: ap_suspend {
+ irq-pin = <&gpio_ap_suspend>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "power_signal_interrupt";
+ };
+ int_deprecated_ap_rst_req: deprecated_ap_rst_req {
+ irq-pin = <&gpio_deprecated_ap_rst_req>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "power_signal_interrupt";
+ };
+ int_power_good: power_good {
+ irq-pin = <&gpio_power_good>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "chipset_power_good_interrupt";
+ };
+ int_ps_hold: ps_hold {
+ irq-pin = <&gpio_ps_hold>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "power_signal_interrupt";
+ };
+ int_warm_reset: warm_reset {
+ irq-pin = <&gpio_warm_reset_l>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "chipset_warm_reset_interrupt";
+ };
+ int_usb_c0_tcpc: usb_c0_tcpc {
+ irq-pin = <&gpio_usb_c0_pd_int_odl>;
+ flags = <GPIO_INT_EDGE_FALLING>;
+ handler = "tcpc_alert_event";
+ };
+ int_usb_c1_tcpc: usb_c1_tcpc {
+ irq-pin = <&gpio_usb_c1_pd_int_odl>;
+ flags = <GPIO_INT_EDGE_FALLING>;
+ handler = "tcpc_alert_event";
+ };
+ int_usb_c0_swctl: usb_c0_swctl {
+ irq-pin = <&gpio_usb_c0_swctl_int_odl>;
+ flags = <GPIO_INT_EDGE_FALLING>;
+ handler = "ppc_interrupt";
+ };
+ int_usb_c1_swctl: usb_c1_swctl {
+ irq-pin = <&gpio_usb_c1_swctl_int_odl>;
+ flags = <GPIO_INT_EDGE_FALLING>;
+ handler = "ppc_interrupt";
+ };
+ int_usb_c0_bc12: usb_c0_bc12 {
+ irq-pin = <&gpio_usb_c0_bc12_int_l>;
+ flags = <GPIO_INT_EDGE_FALLING>;
+ handler = "usb0_evt";
+ };
+ int_usb_c1_bc12: usb_c1_bc12 {
+ irq-pin = <&gpio_usb_c1_bc12_int_l>;
+ flags = <GPIO_INT_EDGE_FALLING>;
+ handler = "usb1_evt";
+ };
+ int_usb_a0_oc: usb_a0_oc {
+ irq-pin = <&gpio_usb_a0_oc_odl>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "usba_oc_interrupt";
+ };
+ int_ccd_mode: ccd_mode {
+ irq-pin = <&gpio_ccd_mode_odl>;
+ flags = <GPIO_INT_EDGE_FALLING>;
+ handler = "board_connect_c0_sbu";
+ };
+ int_accel: accel {
+ irq-pin = <&gpio_accel_gyro_int_l>;
+ flags = <GPIO_INT_EDGE_FALLING>;
+ handler = "bmi160_interrupt";
+ };
+ int_tablet_mode: tablet_mode {
+ irq-pin = <&gpio_tablet_mode_l>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "gmr_tablet_switch_isr";
+ };
+ int_ec_rst: ec_rst {
+ irq-pin = <&gpio_ec_rst_odl>;
+ flags = <GPIO_INT_EDGE_FALLING>;
+ handler = "wake_isr";
+ };
+ };
+};
diff --git a/zephyr/projects/trogdor/lazor/keyboard.dts b/zephyr/projects/trogdor/lazor/keyboard.dts
new file mode 100644
index 0000000000..b8689b883c
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/keyboard.dts
@@ -0,0 +1,38 @@
+/* Copyright 2021 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/ {
+ cros-keyscan {
+ compatible = "cros-keyscan";
+
+ actual-key-mask = <
+ 0x14 /* C0 */
+ 0xff /* C1 */
+ 0xff /* C2 */
+ 0xff /* C3 */
+ 0xff /* C4 */
+ 0xf5 /* C5 */
+ 0xff /* C6 */
+ 0xa4 /* C7 */
+ 0xff /* C8 */
+ 0xfe /* C9 */
+ 0x55 /* C10 */
+ 0xfa /* C11 */
+ 0xca /* C12 */
+ >;
+ };
+
+ kblight {
+ compatible = "cros-ec,kblight-pwm";
+ pwms = <&pwm3 0 PWM_KHZ(10) PWM_POLARITY_NORMAL>;
+ generic-pwm-channel = <0>;
+ };
+};
+
+&pwm3 {
+ status = "okay";
+ pinctrl-0 = <&pwm3_gp80>;
+ pinctrl-names = "default";
+};
diff --git a/zephyr/projects/trogdor/lazor/led.dts b/zephyr/projects/trogdor/lazor/led.dts
new file mode 100644
index 0000000000..4527afd34c
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/led.dts
@@ -0,0 +1,90 @@
+/ {
+ led-colors {
+ compatible = "cros-ec,led-policy";
+
+ power-state-charge {
+ charge-state = "PWR_STATE_CHARGE";
+
+ color-0 {
+ led-color = <&color_amber>;
+ };
+ };
+
+ power-state-discharge-s0 {
+ charge-state = "PWR_STATE_DISCHARGE";
+ chipset-state = "POWER_S0";
+
+ color-0 {
+ led-color = <&color_blue>;
+ };
+ };
+
+ power-state-discharge-s3 {
+ charge-state = "PWR_STATE_DISCHARGE";
+ chipset-state = "POWER_S3";
+
+ /* Amber 1 sec, off 3 sec */
+ color-0 {
+ led-color = <&color_amber>;
+ period-ms = <1000>;
+ };
+ color-1 {
+ led-color = <&color_off>;
+ period-ms = <3000>;
+ };
+ };
+
+ power-state-discharge-s5 {
+ charge-state = "PWR_STATE_DISCHARGE";
+ chipset-state = "POWER_S5";
+
+ color-0 {
+ led-color = <&color_off>;
+ };
+ };
+
+ power-state-error {
+ charge-state = "PWR_STATE_ERROR";
+
+ /* Amber 1 sec, off 1 sec */
+ color-0 {
+ led-color = <&color_amber>;
+ period-ms = <1000>;
+ };
+ color-1 {
+ led-color = <&color_off>;
+ period-ms = <1000>;
+ };
+ };
+
+ power-state-near-full {
+ charge-state = "PWR_STATE_CHARGE_NEAR_FULL";
+
+ color-0 {
+ led-color = <&color_blue>;
+ };
+ };
+
+ power-state-forced-idle {
+ charge-state = "PWR_STATE_FORCED_IDLE";
+
+ /* Blue 2 sec, Amber 2 sec */
+ color-0 {
+ led-color = <&color_blue>;
+ period-ms = <2000>;
+ };
+ color-1 {
+ led-color = <&color_amber>;
+ period-ms = <2000>;
+ };
+ };
+
+ power-state-idle {
+ charge-state = "PWR_STATE_IDLE";
+
+ color-0 {
+ led-color = <&color_blue>;
+ };
+ };
+ };
+};
diff --git a/zephyr/projects/trogdor/lazor/motionsense.dts b/zephyr/projects/trogdor/lazor/motionsense.dts
new file mode 100644
index 0000000000..75fe31b997
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/motionsense.dts
@@ -0,0 +1,181 @@
+/* Copyright 2020 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/motionsense/utils.h>
+
+
+/ {
+ aliases {
+ /*
+ * motion sense's <>_INT_EVENT is handled
+ * by alias. Using the alias, each driver creates
+ * its own <>_INT_EVENT.
+ */
+ bmi160-int = &base_accel;
+ };
+
+ /*
+ * Declare mutexes used by sensor drivers.
+ * A mutex node is used to create an instance of mutex_t.
+ * A mutex node is referenced by a sensor node if the
+ * corresponding sensor driver needs to use the
+ * instance of the mutex.
+ */
+ motionsense-mutex {
+ compatible = "cros-ec,motionsense-mutex";
+ lid_mutex: lid-mutex {
+ };
+
+ mutex_bmi160: bmi160-mutex {
+ };
+ };
+
+ /* Rotation matrix used by drivers. */
+ motionsense-rotation-ref {
+ compatible = "cros-ec,motionsense-rotation-ref";
+ lid_rot_ref: lid-rotation-ref {
+ mat33 = <(-1) 0 0
+ 0 (-1) 0
+ 0 0 1>;
+ };
+
+ base_rot_ref: base-rotation-ref {
+ mat33 = <1 0 0
+ 0 (-1) 0
+ 0 0 (-1)>;
+ };
+ };
+
+ /*
+ * Driver specific data. A driver-specific data can be shared with
+ * different motion sensors while they are using the same driver.
+ *
+ * If a node's compatible starts with "cros-ec,accelgyro-", it is for
+ * a common structure defined in accelgyro.h.
+ * e.g) compatible = "cros-ec,accelgyro-als-drv-data" is for
+ * "struct als_drv_data_t" in accelgyro.h
+ */
+ motionsense-sensor-data {
+ bma255_data: bma255-drv-data {
+ compatible = "cros-ec,drvdata-bma255";
+ status = "okay";
+ };
+
+ bmi160_data: bmi160-drv-data {
+ compatible = "cros-ec,drvdata-bmi160";
+ status = "okay";
+ };
+
+ kx022_data: kx022-drv-data {
+ compatible = "cros-ec,drvdata-kionix";
+ status = "okay";
+ };
+ };
+
+ /*
+ * List of motion sensors that creates motion_sensors array.
+ * The nodelabel "lid_accel" and "base_accel" are used to indicate
+ * motion sensor IDs for lid angle calculation.
+ */
+ motionsense-sensor {
+ lid_accel: lid-accel {
+ compatible = "cros-ec,bma255";
+ status = "okay";
+
+ active-mask = "SENSOR_ACTIVE_S0_S3_S5";
+ location = "MOTIONSENSE_LOC_LID";
+ mutex = <&lid_mutex>;
+ port = <&i2c_sensor>;
+ rot-standard-ref = <&lid_rot_ref>;
+ default-range = <2>;
+ drv-data = <&bma255_data>;
+ i2c-spi-addr-flags = "BMA2x2_I2C_ADDR1_FLAGS";
+ configs {
+ compatible =
+ "cros-ec,motionsense-sensor-config";
+ ec-s0 {
+ odr = <(10000 | ROUND_UP_FLAG)>;
+ };
+ ec-s3 {
+ odr = <(10000 | ROUND_UP_FLAG)>;
+ };
+ };
+ };
+
+ base_accel: base-accel {
+ compatible = "cros-ec,bmi160-accel";
+ status = "okay";
+
+ active-mask = "SENSOR_ACTIVE_S0_S3_S5";
+ location = "MOTIONSENSE_LOC_BASE";
+ mutex = <&mutex_bmi160>;
+ port = <&i2c_sensor>;
+ rot-standard-ref = <&base_rot_ref>;
+ drv-data = <&bmi160_data>;
+ configs {
+ compatible =
+ "cros-ec,motionsense-sensor-config";
+ ec-s0 {
+ odr = <(10000 | ROUND_UP_FLAG)>;
+ };
+ ec-s3 {
+ odr = <(10000 | ROUND_UP_FLAG)>;
+ };
+ };
+ };
+
+ base-gyro {
+ compatible = "cros-ec,bmi160-gyro";
+ status = "okay";
+
+ active-mask = "SENSOR_ACTIVE_S0_S3_S5";
+ location = "MOTIONSENSE_LOC_BASE";
+ mutex = <&mutex_bmi160>;
+ port = <&i2c_sensor>;
+ rot-standard-ref = <&base_rot_ref>;
+ drv-data = <&bmi160_data>;
+ };
+ };
+
+ /*
+ * List of alternative motion sensors that creates
+ * motion_sensors_alt array.
+ */
+ motionsense-sensor-alt {
+ alt_lid_accel {
+ compatible = "cros-ec,kx022";
+ status = "okay";
+ active-mask = "SENSOR_ACTIVE_S0_S3_S5";
+ location = "MOTIONSENSE_LOC_LID";
+ mutex = <&lid_mutex>;
+ port = <&i2c_sensor>;
+ rot-standard-ref = <&lid_rot_ref>;
+ drv-data = <&kx022_data>;
+ alternate-for = <&lid_accel>;
+ configs {
+ compatible =
+ "cros-ec,motionsense-sensor-config";
+ ec-s0 {
+ odr = <(10000 | ROUND_UP_FLAG)>;
+ };
+ ec-s3 {
+ odr = <(10000 | ROUND_UP_FLAG)>;
+ };
+ };
+ };
+ };
+
+ motionsense-sensor-info {
+ compatible = "cros-ec,motionsense-sensor-info";
+
+ /*
+ * list of GPIO interrupts that have to
+ * be enabled at initial stage
+ */
+ sensor-irqs = <&int_accel>;
+ /* list of sensors in force mode */
+ accel-force-mode-sensors = <&lid_accel>;
+ };
+};
diff --git a/zephyr/projects/trogdor/lazor/prj.conf b/zephyr/projects/trogdor/lazor/prj.conf
new file mode 100644
index 0000000000..358de69d68
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/prj.conf
@@ -0,0 +1,164 @@
+# Copyright 2021 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+CONFIG_CROS_EC=y
+#
+# Lazor actually has a NPCX7M6FC, but
+# the NPCX7M7FC is actually the same die, without the
+# extra RAM being tested. The code size really could
+# do with the extra space, so we pretend the EC is the
+# part with the larger RAM. YMMV.
+#
+CONFIG_SOC_NPCX7M7FC=y
+CONFIG_SOC_SERIES_NPCX7=y
+CONFIG_SHIMMED_TASKS=y
+CONFIG_PLATFORM_EC=y
+CONFIG_PLATFORM_EC_BRINGUP=y
+CONFIG_PLATFORM_EC_EXTPOWER_GPIO=y
+CONFIG_PLATFORM_EC_SWITCH=y
+CONFIG_PLATFORM_EC_LID_SWITCH=y
+CONFIG_PLATFORM_EC_BACKLIGHT_LID=y
+CONFIG_PLATFORM_EC_POWER_BUTTON=y
+
+# I2C
+CONFIG_I2C=y
+
+# LED
+CONFIG_PLATFORM_EC_LED_DT=y
+
+# PWM
+CONFIG_PWM=y
+CONFIG_PWM_SHELL=n
+
+# Application Processor is Qualcomm SC7180
+CONFIG_AP_ARM_QUALCOMM_SC7180=y
+
+# Board version is selected over GPIO board ID pins.
+CONFIG_PLATFORM_EC_BOARD_VERSION_GPIO=y
+
+# LN9310 Switchcap
+CONFIG_PLATFORM_EC_SWITCHCAP_LN9310=y
+
+# Power Sequencing
+CONFIG_PLATFORM_EC_POWERSEQ=y
+CONFIG_PLATFORM_EC_POWERSEQ_HOST_SLEEP=y
+CONFIG_PLATFORM_EC_POWER_SLEEP_FAILURE_DETECTION=y
+CONFIG_PLATFORM_EC_CHIPSET_RESET_HOOK=y
+CONFIG_PLATFORM_EC_CHIPSET_RESUME_INIT_HOOK=y
+
+# Trogdor family does not use EFS2
+CONFIG_PLATFORM_EC_VBOOT_EFS2=n
+
+# MKBP event
+CONFIG_PLATFORM_EC_MKBP_EVENT=y
+CONFIG_PLATFORM_EC_MKBP_USE_GPIO=y
+
+# Keyboard
+CONFIG_PLATFORM_EC_KEYBOARD=y
+CONFIG_PLATFORM_EC_KEYBOARD_PROTOCOL_MKBP=y
+CONFIG_PLATFORM_EC_MKBP_INPUT_DEVICES=y
+CONFIG_PLATFORM_EC_KEYBOARD_COL2_INVERTED=y
+CONFIG_PLATFORM_EC_VOLUME_BUTTONS=y
+CONFIG_PLATFORM_EC_CMD_BUTTON=y
+CONFIG_CROS_KB_RAW_NPCX=y
+
+# ADC
+CONFIG_ADC=y
+CONFIG_ADC_SHELL=n
+
+# Battery
+CONFIG_PLATFORM_EC_BATTERY=y
+CONFIG_PLATFORM_EC_BATTERY_SMART=y
+CONFIG_PLATFORM_EC_I2C_VIRTUAL_BATTERY=y
+CONFIG_PLATFORM_EC_I2C_PASSTHRU_RESTRICTED=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_CHARGER_ISL9238=y
+CONFIG_PLATFORM_EC_CHARGE_RAMP_HW=y
+CONFIG_PLATFORM_EC_USE_BATTERY_DEVICE_CHEMISTRY=y
+CONFIG_PLATFORM_EC_BATTERY_DEVICE_CHEMISTRY="LION"
+CONFIG_PLATFORM_EC_BATTERY_REVIVE_DISCONNECT=y
+CONFIG_PLATFORM_EC_CHARGER_DISCHARGE_ON_AC=y
+CONFIG_PLATFORM_EC_CHARGER_DISCHARGE_ON_AC_CHARGER=y
+CONFIG_PLATFORM_EC_CHARGER_MIN_BAT_PCT_FOR_POWER_ON=2
+CONFIG_PLATFORM_EC_CHARGER_MIN_POWER_MW_FOR_POWER_ON=10000
+CONFIG_PLATFORM_EC_CHARGER_PROFILE_OVERRIDE=y
+CONFIG_PLATFORM_EC_CHARGER_PSYS=y
+CONFIG_PLATFORM_EC_CHARGER_PSYS_READ=y
+CONFIG_PLATFORM_EC_CHARGER_SENSE_RESISTOR=10
+CONFIG_PLATFORM_EC_CHARGER_SENSE_RESISTOR_AC=20
+CONFIG_PLATFORM_EC_CONSOLE_CMD_CHARGER_ADC_AMON_BMON=y
+
+# USB-A
+CONFIG_PLATFORM_EC_USBA=y
+
+# USB-C
+CONFIG_PLATFORM_EC_BC12_DETECT_PI3USB9201=y
+CONFIG_PLATFORM_EC_USB_PD_USB32_DRD=n
+CONFIG_PLATFORM_EC_USBC_PPC_SN5S330=y
+CONFIG_PLATFORM_EC_USBC_RETIMER_FW_UPDATE=n
+CONFIG_PLATFORM_EC_USBC_SS_MUX_DFP_ONLY=y
+CONFIG_PLATFORM_EC_USB_DRP_ACC_TRYSRC=y
+CONFIG_PLATFORM_EC_USB_PD_5V_EN_CUSTOM=y
+CONFIG_PLATFORM_EC_USB_PD_VBUS_DETECT_TCPC=y
+CONFIG_PLATFORM_EC_USB_PD_DISCHARGE_PPC=y
+CONFIG_PLATFORM_EC_USB_PD_REV30=n
+CONFIG_PLATFORM_EC_USB_PD_TBT_COMPAT_MODE=n
+CONFIG_PLATFORM_EC_USB_PD_USB4=n
+CONFIG_PLATFORM_EC_USB_PD_TCPC_LOW_POWER=y
+CONFIG_PLATFORM_EC_USB_PD_TCPM_MULTI_PS8XXX=y
+CONFIG_PLATFORM_EC_USB_PD_TCPM_PS8751=y
+CONFIG_PLATFORM_EC_USB_PD_TCPM_PS8805=y
+CONFIG_PLATFORM_EC_USB_PD_TCPC_RUNTIME_CONFIG=n
+CONFIG_PLATFORM_EC_USB_MUX_RUNTIME_CONFIG=n
+CONFIG_PLATFORM_EC_USB_PD_LOGGING=y
+
+# USB ID
+# This is allocated specifically for Trogdor
+# http://google3/hardware/standards/usb/
+# TODO(b/183608112): Move to device tree
+CONFIG_PLATFORM_EC_USB_PID=0x5043
+
+# RTC
+CONFIG_PLATFORM_EC_RTC=y
+CONFIG_CROS_RTC_NPCX=y
+CONFIG_PLATFORM_EC_HOSTCMD_RTC=y
+CONFIG_PLATFORM_EC_CONSOLE_CMD_RTC=y
+
+# EC software sync
+CONFIG_PLATFORM_EC_VBOOT_HASH=y
+
+# Sensors
+CONFIG_PLATFORM_EC_MOTIONSENSE=y
+CONFIG_PLATFORM_EC_ACCEL_FIFO=y
+CONFIG_PLATFORM_EC_CONSOLE_CMD_ACCELS=y
+CONFIG_PLATFORM_EC_CONSOLE_CMD_ACCEL_INFO=y
+CONFIG_PLATFORM_EC_GMR_TABLET_MODE=y
+CONFIG_PLATFORM_EC_LID_ANGLE=y
+CONFIG_PLATFORM_EC_LID_ANGLE_UPDATE=y
+CONFIG_PLATFORM_EC_SENSOR_TIGHT_TIMESTAMPS=y
+CONFIG_PLATFORM_EC_TABLET_MODE=y
+CONFIG_PLATFORM_EC_TABLET_MODE_SWITCH=y
+
+# Sensor Drivers
+CONFIG_PLATFORM_EC_ACCEL_BMA255=y
+CONFIG_PLATFORM_EC_ACCELGYRO_BMI160=y
+CONFIG_PLATFORM_EC_ACCELGYRO_BMI_COMM_I2C=y
+
+# Console history
+CONFIG_SHELL_HISTORY=y
+CONFIG_SHELL_CMDS=y
+CONFIG_SHELL_HELP=n
+CONFIG_SHELL_MINIMAL=y
+
+# Taskinfo
+CONFIG_THREAD_MONITOR=y
+CONFIG_KERNEL_SHELL=y
+
+CONFIG_SYSCON=y
+
+# Features should be enabled. But the code RAM is not enough, disable them.
+#CONFIG_PLATFORM_EC_ACCEL_SPOOF_MODE=y
+#CONFIG_PLATFORM_EC_EMULATED_SYSRQ=y
diff --git a/zephyr/projects/trogdor/lazor/pwm_led.dts b/zephyr/projects/trogdor/lazor/pwm_led.dts
new file mode 100644
index 0000000000..0582966d6a
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/pwm_led.dts
@@ -0,0 +1,59 @@
+/* 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.
+ */
+
+/ {
+ pwm_pins {
+ compatible = "cros-ec,pwm-pin-config";
+
+ pwm_y: pwm_y {
+ #led-pin-cells = <1>;
+ pwms = <&pwm0 0 PWM_HZ(324) PWM_POLARITY_NORMAL>;
+ };
+
+ pwm_b: pwm_b {
+ #led-pin-cells = <1>;
+ pwms = <&pwm2 0 PWM_HZ(324) PWM_POLARITY_NORMAL>;
+ };
+ };
+
+ pwm-led-pins {
+ compatible = "cros-ec,pwm-led-pins";
+
+ color_off: color-off {
+ led-color = "LED_OFF";
+ led-id = "EC_LED_ID_BATTERY_LED";
+ led-pins = <&pwm_y 0>,
+ <&pwm_b 0>;
+ };
+
+ color_amber: color-amber {
+ led-color = "LED_AMBER";
+ led-id = "EC_LED_ID_BATTERY_LED";
+ br-color = "EC_LED_COLOR_AMBER";
+ led-pins = <&pwm_y 100>,
+ <&pwm_b 0>;
+ };
+
+ color_blue: color-blue {
+ led-color = "LED_BLUE";
+ led-id = "EC_LED_ID_BATTERY_LED";
+ br-color = "EC_LED_COLOR_BLUE";
+ led-pins = <&pwm_y 0>,
+ <&pwm_b 100>;
+ };
+ };
+};
+
+&pwm0 {
+ status = "okay";
+ pinctrl-0 = <&pwm0_gpc3>;
+ pinctrl-names = "default";
+};
+
+&pwm2 {
+ status = "okay";
+ pinctrl-0 = <&pwm2_gpc4>;
+ pinctrl-names = "default";
+};
diff --git a/zephyr/projects/trogdor/lazor/src/hibernate.c b/zephyr/projects/trogdor/lazor/src/hibernate.c
new file mode 100644
index 0000000000..388ff1b087
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/src/hibernate.c
@@ -0,0 +1,48 @@
+/* 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 "common.h"
+#include "sku.h"
+#include "system.h"
+#include "usbc_ppc.h"
+
+void board_hibernate(void)
+{
+ int i;
+
+ if (!board_is_clamshell()) {
+ /*
+ * Sensors are unpowered in hibernate. Apply PD to the
+ * interrupt lines such that they don't float.
+ */
+ gpio_pin_configure_dt(
+ GPIO_DT_FROM_NODELABEL(gpio_accel_gyro_int_l),
+ GPIO_DISCONNECTED);
+ gpio_pin_configure_dt(
+ GPIO_DT_FROM_NODELABEL(gpio_lid_accel_int_l),
+ GPIO_DISCONNECTED);
+ }
+
+ /*
+ * Board rev 5+ has the hardware fix. Don't need the following
+ * workaround.
+ */
+ if (system_get_board_version() >= 5)
+ return;
+
+ /*
+ * Enable the PPC power sink path before EC enters hibernate;
+ * otherwise, ACOK won't go High and can't wake EC up. Check the
+ * bug b/170324206 for details.
+ */
+ for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++)
+ ppc_vbus_sink_enable(i, 1);
+}
+
+void board_hibernate_late(void)
+{
+ /* Set the hibernate GPIO to turn off the rails */
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_hibernate_l), 0);
+}
diff --git a/zephyr/projects/trogdor/lazor/src/i2c.c b/zephyr/projects/trogdor/lazor/src/i2c.c
new file mode 100644
index 0000000000..6d737b410f
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/src/i2c.c
@@ -0,0 +1,17 @@
+/* Copyright 2021 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "i2c/i2c.h"
+#include "i2c.h"
+
+/* Lazor board specific i2c implementation */
+
+#ifdef CONFIG_PLATFORM_EC_I2C_PASSTHRU_RESTRICTED
+int board_allow_i2c_passthru(const struct i2c_cmd_desc_t *cmd_desc)
+{
+ return (i2c_get_device_for_port(cmd_desc->port) ==
+ i2c_get_device_for_port(I2C_PORT_VIRTUAL_BATTERY));
+}
+#endif
diff --git a/zephyr/projects/trogdor/lazor/src/power.c b/zephyr/projects/trogdor/lazor/src/power.c
new file mode 100644
index 0000000000..96f9bc43c5
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/src/power.c
@@ -0,0 +1,58 @@
+/* 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/init.h>
+#include <zephyr/drivers/gpio.h>
+
+#include <ap_power/ap_power.h>
+#include "power.h"
+#include "task.h"
+#include "gpio.h"
+
+static void board_power_change(struct ap_power_ev_callback *cb,
+ struct ap_power_ev_data data)
+{
+ switch (data.event) {
+ default:
+ return;
+
+ case AP_POWER_PRE_INIT:
+ /* Turn on the 3.3V rail */
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_en_pp3300_a), 1);
+
+ /* Turn on the 5V rail. */
+#ifdef CONFIG_POWER_PP5000_CONTROL
+ power_5v_enable(task_get_current(), 1);
+#else /* !defined(CONFIG_POWER_PP5000_CONTROL) */
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_en_pp5000_a), 1);
+#endif /* defined(CONFIG_POWER_PP5000_CONTROL) */
+ break;
+
+ case AP_POWER_SHUTDOWN_COMPLETE:
+ /* Turn off the 5V rail. */
+#ifdef CONFIG_POWER_PP5000_CONTROL
+ power_5v_enable(task_get_current(), 0);
+#else /* !defined(CONFIG_POWER_PP5000_CONTROL) */
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_en_pp5000_a), 0);
+#endif /* defined(CONFIG_POWER_PP5000_CONTROL) */
+
+ /* Turn off the 3.3V and 5V rails. */
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_en_pp3300_a), 0);
+ break;
+ }
+}
+
+static int board_power_handler_init(const struct device *unused)
+{
+ static struct ap_power_ev_callback cb;
+
+ /* Setup a suspend/resume callback */
+ ap_power_ev_init_callback(&cb, board_power_change,
+ AP_POWER_PRE_INIT |
+ AP_POWER_SHUTDOWN_COMPLETE);
+ ap_power_ev_add_callback(&cb);
+ return 0;
+}
+SYS_INIT(board_power_handler_init, APPLICATION, 1);
diff --git a/zephyr/projects/trogdor/lazor/src/sku.c b/zephyr/projects/trogdor/lazor/src/sku.c
new file mode 100644
index 0000000000..1d88437031
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/src/sku.c
@@ -0,0 +1,92 @@
+/* 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 "common.h"
+#include "config.h"
+#include "console.h"
+#include "driver/ln9310.h"
+#include "tcpm/ps8xxx_public.h"
+#include "hooks.h"
+#include "sku.h"
+#include "system.h"
+#include "util.h"
+
+#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args)
+#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args)
+
+static uint8_t sku_id;
+
+enum board_model {
+ LAZOR,
+ LIMOZEEN,
+ UNKNOWN,
+};
+
+static const char *const model_name[] = {
+ "LAZOR",
+ "LIMOZEEN",
+ "UNKNOWN",
+};
+
+static enum board_model get_model(void)
+{
+ if (sku_id == 0 || sku_id == 1 || sku_id == 2 || sku_id == 3)
+ return LAZOR;
+ if (sku_id == 4 || sku_id == 5 || sku_id == 6)
+ return LIMOZEEN;
+ return UNKNOWN;
+}
+
+/* Read SKU ID from GPIO and initialize variables for board variants */
+static void sku_init(void)
+{
+ sku_id = system_get_sku_id();
+ CPRINTS("SKU: %u (%s)", sku_id, model_name[get_model()]);
+}
+DECLARE_HOOK(HOOK_INIT, sku_init, HOOK_PRIO_POST_I2C);
+
+enum battery_cell_type board_get_battery_cell_type(void)
+{
+ switch (get_model()) {
+ case LIMOZEEN:
+ return BATTERY_CELL_TYPE_3S;
+ default:
+ return BATTERY_CELL_TYPE_UNKNOWN;
+ }
+}
+
+int board_is_clamshell(void)
+{
+ return get_model() == LIMOZEEN;
+}
+
+__override uint16_t board_get_ps8xxx_product_id(int port)
+{
+ /*
+ * Lazor (SKU_ID: 0, 1, 2, 3) rev 3+ changes TCPC from PS8751 to
+ * PS8805.
+ *
+ * Limozeen (SKU_ID: 4, 5, 6) all-rev uses PS8805.
+ */
+ if (get_model() == LAZOR && system_get_board_version() < 3)
+ return PS8751_PRODUCT_ID;
+
+ return PS8805_PRODUCT_ID;
+}
+
+int board_has_da9313(void)
+{
+ return get_model() == LAZOR;
+}
+
+int board_has_buck_ic(void)
+{
+ return get_model() == LIMOZEEN && system_get_board_version() >= 8;
+}
+
+int board_has_ln9310(void)
+{
+ return get_model() == LIMOZEEN && system_get_board_version() < 8;
+}
diff --git a/zephyr/projects/trogdor/lazor/src/switchcap.c b/zephyr/projects/trogdor/lazor/src/switchcap.c
new file mode 100644
index 0000000000..d8205cbcfc
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/src/switchcap.c
@@ -0,0 +1,128 @@
+/* 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 "common.h"
+#include "config.h"
+#include "console.h"
+#include "driver/ln9310.h"
+#include "gpio/gpio_int.h"
+#include "hooks.h"
+#include "i2c.h"
+#include "power/qcom.h"
+#include "system.h"
+#include "sku.h"
+
+#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args)
+#define CPRINTF(format, args...) cprintf(CC_I2C, format, ##args)
+
+/* LN9310 switchcap */
+const struct ln9310_config_t ln9310_config = {
+ .i2c_port = I2C_PORT_POWER,
+ .i2c_addr_flags = LN9310_I2C_ADDR_0_FLAGS,
+};
+
+static void switchcap_init(void)
+{
+ if (board_has_da9313()) {
+ CPRINTS("Use switchcap: DA9313");
+
+ /*
+ * When the chip in power down mode, it outputs high-Z.
+ * Set pull-down to avoid floating.
+ */
+ gpio_pin_configure_dt(GPIO_DT_FROM_NODELABEL(gpio_da9313_gpio0),
+ GPIO_INPUT | GPIO_PULL_DOWN);
+
+ /*
+ * Configure DA9313 enable, push-pull output. Don't set the
+ * level here; otherwise, it will override its value and
+ * shutdown the switchcap when sysjump to RW.
+ */
+ gpio_pin_configure_dt(GPIO_DT_FROM_NODELABEL(gpio_switchcap_on),
+ GPIO_OUTPUT);
+ } else if (board_has_ln9310()) {
+ CPRINTS("Use switchcap: LN9310");
+
+ /* Enable interrupt for LN9310 */
+ gpio_enable_dt_interrupt(
+ GPIO_INT_FROM_NODELABEL(int_switchcap_pg));
+
+ /*
+ * Configure LN9310 enable, open-drain output. Don't set the
+ * level here; otherwise, it will override its value and
+ * shutdown the switchcap when sysjump to RW.
+ *
+ * Note that the gpio.inc configures it GPIO_OUT_LOW. When
+ * sysjump to RW, will output push-pull a short period of
+ * time. As it outputs LOW, should be fine.
+ *
+ * This GPIO changes like:
+ * (1) EC boots from RO -> high-Z
+ * (2) GPIO init according to gpio.inc -> push-pull LOW
+ * (3) This function configures it -> open-drain HIGH
+ * (4) Power sequence turns on the switchcap -> open-drain LOW
+ * (5) EC sysjumps to RW
+ * (6) GPIO init according to gpio.inc -> push-pull LOW
+ * (7) This function configures it -> open-drain LOW
+ */
+ gpio_pin_configure_dt(GPIO_DT_FROM_NODELABEL(gpio_switchcap_on),
+ GPIO_OUTPUT | GPIO_OPEN_DRAIN);
+
+ /* Only configure the switchcap if not sysjump */
+ if (!system_jumped_late()) {
+ /*
+ * Deassert the enable pin, so the
+ * switchcap won't be enabled after the switchcap is
+ * configured from standby mode to switching mode.
+ */
+ gpio_pin_set_dt(
+ GPIO_DT_FROM_NODELABEL(gpio_switchcap_on), 0);
+ ln9310_init();
+ }
+ } else if (board_has_buck_ic()) {
+ CPRINTS("Use Buck IC");
+ } else {
+ CPRINTS("ERROR: No switchcap solution");
+ }
+}
+DECLARE_HOOK(HOOK_INIT, switchcap_init, HOOK_PRIO_DEFAULT);
+
+void board_set_switchcap_power(int enable)
+{
+ if (board_has_da9313()) {
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_switchcap_on),
+ enable);
+ } else if (board_has_ln9310()) {
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_switchcap_on),
+ enable);
+ ln9310_software_enable(enable);
+ } else if (board_has_buck_ic()) {
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_vbob_en), enable);
+ }
+}
+
+int board_is_switchcap_enabled(void)
+{
+ if (board_has_da9313() || board_has_ln9310())
+ return gpio_pin_get_dt(
+ GPIO_DT_FROM_NODELABEL(gpio_switchcap_on));
+
+ /* Board has buck ic*/
+ return gpio_pin_get_dt(GPIO_DT_FROM_NODELABEL(gpio_vbob_en));
+}
+
+int board_is_switchcap_power_good(void)
+{
+ if (board_has_da9313())
+ return gpio_pin_get_dt(
+ GPIO_DT_FROM_NODELABEL(gpio_da9313_gpio0));
+ else if (board_has_ln9310())
+ return ln9310_power_good();
+
+ /* Board has buck ic no way to check POWER GOOD */
+ return 1;
+}
diff --git a/zephyr/projects/trogdor/lazor/src/usb_pd_policy.c b/zephyr/projects/trogdor/lazor/src/usb_pd_policy.c
new file mode 100644
index 0000000000..8d046826f9
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/src/usb_pd_policy.c
@@ -0,0 +1,261 @@
+/* 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 "charge_manager.h"
+#include "chipset.h"
+#include "console.h"
+#include "system.h"
+#include "usb_mux.h"
+#include "usbc_ppc.h"
+#include "util.h"
+
+#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args)
+#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args)
+
+int pd_check_vconn_swap(int port)
+{
+ /* In G3, do not allow vconn swap since PP5000 rail is off */
+ return gpio_pin_get_dt(GPIO_DT_FROM_NODELABEL(gpio_en_pp5000_a));
+}
+
+static uint8_t vbus_en[CONFIG_USB_PD_PORT_MAX_COUNT];
+#if CONFIG_USB_PD_PORT_MAX_COUNT == 1
+static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5 };
+#else
+static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5,
+ TYPEC_RP_1A5 };
+#endif
+
+static void board_vbus_update_source_current(int port)
+{
+ /* Both port are controlled by PPC SN5S330. */
+ ppc_set_vbus_source_current_limit(port, vbus_rp[port]);
+ ppc_vbus_source_enable(port, vbus_en[port]);
+}
+
+void pd_power_supply_reset(int port)
+{
+ int prev_en;
+
+ prev_en = vbus_en[port];
+
+ /* Disable VBUS */
+ vbus_en[port] = 0;
+ board_vbus_update_source_current(port);
+
+ /* Enable discharge if we were previously sourcing 5V */
+ if (prev_en)
+ 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)
+{
+ /* Disable charging */
+ board_vbus_sink_enable(port, 0);
+
+ pd_set_vbus_discharge(port, 0);
+
+ /* Provide VBUS */
+ vbus_en[port] = 1;
+ board_vbus_update_source_current(port);
+
+ /* notify host of power info change */
+ pd_send_host_event(PD_EVENT_POWER_CHANGE);
+
+ return EC_SUCCESS; /* we are ready */
+}
+
+int board_vbus_source_enabled(int port)
+{
+ return vbus_en[port];
+}
+
+__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp)
+{
+ vbus_rp[port] = rp;
+ board_vbus_update_source_current(port);
+}
+
+int pd_snk_is_vbus_provided(int port)
+{
+ return tcpm_check_vbus_level(port, VBUS_PRESENT);
+}
+
+/* ----------------- Vendor Defined Messages ------------------ */
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+__override int svdm_dp_config(int port, uint32_t *payload)
+{
+ int opos = pd_alt_mode(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT);
+ uint8_t pin_mode = get_dp_pin_mode(port);
+
+ if (!pin_mode)
+ return 0;
+
+ /*
+ * Defer setting the usb_mux until HPD goes high, svdm_dp_attention().
+ * The AP only supports one DP phy. An external DP mux switches between
+ * the two ports. Should switch those muxes when it is really used,
+ * i.e. HPD high; otherwise, the real use case is preempted, like:
+ * (1) plug a dongle without monitor connected to port-0,
+ * (2) plug a dongle without monitor connected to port-1,
+ * (3) plug a monitor to the port-1 dongle.
+ */
+
+ payload[0] =
+ VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_CONFIG | VDO_OPOS(opos));
+ payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */
+ 1, /* DPv1.3 signaling */
+ 2); /* UFP connected */
+ return 2;
+};
+
+__override void svdm_dp_post_config(int port)
+{
+ dp_flags[port] |= DP_FLAGS_DP_ON;
+}
+
+/**
+ * Is the port fine to be muxed its DisplayPort lines?
+ *
+ * Only one port can be muxed to DisplayPort at a time.
+ *
+ * @param port Port number of TCPC.
+ * @return 1 is fine; 0 is bad as other port is already muxed;
+ */
+static int is_dp_muxable(int port)
+{
+ int i;
+
+ for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++)
+ if (i != port) {
+ if (usb_mux_get(i) & USB_PD_MUX_DP_ENABLED)
+ return 0;
+ }
+
+ return 1;
+}
+
+__override int svdm_dp_attention(int port, uint32_t *payload)
+{
+ const struct gpio_dt_spec *hpd =
+ GPIO_DT_FROM_NODELABEL(gpio_dp_hot_plug_det);
+ int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]);
+ int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]);
+ int cur_lvl = gpio_pin_get_dt(hpd);
+ mux_state_t mux_state;
+
+ dp_status[port] = payload[1];
+
+ if (!is_dp_muxable(port)) {
+ /* TODO(waihong): Info user? */
+ CPRINTS("p%d: The other port is already muxed.", port);
+ return 0;
+ }
+
+ /*
+ * Initial implementation to handle HPD. Only the first-plugged port
+ * works, i.e. sending HPD signal to AP. The second-plugged port
+ * will be ignored.
+ *
+ * TODO(waihong): Continue the above case, if the first-plugged port
+ * is then unplugged, switch to the second-plugged port and signal AP?
+ */
+ if (lvl) {
+ /*
+ * Enable and switch the DP port selection mux to the
+ * correct port.
+ *
+ * TODO(waihong): Better to move switching DP mux to
+ * the usb_mux abstraction.
+ */
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_dp_mux_sel),
+ port == 1);
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_dp_mux_oe_l), 0);
+
+ /* Connect the SBU lines in PPC chip. */
+ if (IS_ENABLED(CONFIG_USBC_PPC_SBU))
+ ppc_set_sbu(port, 1);
+
+ /*
+ * Connect the USB SS/DP lines in TCPC chip.
+ *
+ * When mf_pref not true, still use the dock muxing
+ * because of the board USB-C topology (limited to 2
+ * lanes DP).
+ */
+ usb_mux_set(port, USB_PD_MUX_DOCK, USB_SWITCH_CONNECT,
+ polarity_rm_dts(pd_get_polarity(port)));
+ } else {
+ /* Disconnect the DP port selection mux. */
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_dp_mux_oe_l), 1);
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_dp_mux_sel), 0);
+
+ /* Disconnect the SBU lines in PPC chip. */
+ if (IS_ENABLED(CONFIG_USBC_PPC_SBU))
+ ppc_set_sbu(port, 0);
+
+ /* Disconnect the DP but keep the USB SS lines in TCPC chip. */
+ usb_mux_set(port, USB_PD_MUX_USB_ENABLED, USB_SWITCH_CONNECT,
+ polarity_rm_dts(pd_get_polarity(port)));
+ }
+
+ if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && (irq || lvl))
+ /*
+ * Wake up the AP. IRQ or level high indicates a DP sink is now
+ * present.
+ */
+ pd_notify_dp_alt_mode_entry(port);
+
+ /* Configure TCPC for the HPD event, for proper muxing */
+ mux_state = (lvl ? USB_PD_MUX_HPD_LVL : USB_PD_MUX_HPD_LVL_DEASSERTED) |
+ (irq ? USB_PD_MUX_HPD_IRQ : USB_PD_MUX_HPD_IRQ_DEASSERTED);
+ usb_mux_hpd_update(port, mux_state);
+
+ /* Signal AP for the HPD event, through GPIO to AP */
+ if (irq & cur_lvl) {
+ uint64_t now = get_time().val;
+ /* Wait for the minimum spacing between IRQ_HPD if needed */
+ if (now < svdm_hpd_deadline[port])
+ usleep(svdm_hpd_deadline[port] - now);
+
+ /* Generate IRQ_HPD pulse */
+ gpio_pin_set_dt(hpd, 0);
+ usleep(HPD_DSTREAM_DEBOUNCE_IRQ);
+ gpio_pin_set_dt(hpd, 1);
+
+ /* Set the minimum time delay (2ms) for the next HPD IRQ */
+ svdm_hpd_deadline[port] =
+ get_time().val + HPD_USTREAM_DEBOUNCE_LVL;
+ } else if (irq & !lvl) {
+ CPRINTF("ERR:HPD:IRQ&LOW\n");
+ return 0;
+ }
+ gpio_pin_set_dt(hpd, lvl);
+ /* Set the minimum time delay (2ms) for the next HPD IRQ */
+ svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL;
+
+ return 1;
+}
+
+__override void svdm_exit_dp_mode(int port)
+{
+ if (is_dp_muxable(port)) {
+ /* Disconnect the DP port selection mux. */
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_dp_mux_oe_l), 1);
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_dp_mux_sel), 0);
+
+ /* Signal AP for the HPD low event */
+ usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED |
+ USB_PD_MUX_HPD_IRQ_DEASSERTED);
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_dp_hot_plug_det),
+ 0);
+ }
+}
+#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
diff --git a/zephyr/projects/trogdor/lazor/src/usbc_config.c b/zephyr/projects/trogdor/lazor/src/usbc_config.c
new file mode 100644
index 0000000000..f6bfdfb186
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/src/usbc_config.c
@@ -0,0 +1,335 @@
+/* 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.
+ */
+
+/* Lazor board-specific USB-C configuration */
+
+#include "battery_fuel_gauge.h"
+#include "bc12/pi3usb9201_public.h"
+#include "charger.h"
+#include "charger/isl923x_public.h"
+#include "charge_manager.h"
+#include "charge_state.h"
+#include "common.h"
+#include "config.h"
+#include "driver/ln9310.h"
+#include "gpio_signal.h"
+#include "gpio/gpio_int.h"
+#include "hooks.h"
+#include "ppc/sn5s330_public.h"
+#include "system.h"
+#include "tcpm/ps8xxx_public.h"
+#include "tcpm/tcpci.h"
+#include "timer.h"
+#include "usb_pd.h"
+#include "usb_mux.h"
+#include "usbc_ocp.h"
+#include "usbc_ppc.h"
+
+#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args)
+#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args)
+
+int charger_profile_override(struct charge_state_data *curr)
+{
+ int usb_mv;
+ int port;
+
+ if (curr->state != ST_CHARGE)
+ return 0;
+
+ /* Lower the max requested voltage to 5V when battery is full. */
+ if (chipset_in_state(CHIPSET_STATE_ANY_OFF) &&
+ !(curr->batt.flags & BATT_FLAG_BAD_STATUS) &&
+ !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) &&
+ (curr->batt.status & STATUS_FULLY_CHARGED))
+ usb_mv = 5000;
+ else
+ usb_mv = PD_MAX_VOLTAGE_MV;
+
+ if (pd_get_max_voltage() != usb_mv) {
+ CPRINTS("VBUS limited to %dmV", usb_mv);
+ for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++)
+ pd_set_external_voltage_limit(port, usb_mv);
+ }
+
+ return 0;
+}
+
+enum ec_status charger_profile_override_get_param(uint32_t param,
+ uint32_t *value)
+{
+ return EC_RES_INVALID_PARAM;
+}
+
+enum ec_status charger_profile_override_set_param(uint32_t param,
+ uint32_t value)
+{
+ return EC_RES_INVALID_PARAM;
+}
+
+static void usba_oc_deferred(void)
+{
+ /* Use next number after all USB-C ports to indicate the USB-A port */
+ board_overcurrent_event(
+ CONFIG_USB_PD_PORT_MAX_COUNT,
+ !gpio_pin_get_dt(GPIO_DT_FROM_NODELABEL(gpio_usb_a0_oc_odl)));
+}
+DECLARE_DEFERRED(usba_oc_deferred);
+
+void usba_oc_interrupt(enum gpio_signal signal)
+{
+ hook_call_deferred(&usba_oc_deferred_data, 0);
+}
+
+void ppc_interrupt(enum gpio_signal signal)
+{
+ switch (signal) {
+ case GPIO_SIGNAL(DT_NODELABEL(gpio_usb_c0_swctl_int_odl)):
+ sn5s330_interrupt(0);
+ break;
+ case GPIO_SIGNAL(DT_NODELABEL(gpio_usb_c1_swctl_int_odl)):
+ sn5s330_interrupt(1);
+ break;
+ default:
+ break;
+ }
+}
+
+static void board_connect_c0_sbu_deferred(void)
+{
+ /*
+ * If CCD_MODE_ODL asserts, it means there's a debug accessory connected
+ * and we should enable the SBU FETs.
+ */
+ ppc_set_sbu(0, 1);
+}
+DECLARE_DEFERRED(board_connect_c0_sbu_deferred);
+
+void board_connect_c0_sbu(enum gpio_signal s)
+{
+ hook_call_deferred(&board_connect_c0_sbu_deferred_data, 0);
+}
+
+/* GPIO Interrupt Handlers */
+void tcpc_alert_event(enum gpio_signal signal)
+{
+ int port = -1;
+
+ switch (signal) {
+ case GPIO_USB_C0_PD_INT_ODL:
+ port = 0;
+ break;
+ case GPIO_USB_C1_PD_INT_ODL:
+ port = 1;
+ break;
+ default:
+ return;
+ }
+
+ schedule_deferred_pd_interrupt(port);
+}
+
+/*
+ * Port-0/1 USB mux driver.
+ *
+ * The USB mux is handled by TCPC chip and the HPD update is through a GPIO
+ * to AP. But the TCPC chip is also needed to know the HPD status; otherwise,
+ * the mux misbehaves.
+ */
+const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = {
+ {
+ .mux =
+ &(const struct usb_mux){
+ .usb_port = 0,
+ .driver = &tcpci_tcpm_usb_mux_driver,
+ .hpd_update = &ps8xxx_tcpc_update_hpd_status,
+ },
+ },
+ {
+ .mux =
+ &(const struct usb_mux){
+ .usb_port = 1,
+ .driver = &tcpci_tcpm_usb_mux_driver,
+ .hpd_update = &ps8xxx_tcpc_update_hpd_status,
+ },
+ }
+};
+
+__override int board_get_default_battery_type(void)
+{
+ /*
+ * A 2S battery is set as default. If the board is configured to use
+ * a 3S battery, according to its SKU_ID, return a 3S battery as
+ * default. It helps to configure the charger to output a correct
+ * voltage in case the battery is not attached.
+ */
+ if (board_get_battery_cell_type() == BATTERY_CELL_TYPE_3S)
+ return BATTERY_LGC_AP18C8K;
+
+ return DEFAULT_BATTERY_TYPE;
+}
+
+/* Initialize board USC-C things */
+static void board_init_usbc(void)
+{
+ /* Enable USB-A overcurrent interrupt */
+ gpio_enable_dt_interrupt(GPIO_INT_FROM_NODELABEL(int_usb_a0_oc));
+ /*
+ * The H1 SBU line for CCD are behind PPC chip. The PPC internal FETs
+ * for SBU may be disconnected after DP alt mode is off. Should enable
+ * the CCD_MODE_ODL interrupt to make sure the SBU FETs are connected.
+ */
+ gpio_enable_dt_interrupt(GPIO_INT_FROM_NODELABEL(int_ccd_mode));
+}
+DECLARE_HOOK(HOOK_INIT, board_init_usbc, HOOK_PRIO_DEFAULT);
+
+void board_tcpc_init(void)
+{
+ /* Only reset TCPC if not sysjump */
+ if (!system_jumped_late()) {
+ /* TODO(crosbug.com/p/61098): How long do we need to wait? */
+ board_reset_pd_mcu();
+ }
+
+ /* Enable PPC interrupts */
+ gpio_enable_dt_interrupt(GPIO_INT_FROM_NODELABEL(int_usb_c0_swctl));
+
+ /* Enable TCPC interrupts */
+ gpio_enable_dt_interrupt(GPIO_INT_FROM_NODELABEL(int_usb_c0_tcpc));
+ gpio_enable_dt_interrupt(GPIO_INT_FROM_NODELABEL(int_usb_c0_tcpc));
+
+ /*
+ * Initialize HPD to low; after sysjump SOC needs to see
+ * HPD pulse to enable video path
+ */
+ for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port)
+ usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED |
+ USB_PD_MUX_HPD_IRQ_DEASSERTED);
+}
+DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_POST_I2C);
+
+void board_reset_pd_mcu(void)
+{
+ cprints(CC_USB, "Resetting TCPCs...");
+ cflush();
+
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_usb_c0_pd_rst_l), 0);
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_usb_c1_pd_rst_l), 0);
+ msleep(PS8XXX_RESET_DELAY_MS);
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_usb_c0_pd_rst_l), 1);
+ gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_usb_c1_pd_rst_l), 1);
+}
+
+void board_set_tcpc_power_mode(int port, int mode)
+{
+ /* Ignore the "mode" to turn the chip on. We can only do a reset. */
+ if (mode)
+ return;
+
+ board_reset_pd_mcu();
+}
+
+int board_vbus_sink_enable(int port, int enable)
+{
+ /* Both ports are controlled by PPC SN5S330 */
+ return ppc_vbus_sink_enable(port, enable);
+}
+
+int board_is_sourcing_vbus(int port)
+{
+ /* Both ports are controlled by PPC SN5S330 */
+ return ppc_is_sourcing_vbus(port);
+}
+
+void board_overcurrent_event(int port, int is_overcurrented)
+{
+ /* TODO(b/120231371): Notify AP */
+ CPRINTS("p%d: overcurrent!", port);
+}
+
+int board_set_active_charge_port(int port)
+{
+ int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT);
+ int i;
+
+ if (!is_real_port && port != CHARGE_PORT_NONE)
+ return EC_ERROR_INVAL;
+
+ if (port == CHARGE_PORT_NONE) {
+ CPRINTS("Disabling all charging port");
+
+ /* Disable all ports. */
+ for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) {
+ /*
+ * Do not return early if one fails otherwise we can
+ * get into a boot loop assertion failure.
+ */
+ if (board_vbus_sink_enable(i, 0))
+ CPRINTS("Disabling p%d sink path failed.", i);
+ }
+
+ return EC_SUCCESS;
+ }
+
+ /* Check if the port is sourcing VBUS. */
+ if (board_is_sourcing_vbus(port)) {
+ CPRINTS("Skip enable p%d", port);
+ return EC_ERROR_INVAL;
+ }
+
+ CPRINTS("New charge port: p%d", port);
+
+ /*
+ * Turn off the other ports' sink path FETs, before enabling the
+ * requested charge port.
+ */
+ for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) {
+ if (i == port)
+ continue;
+
+ if (board_vbus_sink_enable(i, 0))
+ CPRINTS("p%d: sink path disable failed.", i);
+ }
+
+ /* Enable requested charge port. */
+ if (board_vbus_sink_enable(port, 1)) {
+ CPRINTS("p%d: sink path enable failed.", port);
+ return EC_ERROR_UNKNOWN;
+ }
+
+ return EC_SUCCESS;
+}
+
+void board_set_charge_limit(int port, int supplier, int charge_ma, int max_ma,
+ int charge_mv)
+{
+ /*
+ * Ignore lower charge ceiling on PD transition if our battery is
+ * critical, as we may brownout.
+ */
+ if (supplier == CHARGE_SUPPLIER_PD && charge_ma < 1500 &&
+ charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) {
+ CPRINTS("Using max ilim %d", max_ma);
+ charge_ma = max_ma;
+ }
+
+ charge_set_input_current_limit(
+ MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT), charge_mv);
+}
+
+uint16_t tcpc_get_alert_status(void)
+{
+ uint16_t status = 0;
+
+ if (!gpio_pin_get_dt(GPIO_DT_FROM_NODELABEL(gpio_usb_c0_pd_int_odl)))
+ if (gpio_pin_get_dt(
+ GPIO_DT_FROM_NODELABEL(gpio_usb_c0_pd_rst_l)))
+ status |= PD_STATUS_TCPC_ALERT_0;
+ if (!gpio_pin_get_dt(GPIO_DT_FROM_NODELABEL(gpio_usb_c0_pd_int_odl)))
+ if (gpio_pin_get_dt(
+ GPIO_DT_FROM_NODELABEL(gpio_usb_c1_pd_rst_l)))
+ status |= PD_STATUS_TCPC_ALERT_1;
+
+ return status;
+}
diff --git a/zephyr/projects/trogdor/lazor/usbc.dts b/zephyr/projects/trogdor/lazor/usbc.dts
new file mode 100644
index 0000000000..7864c2716b
--- /dev/null
+++ b/zephyr/projects/trogdor/lazor/usbc.dts
@@ -0,0 +1,36 @@
+/* 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.
+ */
+
+/ {
+ usbc {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* TODO(b/227359762): lazor: move UBC-C configuration into the
+ * devicetree
+ */
+ port0@0 {
+ compatible = "named-usbc-port";
+ reg = <0>;
+
+ bc12 = <&bc12_port0>;
+ tcpc = <&tcpc_port0>;
+
+ ppc = <&ppc_port0>;
+
+ chg = <&charger>;
+ };
+
+ port1@1 {
+ compatible = "named-usbc-port";
+ reg = <1>;
+
+ bc12 = <&bc12_port1>;
+ tcpc = <&tcpc_port1>;
+
+ ppc = <&ppc_port1>;
+ };
+ };
+};