summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mainboard/google/brox/Kconfig157
-rw-r--r--src/mainboard/google/brox/Kconfig.name4
-rw-r--r--src/mainboard/google/brox/Makefile.inc23
-rw-r--r--src/mainboard/google/brox/acpi/gps.asl104
-rw-r--r--src/mainboard/google/brox/acpi/gpu_defines.h60
-rw-r--r--src/mainboard/google/brox/acpi/gpu_ec.asl13
-rw-r--r--src/mainboard/google/brox/acpi/gpu_top.asl100
-rw-r--r--src/mainboard/google/brox/acpi/nbci.asl77
-rw-r--r--src/mainboard/google/brox/acpi/nvjt.asl129
-rw-r--r--src/mainboard/google/brox/acpi/nvop.asl69
-rw-r--r--src/mainboard/google/brox/acpi/nvpcf.asl67
-rw-r--r--src/mainboard/google/brox/acpi/peg.asl99
-rw-r--r--src/mainboard/google/brox/acpi/power.asl431
-rw-r--r--src/mainboard/google/brox/acpi/utility.asl54
-rw-r--r--src/mainboard/google/brox/board_info.txt6
-rw-r--r--src/mainboard/google/brox/bootblock.c19
-rw-r--r--src/mainboard/google/brox/chromeos.c29
-rw-r--r--src/mainboard/google/brox/chromeos.fmd60
-rw-r--r--src/mainboard/google/brox/dsdt.asl47
-rw-r--r--src/mainboard/google/brox/ec.c22
-rw-r--r--src/mainboard/google/brox/mainboard.c236
-rw-r--r--src/mainboard/google/brox/romstage.c26
-rw-r--r--src/mainboard/google/brox/smihandler.c29
-rw-r--r--src/mainboard/google/brox/spd/Makefile.inc6
-rw-r--r--src/mainboard/google/brox/variants/baseboard/brox/Makefile.inc12
-rw-r--r--src/mainboard/google/brox/variants/baseboard/brox/devicetree.cb205
-rw-r--r--src/mainboard/google/brox/variants/baseboard/brox/gma-mainboard.ads13
-rw-r--r--src/mainboard/google/brox/variants/baseboard/brox/gpio.c46
-rw-r--r--src/mainboard/google/brox/variants/baseboard/brox/include/baseboard/ec.h79
-rw-r--r--src/mainboard/google/brox/variants/baseboard/brox/include/baseboard/gpio.h22
-rw-r--r--src/mainboard/google/brox/variants/baseboard/brox/memory.c103
-rw-r--r--src/mainboard/google/brox/variants/baseboard/brox/ramstage.c48
-rw-r--r--src/mainboard/google/brox/variants/baseboard/include/baseboard/variants.h90
-rw-r--r--src/mainboard/google/brox/variants/brox/Makefile.inc8
-rw-r--r--src/mainboard/google/brox/variants/brox/data.vbtbin0 -> 8704 bytes
-rw-r--r--src/mainboard/google/brox/variants/brox/fw_config.c8
-rw-r--r--src/mainboard/google/brox/variants/brox/gpio.c218
-rw-r--r--src/mainboard/google/brox/variants/brox/include/variant/ec.h8
-rw-r--r--src/mainboard/google/brox/variants/brox/include/variant/gpio.h14
-rw-r--r--src/mainboard/google/brox/variants/brox/memory/Makefile.inc7
-rw-r--r--src/mainboard/google/brox/variants/brox/memory/dram_id.generated.txt7
-rw-r--r--src/mainboard/google/brox/variants/brox/memory/mem_parts_used.txt1
-rw-r--r--src/mainboard/google/brox/variants/brox/overridetree.cb4
-rw-r--r--src/mainboard/google/brox/variants/brox/ramstage.c18
-rw-r--r--src/mainboard/google/brox/variants/brox/variant.c9
-rw-r--r--src/mainboard/google/brox/wwan_power.asl14
46 files changed, 2801 insertions, 0 deletions
diff --git a/src/mainboard/google/brox/Kconfig b/src/mainboard/google/brox/Kconfig
new file mode 100644
index 0000000000..70a9735f58
--- /dev/null
+++ b/src/mainboard/google/brox/Kconfig
@@ -0,0 +1,157 @@
+config BOARD_GOOGLE_BROX_COMMON
+ def_bool n
+ select DRIVERS_GENERIC_GPIO_KEYS
+ select DRIVERS_I2C_GENERIC
+ select DRIVERS_I2C_HID
+ select DRIVERS_INTEL_DPTF
+ select DRIVERS_INTEL_DPTF_SUPPORTS_TPCH
+ select DRIVERS_INTEL_PMC
+ select DRIVERS_INTEL_SOUNDWIRE
+ select DRIVERS_INTEL_USB4_RETIMER
+ select DRIVERS_SPI_ACPI
+ select DRIVERS_WIFI_GENERIC
+ select EC_GOOGLE_CHROMEEC
+ select EC_GOOGLE_CHROMEEC_BOARDID
+ select EC_GOOGLE_CHROMEEC_ESPI
+ select EC_GOOGLE_CHROMEEC_SKUID
+ select ENABLE_TCSS_USB_DETECTION if !CHROMEOS
+ select FW_CONFIG
+ select FW_CONFIG_SOURCE_CHROMEEC_CBI
+ select GOOGLE_SMBIOS_MAINBOARD_VERSION
+ select HAVE_ACPI_RESUME
+ select HAVE_ACPI_TABLES
+ select HAVE_FSP_LOGO_SUPPORT if RUN_FSP_GOP
+ select I2C_TPM
+ select INTEL_LPSS_UART_FOR_CONSOLE
+ select MAINBOARD_HAS_CHROMEOS
+ select MAINBOARD_HAS_TPM2
+ select PMC_IPC_ACPI_INTERFACE
+ select SOC_INTEL_CSE_LITE_SKU
+# select SOC_INTEL_CSE_SEND_EOP_ASYNC
+ select SOC_INTEL_COMMON_BLOCK_USB4
+ select SOC_INTEL_COMMON_BLOCK_TCSS
+ select SOC_INTEL_ENABLE_USB4_PCIE_RESOURCES
+ select SOC_INTEL_COMMON_BASECODE_DEBUG_FEATURE
+ select SOC_INTEL_CRASHLOG
+ select SOC_INTEL_CSE_PRE_CPU_RESET_TELEMETRY_V1
+
+config BOARD_GOOGLE_BASEBOARD_BROX
+ def_bool n
+ select BOARD_GOOGLE_BROX_COMMON
+ select BOARD_ROMSIZE_KB_32768
+ select DRIVERS_AUDIO_SOF
+ select DRIVERS_GFX_GENERIC
+ select HAVE_SLP_S0_GATE
+ select MEMORY_SOLDERDOWN
+ select SOC_INTEL_COMMON_BLOCK_IPU
+ select SOC_INTEL_CRASHLOG
+ select SOC_INTEL_RAPTORLAKE
+ select SOC_INTEL_RAPTORLAKE_PCH_S
+ select SYSTEM_TYPE_LAPTOP
+ select TPM_GOOGLE_CR50
+
+config BOARD_GOOGLE_BROX
+ bool "-> Brox"
+ select BOARD_GOOGLE_BASEBOARD_BROX
+
+if BOARD_GOOGLE_BROX_COMMON
+
+config BASEBOARD_DIR
+ string
+ default "brox" if BOARD_GOOGLE_BASEBOARD_BROX
+
+config CHROMEOS
+ select EC_GOOGLE_CHROMEEC_SWITCHES
+ select HAS_RECOVERY_MRC_CACHE
+
+config CHROMEOS_WIFI_SAR
+ bool "Enable SAR options for ChromeOS build"
+ depends on CHROMEOS
+ select DSAR_ENABLE
+ select GEO_SAR_ENABLE
+ select SAR_ENABLE
+ select USE_SAR
+
+config DEVICETREE
+ default "variants/baseboard/\$(CONFIG_BASEBOARD_DIR)/devicetree.cb"
+
+config DRIVER_TPM_I2C_BUS
+ hex
+ default 0x1 if BOARD_GOOGLE_BROX
+
+config DRIVER_TPM_I2C_ADDR
+ hex
+ default 0x50
+
+config FMDFILE
+ default "src/mainboard/\$(CONFIG_MAINBOARD_DIR)/chromeos.fmd" if CHROMEOS
+
+config TPM_TIS_ACPI_INTERRUPT
+ int
+ default 13
+
+config OVERRIDE_DEVICETREE
+ default "variants/\$(CONFIG_VARIANT_DIR)/overridetree.cb"
+
+config MAINBOARD_DIR
+ default "google/brox"
+
+config MAINBOARD_FAMILY
+ string
+ default "Google_Brox" if BOARD_GOOGLE_BASEBOARD_BROX
+
+config MAINBOARD_PART_NUMBER
+ default "Brox" if BOARD_GOOGLE_BROX
+
+config VARIANT_DIR
+ default "brox" if BOARD_GOOGLE_BROX
+
+config VBOOT
+ select VBOOT_EARLY_EC_SYNC
+ select VBOOT_LID_SWITCH
+
+config DIMM_SPD_SIZE
+ default 512
+
+config UART_FOR_CONSOLE
+ int
+ default 0
+
+config HAVE_WWAN_POWER_SEQUENCE
+ def_bool n
+ help
+ Select this if the variant has a WWAN module and requires the poweroff sequence
+ to be performed on shutdown. Must define WWAN_FCPO, WWAN_RST and WWAN_PERST GPIOs
+ in variant.h, as well as T1_OFF_MS (time between PERST & RST) and T2_OFF_MS (time
+ between RST and FCPO). WWAN_PERST and T1_OFF_MS are only necessary for PCIe WWAN
+ (when HAVE_PCIE_WWAN is also selected).
+
+config HAVE_PCIE_WWAN
+ def_bool n
+
+config USE_PM_ACPI_TIMER
+ default y if BOARD_GOOGLE_PRIMUS4ES
+ default n
+
+config MEMORY_SODIMM
+ def_bool n
+ select SPD_CACHE_ENABLE
+ select SPD_CACHE_IN_FMAP
+
+config MEMORY_SOLDERDOWN
+ def_bool n
+ select CHROMEOS_DRAM_PART_NUMBER_IN_CBI if CHROMEOS
+ select HAVE_SPD_IN_CBFS
+
+config HAVE_SLP_S0_GATE
+ def_bool n
+
+config PCIEXP_DEFAULT_MAX_RESIZABLE_BAR_BITS
+ int
+ default 33
+
+config VBT_DATA_SIZE_KB
+ int
+ default 10
+
+endif # BOARD_GOOGLE_BROX_COMMON
diff --git a/src/mainboard/google/brox/Kconfig.name b/src/mainboard/google/brox/Kconfig.name
new file mode 100644
index 0000000000..95dd5e318e
--- /dev/null
+++ b/src/mainboard/google/brox/Kconfig.name
@@ -0,0 +1,4 @@
+comment "Brox"
+
+config BOARD_GOOGLE_BROX
+ bool "-> Brox"
diff --git a/src/mainboard/google/brox/Makefile.inc b/src/mainboard/google/brox/Makefile.inc
new file mode 100644
index 0000000000..8c7e42d5f7
--- /dev/null
+++ b/src/mainboard/google/brox/Makefile.inc
@@ -0,0 +1,23 @@
+## SPDX-License-Identifier: GPL-2.0-only
+
+bootblock-y += bootblock.c
+
+verstage-$(CONFIG_CHROMEOS) += chromeos.c
+
+romstage-$(CONFIG_CHROMEOS) += chromeos.c
+romstage-y += romstage.c
+
+ramstage-$(CONFIG_CHROMEOS) += chromeos.c
+ramstage-y += mainboard.c
+ramstage-y += ec.c
+
+BASEBOARD_DIR:=$(call strip_quotes,$(CONFIG_BASEBOARD_DIR))
+
+subdirs-y += variants/baseboard/$(BASEBOARD_DIR)
+subdirs-y += variants/$(VARIANT_DIR)
+subdirs-y += variants/$(VARIANT_DIR)/memory
+subdirs-$(CONFIG_HAVE_SPD_IN_CBFS) += spd
+
+CPPFLAGS_common += -I$(src)/mainboard/$(MAINBOARDDIR)/variants/baseboard/include
+CPPFLAGS_common += -I$(src)/mainboard/$(MAINBOARDDIR)/variants/baseboard/$(BASEBOARD_DIR)/include
+CPPFLAGS_common += -I$(src)/mainboard/$(MAINBOARDDIR)/variants/$(VARIANT_DIR)/include
diff --git a/src/mainboard/google/brox/acpi/gps.asl b/src/mainboard/google/brox/acpi/gps.asl
new file mode 100644
index 0000000000..f201037f06
--- /dev/null
+++ b/src/mainboard/google/brox/acpi/gps.asl
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#define GPS_FUNC_SUPPORT 0
+#define GPS_FUNC_GETCALLBACKS 0x13
+#define GPS_FUNC_PSHARESTATUS 0x20
+#define GPS_FUNC_PSHAREPARAMS 0x2a
+#define GPS_FUNC_REQUESTDXSTATE 0x12
+
+#define QUERY_GET_STATUS 0
+#define QUERY_GET_SUPPORTED_FIELDS 1
+#define QUERY_GET_CURRENT_LIMITS 2
+
+#define EC_D_NOTIFY_MASK 0x7
+
+/* GPS return Package */
+Name (GPSP, Buffer (0x28) {0x0})
+CreateDWordField (GPSP, 0, RETN)
+CreateDWordField (GPSP, 4, VRV1)
+CreateDWordField (GPSP, 8, TGPU)
+
+/* GETCALLBACKS return value
+ [0]: Callback for post-mode set
+ [1]: Callback for pre-mode set
+ [2]: Callback for post power state transition */
+Name (GPSR, Buffer (4) { 0x4, 0x0, 0x0, 0x0 })
+
+Method (GPS, 2, Serialized)
+{
+ Switch (ToInteger (Arg0))
+ {
+ Case (GPS_FUNC_SUPPORT)
+ {
+ Return (LTOB(
+ (1 << GPS_FUNC_SUPPORT) |
+ (1 << GPS_FUNC_GETCALLBACKS) |
+ (1 << GPS_FUNC_PSHARESTATUS) |
+ (1 << GPS_FUNC_PSHAREPARAMS) |
+ (1 << GPS_FUNC_REQUESTDXSTATE)))
+ }
+ Case (GPS_FUNC_GETCALLBACKS)
+ {
+ CreateDWordField (Arg1, 0, QURY)
+
+ /* Driver querying for which callbacks the ACPI code
+ wants callbacks for. */
+ If (QURY == 0)
+ {
+ Return (GPSR)
+ }
+
+ If (QURY & 0x4)
+ {
+ Printf("GPS: Kernel driver callback post power state transition")
+ Return (GPSR)
+ }
+ }
+ Case (GPS_FUNC_PSHARESTATUS)
+ {
+ Return (ITOB(
+ (0 << 0) | /* GPS_FUNC_PSHAREPARAMS should not be called
+ again after initialization, i.e., its return
+ value is not dynamically updated. */
+ (1 << 0) | /* System uses both a GPIO and ACPI notification
+ codes to set multiple GPU power limits. */
+ (0 << 21))) /* EDPpeak limit is default */
+ }
+ Case (GPS_FUNC_PSHAREPARAMS)
+ {
+ CreateField (Arg1, 0, 4, QUTY) /* Query type */
+
+ /* Version of return value */
+ VRV1 = 0x10000
+ Switch (ToInteger (QUTY))
+ {
+ Case (QUERY_GET_STATUS)
+ {
+ Return (GPSP)
+ }
+ Case (QUERY_GET_SUPPORTED_FIELDS)
+ {
+ /* Only GPU temperature is supported */
+ RETN = 0x100 | ToInteger (QUTY)
+ Return (GPSP)
+ }
+ Case (QUERY_GET_CURRENT_LIMITS)
+ {
+ /* Request a limit of '0' for the GPU temperature,
+ meaning there is no limit. */
+ RETN = 0x102
+ TGPU = 0
+ Return (GPSP)
+ }
+ }
+ }
+ Case (GPS_FUNC_REQUESTDXSTATE)
+ {
+ Local0 = ToInteger(\_SB.PCI0.LPCB.EC0.GPUD) & EC_D_NOTIFY_MASK
+ \_SB.PCI0.PEG0.PEGP.DNOT (Local0, 1)
+ Return (NV_ERROR_SUCCESS)
+ }
+ }
+
+ Return (NV_ERROR_UNSUPPORTED)
+}
diff --git a/src/mainboard/google/brox/acpi/gpu_defines.h b/src/mainboard/google/brox/acpi/gpu_defines.h
new file mode 100644
index 0000000000..1cb03145b0
--- /dev/null
+++ b/src/mainboard/google/brox/acpi/gpu_defines.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#define NV_ERROR_SUCCESS 0x0
+#define NV_ERROR_UNSPECIFIED 0x80000001
+#define NV_ERROR_UNSUPPORTED 0x80000002
+
+#define PCI_OWNER_SBIOS 0x0
+#define PCI_OWNER_DRIVER 0x1
+
+#define OPTIMUS_POWER_CONTROL_DISABLE 0x2
+#define OPTIMUS_POWER_CONTROL_ENABLE 0x3
+
+#define OPTIMUS_CONTROL_NO_RUN_PS0 0x0
+#define OPTIMUS_CONTROL_RUN_PS0 0x1
+
+#define GC6_STATE_EXITED 0x0
+#define GC6_STATE_ENTERED 0x1
+#define GC6_STATE_TRANSITION 0x2
+
+#define GC6_DEFER_DISABLE 0x0
+#define GC6_DEFER_ENABLE 0x1
+
+#define NOTIFY_GPS_EVENT_STATUS_CHANGE 0xc0
+#define NOTIFY_GPS_NVPCF_STATUS_CHANGE 0xc5
+#define NOTIFY_GPS_EVENT_LIMIT_POWER_0 0xd1
+#define NOTIFY_GPS_EVENT_LIMIT_POWER_1 0xd2
+#define NOTIFY_GPS_EVENT_LIMIT_POWER_2 0xd3
+#define NOTIFY_GPS_EVENT_LIMIT_POWER_3 0xd4
+#define NOTIFY_GPS_EVENT_LIMIT_POWER_4 0xd5
+
+/* Defines for NVJT subfunction */
+#define NVJT_GPC_GSS 0
+#define NVJT_GPC_EGNS 1
+#define NVJT_GPC_EGIS 2
+#define NVJT_GPS_XGXS 3
+#define NVJT_GPS_XGIS 4
+
+#define UUID_NVOP "a486d8f8-0bda-471b-a72b-6042a6b5bee0"
+#define UUID_NVJT "cbeca351-067b-4924-9cbd-b46b00b86f34"
+#define UUID_NBCI "d4a50b75-65c7-46f7-bfb7-41514cea0244"
+#define UUID_NVPCF "36b49710-2483-11e7-9598-0800200c9a66"
+#define UUID_GPS "a3132d01-8cda-49ba-a52e-bc9d46df6b81"
+
+#define REVISION_MIN_NVOP 0x100
+#define REVISION_MIN_NVJT 0x100
+#define REVISION_MIN_NBCI 0x102
+#define REVISION_MIN_NVPCF 0x200
+#define REVISION_MIN_GPS 0x200
+
+#define D1_EC 0
+#define D2_EC 1
+#define D3_EC 2
+#define D4_EC 3
+#define D5_EC 4
+
+#define D1_GPU 0xD1
+#define D2_GPU 0xD2
+#define D3_GPU 0xD3
+#define D4_GPU 0xD4
+#define D5_GPU 0xD5
diff --git a/src/mainboard/google/brox/acpi/gpu_ec.asl b/src/mainboard/google/brox/acpi/gpu_ec.asl
new file mode 100644
index 0000000000..59875ad138
--- /dev/null
+++ b/src/mainboard/google/brox/acpi/gpu_ec.asl
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#define EC_D_NOTIFY_MASK 0x7
+
+Scope (\_SB.PCI0.LPCB.EC0)
+{
+ /* EC has data for GPU in memmap */
+ Method (_Q0C, 0, Serialized)
+ {
+ Local0 = ToInteger(GPUD) & EC_D_NOTIFY_MASK
+ \_SB.PCI0.PEG0.PEGP.DNOT (Local0, 0)
+ }
+}
diff --git a/src/mainboard/google/brox/acpi/gpu_top.asl b/src/mainboard/google/brox/acpi/gpu_top.asl
new file mode 100644
index 0000000000..492502c3d4
--- /dev/null
+++ b/src/mainboard/google/brox/acpi/gpu_top.asl
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "gpu_defines.h"
+
+Scope (\_SB.PCI0.PEG0)
+{
+ #include "peg.asl"
+
+ Device (PEGP)
+ {
+ Name (_ADR, 0x0)
+ OperationRegion (PCIC, PCI_Config, 0x00, 0x100)
+ Field (PCIC, DWordAcc, NoLock, Preserve)
+ {
+ NVID, 16,
+ NDID, 16,
+ CMDR, 8,
+ VGAR, 2008, /* VGA Registers */
+ }
+
+ #include "utility.asl"
+ #include "power.asl"
+ #include "nvop.asl"
+ #include "nvjt.asl"
+ #include "nbci.asl"
+ #include "nvpcf.asl"
+ #include "gps.asl"
+ #include "gpu_ec.asl"
+
+ /* Convert D Notify from EC to GPU */
+ Method (CNVD, 1, NotSerialized)
+ {
+ Switch (ToInteger(Arg0)) {
+ Case (D1_EC) { Return (D1_GPU) }
+ Case (D2_EC) { Return (D2_GPU) }
+ Case (D3_EC) { Return (D3_GPU) }
+ Case (D4_EC) { Return (D4_GPU) }
+ Case (D5_EC) { Return (D5_GPU) }
+ Default { Return (D5_GPU) }
+ }
+ }
+
+ /* Current D Notify Value, defaults to D1
+ * Arg0 == Shared value
+ * Arg1 == force notification if no change (0 or 1)
+ */
+ Name (CDNV, D1_EC)
+ Method (DNOT, 2, Serialized)
+ {
+ Printf ("EC: GPU D-Notify, %o", Arg0)
+ If ((Arg0 != CDNV) || (Arg1 == 1))
+ {
+ CDNV = Arg0
+ Local0 = CNVD (Arg0)
+ Notify (\_SB.PCI0.PEG0.PEGP, Local0)
+ }
+ }
+
+ Method (_DSM, 4, Serialized)
+ {
+ If (Arg0 == ToUUID (UUID_NVOP))
+ {
+ If (ToInteger(Arg1) >= REVISION_MIN_NVOP)
+ {
+ Return (NVOP (Arg2, Arg3))
+ }
+ }
+ ElseIf (Arg0 == ToUUID (UUID_NVJT))
+ {
+ If (ToInteger (Arg1) >= REVISION_MIN_NVJT)
+ {
+ Return (NVJT (Arg2, Arg3))
+ }
+ }
+ ElseIf (Arg0 == ToUUID (UUID_NBCI))
+ {
+ If (ToInteger (Arg1) >= REVISION_MIN_NBCI)
+ {
+ Return (NBCI (Arg2, Arg3))
+ }
+ }
+ ElseIf (Arg0 == ToUUID (UUID_NVPCF))
+ {
+ If (ToInteger (Arg1) >= REVISION_MIN_NVPCF)
+ {
+ Return (NPCF (Arg2, Arg3))
+ }
+ }
+ ElseIf (Arg0 == ToUUID (UUID_GPS))
+ {
+ If (ToInteger (Arg1) >= REVISION_MIN_GPS)
+ {
+ Return (GPS (Arg2, Arg3))
+ }
+ }
+
+ Return (NV_ERROR_UNSUPPORTED)
+ }
+ }
+}
diff --git a/src/mainboard/google/brox/acpi/nbci.asl b/src/mainboard/google/brox/acpi/nbci.asl
new file mode 100644
index 0000000000..274c04be7f
--- /dev/null
+++ b/src/mainboard/google/brox/acpi/nbci.asl
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#define NBCI_FUNC_SUPPORT 0
+#define NBCI_FUNC_PLATCAPS 1
+#define NBCI_FUNC_GETOBJBYTYPE 16
+#define NBCI_FUNC_GETCALLBACKS 19
+
+/* 'DR' in ASCII, for DRiver Object */
+#define NBCI_OBJTYPE_DR 0x4452
+
+#define GPS_FUNC_GETCALLBACKS 0x13
+
+Method (NBCI, 2, Serialized)
+{
+ Switch (ToInteger (Arg0))
+ {
+ Case (NBCI_FUNC_SUPPORT)
+ {
+ Return (ITOB(
+ (1 << NBCI_FUNC_SUPPORT) |
+ (1 << NBCI_FUNC_PLATCAPS) |
+ (1 << NBCI_FUNC_GETOBJBYTYPE)))
+ }
+ Case (NBCI_FUNC_PLATCAPS)
+ {
+ Return (ITOB(
+ (0 << 10) | /* No 3D Hotkeys */
+ (0 << 9) | /* Do not enumerate a dock */
+ (0 << 7) | /* Does not have DISPLAYSTATUS */
+ (0 << 5) | /* No LID support */
+ (0 << 4))) /* No Aux power state request */
+ }
+ Case (NBCI_FUNC_GETCALLBACKS)
+ {
+ /* Re-use the GPS subfunction's GETCALLBACKS Method */
+ Return (GPS (GPS_FUNC_GETCALLBACKS, Arg1))
+ }
+ Case (NBCI_FUNC_GETOBJBYTYPE)
+ {
+ CreateWordField (Arg1, 2, BFF0)
+ If (BFF0 == NBCI_OBJTYPE_DR)
+ {
+ Return (Buffer(0xa1)
+ {
+ /* DR ("Driver Object") is a data object which
+ * might vary depending on the eDP panel used. */
+ 0x57, 0x74, 0xdc, 0x86, 0x75, 0x84, 0xec, 0xe7,
+ 0x52, 0x44, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0xde, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x47, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x45, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x51, 0x00, 0x00, 0x00, 0x04, 0x00, 0x4f, 0x00,
+ 0x00, 0x00, 0x05, 0x00, 0x4d, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x00,
+ 0x49, 0x00, 0x00, 0x00, 0x08, 0x00, 0x47, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd9, 0x1c,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x41, 0x5d, 0xc9, 0x00, 0x01, 0x24, 0x2e, 0x00,
+ 0x02, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0xd9, 0x1c, 0x04, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x68, 0x9e,
+ 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00
+ })
+ } Else {
+ Return (NV_ERROR_UNSPECIFIED)
+ }
+
+ }
+ }
+
+ Return (NV_ERROR_UNSUPPORTED)
+}
diff --git a/src/mainboard/google/brox/acpi/nvjt.asl b/src/mainboard/google/brox/acpi/nvjt.asl
new file mode 100644
index 0000000000..17011ec2dd
--- /dev/null
+++ b/src/mainboard/google/brox/acpi/nvjt.asl
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#define JT_FUNC_SUPPORT 0
+#define JT_FUNC_CAPS 1
+#define JT_FUNC_POWERCONTROL 3
+#define JT_FUNC_PLATPOLICY 4
+
+Method (NVJT, 2, Serialized)
+{
+ Switch (ToInteger(Arg0))
+ {
+ Case (JT_FUNC_SUPPORT)
+ {
+ Return (ITOB(
+ (1 << JT_FUNC_SUPPORT) |
+ (1 << JT_FUNC_CAPS) |
+ (1 << JT_FUNC_POWERCONTROL) |
+ (1 << JT_FUNC_PLATPOLICY)))
+ }
+ Case (JT_FUNC_CAPS)
+ {
+ Return (ITOB(
+ (0 << 0) | /* JTE: G-Sync NVSR Power Features Enabled */
+ (1 << 0) | /* NVSE: NVSR Disabled */
+ (0 << 3) | /* PPR: Panel Power Rail */
+ (0 << 5) | /* SRPR: Self-Refresh Controller Power Rail */
+ (0 << 6) | /* FBPR: FB Power Rail */
+ (0 << 8) | /* GPR: GPU Power Rail */
+ (0 << 10) | /* GCR: GC6 ROM */
+ (1 << 11) | /* PTH: No SMI Handler */
+ (0 << 12) | /* NOT: Supports Notify on GC6 State done */
+ (1 << 13) | /* MHYB: MS Hybrid Support (deferred GC6) */
+ (0 << 14) | /* RPC: Root Port Control */
+ (0 << 15) | /* GC6 Version (GC6-E) */
+ (0 << 17) | /* GEI: GC6 Exit ISR Support */
+ (0 << 18) | /* GSW: GC6 Self Wakeup */
+ (0x200 << 20))) /* MXRV: Highest Revision */
+ }
+ Case (JT_FUNC_POWERCONTROL)
+ {
+ CreateField (Arg1, 0, 3, GPC) /* GPU Power Control */
+ CreateField (Arg1, 4, 1, PPC) /* Panel Power Control */
+ CreateField (Arg1, 14, 2, DFGC) /* Defer GC6 enter/exit */
+ CreateField (Arg1, 16, 3, GPCX) /* Deferred GC6 exit */
+
+ /* Deferred GC6 entry/exit is requested */
+ If (ToInteger(GPC) != 0 || ToInteger(DFGC) != 0)
+ {
+ DFEN = ToInteger(DFGC)
+ DFCI = ToInteger(GPC)
+ DFCO = ToInteger(GPCX)
+ }
+
+ Local0 = Buffer (4) { 0x0 }
+ CreateField (Local0, 0, 3, CGCS) /* Current GC State */
+ CreateField (Local0, 3, 1, CGPS) /* Current GPU power status */
+ CreateField (Local0, 7, 1, CPSS) /* Current panel and SRC state */
+
+ /* Leave early if deferred GC6 is requested */
+ If (DFEN != 0)
+ {
+ CGCS = 1
+ CGPS = 1
+ Return (Local0)
+ }
+
+ Switch (ToInteger(GPC))
+ {
+ /* Get GCU GCx Sleep Status */
+ Case (NVJT_GPC_GSS)
+ {
+ If (PSTA () != 0)
+ {
+ CGPS = 1
+ CGCS = 1
+ }
+ Else
+ {
+ CGPS = 0
+ CGCS = 3
+ }
+ }
+ Case (NVJT_GPC_EGNS)
+ {
+ /* Enter GC6; no self-refresh */
+ GC6I ()
+ CPSS = 1
+ CGCS = 0
+ }
+ Case (NVJT_GPC_EGIS)
+ {
+ /* Enter GC6; enable self-refresh */
+ GC6I ()
+ If (ToInteger (PPC) == 0)
+ {
+ CPSS = 0
+ }
+ CGCS = 0
+ }
+ Case (NVJT_GPS_XGXS)
+ {
+ /* Exit GC6; stop self-refresh */
+ GC6O ()
+ CGCS = 1
+ CGPS = 1
+ If (ToInteger (PPC) != 0)
+ {
+ CPSS = 0
+ }
+ }
+ Case (NVJT_GPS_XGIS)
+ {
+ /* Exit GC6 for self-refresh */
+ GC6O ()
+ CGCS = 1
+ CGPS = 1
+ If (ToInteger (PPC) != 0)
+ {
+ CPSS = 0
+ }
+ }
+ }
+
+ Return (Local0)
+ }
+ }
+
+ Return (NV_ERROR_UNSUPPORTED)
+}
diff --git a/src/mainboard/google/brox/acpi/nvop.asl b/src/mainboard/google/brox/acpi/nvop.asl
new file mode 100644
index 0000000000..ecf962e180
--- /dev/null
+++ b/src/mainboard/google/brox/acpi/nvop.asl
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#define NVOP_FUNC_SUPPORT 0x00
+#define NVOP_FUNC_GET_OBJ_BY_TYPE 0x10
+#define NVOP_FUNC_OPTIMUS_CAPS 0x1a
+#define NVOP_FUNC_OPTIMUS_STATUS 0x1b
+
+Method (NVOP, 2, Serialized)
+{
+ Switch (ToInteger (Arg0))
+ {
+ Case (NVOP_FUNC_SUPPORT)
+ {
+ Return (ITOB (
+ (1 << NVOP_FUNC_SUPPORT) |
+ (1 << NVOP_FUNC_OPTIMUS_CAPS) |
+ (1 << NVOP_FUNC_OPTIMUS_STATUS)))
+ }
+ Case (NVOP_FUNC_OPTIMUS_CAPS)
+ {
+ CreateField(Arg1, 0, 1, FLUP) /* Flag Update */
+ CreateField(Arg1, 1, 1, CSOT) /* Change configuration Space Owner Target */
+ CreateField(Arg1, 2, 1, CSOW) /* Change configuration Space Owner Write */
+ CreateField(Arg1, 24, 2, NPCE) /* New Power Control Enable setting */
+
+ /* Change Optimus power control capabilities */
+ If (ToInteger (FLUP) != 0 && ToInteger (NPCE) != 0)
+ {
+ OPCS = NPCE
+ }
+
+ /* Change PCI configuration space save/restore owner */
+ If (ToInteger (CSOW) == 1)
+ {
+ PCIO = CSOT
+ }
+
+ /* Current GPU Control Status */
+ If (PSTA () == 1)
+ {
+ Local0 = 3
+ }
+ Else
+ {
+ Local0 = 0
+ }
+
+ Return (ITOB (
+ (1 << 0) | /* Optimus Enabled */
+ (Local0 << 3) | /* Current GPU Control Status */
+ (0 << 6) | /* Shared Discrete GPU Hotplug Capabilities */
+ (0 << 7) | /* MUXed DDC/Aux Capabilities */
+ (PCIO << 8) | /* PCIe Configuration Space Owner */
+ (1 << 24) | /* Platform Optimus Power Capabilities */
+ (0 << 27))) /* Optimus HD Audio Codec Capabilities */
+ }
+ Case (NVOP_FUNC_OPTIMUS_STATUS)
+ {
+ Return (ITOB (
+ (0 << 0) | /* Optimus Audio Codec Control */
+ (0 << 2) | /* Request GPU Power State */
+ (0 << 4) | /* Evaluate Requested GPU Power State */
+ (0 << 5) | /* Request Optimus Adapter Policy */
+ (0 << 7))) /* Evaluate Requested Optimus Adapter Selection */
+ }
+ }
+
+ Return (NV_ERROR_UNSUPPORTED)
+}
diff --git a/src/mainboard/google/brox/acpi/nvpcf.asl b/src/mainboard/google/brox/acpi/nvpcf.asl
new file mode 100644
index 0000000000..9f6c5e1149
--- /dev/null
+++ b/src/mainboard/google/brox/acpi/nvpcf.asl
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#define NVPCF_FUNC_SUPPORT 0
+#define NVPCF_FUNC_GET_STATIC_CONFIG_TABLES 1
+#define NVPCF_FUNC_UPDATE_DYNAMIC_PARAMS 2
+
+Method (NPCF, 2, Serialized)
+{
+ Switch (ToInteger (Arg0))
+ {
+ Case (NVPCF_FUNC_SUPPORT)
+ {
+ Return (ITOB(
+ (1 << NVPCF_FUNC_SUPPORT) |
+ (1 << NVPCF_FUNC_GET_STATIC_CONFIG_TABLES) |
+ (1 << NVPCF_FUNC_UPDATE_DYNAMIC_PARAMS)))
+ }
+ Case (NVPCF_FUNC_GET_STATIC_CONFIG_TABLES)
+ {
+ Return (Buffer () {
+ /* System Device Table Header (v2.0) */
+ 0x20, 0x03, 0x01,
+
+ /* System Device Table Entries */
+ 0x00, /* [3:0] CPU type (0=Intel, 1=AMD),
+ [7:4] GPU type (0=Nvidia) */
+
+ /* System Controller Table Header (v2.2), 1 controller entry */
+ 0x22, 0x04, 0x05, 0x01,
+
+ /* Controller #1 Flags */
+ 0x01, /* [3:0] Controller class
+ 0=Disabled, 1=Dynamic Boost,
+ 2=CTGP-only.
+ [7:4] Reserved. Set to 0. */
+ /* Controller #1 Params */
+ /* Class = Dynamic Boost
+ [0:0] DC support
+ 0=Not supported, 1=Supported
+ [31:1] Reserved. Set to 0. */
+ 0x00, 0x00, 0x00, 0x00,
+
+ /* Twos-complement checksum */
+ 0xaf
+ })
+ }
+ Case (NVPCF_FUNC_UPDATE_DYNAMIC_PARAMS)
+ {
+ Local0 = Buffer (0x31) {
+ /* Dynamic Params Table Header (1 controller entry, 0x1c bytes) */
+ 0x22, 0x05, 0x10, 0x1c, 0x01 }
+
+ CreateWordField (Local0, 0x1d, MAGA)
+ CreateWordField (Local0, 0x19, TPPA)
+ CreateDWordField (Local0, 0x15, CEO0)
+
+ MAGA = 0x50 /* TGP on AC = 10W in 1/8-Watt increments */
+ TPPA = 0xc8 /* TPPA = 25W in 1/8-Watt increments */
+ CEO0 = 0x200 /* [7:0] Controller index
+ [8:8] Disable controller on AC
+ [9:9] Disable controller on DC */
+ Return (Local0)
+ }
+ }
+
+ Return (NV_ERROR_UNSUPPORTED)
+}
diff --git a/src/mainboard/google/brox/acpi/peg.asl b/src/mainboard/google/brox/acpi/peg.asl
new file mode 100644
index 0000000000..ebaeaecd25
--- /dev/null
+++ b/src/mainboard/google/brox/acpi/peg.asl
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+External (\_SB.PCI0.PEG0.PEGP.NPON, MethodObj)
+External (\_SB.PCI0.PEG0.PEGP.NPOF, MethodObj)
+
+OperationRegion (PCIC, PCI_Config, 0x00, 0x100)
+Field (PCIC, AnyAcc, NoLock, Preserve)
+{
+ Offset (0x4a),
+ CEDR, 1, /* Correctable Error Detected, RW/1C/V */
+ Offset (0x52),
+ , 13,
+ LASX, 1, /* Link Active Status */
+ Offset (0x69),
+ , 2,
+ LREN, 1, /* LTR Enabled */
+ Offset (0xe0),
+ , 7,
+ NCB7, 1, /* Scratch bit to save L2/3 state */
+ Offset (0xe2),
+ , 2,
+ L23E, 1, /* L23_Rdy Entry request */
+ L23R, 1 /* L23_Rdy Detect Transition */
+}
+
+/* L2/3 Entry sequence */
+Method (DL23, 0, Serialized)
+{
+ L23E = 1
+ Local0 = 8
+ While (Local0 > 0)
+ {
+ If (!L23E)
+ {
+ Break
+ }
+
+ Sleep (2)
+ Local0--
+ }
+ NCB7 = 1
+}
+
+/* L2/3 exit seqeuence */
+Method (LD23, 0, Serialized)
+{
+ If (!NCB7)
+ {
+ Return
+ }
+
+ L23R = 1
+ Local0 = 20
+ While (Local0 > 0)
+ {
+ If (!L23R)
+ {
+ Break
+ }
+
+ Sleep (2)
+ Local0--
+ }
+
+ NCB7 = 0
+ Local0 = 8
+ While (Local0 > 0)
+ {
+ If (LASX == 1)
+ {
+ Break
+ }
+
+ Sleep (2)
+ Local0--
+ }
+}
+
+/* PEG Power Resource */
+PowerResource (PGPR, 0, 0)
+{
+ Method (_ON, 0, Serialized)
+ {
+ /* Power up GPU from GCOFF (or GC6 exit if deferred) */
+ \_SB.PCI0.PEG0.PEGP.NPON ()
+ _STA = 1
+ }
+ Method (_OFF, 0, Serialized)
+ {
+ /* Power down GPU to GCOFF (or GC6 entry if deferred) */
+ _STA = 0
+ \_SB.PCI0.PEG0.PEGP.NPOF ()
+ }
+ Name (_STA, 0)
+}
+
+Name (_PR0, Package() { PGPR })
+Name (_PR2, Package() { PGPR })
+Name (_PR3, Package() { PGPR })
diff --git a/src/mainboard/google/brox/acpi/power.asl b/src/mainboard/google/brox/acpi/power.asl
new file mode 100644
index 0000000000..389bc4a2a1
--- /dev/null
+++ b/src/mainboard/google/brox/acpi/power.asl
@@ -0,0 +1,431 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <device/pci_ids.h>
+
+External (\_SB.PCI0.PMC.IPCS, MethodObj)
+
+/* Voltage rail control signals */
+
+#define GPIO_1V8_PWR_EN GPP_E11
+
+#define GPIO_NV33_PWR_EN GPP_E1
+#define GPIO_NV33_PG GPP_E2
+
+#define GPIO_1V8_PG GPP_E20
+#define GPIO_NV12_PWR_EN GPP_D0
+#define GPIO_NV12_PG GPP_D1
+
+#define GPIO_NVVDD_PWR_EN GPP_E0
+#define GPIO_PEXVDD_PWR_EN GPP_E10
+#define GPIO_PEXVDD_PG GPP_E17
+#define GPIO_FBVDD_PWR_EN GPP_A19
+#define GPIO_FBVDD_PG GPP_E4
+
+#define GPIO_GPU_PERST_L GPP_B3
+#define GPIO_GPU_ALLRAILS_PG GPP_E5
+#define GPIO_GPU_NVVDD_EN GPP_A17
+
+#define GC6_DEFER_TYPE_EXIT_GC6 3
+
+/* 250ms in "Timer" units (i.e. 100ns increments) */
+#define MIN_OFF_TIME_TIMERS 2500000
+
+#define SRCCLK_DISABLE 0
+#define SRCCLK_ENABLE 1
+
+#define GPU_POWER_STATE_OFF 0
+#define GPU_POWER_STATE_ON 1
+
+/* Dynamically-assigned NVVDD PG GPIO, set in _INI in SSDT */
+Name (NVPG, 0)
+Name (GPEN, 0)
+
+/* Optimus Power Control State */
+Name (OPCS, OPTIMUS_POWER_CONTROL_DISABLE)
+
+/* PCI configuration space Owner */
+Name (PCIO, PCI_OWNER_DRIVER)
+
+/* Saved PCI configuration space memory (VGA Buffer) */
+Name (VGAB, Buffer (0xfb) { 0x00 })
+
+/* Deferred GPU State */
+Name (OPS0, OPTIMUS_CONTROL_NO_RUN_PS0)
+
+/* GC6 Entry/Exit state */
+Name (GC6E, GC6_STATE_EXITED)
+
+/* Power State, GCOFF, GCON */
+Name (GPPS, GPU_POWER_STATE_ON)
+
+/* Defer GC6 entry / exit until D3-cold request */
+Name (DFEN, 0)
+/* Deferred GC6 Enter control */
+Name (DFCI, 0)
+/* Deferred GC6 Exit control */
+Name (DFCO, 0)
+/* GCOFF Timer */
+Name (GCOT, 0)
+
+#define PMC_SRCCLK_PIN 0x1
+#define PMC_SRCCLK_ENABLE 0x1
+#define PMC_SRCCLK_DISABLE 0x0
+
+#define PMC_RP_IDX (1 << 27)
+#define PMC_RP_ENABLE (1 << 27)
+#define PMC_RP_DISABLE 0x0
+/* Copy of LTR enable bit from PEG port */
+Name (SLTR, 0)
+
+/* Control the PCIe SRCCLK# for dGPU */
+Method (SRCC, 1, Serialized)
+{
+ If (!Arg0)
+ {
+ Local0 = PMC_SRCCLK_DISABLE
+ Local1 = PMC_RP_DISABLE
+ }
+ Else
+ {
+ Local0 = PMC_SRCCLK_ENABLE
+ Local1 = PMC_RP_ENABLE
+ }
+
+ \_SB.PCI0.PMC.IPCS (0xac, 0, 16, PMC_SRCCLK_PIN,
+ Local0, PMC_RP_IDX, Local1)
+}
+
+/* "GC6 In", i.e. GC6 Entry Sequence */
+Method (GC6I, 0, Serialized)
+{
+ GC6E = GC6_STATE_TRANSITION
+
+ /* Save the PEG port's LTR setting */
+ SLTR = LREN
+
+ /* Put PCIe link into L2/3 */
+ \_SB.PCI0.PEG0.DL23 ()
+
+ /* Wait for GPU to deassert its GPIO4, i.e. GPU_NVVDD_EN */
+ GPPL (GPIO_GPU_NVVDD_EN, 0, 20)
+
+ /* Deassert PG_GPU_ALLRAILS */
+ CTXS (GPIO_GPU_ALLRAILS_PG)
+
+ /* Ramp down FBVDD - TODO: Remove Agah when board is dropped */
+ CTXS (GPIO_FBVDD_PWR_EN)
+
+ /* Ramp down PEXVDD */
+ CTXS (GPIO_PEXVDD_PWR_EN)
+ Sleep (2)
+
+ /* Deassert EN_PPVAR_GPU_NVVDD */
+ CTXS (GPIO_NVVDD_PWR_EN)
+ Sleep (2)
+
+ /* Assert GPU_PERST_L */
+ CTXS (GPIO_GPU_PERST_L)
+
+ /* Disable PCIe SRCCLK# */
+ SRCC (SRCCLK_DISABLE)
+
+ GC6E = GC6_STATE_ENTERED
+}
+
+/* "GC6 Out", i.e. GC6 Exit Sequence */
+Method (GC6O, 0, Serialized)
+{
+ GC6E = GC6_STATE_TRANSITION
+
+ /* Re-enable PCIe SRCCLK# */
+ SRCC (SRCCLK_ENABLE)
+
+ /* Deassert GPU_PERST_L */
+ STXS (GPIO_GPU_PERST_L)
+
+ /* Wait for GPU to assert GPU_NVVDD_EN */
+ GPPL (GPIO_GPU_NVVDD_EN, 1, 20)
+
+ /* Ramp up NVVDD */
+ STXS (GPIO_NVVDD_PWR_EN)
+ GPPL (NVPG, 1, 4)
+
+ /* Ramp up PEXVDD */
+ STXS (GPIO_PEXVDD_PWR_EN)
+ GPPL (GPIO_PEXVDD_PG, 1, 4)
+
+ /* Ramp up FBVDD - TODO: Remove Agah when board is dropped */
+ STXS (GPIO_FBVDD_PWR_EN)
+
+
+ /* Assert PG_GPU_ALLRAILS */
+ STXS (GPIO_GPU_ALLRAILS_PG)
+
+ /* Restore PCIe link back to L0 state */
+ \_SB.PCI0.PEG0.LD23 ()
+
+ /* Wait for dGPU to reappear on the bus */
+ Local0 = 50
+ While (NVID != PCI_VID_NVIDIA)
+ {
+ Stall (100)
+ Local0--
+ If (Local0 == 0)
+ {
+ Break
+ }
+ }
+
+ /* Restore the PEG LTR enable bit */
+ LREN = SLTR
+
+ /* Clear recoverable errors detected bit */
+ CEDR = 1
+
+ GC6E = GC6_STATE_EXITED
+}
+
+/* GCOFF exit sequence */
+Method (PGON, 0, Serialized)
+{
+ Local0 = Timer - GCOT
+ If (Local0 < MIN_OFF_TIME_TIMERS)
+ {
+ Local1 = (MIN_OFF_TIME_TIMERS - Local0) / 10000
+ Printf("Sleeping %o to ensure min GCOFF time", Local1)
+ Sleep (Local1)
+ }
+
+ /* Assert PERST# */
+ CTXS (GPIO_GPU_PERST_L)
+
+ /* Ramp up 1.2V rail on boards with support */
+ STXS (GPIO_NV12_PWR_EN)
+ GPPL (GPIO_NV12_PG, 1, 5)
+
+ /* Ramp up 1.8V rail */
+ STXS (GPEN)
+ GPPL (GPIO_1V8_PG, 1, 20)
+
+ /* Ramp up NV33 rail */
+ STXS (GPIO_NV33_PWR_EN)
+ GPPL (GPIO_NV33_PG, 1, 20)
+
+ /* Ramp up NVVDD rail */
+ STXS (GPIO_NVVDD_PWR_EN)
+ GPPL (NVPG, 1, 5)
+
+ /* Ramp up PEXVDD rail */
+ STXS (GPIO_PEXVDD_PWR_EN)
+ GPPL (GPIO_PEXVDD_PG, 1, 5)
+
+ /* Ramp up FBVDD rail */
+ STXS (GPIO_FBVDD_PWR_EN)
+
+ GPPL (GPIO_FBVDD_PG, 1, 5)
+
+ /* All rails are good */
+ STXS (GPIO_GPU_ALLRAILS_PG)
+ Sleep (1)
+
+ /* Deassert PERST# */
+ STXS (GPIO_GPU_PERST_L)
+
+
+ GC6E = GC6_STATE_EXITED
+ GPPS = GPU_POWER_STATE_ON
+}
+
+/* GCOFF entry sequence */
+Method (PGOF, 0, Serialized)
+{
+ /* Assert PERST# */
+ CTXS (GPIO_GPU_PERST_L)
+
+ /* All rails are about to go down */
+ CTXS (GPIO_GPU_ALLRAILS_PG)
+ Sleep (1)
+
+ /* Ramp down FBVDD */
+ CTXS (GPIO_FBVDD_PWR_EN)
+
+ /* Ramp down PEXVDD and let rail discharge to <10% */
+ CTXS (GPIO_PEXVDD_PWR_EN)
+ Sleep (2)
+
+ /* Ramp down NVVDD */
+ CTXS (GPIO_NVVDD_PWR_EN)
+ Sleep (2)
+
+ /* Ramp down NV33 */
+ CTXS (GPIO_NV33_PWR_EN)
+ Sleep (4)
+
+ /* Ramp down 1.8V */
+ CTXS (GPEN)
+
+ /* Ramp down 1.2V rail on boards with support */
+ CTXS (GPIO_NV12_PWR_EN)
+
+ GCOT = Timer
+
+ GPPS = GPU_POWER_STATE_OFF
+}
+
+/* GCOFF Out, i.e. full power-on sequence */
+Method (GCOO, 0, Serialized)
+{
+ If (GPPS == GPU_POWER_STATE_ON)
+ {
+ Printf ("PGON: GPU already on")
+ Return
+ }
+
+ SRCC (SRCCLK_ENABLE)
+ PGON ()
+ \_SB.PCI0.PEG0.LD23 ()
+
+ /* Wait for dGPU to reappear on the bus */
+ Local0 = 50
+ While (NVID != PCI_VID_NVIDIA)
+ {
+ Stall (100)
+ Local0--
+ If (Local0 == 0)
+ {
+ Break
+ }
+ }
+
+ /* Restore the PEG LTR enable bit */
+ LREN = SLTR
+
+ /* Clear recoverable errors detected bit */
+ CEDR = 1
+
+ /* Restore the PEG LTR enable bit */
+ LREN = SLTR
+
+ /* Clear recoverable errors detected bit */
+ CEDR = 1
+}
+
+/* GCOFF In, i.e. full power-off sequence */
+Method (GCOI, 0, Serialized)
+{
+ If (GPPS == GPU_POWER_STATE_OFF)
+ {
+ Printf ("GPU already off")
+ Return
+ }
+
+ /* Save the PEG port's LTR setting */
+ SLTR = LREN
+ \_SB.PCI0.PEG0.DL23 ()
+ PGOF ()
+ SRCC (SRCCLK_DISABLE)
+}
+
+/* Handle deferred GC6 vs. poweron request */
+Method (NPON, 0, Serialized)
+{
+ If (DFEN == GC6_DEFER_ENABLE)
+ {
+ If (DFCO == GC6_DEFER_TYPE_EXIT_GC6)
+ {
+ GC6O ()
+ }
+
+ DFEN = GC6_DEFER_DISABLE
+ }
+ Else
+ {
+ GCOO ()
+ }
+}
+
+/* Handle deferred GC6 vs. poweroff request */
+Method (NPOF, 0, Serialized)
+{
+ /* Don't touch the `DFEN` flag until the GC6 exit. */
+ If (DFEN == GC6_DEFER_ENABLE)
+ {
+ /* Deferred GC6 entry */
+ If (DFCI == NVJT_GPC_EGNS || DFCI == NVJT_GPC_EGIS)
+ {
+ GC6I ()
+ }
+ }
+ Else
+ {
+ GCOI ()
+ }
+}
+
+Method (_ON, 0, Serialized)
+{
+ PGON ()
+}
+
+Method (_OFF, 0, Serialized)
+{
+ PGOF ()
+}
+
+/* Put device into D0 */
+Method (_PS0, 0, NotSerialized)
+{
+ If (OPS0 == OPTIMUS_CONTROL_RUN_PS0)
+ {
+ /* Restore PCI config space */
+ If (PCIO == PCI_OWNER_SBIOS)
+ {
+ VGAR = VGAB
+ }
+
+ /* Poweron or deferred GC6 exit */
+ NPON ()
+
+ OPS0 = OPTIMUS_CONTROL_NO_RUN_PS0
+ }
+}
+
+/* Put device into D3 */
+Method (_PS3, 0, NotSerialized)
+{
+ If (OPCS == OPTIMUS_POWER_CONTROL_ENABLE)
+ {
+ /* Save PCI config space to ACPI buffer */
+ If (PCIO == PCI_OWNER_SBIOS)
+ {
+ VGAB = VGAR
+ }
+
+ /* Poweroff or deferred GC6 entry */
+ NPOF ()
+
+ /* Because _PS3 ran NPOF, _PS0 must run NPON */
+ OPS0 = OPTIMUS_CONTROL_RUN_PS0
+
+ /* OPCS is one-shot, so reset it */
+ OPCS = OPTIMUS_POWER_CONTROL_DISABLE
+ }
+}
+
+Method (PSTA, 0, Serialized)
+{
+ If (GC6E == GC6_STATE_EXITED &&
+ \_SB.PCI0.GTXS(GPIO_GPU_ALLRAILS_PG) == 1)
+ {
+ Return (1)
+ }
+ Else
+ {
+ Return (0)
+ }
+}
+
+Method (_STA, 0, Serialized)
+{
+ Return (0xF)
+}
diff --git a/src/mainboard/google/brox/acpi/utility.asl b/src/mainboard/google/brox/acpi/utility.asl
new file mode 100644
index 0000000000..49f3dca8e9
--- /dev/null
+++ b/src/mainboard/google/brox/acpi/utility.asl
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/*
+ * Poll a GPIO until it goes to the specified state
+ * Arg0 == GPIO #
+ * Arg1 == state (0 or 1)
+ * Arg2 == timeout in ms
+ */
+Method (GPPL, 3, Serialized)
+{
+ Local0 = 0
+ Local1 = Arg2 * 10
+ While (Local0 < Local1)
+ {
+ If (\_SB.PCI0.GRXS (Arg0) == Arg1) {
+ Return (0)
+ } Else {
+ Local0++
+ }
+ Stall (100)
+ }
+
+ If (Local0 == Arg2) {
+ Printf("[ERROR] GPPL for %o timed out", Arg0)
+ }
+
+ Return (0xFF)
+}
+
+/* Convert from 32-bit integer to 4-byte buffer (little-endian) */
+Method (ITOB, 1)
+{
+ Local0 = Buffer(4) { 0, 0, 0, 0 }
+ Local0[0] = Arg0 & 0xFF
+ Local0[1] = (Arg0 >> 8) & 0xFF
+ Local0[2] = (Arg0 >> 16) & 0xFF
+ Local0[3] = (Arg0 >> 24) & 0xFF
+ Return (Local0)
+}
+
+/* Convert from 64-bit integer to 8-byte buffer (little-endian) */
+Method (LTOB, 1)
+{
+ Local0 = Buffer(8) { 0, 0, 0, 0, 0, 0, 0, 0 }
+ Local0[0] = Arg0 & 0xFF
+ Local0[1] = (Arg0 >> 8) & 0xFF
+ Local0[2] = (Arg0 >> 16) & 0xFF
+ Local0[3] = (Arg0 >> 24) & 0xFF
+ Local0[4] = (Arg0 >> 32) & 0xFF
+ Local0[5] = (Arg0 >> 40) & 0xFF
+ Local0[6] = (Arg0 >> 48) & 0xFF
+ Local0[7] = (Arg0 >> 56) & 0xFF
+ Return (Local0)
+}
diff --git a/src/mainboard/google/brox/board_info.txt b/src/mainboard/google/brox/board_info.txt
new file mode 100644
index 0000000000..ae581b69a8
--- /dev/null
+++ b/src/mainboard/google/brox/board_info.txt
@@ -0,0 +1,6 @@
+Vendor name: Google
+Board name: Brox
+Category: laptop
+ROM protocol: SPI
+ROM socketed: n
+Flashrom support: y
diff --git a/src/mainboard/google/brox/bootblock.c b/src/mainboard/google/brox/bootblock.c
new file mode 100644
index 0000000000..c24e9590e2
--- /dev/null
+++ b/src/mainboard/google/brox/bootblock.c
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <baseboard/variants.h>
+#include <bootblock_common.h>
+
+void bootblock_mainboard_early_init(void)
+{
+ const struct pad_config *pads;
+ size_t num;
+ pads = variant_early_gpio_table(&num);
+ gpio_configure_pads(pads, num);
+}
+
+void bootblock_mainboard_init(void)
+{
+ variant_update_descriptor();
+}
+
+void __weak variant_update_descriptor(void) {}
diff --git a/src/mainboard/google/brox/chromeos.c b/src/mainboard/google/brox/chromeos.c
new file mode 100644
index 0000000000..5c99371eb1
--- /dev/null
+++ b/src/mainboard/google/brox/chromeos.c
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <baseboard/gpio.h>
+#include <bootmode.h>
+#include <boot/coreboot_tables.h>
+#include <gpio.h>
+#include <types.h>
+
+void fill_lb_gpios(struct lb_gpios *gpios)
+{
+ struct lb_gpio chromeos_gpios[] = {
+ {-1, ACTIVE_HIGH, get_lid_switch(), "lid"},
+ {-1, ACTIVE_HIGH, 0, "power"},
+ {-1, ACTIVE_HIGH, gfx_get_init_done(), "oprom"},
+ {GPIO_EC_IN_RW, ACTIVE_HIGH, gpio_get(GPIO_EC_IN_RW), "EC in RW"},
+ };
+ lb_add_gpios(gpios, chromeos_gpios, ARRAY_SIZE(chromeos_gpios));
+}
+
+int get_write_protect_state(void)
+{
+ return gpio_get(GPIO_PCH_WP);
+}
+
+int get_ec_is_trusted(void)
+{
+ /* EC is trusted if not in RW. */
+ return !gpio_get(GPIO_EC_IN_RW);
+}
diff --git a/src/mainboard/google/brox/chromeos.fmd b/src/mainboard/google/brox/chromeos.fmd
new file mode 100644
index 0000000000..59b24dd4a2
--- /dev/null
+++ b/src/mainboard/google/brox/chromeos.fmd
@@ -0,0 +1,60 @@
+FLASH 32M {
+ SI_ALL 5M {
+ SI_DESC 4K
+ SI_ME {
+ CSE_LAYOUT 8K
+ CSE_RO 1640K
+ CSE_DATA 420K
+ # 64-KiB aligned to optimize RW erases during CSE update.
+ CSE_RW 3008K
+ }
+ }
+ SI_BIOS 27M {
+ RW_SECTION_A 8M {
+ VBLOCK_A 64K
+ FW_MAIN_A(CBFS)
+ RW_FWID_A 64
+ ME_RW_A(CBFS) 3008K
+ }
+ RW_LEGACY(CBFS) 2M
+ RW_MISC 1M {
+ UNIFIED_MRC_CACHE(PRESERVE) 128K {
+ RECOVERY_MRC_CACHE 64K
+ RW_MRC_CACHE 64K
+ }
+ RW_ELOG(PRESERVE) 16K
+ RW_SHARED 16K {
+ SHARED_DATA 8K
+ VBLOCK_DEV 8K
+ }
+ # The RW_SPD_CACHE region is only used for brox variants that use DDRx memory.
+ # It is placed in the common `chromeos.fmd` file because it is only 4K and there
+ # is free space in the RW_MISC region that cannot be easily reclaimed because
+ # the RW_SECTION_B must start on the 16M boundary.
+ RW_SPD_CACHE(PRESERVE) 4K
+ RW_VPD(PRESERVE) 8K
+ RW_NVRAM(PRESERVE) 24K
+ }
+ # This section starts at the 16M boundary in SPI flash.
+ # ADL does not support a region crossing this boundary,
+ # because the SPI flash is memory-mapped into two non-
+ # contiguous windows.
+ RW_SECTION_B 8M {
+ VBLOCK_B 64K
+ FW_MAIN_B(CBFS)
+ RW_FWID_B 64
+ ME_RW_B(CBFS) 3008K
+ }
+ # Make WP_RO region align with SPI vendor
+ # memory protected range specification.
+ WP_RO 8M {
+ RO_VPD(PRESERVE) 16K
+ RO_SECTION {
+ FMAP 2K
+ RO_FRID 64
+ GBB@4K 448K
+ COREBOOT(CBFS)
+ }
+ }
+ }
+}
diff --git a/src/mainboard/google/brox/dsdt.asl b/src/mainboard/google/brox/dsdt.asl
new file mode 100644
index 0000000000..6ae46946aa
--- /dev/null
+++ b/src/mainboard/google/brox/dsdt.asl
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <acpi/acpi.h>
+#include <variant/ec.h>
+
+DefinitionBlock(
+ "dsdt.aml",
+ "DSDT",
+ ACPI_DSDT_REV_2,
+ OEM_ID,
+ ACPI_TABLE_CREATOR,
+ 0x20110725
+)
+{
+ #include <acpi/dsdt_top.asl>
+ #include <cpu/intel/common/acpi/cpu.asl>
+ #include <soc/intel/common/acpi/platform.asl>
+ #include <soc/intel/common/block/acpi/acpi/globalnvs.asl>
+
+ Scope (\_SB) {
+#if CONFIG(HAVE_WWAN_POWER_SEQUENCE)
+ #include "wwan_power.asl"
+#endif
+ Device (PCI0)
+ {
+ #include <soc/intel/common/block/acpi/acpi/northbridge.asl>
+ #include <soc/intel/alderlake/acpi/southbridge.asl>
+ #include <soc/intel/alderlake/acpi/tcss.asl>
+ }
+ }
+
+ /* Chipset specific sleep states */
+ #include <southbridge/intel/common/acpi/sleepstates.asl>
+
+ /* ChromeOS Embedded Controller */
+ Scope (\_SB.PCI0.LPCB)
+ {
+ /* ACPI code for EC SuperIO functions */
+ #include <ec/google/chromeec/acpi/superio.asl>
+ /* ACPI code for EC functions */
+ #include <ec/google/chromeec/acpi/ec.asl>
+ }
+
+#if CONFIG(INCLUDE_NVIDIA_GPU_ASL)
+ #include "acpi/gpu_top.asl"
+#endif
+}
diff --git a/src/mainboard/google/brox/ec.c b/src/mainboard/google/brox/ec.c
new file mode 100644
index 0000000000..f828bc5547
--- /dev/null
+++ b/src/mainboard/google/brox/ec.c
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <acpi/acpi.h>
+#include <console/console.h>
+#include <ec/ec.h>
+#include <ec/google/chromeec/ec.h>
+#include <variant/ec.h>
+
+void mainboard_ec_init(void)
+{
+ static const struct google_chromeec_event_info info = {
+ .log_events = MAINBOARD_EC_LOG_EVENTS,
+ .sci_events = MAINBOARD_EC_SCI_EVENTS,
+ .s3_wake_events = MAINBOARD_EC_S3_WAKE_EVENTS,
+ .s5_wake_events = MAINBOARD_EC_S5_WAKE_EVENTS,
+ .s0ix_wake_events = MAINBOARD_EC_S0IX_WAKE_EVENTS,
+ };
+
+ printk(BIOS_DEBUG, "mainboard: EC init\n");
+
+ google_chromeec_events_init(&info, acpi_is_wakeup_s3());
+}
diff --git a/src/mainboard/google/brox/mainboard.c b/src/mainboard/google/brox/mainboard.c
new file mode 100644
index 0000000000..f892099be8
--- /dev/null
+++ b/src/mainboard/google/brox/mainboard.c
@@ -0,0 +1,236 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <acpi/acpigen.h>
+#include <baseboard/gpio.h>
+#include <baseboard/variants.h>
+#include <device/device.h>
+#include <drivers/tpm/cr50.h>
+#include <drivers/wwan/fm/chip.h>
+#include <ec/ec.h>
+#include <fw_config.h>
+#include <security/tpm/tss.h>
+#include <soc/gpio.h>
+#include <soc/ramstage.h>
+#include <stdio.h>
+
+WEAK_DEV_PTR(rp6_wwan);
+WEAK_DEV_PTR(dgpu);
+
+static void add_fw_config_oem_string(const struct fw_config *config, void *arg)
+{
+ struct smbios_type11 *t;
+ char buffer[64];
+
+ t = (struct smbios_type11 *)arg;
+
+ snprintf(buffer, sizeof(buffer), "%s-%s", config->field_name, config->option_name);
+ t->count = smbios_add_string(t->eos, buffer);
+}
+
+static void mainboard_smbios_strings(struct device *dev, struct smbios_type11 *t)
+{
+ fw_config_for_each_found(add_fw_config_oem_string, t);
+}
+
+void mainboard_update_soc_chip_config(struct soc_intel_alderlake_config *config)
+{
+ int ret;
+
+ ret = tlcl_lib_init();
+ if (ret != VB2_SUCCESS) {
+ printk(BIOS_ERR, "tlcl_lib_init() failed: 0x%x\n", ret);
+ return;
+ }
+
+ if (cr50_is_long_interrupt_pulse_enabled()) {
+ printk(BIOS_INFO, "Enabling GPIO PM b/c CR50 has long IRQ pulse support\n");
+ config->gpio_override_pm = 0;
+ } else {
+ printk(BIOS_INFO, "Disabling GPIO PM b/c CR50 does not have long IRQ pulse "
+ "support\n");
+ config->gpio_override_pm = 1;
+ config->gpio_pm[COMM_0] = 0;
+ config->gpio_pm[COMM_1] = 0;
+ config->gpio_pm[COMM_2] = 0;
+ config->gpio_pm[COMM_3] = 0;
+ config->gpio_pm[COMM_4] = 0;
+ config->gpio_pm[COMM_5] = 0;
+ }
+
+ variant_update_soc_chip_config(config);
+}
+
+void __weak variant_update_soc_chip_config(struct soc_intel_alderlake_config *config)
+{
+ /* default implementation does nothing */
+}
+
+void __weak variant_init(void)
+{
+ /* default implementation does nothing */
+}
+
+void __weak fw_config_gpio_padbased_override(struct pad_config *padbased_table)
+{
+ /* default implementation does nothing */
+}
+
+void __weak variant_configure_pads(void)
+{
+ const struct pad_config *base_pads;
+ const struct pad_config *override_pads;
+ size_t base_num, override_num;
+
+ base_pads = variant_gpio_table(&base_num);
+ override_pads = variant_gpio_override_table(&override_num);
+ gpio_configure_pads_with_override(base_pads, base_num, override_pads, override_num);
+}
+
+static void mainboard_init(void *chip_info)
+{
+ variant_configure_pads();
+ variant_init();
+ variant_devtree_update();
+}
+
+void __weak variant_devtree_update(void)
+{
+ /* Override dev tree settings per board */
+}
+
+static void mainboard_dev_init(struct device *dev)
+{
+ mainboard_ec_init();
+}
+
+static void mainboard_generate_wwan_shutdown(const struct device *dev)
+{
+ const struct drivers_wwan_fm_config *config = config_of(dev);
+ const struct device *parent = dev->bus->dev;
+
+ if (!config)
+ return;
+ if (config->rtd3dev) {
+ acpigen_write_store();
+ acpigen_emit_namestring(acpi_device_path_join(parent, "RTD3._STA"));
+ acpigen_emit_byte(LOCAL0_OP);
+ acpigen_write_if_lequal_op_int(LOCAL0_OP, ONE_OP);
+ {
+ acpigen_emit_namestring(acpi_device_path_join(dev, "DPTS"));
+ acpigen_emit_byte(ARG0_OP);
+ }
+ acpigen_write_if_end();
+ }
+}
+
+static void mainboard_generate_dgpu_shutdown(const struct device *dev)
+{
+ /* Call `_OFF` from the Power Resource associated with the dGPU's PEG port. */
+ const struct device *parent = dev->bus->dev;
+
+ if (parent)
+ acpigen_emit_namestring(acpi_device_path_join(parent, "PGPR._OFF"));
+}
+
+static void mainboard_generate_mpts(void)
+{
+ const struct device *wwan = DEV_PTR(rp6_wwan);
+ const struct device *dgpu = DEV_PTR(dgpu);
+
+ /*
+ * If HAVE_WWAN_POWER_SEQUENCE is selected, MPTS will be added to the
+ * DSDT via wwan_power.asl. We can't add MPTS to the SSDT as well,
+ * since the duplicate definition will result in a kernel error.
+ *
+ * This special case can be removed in the future if the power-off
+ * sequences for all WWAN devices used on brox are moved to the SSDT.
+ */
+ if (CONFIG(HAVE_WWAN_POWER_SEQUENCE)) {
+ if (wwan || dgpu)
+ printk(BIOS_ERR, "Skip adding duplicate MPTS entry to SSDT\n");
+ return;
+ }
+
+ acpigen_write_scope("\\_SB");
+ acpigen_write_method_serialized("MPTS", 1);
+ if (wwan)
+ mainboard_generate_wwan_shutdown(wwan);
+ if (dgpu)
+ mainboard_generate_dgpu_shutdown(dgpu);
+
+ acpigen_write_method_end(); /* Method */
+ acpigen_write_scope_end(); /* Scope */
+}
+
+static void mainboard_generate_s0ix_hook(void)
+{
+ acpigen_write_if_lequal_op_int(ARG0_OP, 1);
+ {
+ if (CONFIG(HAVE_SLP_S0_GATE))
+ acpigen_soc_clear_tx_gpio(GPIO_SLP_S0_GATE);
+ variant_generate_s0ix_hook(S0IX_ENTRY);
+ }
+ acpigen_write_else();
+ {
+ if (CONFIG(HAVE_SLP_S0_GATE))
+ acpigen_soc_set_tx_gpio(GPIO_SLP_S0_GATE);
+ variant_generate_s0ix_hook(S0IX_EXIT);
+ }
+ acpigen_write_if_end();
+}
+
+static void mainboard_fill_ssdt(const struct device *dev)
+{
+ mainboard_generate_mpts();
+
+ /* for variant to fill additional SSDT */
+ variant_fill_ssdt(dev);
+
+ acpigen_write_scope("\\_SB");
+ acpigen_write_method_serialized("MS0X", 1);
+ mainboard_generate_s0ix_hook();
+ acpigen_write_method_end(); /* Method */
+ acpigen_write_scope_end(); /* Scope */
+
+}
+
+void __weak variant_fill_ssdt(const struct device *dev)
+{
+ /* Add board-specific SSDT entries */
+}
+
+void __weak variant_generate_s0ix_hook(enum s0ix_entry entry)
+{
+ /* Add board-specific MS0X entries */
+ /*
+ if (s0ix_entry == S0IX_ENTRY) {
+ implement variant operations here
+ }
+ if (s0ix_entry == S0IX_EXIT) {
+ implement variant operations here
+ }
+ */
+}
+
+static void mainboard_enable(struct device *dev)
+{
+ dev->ops->init = mainboard_dev_init;
+ dev->ops->get_smbios_strings = mainboard_smbios_strings;
+ dev->ops->acpi_fill_ssdt = mainboard_fill_ssdt;
+}
+
+
+void __weak variant_finalize(void)
+{
+}
+
+static void mainboard_final(void *chip_info)
+{
+ variant_finalize();
+}
+
+struct chip_operations mainboard_ops = {
+ .init = mainboard_init,
+ .enable_dev = mainboard_enable,
+ .final = mainboard_final,
+};
diff --git a/src/mainboard/google/brox/romstage.c b/src/mainboard/google/brox/romstage.c
new file mode 100644
index 0000000000..4e88eca617
--- /dev/null
+++ b/src/mainboard/google/brox/romstage.c
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <baseboard/gpio.h>
+#include <baseboard/variants.h>
+#include <fsp/api.h>
+#include <gpio.h>
+#include <soc/romstage.h>
+#include <string.h>
+
+void mainboard_memory_init_params(FSPM_UPD *memupd)
+{
+ const struct mb_cfg *mem_config = variant_memory_params();
+ bool half_populated = variant_is_half_populated();
+ struct mem_spd spd_info;
+
+ memset(&spd_info, 0, sizeof(spd_info));
+ variant_get_spd_info(&spd_info);
+
+ const struct pad_config *pads;
+ size_t pads_num;
+
+ memcfg_init(memupd, mem_config, &spd_info, half_populated);
+
+ pads = variant_romstage_gpio_table(&pads_num);
+ gpio_configure_pads(pads, pads_num);
+}
diff --git a/src/mainboard/google/brox/smihandler.c b/src/mainboard/google/brox/smihandler.c
new file mode 100644
index 0000000000..9208d51613
--- /dev/null
+++ b/src/mainboard/google/brox/smihandler.c
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <cpu/x86/smm.h>
+#include <ec/google/chromeec/ec.h>
+#include <ec/google/chromeec/smm.h>
+#include <elog.h>
+#include <intelblocks/smihandler.h>
+#include <variant/ec.h>
+
+void mainboard_smi_sleep(u8 slp_typ)
+{
+ chromeec_smi_sleep(slp_typ, MAINBOARD_EC_S3_WAKE_EVENTS, MAINBOARD_EC_S5_WAKE_EVENTS);
+}
+
+int mainboard_smi_apmc(u8 apmc)
+{
+ chromeec_smi_apmc(apmc, MAINBOARD_EC_SCI_EVENTS, MAINBOARD_EC_SMI_EVENTS);
+ return 0;
+}
+
+void elog_gsmi_cb_mainboard_log_wake_source(void)
+{
+ google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS | MAINBOARD_EC_S0IX_WAKE_EVENTS);
+}
+
+void mainboard_smi_espi_handler(void)
+{
+ chromeec_smi_process_events();
+}
diff --git a/src/mainboard/google/brox/spd/Makefile.inc b/src/mainboard/google/brox/spd/Makefile.inc
new file mode 100644
index 0000000000..be4d98bd1d
--- /dev/null
+++ b/src/mainboard/google/brox/spd/Makefile.inc
@@ -0,0 +1,6 @@
+## SPDX-License-Identifier: GPL-2.0-or-later
+##
+
+ifneq ($(SPD_SOURCES),)
+LIB_SPD_DEPS := $(SPD_SOURCES)
+endif
diff --git a/src/mainboard/google/brox/variants/baseboard/brox/Makefile.inc b/src/mainboard/google/brox/variants/baseboard/brox/Makefile.inc
new file mode 100644
index 0000000000..3a6695828f
--- /dev/null
+++ b/src/mainboard/google/brox/variants/baseboard/brox/Makefile.inc
@@ -0,0 +1,12 @@
+## SPDX-License-Identifier: GPL-2.0-only
+
+bootblock-y += gpio.c
+
+romstage-y += memory.c
+romstage-y += gpio.c
+romstage-$(CONFIG_MAINBOARD_USE_EARLY_LIBGFXINIT) += gma-mainboard.ads
+
+ramstage-y += gpio.c
+ramstage-y += ramstage.c
+
+smm-$(CONFIG_SMMSTORE) += gpio.c
diff --git a/src/mainboard/google/brox/variants/baseboard/brox/devicetree.cb b/src/mainboard/google/brox/variants/baseboard/brox/devicetree.cb
new file mode 100644
index 0000000000..186aadb52d
--- /dev/null
+++ b/src/mainboard/google/brox/variants/baseboard/brox/devicetree.cb
@@ -0,0 +1,205 @@
+chip soc/intel/alderlake
+
+ # GPE configuration
+ register "pmc_gpe0_dw0" = "GPP_A"
+ register "pmc_gpe0_dw1" = "GPP_E"
+ register "pmc_gpe0_dw2" = "GPP_F"
+
+ # EC host command ranges are in 0x800-0x8ff & 0x200-0x20f
+ register "gen1_dec" = "0x00fc0801"
+ register "gen2_dec" = "0x000c0201"
+ # EC memory map range is 0x900-0x9ff
+ register "gen3_dec" = "0x00fc0901"
+
+ # S0ix enable
+ register "s0ix_enable" = "1"
+
+ # DPTF enable
+ register "dptf_enable" = "1"
+
+ register "tcc_offset" = "10" # TCC of 90
+
+ # Enable CNVi BT
+ register "cnvi_bt_core" = "true"
+
+ register "usb2_ports[0]" = "USB2_PORT_TYPE_C(OC0)" # USB2_C0
+ register "usb2_ports[1]" = "USB2_PORT_TYPE_C(OC1)" # USB2_C1
+ register "usb2_ports[2]" = "USB2_PORT_TYPE_C(OC2)" # USB2_C2
+ register "usb2_ports[3]" = "USB2_PORT_MID(OC_SKIP)" # M.2 WWAN
+ register "usb2_ports[5]" = "USB2_PORT_MID(OC_SKIP)" # M.2 Camera
+ register "usb2_ports[8]" = "USB2_PORT_MID(OC_SKIP)" # Type-A Port A0
+ register "usb2_ports[9]" = "USB2_PORT_MID(OC_SKIP)" # M.2 Bluetooth
+
+ register "usb3_ports[0]" = "USB3_PORT_DEFAULT(OC3)" # USB3/2 Type A port A0
+ register "usb3_ports[3]" = "USB3_PORT_DEFAULT(OC_SKIP)" # M.2 WWAN
+
+ register "tcss_ports[0]" = "TCSS_PORT_DEFAULT(OC0)"
+ register "tcss_ports[1]" = "TCSS_PORT_DEFAULT(OC1)"
+ register "tcss_ports[2]" = "TCSS_PORT_DEFAULT(OC2)"
+
+ register "serial_io_i2c_mode" = "{
+ [PchSerialIoIndexI2C0] = PchSerialIoPci,
+ [PchSerialIoIndexI2C1] = PchSerialIoPci,
+ [PchSerialIoIndexI2C2] = PchSerialIoPci,
+ [PchSerialIoIndexI2C3] = PchSerialIoPci,
+ [PchSerialIoIndexI2C4] = PchSerialIoDisabled,
+ [PchSerialIoIndexI2C5] = PchSerialIoPci,
+ }"
+
+ register "serial_io_gspi_mode" = "{
+ [PchSerialIoIndexGSPI0] = PchSerialIoDisabled,
+ [PchSerialIoIndexGSPI1] = PchSerialIoPci,
+ }"
+
+ register "serial_io_uart_mode" = "{
+ [PchSerialIoIndexUART0] = PchSerialIoPci,
+ [PchSerialIoIndexUART1] = PchSerialIoDisabled,
+ [PchSerialIoIndexUART2] = PchSerialIoDisabled,
+ }"
+
+ register "pch_slp_s3_min_assertion_width" = "SLP_S3_ASSERTION_50_MS"
+ register "pch_slp_s4_min_assertion_width" = "SLP_S4_ASSERTION_1S"
+ register "pch_slp_sus_min_assertion_width" = "SLP_SUS_ASSERTION_1_S"
+ register "pch_slp_a_min_assertion_width" = "SLP_A_ASSERTION_98_MS"
+ register "pch_reset_power_cycle_duration" = "POWER_CYCLE_DURATION_1S"
+
+ # HD Audio
+ register "pch_hda_dsp_enable" = "1"
+ register "pch_hda_idisp_link_tmode" = "HDA_TMODE_8T"
+ register "pch_hda_idisp_link_frequency" = "HDA_LINKFREQ_96MHZ"
+ register "pch_hda_idisp_codec_enable" = "1"
+
+ # FIVR RFI Spread Spectrum 1.5%
+ register "fivr_spread_spectrum" = "FIVR_SS_1_5"
+
+ # Intel Common SoC Config
+ #+-------------------+---------------------------+
+ #| Field | Value |
+ #+-------------------+---------------------------+
+ #| GSPI1 | Fingerprint MCU |
+ #| I2C0 | Audio and WFC |
+ #| I2C1 | cr50 TPM. Early init is |
+ #| | required to set up a BAR |
+ #| | for TPM communication |
+ #| I2C2 | SAR0 |
+ #| I2C3 | Touchscreen |
+ #| I2C5 | Trackpad |
+ #+-------------------+---------------------------+
+ register "common_soc_config" = "{
+ .i2c[0] = {
+ .speed = I2C_SPEED_FAST,
+ .rise_time_ns = 650,
+ .fall_time_ns = 400,
+ .data_hold_time_ns = 50,
+ },
+ .i2c[1] = {
+ .speed = I2C_SPEED_FAST,
+ .rise_time_ns = 650,
+ .fall_time_ns = 400,
+ .data_hold_time_ns = 50,
+ },
+ .i2c[2] = {
+ .speed = I2C_SPEED_FAST,
+ .rise_time_ns = 900,
+ .fall_time_ns = 400,
+ .data_hold_time_ns = 50,
+ },
+ .i2c[3] = {
+ .early_init = 1,
+ .speed = I2C_SPEED_FAST,
+ .rise_time_ns = 600,
+ .fall_time_ns = 400,
+ .data_hold_time_ns = 50,
+ },
+ .i2c[5] = {
+ .speed = I2C_SPEED_FAST,
+ .rise_time_ns = 650,
+ .fall_time_ns = 400,
+ .data_hold_time_ns = 50,
+ },
+ }"
+
+ device domain 0 on
+ # The timing values can be derived from datasheet of display panel
+ # You can use EDID string to identify the type of display on the board
+ # use below command to get display info from EDID
+ # strings /sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-eDP-1/edid
+
+ # refer to display PRM document (Volume 2b: Command Reference: Registers)
+ # for more info on display control registers
+ # https://01.org/linuxgraphics/documentation/hardware-specification-prms
+ #+-----------------------------+---------------------------------------+-----+
+ #| Intel docs | devicetree.cb | eDP |
+ #+-----------------------------+---------------------------------------+-----+
+ #| Power up delay | `gpu_panel_power_up_delay` | T3 |
+ #+-----------------------------+---------------------------------------+-----+
+ #| Power on to backlight on | `gpu_panel_power_backlight_on_delay` | T7 |
+ #+-----------------------------+---------------------------------------+-----+
+ #| Power Down delay | `gpu_panel_power_down_delay` | T10 |
+ #+-----------------------------+---------------------------------------+-----+
+ #| Backlight off to power down | `gpu_panel_power_backlight_off_delay` | T9 |
+ #+-----------------------------+---------------------------------------+-----+
+ #| Power Cycle Delay | `gpu_panel_power_cycle_delay` | T12 |
+ #+-----------------------------+---------------------------------------+-----+
+ device ref igpu on
+ register "panel_cfg" = "{
+ .up_delay_ms = 200,
+ .down_delay_ms = 50,
+ .cycle_delay_ms = 500,
+ .backlight_on_delay_ms = 1,
+ .backlight_off_delay_ms = 200,
+ .backlight_pwm_hz = 200,
+ }"
+ end
+ device ref dtt on end
+# device ref tbt_pcie_rp0 off end
+# device ref tbt_pcie_rp1 off end
+# device ref tbt_pcie_rp2 off end
+# device ref tcss_xhci on end
+# device ref tcss_dma0 on end
+# device ref tcss_dma1 on end
+ device ref xhci on end
+ device ref shared_sram on end
+ device ref cnvi_wifi on
+ chip drivers/wifi/generic
+ register "wake" = "GPE0_PME_B0"
+ register "add_acpi_dma_property" = "true"
+ device generic 0 on end
+ end
+ end
+ device ref i2c3 on end
+ device ref heci1 on end
+ device ref sata on end
+ device ref pcie_rp8 on
+ # Enable SD Card PCIE 8 using clk 3
+ register "pch_pcie_rp[PCH_RP(8)]" = "{
+ .clk_src = 3,
+ .clk_req = 3,
+ .flags = PCIE_RP_HOTPLUG | PCIE_RP_LTR | PCIE_RP_AER,
+ }"
+ end #PCIE8 SD card
+ device ref pcie_rp9 on
+ # Enable NVMe PCIE 9 using clk 1
+ register "pch_pcie_rp[PCH_RP(9)]" = "{
+ .clk_src = 1,
+ .clk_req = 1,
+ .flags = PCIE_RP_LTR | PCIE_RP_AER,
+ }"
+ end #PCIE9-12 SSD
+ device ref uart0 on end
+ device ref gspi1 on end
+ device ref pch_espi on
+ chip ec/google/chromeec
+ device pnp 0c09.0 on end
+ end
+ end
+ device ref hda on
+ chip drivers/sof
+ register "spkr_tplg" = "max98360a"
+ register "jack_tplg" = "rt5682"
+ register "mic_tplg" = "_2ch_pdm0"
+ device generic 0 on end
+ end
+ end
+ end
+end
diff --git a/src/mainboard/google/brox/variants/baseboard/brox/gma-mainboard.ads b/src/mainboard/google/brox/variants/baseboard/brox/gma-mainboard.ads
new file mode 100644
index 0000000000..3b02f14d95
--- /dev/null
+++ b/src/mainboard/google/brox/variants/baseboard/brox/gma-mainboard.ads
@@ -0,0 +1,13 @@
+-- SPDX-License-Identifier: GPL-2.0-or-later
+
+with HW.GFX.GMA;
+with HW.GFX.GMA.Display_Probing;
+
+use HW.GFX.GMA;
+use HW.GFX.GMA.Display_Probing;
+
+private package GMA.Mainboard is
+ ports : constant Port_List :=
+ (eDP,
+ others => Disabled);
+end GMA.Mainboard;
diff --git a/src/mainboard/google/brox/variants/baseboard/brox/gpio.c b/src/mainboard/google/brox/variants/baseboard/brox/gpio.c
new file mode 100644
index 0000000000..6161b2ab83
--- /dev/null
+++ b/src/mainboard/google/brox/variants/baseboard/brox/gpio.c
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <baseboard/gpio.h>
+#include <baseboard/variants.h>
+#include <types.h>
+#include <soc/gpio.h>
+#include <vendorcode/google/chromeos/chromeos.h>
+
+/* Pad configuration in ramstage */
+static const struct pad_config gpio_table[] = {
+};
+
+/* Early pad configuration in bootblock */
+static const struct pad_config early_gpio_table[] = {
+};
+
+const struct pad_config *__weak variant_gpio_table(size_t *num)
+{
+ *num = ARRAY_SIZE(gpio_table);
+ return gpio_table;
+}
+
+const struct pad_config *__weak variant_gpio_override_table(size_t *num)
+{
+ *num = 0;
+ return NULL;
+}
+
+const struct pad_config *__weak variant_early_gpio_table(size_t *num)
+{
+ *num = ARRAY_SIZE(early_gpio_table);
+ return early_gpio_table;
+}
+
+static const struct cros_gpio cros_gpios[] = {
+ CROS_GPIO_REC_AL(CROS_GPIO_VIRTUAL, CROS_GPIO_DEVICE_NAME),
+ CROS_GPIO_WP_AH(GPIO_PCH_WP, CROS_GPIO_DEVICE_NAME),
+};
+
+DECLARE_WEAK_CROS_GPIOS(cros_gpios);
+
+const struct pad_config *__weak variant_romstage_gpio_table(size_t *num)
+{
+ *num = 0;
+ return NULL;
+}
diff --git a/src/mainboard/google/brox/variants/baseboard/brox/include/baseboard/ec.h b/src/mainboard/google/brox/variants/baseboard/brox/include/baseboard/ec.h
new file mode 100644
index 0000000000..722f48bb32
--- /dev/null
+++ b/src/mainboard/google/brox/variants/baseboard/brox/include/baseboard/ec.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __BASEBOARD_EC_H__
+#define __BASEBOARD_EC_H__
+
+#include <baseboard/gpio.h>
+#include <ec/ec.h>
+#include <ec/google/chromeec/ec_commands.h>
+
+#define VARIANT_EC_SCI_EVENTS 0
+
+#define MAINBOARD_EC_SCI_EVENTS \
+ (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_LOW) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_CRITICAL) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_STATUS) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_THRESHOLD) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_START) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_STOP) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_MKBP) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_PD_MCU) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_MODE_CHANGE) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_USB_MUX) |\
+ VARIANT_EC_SCI_EVENTS)
+#define MAINBOARD_EC_SMI_EVENTS \
+ (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED))
+/* EC can wake from S5 with lid or power button */
+#define MAINBOARD_EC_S5_WAKE_EVENTS \
+ (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON))
+/*
+ * EC can wake from S3/S0ix with:
+ * 1. Lid open
+ * 2. AC Connect/Disconnect
+ * 3. Power button
+ * 4. Key press
+ * 5. Mode change
+ * 6. Low battery
+ */
+#define MAINBOARD_EC_S3_WAKE_EVENTS \
+ (MAINBOARD_EC_S5_WAKE_EVENTS |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEY_PRESSED) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_MODE_CHANGE) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_CRITICAL) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_SHUTDOWN))
+#define MAINBOARD_EC_S0IX_WAKE_EVENTS \
+ (MAINBOARD_EC_S3_WAKE_EVENTS |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_USB_MUX) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_HANG_DETECT))
+/* Log EC wake events plus EC shutdown events */
+#define MAINBOARD_EC_LOG_EVENTS \
+ (EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_SHUTDOWN) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_PANIC))
+/*
+ * ACPI related definitions for ASL code.
+ */
+/* Enable Keyboard Backlight */
+#define EC_ENABLE_KEYBOARD_BACKLIGHT
+/* Enable MKBP for buttons and switches */
+#define EC_ENABLE_MKBP_DEVICE
+/* Enable LID switch and provide wake pin for EC */
+#define EC_ENABLE_LID_SWITCH
+#define EC_ENABLE_WAKE_PIN GPE_EC_WAKE
+/* Enable EC backed PD MCU device in ACPI */
+#define EC_ENABLE_PD_MCU_DEVICE
+#define SIO_EC_MEMMAP_ENABLE /* EC Memory Map Resources */
+#define SIO_EC_HOST_ENABLE /* EC Host Interface Resources */
+#define SIO_EC_ENABLE_PS2K /* Enable PS/2 Keyboard */
+
+#define EC_ENABLE_SYNC_IRQ /* Enable tight timestamp / wake support */
+
+#endif /* __BASEBOARD_EC_H__ */
diff --git a/src/mainboard/google/brox/variants/baseboard/brox/include/baseboard/gpio.h b/src/mainboard/google/brox/variants/baseboard/brox/include/baseboard/gpio.h
new file mode 100644
index 0000000000..0de7ffd36c
--- /dev/null
+++ b/src/mainboard/google/brox/variants/baseboard/brox/include/baseboard/gpio.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __BASEBOARD_GPIO_H__
+#define __BASEBOARD_GPIO_H__
+
+#include <soc/gpe.h>
+#include <soc/gpio.h>
+
+/* eSPI virtual wire reporting */
+#define EC_SCI_GPI GPE0_ESPI
+/* EC wake is EC_PCH_INT which is routed to GPP_F17 pin */
+#define GPE_EC_WAKE GPE0_DW2_17
+/* WP signal to PCH */
+#define GPIO_PCH_WP GPP_E15
+/* EC in RW or RO */
+#define GPIO_EC_IN_RW GPP_F18
+/* Used to gate SoC's SLP_S0# signal */
+#define GPIO_SLP_S0_GATE GPP_F9
+/* GPIO IRQ for tight timestamps / wake support */
+#define EC_SYNC_IRQ GPP_F17_IRQ
+
+#endif /* __BASEBOARD_GPIO_H__ */
diff --git a/src/mainboard/google/brox/variants/baseboard/brox/memory.c b/src/mainboard/google/brox/variants/baseboard/brox/memory.c
new file mode 100644
index 0000000000..bcad9b4be9
--- /dev/null
+++ b/src/mainboard/google/brox/variants/baseboard/brox/memory.c
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <baseboard/gpio.h>
+#include <baseboard/variants.h>
+#include <gpio.h>
+
+static const struct mb_cfg baseboard_memcfg = {
+ .type = MEM_TYPE_LP4X,
+
+ .rcomp = {
+ /* Baseboard uses only 100ohm Rcomp resistors */
+ .resistor = 100,
+
+ /* Baseboard Rcomp target values */
+ .targets = {40, 30, 30, 30, 30},
+ },
+
+ /* DQ byte map */
+ .lpx_dq_map = {
+ .ddr0 = {
+ .dq0 = { 9, 11, 8, 10, 12, 14, 13, 15, },
+ .dq1 = { 4, 7, 6, 5, 2, 3, 0, 1, },
+ },
+ .ddr1 = {
+ .dq0 = { 15, 12, 14, 13, 9, 10, 11, 8, },
+ .dq1 = { 0, 1, 3, 2, 7, 5, 4, 6, },
+ },
+ .ddr2 = {
+ .dq0 = { 2, 3, 1, 0, 6, 7, 5, 4, },
+ .dq1 = { 15, 9, 14, 8, 11, 10, 13, 12, },
+ },
+ .ddr3 = {
+ .dq0 = { 3, 1, 2, 0, 4, 6, 7, 5, },
+ .dq1 = { 13, 15, 14, 12, 11, 9, 8, 10, },
+ },
+ .ddr4 = {
+ .dq0 = { 13, 12, 14, 15, 9, 8, 10, 11, },
+ .dq1 = { 4, 7, 5, 6, 1, 2, 0, 3, },
+ },
+ .ddr5 = {
+ .dq0 = { 5, 0, 6, 4, 3, 1, 7, 2, },
+ .dq1 = { 11, 9, 10, 8, 15, 12, 14, 13, },
+ },
+ .ddr6 = {
+ .dq0 = { 15, 12, 14, 13, 10, 9, 11, 8, },
+ .dq1 = { 0, 1, 2, 3, 5, 6, 4, 7, },
+ },
+ .ddr7 = {
+ .dq0 = { 0, 3, 1, 2, 4, 5, 6, 7, },
+ .dq1 = { 11, 8, 13, 14, 9, 12, 15, 10, },
+ },
+ },
+
+ /* DQS CPU<>DRAM map */
+ .lpx_dqs_map = {
+ .ddr0 = { .dqs0 = 1, .dqs1 = 0 },
+ .ddr1 = { .dqs0 = 1, .dqs1 = 0 },
+ .ddr2 = { .dqs0 = 0, .dqs1 = 1 },
+ .ddr3 = { .dqs0 = 0, .dqs1 = 1 },
+ .ddr4 = { .dqs0 = 1, .dqs1 = 0 },
+ .ddr5 = { .dqs0 = 0, .dqs1 = 1 },
+ .ddr6 = { .dqs0 = 1, .dqs1 = 0 },
+ .ddr7 = { .dqs0 = 0, .dqs1 = 1 },
+ },
+
+ .ect = 1, /* Enable Early Command Training */
+};
+
+const struct mb_cfg *__weak variant_memory_params(void)
+{
+ return &baseboard_memcfg;
+}
+
+int __weak variant_memory_sku(void)
+{
+ /*
+ * Memory configuration board straps
+ * GPIO_MEM_CONFIG_0 GPP_E11
+ * GPIO_MEM_CONFIG_1 GPP_E2
+ * GPIO_MEM_CONFIG_2 GPP_E1
+ * GPIO_MEM_CONFIG_3 GPP_E12
+ */
+ gpio_t spd_gpios[] = {
+ GPP_E11,
+ GPP_E2,
+ GPP_E1,
+ GPP_E12,
+ };
+
+ return gpio_base2_value(spd_gpios, ARRAY_SIZE(spd_gpios));
+}
+
+bool __weak variant_is_half_populated(void)
+{
+ /* GPIO_MEM_CH_SEL GPP_E13 */
+ return gpio_get(GPP_E13);
+}
+
+void __weak variant_get_spd_info(struct mem_spd *spd_info)
+{
+ spd_info->topo = MEM_TOPO_MEMORY_DOWN;
+ spd_info->cbfs_index = variant_memory_sku();
+}
diff --git a/src/mainboard/google/brox/variants/baseboard/brox/ramstage.c b/src/mainboard/google/brox/variants/baseboard/brox/ramstage.c
new file mode 100644
index 0000000000..78538631e7
--- /dev/null
+++ b/src/mainboard/google/brox/variants/baseboard/brox/ramstage.c
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <acpi/acpi_device.h>
+#include <baseboard/variants.h>
+#include <console/console.h>
+#include <device/pci_ops.h>
+#include <drivers/intel/dptf/chip.h>
+#include <intelblocks/power_limit.h>
+#include <soc/pci_devs.h>
+
+
+WEAK_DEV_PTR(dptf_policy);
+
+void variant_update_power_limits(const struct cpu_power_limits *limits, size_t num_entries)
+{
+ if (!num_entries)
+ return;
+
+ const struct device *policy_dev = DEV_PTR(dptf_policy);
+ if (!policy_dev)
+ return;
+
+ struct drivers_intel_dptf_config *config = policy_dev->chip_info;
+
+ uint16_t mchid = pci_s_read_config16(PCI_DEV(0, 0, 0), PCI_DEVICE_ID);
+
+ u8 tdp = get_cpu_tdp();
+
+ for (size_t i = 0; i < num_entries; i++) {
+ if (mchid == limits[i].mchid && tdp == limits[i].cpu_tdp) {
+ struct dptf_power_limits *settings = &config->controls.power_limits;
+ config_t *conf = config_of_soc();
+ struct soc_power_limits_config *soc_config = conf->power_limits_config;
+ settings->pl1.min_power = limits[i].pl1_min_power;
+ settings->pl1.max_power = limits[i].pl1_max_power;
+ settings->pl2.min_power = limits[i].pl2_min_power;
+ settings->pl2.max_power = limits[i].pl2_max_power;
+ soc_config->tdp_pl4 = DIV_ROUND_UP(limits[i].pl4_power,
+ MILLIWATTS_TO_WATTS);
+ printk(BIOS_INFO, "Overriding power limits PL1 (%u, %u) PL2 (%u, %u) PL4 (%u)\n",
+ limits[i].pl1_min_power,
+ limits[i].pl1_max_power,
+ limits[i].pl2_min_power,
+ limits[i].pl2_max_power,
+ limits[i].pl4_power);
+ }
+ }
+}
diff --git a/src/mainboard/google/brox/variants/baseboard/include/baseboard/variants.h b/src/mainboard/google/brox/variants/baseboard/include/baseboard/variants.h
new file mode 100644
index 0000000000..ad8eb05833
--- /dev/null
+++ b/src/mainboard/google/brox/variants/baseboard/include/baseboard/variants.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __BASEBOARD_VARIANTS_H__
+#define __BASEBOARD_VARIANTS_H__
+
+#include <chip.h>
+#include <soc/gpio.h>
+#include <soc/meminit.h>
+#include <stdint.h>
+
+/* The next set of functions return the gpio table and fill in the number of entries for
+ * each table.
+ */
+
+const struct pad_config *variant_gpio_table(size_t *num);
+const struct pad_config *variant_gpio_override_table(size_t *num);
+const struct pad_config *variant_early_gpio_table(size_t *num);
+const struct pad_config *variant_romstage_gpio_table(size_t *num);
+void fw_config_gpio_padbased_override(struct pad_config *padbased_table);
+
+const struct mb_cfg *variant_memory_params(void);
+void variant_get_spd_info(struct mem_spd *spd_info);
+int variant_memory_sku(void);
+bool variant_is_half_populated(void);
+void variant_update_soc_chip_config(struct soc_intel_alderlake_config *config);
+void variant_fill_ssdt(const struct device *dev);
+void variant_configure_pads(void);
+
+enum s0ix_entry {
+ S0IX_EXIT,
+ S0IX_ENTRY,
+};
+
+void variant_generate_s0ix_hook(enum s0ix_entry entry);
+
+/* Modify devictree settings during ramstage */
+void variant_devtree_update(void);
+
+void variant_update_descriptor(void);
+
+struct cpu_power_limits {
+ uint16_t mchid;
+ u8 cpu_tdp;
+ unsigned int pl1_min_power;
+ unsigned int pl1_max_power;
+ unsigned int pl2_min_power;
+ unsigned int pl2_max_power;
+ unsigned int pl4_power;
+};
+
+struct system_power_limits {
+ uint16_t mchid;
+ u8 cpu_tdp;
+ /* PsysPL2 in Watts */
+ unsigned int psys_pl2_power;
+};
+
+struct psys_config {
+ /*
+ * The efficiency of type-c chargers
+ * For example, 'efficiency = 97' means setting 97% of max power to account for
+ * cable loss and FET Rdson loss in the path from the source.
+ */
+ unsigned int efficiency;
+
+ /* The maximum current maps to the Psys signal */
+ unsigned int psys_imax_ma;
+
+ /* The voltage of barrel jack */
+ unsigned int bj_volts_mv;
+};
+
+/* Modify Power Limit devictree settings during ramstage */
+void variant_update_power_limits(const struct cpu_power_limits *limits,
+ size_t num_entries);
+
+
+/*
+ * Modify Power Limit and PsysPL devictree settings during ramstage.
+ * Note, this function must be called in front of calling variant_update_power_limits.
+ */
+void variant_update_psys_power_limits(const struct cpu_power_limits *limits,
+ const struct system_power_limits *sys_limits,
+ size_t num_entries,
+ const struct psys_config *config);
+
+void variant_init(void);
+void variant_finalize(void);
+
+#endif /*__BASEBOARD_VARIANTS_H__ */
diff --git a/src/mainboard/google/brox/variants/brox/Makefile.inc b/src/mainboard/google/brox/variants/brox/Makefile.inc
new file mode 100644
index 0000000000..4a7ff71e45
--- /dev/null
+++ b/src/mainboard/google/brox/variants/brox/Makefile.inc
@@ -0,0 +1,8 @@
+## SPDX-License-Identifier: GPL-2.0-only
+
+bootblock-y += gpio.c
+romstage-y += gpio.c
+ramstage-$(CONFIG_FW_CONFIG) += fw_config.c
+ramstage-$(CONFIG_FW_CONFIG) += variant.c
+ramstage-y += gpio.c
+ramstage-y += ramstage.c
diff --git a/src/mainboard/google/brox/variants/brox/data.vbt b/src/mainboard/google/brox/variants/brox/data.vbt
new file mode 100644
index 0000000000..716d09f557
--- /dev/null
+++ b/src/mainboard/google/brox/variants/brox/data.vbt
Binary files differ
diff --git a/src/mainboard/google/brox/variants/brox/fw_config.c b/src/mainboard/google/brox/variants/brox/fw_config.c
new file mode 100644
index 0000000000..d1bdc80901
--- /dev/null
+++ b/src/mainboard/google/brox/variants/brox/fw_config.c
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <bootstate.h>
+
+static void fw_config_handle(void *unused)
+{
+}
+BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_ENTRY, fw_config_handle, NULL);
diff --git a/src/mainboard/google/brox/variants/brox/gpio.c b/src/mainboard/google/brox/variants/brox/gpio.c
new file mode 100644
index 0000000000..444adc4fa9
--- /dev/null
+++ b/src/mainboard/google/brox/variants/brox/gpio.c
@@ -0,0 +1,218 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <baseboard/variants.h>
+#include <boardid.h>
+#include <soc/gpio.h>
+
+static const struct pad_config board_id0_1_overrides[] = {
+ /* B2 : VRALERT# ==> NC */
+ PAD_NC(GPP_B2, NONE),
+ /* B7 : ISH_12C1_SDA ==> PCH_I2C_TPM_SDA */
+ PAD_CFG_NF_LOCK(GPP_B7, NONE, NF2, LOCK_CONFIG),
+ /* B8 : ISH_12C1_SCL ==> PCH_I2C_TPM_SCL */
+ PAD_CFG_NF_LOCK(GPP_B8, NONE, NF2, LOCK_CONFIG),
+ /* B15 : TIME_SYNC0 ==> NC */
+ PAD_NC(GPP_B15, NONE),
+ /* C3 : SML0CLK ==> NC */
+ PAD_NC(GPP_C3, NONE),
+ /* C4 : SML0DATA ==> NC */
+ PAD_NC(GPP_C4, NONE),
+ /* D13 : ISH_UART0_RXD ==> PCH_I2C_CAM_SDA */
+ PAD_CFG_NF(GPP_D13, NONE, DEEP, NF3),
+ /* D14 : ISH_UART0_TXD ==> PCH_I2C_CAM_SCL */
+ PAD_CFG_NF(GPP_D14, NONE, DEEP, NF3),
+ /* F19 : SRCCLKREQ6# ==> WWAN_SIM1_DET_OD */
+ PAD_CFG_GPI(GPP_F19, UP_20K, DEEP),
+ /* F20 : EXT_PWR_GATE# ==> HPS_RST_R */
+ PAD_CFG_GPO(GPP_F20, 0, DEEP),
+ /* F21 : EXT_PWR_GATE2# ==> WAKE_ON_WWAN_ODL */
+ PAD_NC(GPP_F21, NONE),
+ /* H13 : I2C7_SCL ==> EN_PP3300_SD */
+ PAD_CFG_GPO(GPP_H13, 1, DEEP),
+ /* H21 : IMGCLKOUT2 ==> WLAN_INT_L */
+ PAD_CFG_GPI_APIC(GPP_H21, NONE, DEEP, EDGE_SINGLE, NONE),
+ /* GPD2: LAN_WAKE# ==> NC */
+ PAD_NC(GPD2, NONE),
+};
+
+/* Early pad configuration in bootblock for board id < 2 */
+static const struct pad_config early_gpio_table[] = {
+ /* A13 : PMC_I2C_SCL ==> GSC_PCH_INT_ODL */
+ PAD_CFG_GPI_APIC(GPP_A13, NONE, PLTRST, LEVEL, INVERT),
+ /* B7 : ISH_12C1_SDA ==> PCH_I2C_TPM_SDA */
+ PAD_CFG_NF(GPP_B7, NONE, DEEP, NF2),
+ /* B8 : ISH_12C1_SCL ==> PCH_I2C_TPM_SCL */
+ PAD_CFG_NF(GPP_B8, NONE, DEEP, NF2),
+ /*
+ * D1 : ISH_GP1 ==> FP_RST_ODL
+ * FP_RST_ODL comes out of reset as hi-z and does not have an external pull-down.
+ * To ensure proper power sequencing for the FPMCU device, reset signal is driven low
+ * early on in bootblock, followed by enabling of power. Reset signal is deasserted
+ * later on in ramstage. Since reset signal is asserted in bootblock, it results in
+ * FPMCU not working after a S3 resume. This is a known issue.
+ */
+ PAD_CFG_GPO(GPP_D1, 0, DEEP),
+ /* D2 : ISH_GP2 ==> EN_FP_PWR */
+ PAD_CFG_GPO(GPP_D2, 1, DEEP),
+ /* E0 : SATAXPCIE0 ==> WWAN_PERST_L (updated in ramstage) */
+ PAD_CFG_GPO(GPP_E0, 0, DEEP),
+ /* E13 : THC0_SPI1_IO2 ==> MEM_CH_SEL */
+ PAD_CFG_GPI(GPP_E13, NONE, DEEP),
+ /* E16 : RSVD_TP ==> WWAN_RST_L (updated in ramstage) */
+ PAD_CFG_GPO(GPP_E16, 0, DEEP),
+ /* E15 : RSVD_TP ==> PCH_WP_OD */
+ PAD_CFG_GPI_GPIO_DRIVER(GPP_E15, NONE, DEEP),
+ /* F18 : THC1_SPI2_INT# ==> EC_IN_RW_OD */
+ PAD_CFG_GPI(GPP_F18, NONE, DEEP),
+ /* F21 : EXT_PWR_GATE2# ==> NC */
+ PAD_NC(GPP_F21, NONE),
+ /* H10 : UART0_RXD ==> UART_PCH_RX_DBG_TX */
+ PAD_CFG_NF(GPP_H10, NONE, DEEP, NF2),
+ /* H11 : UART0_TXD ==> UART_PCH_TX_DBG_RX */
+ PAD_CFG_NF(GPP_H11, NONE, DEEP, NF2),
+ /* H13 : I2C7_SCL ==> EN_PP3300_SD */
+ PAD_CFG_GPO(GPP_H13, 1, DEEP),
+};
+
+/* Early pad configuration in bootblock for board id 2 */
+static const struct pad_config early_gpio_table_id2[] = {
+ /* A12 : SATAXPCIE1 ==> EN_PP3300_WWAN */
+ PAD_CFG_GPO(GPP_A12, 1, DEEP),
+ /* A13 : PMC_I2C_SCL ==> GSC_PCH_INT_ODL */
+ PAD_CFG_GPI_APIC(GPP_A13, NONE, PLTRST, LEVEL, INVERT),
+ /* B4 : PROC_GP3 ==> SSD_PERST_L */
+ PAD_CFG_GPO(GPP_B4, 0, DEEP),
+ /* B7 : ISH_12C1_SDA ==> PCH_I2C_TPM_SDA */
+ PAD_CFG_NF(GPP_B7, NONE, DEEP, NF2),
+ /* B8 : ISH_12C1_SCL ==> PCH_I2C_TPM_SCL */
+ PAD_CFG_NF(GPP_B8, NONE, DEEP, NF2),
+ /*
+ * D1 : ISH_GP1 ==> FP_RST_ODL
+ * FP_RST_ODL comes out of reset as hi-z and does not have an external pull-down.
+ * To ensure proper power sequencing for the FPMCU device, reset signal is driven low
+ * early on in bootblock, followed by enabling of power. Reset signal is deasserted
+ * later on in ramstage. Since reset signal is asserted in bootblock, it results in
+ * FPMCU not working after a S3 resume. This is a known issue.
+ */
+ PAD_CFG_GPO(GPP_D1, 0, DEEP),
+ /* D2 : ISH_GP2 ==> EN_FP_PWR */
+ PAD_CFG_GPO(GPP_D2, 1, DEEP),
+ /* D11 : ISH_SPI_MISO ==> EN_PP3300_SSD */
+ PAD_CFG_GPO(GPP_D11, 1, DEEP),
+ /* E0 : SATAXPCIE0 ==> WWAN_PERST_L (updated in ramstage) */
+ PAD_CFG_GPO(GPP_E0, 0, DEEP),
+ /* E13 : THC0_SPI1_IO2 ==> MEM_CH_SEL */
+ PAD_CFG_GPI(GPP_E13, NONE, DEEP),
+ /* E16 : RSVD_TP ==> WWAN_RST_L (updated in ramstage) */
+ PAD_CFG_GPO(GPP_E16, 0, DEEP),
+ /* E15 : RSVD_TP ==> PCH_WP_OD */
+ PAD_CFG_GPI_GPIO_DRIVER(GPP_E15, NONE, DEEP),
+ /* F18 : THC1_SPI2_INT# ==> EC_IN_RW_OD */
+ PAD_CFG_GPI(GPP_F18, NONE, DEEP),
+ /* F21 : EXT_PWR_GATE2# ==> WWAN_FCPO_L (updated in romstage) */
+ PAD_CFG_GPO(GPP_F21, 0, DEEP),
+ /* H10 : UART0_RXD ==> UART_PCH_RX_DBG_TX */
+ PAD_CFG_NF(GPP_H10, NONE, DEEP, NF2),
+ /* H11 : UART0_TXD ==> UART_PCH_TX_DBG_RX */
+ PAD_CFG_NF(GPP_H11, NONE, DEEP, NF2),
+ /* H13 : I2C7_SCL ==> EN_PP3300_SD */
+ PAD_NC(GPP_H13, UP_20K),
+};
+
+/* Early pad configuration in bootblock for board id 4 */
+static const struct pad_config early_gpio_table_id4[] = {
+ /* A12 : SATAXPCIE1 ==> EN_PP3300_WWAN */
+ PAD_CFG_GPO(GPP_A12, 1, DEEP),
+ /* A13 : PMC_I2C_SCL ==> GSC_PCH_INT_ODL */
+ PAD_CFG_GPI_APIC(GPP_A13, NONE, PLTRST, LEVEL, INVERT),
+ /* B4 : PROC_GP3 ==> SSD_PERST_L */
+ PAD_CFG_GPO(GPP_B4, 0, DEEP),
+ /* H6 : ISH_12C1_SDA ==> PCH_I2C_TPM_SDA */
+ PAD_CFG_NF(GPP_H6, NONE, DEEP, NF1),
+ /* H7 : ISH_12C1_SCL ==> PCH_I2C_TPM_SCL */
+ PAD_CFG_NF(GPP_H7, NONE, DEEP, NF1),
+ /*
+ * D1 : ISH_GP1 ==> FP_RST_ODL
+ * FP_RST_ODL comes out of reset as hi-z and does not have an external
+ * pull-down. To ensure proper power sequencing for the FPMCU device,
+ * reset signal is driven low early on in bootblock, followed by
+ * enabling of power. Reset signal is deasserted later on in ramstage.
+ * Since reset signal is asserted in bootblock, it results in FPMCU not
+ * working after a S3 resume. This is a known issue.
+ */
+ PAD_CFG_GPO(GPP_D1, 0, DEEP),
+ /* D2 : ISH_GP2 ==> EN_FP_PWR */
+ PAD_CFG_GPO(GPP_D2, 1, DEEP),
+ /* D11 : ISH_SPI_MISO ==> EN_PP3300_SSD */
+ PAD_CFG_GPO(GPP_D11, 1, DEEP),
+ /* E0 : SATAXPCIE0 ==> WWAN_PERST_L (updated in ramstage) */
+ PAD_CFG_GPO(GPP_E0, 0, DEEP),
+ /* E13 : THC0_SPI1_IO2 ==> MEM_CH_SEL */
+ PAD_CFG_GPI(GPP_E13, NONE, DEEP),
+ /* E16 : RSVD_TP ==> WWAN_RST_L (updated in ramstage) */
+ PAD_CFG_GPO(GPP_E16, 0, DEEP),
+ /* E15 : RSVD_TP ==> PCH_WP_OD */
+ PAD_CFG_GPI_GPIO_DRIVER(GPP_E15, NONE, DEEP),
+ /* F18 : THC1_SPI2_INT# ==> EC_IN_RW_OD */
+ PAD_CFG_GPI(GPP_F18, NONE, DEEP),
+ /* F21 : EXT_PWR_GATE2# ==> WWAN_FCPO_L (updated in romstage) */
+ PAD_CFG_GPO(GPP_F21, 0, DEEP),
+ /* H10 : UART0_RXD ==> UART_PCH_RX_DBG_TX */
+ PAD_CFG_NF(GPP_H10, NONE, DEEP, NF2),
+ /* H11 : UART0_TXD ==> UART_PCH_TX_DBG_RX */
+ PAD_CFG_NF(GPP_H11, NONE, DEEP, NF2),
+ /* H13 : I2C7_SCL ==> EN_PP3300_SD */
+ PAD_NC(GPP_H13, UP_20K),
+};
+
+static const struct pad_config romstage_gpio_table[] = {
+ /* B4 : PROC_GP3 ==> SSD_PERST_L */
+ PAD_CFG_GPO(GPP_B4, 1, DEEP),
+
+ /* Enable touchscreen, hold in reset */
+ /* C0 : SMBCLK ==> EN_PP3300_TCHSCR */
+ PAD_CFG_GPO(GPP_C0, 1, DEEP),
+ /* C1 : SMBDATA ==> USI_RST_L */
+ PAD_CFG_GPO(GPP_C1, 0, DEEP),
+
+ /* D1 : ISH_GP1 ==> FP_RST_ODL */
+ PAD_CFG_GPO(GPP_D1, 0, DEEP),
+ /* D2 : ISH_GP2 ==> EN_FP_PWR */
+ PAD_CFG_GPO(GPP_D2, 0, DEEP),
+
+ /* F21 : EXT_PWR_GATE2# ==> WWAN_FCPO_L (set here for correct power sequencing) */
+ PAD_CFG_GPO(GPP_F21, 1, DEEP),
+};
+
+const struct pad_config *variant_gpio_override_table(size_t *num)
+{
+ const uint32_t id = board_id();
+ if (id == BOARD_ID_UNKNOWN || id < 2) {
+ *num = ARRAY_SIZE(board_id0_1_overrides);
+ return board_id0_1_overrides;
+ }
+
+ *num = 0;
+ return NULL;
+}
+
+const struct pad_config *variant_early_gpio_table(size_t *num)
+{
+ const uint32_t id = board_id();
+ if (id == BOARD_ID_UNKNOWN || id < 2) {
+ *num = ARRAY_SIZE(early_gpio_table);
+ return early_gpio_table;
+ } else if (id >= 4) {
+ *num = ARRAY_SIZE(early_gpio_table_id4);
+ return early_gpio_table_id4;
+ }
+
+ *num = ARRAY_SIZE(early_gpio_table_id2);
+ return early_gpio_table_id2;
+}
+
+const struct pad_config *variant_romstage_gpio_table(size_t *num)
+{
+ *num = ARRAY_SIZE(romstage_gpio_table);
+ return romstage_gpio_table;
+}
diff --git a/src/mainboard/google/brox/variants/brox/include/variant/ec.h b/src/mainboard/google/brox/variants/brox/include/variant/ec.h
new file mode 100644
index 0000000000..4fc0622f15
--- /dev/null
+++ b/src/mainboard/google/brox/variants/brox/include/variant/ec.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef MAINBOARD_EC_H
+#define MAINBOARD_EC_H
+
+#include <baseboard/ec.h>
+
+#endif /* MAINBOARD_GPIO_H */
diff --git a/src/mainboard/google/brox/variants/brox/include/variant/gpio.h b/src/mainboard/google/brox/variants/brox/include/variant/gpio.h
new file mode 100644
index 0000000000..3179c6fc1f
--- /dev/null
+++ b/src/mainboard/google/brox/variants/brox/include/variant/gpio.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __MAINBOARD_GPIO_H__
+#define __MAINBOARD_GPIO_H__
+
+#include <baseboard/gpio.h>
+
+#define T1_OFF_MS 16
+#define T2_OFF_MS 2
+#define WWAN_FCPO GPP_F21
+#define WWAN_RST GPP_E16
+#define WWAN_PERST GPP_E0
+
+#endif /* __MAINBOARD_GPIO_H__ */
diff --git a/src/mainboard/google/brox/variants/brox/memory/Makefile.inc b/src/mainboard/google/brox/variants/brox/memory/Makefile.inc
new file mode 100644
index 0000000000..3b4cd12477
--- /dev/null
+++ b/src/mainboard/google/brox/variants/brox/memory/Makefile.inc
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# This is an auto-generated file. Do not edit!!
+# Generated by:
+# ./util/spd_tools/bin/part_id_gen ADL lp5 src/mainboard/google/brox/variants/brox/memory src/mainboard/google/brox/variants/brox/memory/mem_parts_used.txt
+
+SPD_SOURCES =
+SPD_SOURCES += spd/lp5/set-0/spd-1.hex # ID = 0(0b0000) Parts = MT62F512M32D2DR-031 WT:B
diff --git a/src/mainboard/google/brox/variants/brox/memory/dram_id.generated.txt b/src/mainboard/google/brox/variants/brox/memory/dram_id.generated.txt
new file mode 100644
index 0000000000..4699178726
--- /dev/null
+++ b/src/mainboard/google/brox/variants/brox/memory/dram_id.generated.txt
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# This is an auto-generated file. Do not edit!!
+# Generated by:
+# ./util/spd_tools/bin/part_id_gen ADL lp5 src/mainboard/google/brox/variants/brox/memory src/mainboard/google/brox/variants/brox/memory/mem_parts_used.txt
+
+DRAM Part Name ID to assign
+MT62F512M32D2DR-031 WT:B 0 (0000)
diff --git a/src/mainboard/google/brox/variants/brox/memory/mem_parts_used.txt b/src/mainboard/google/brox/variants/brox/memory/mem_parts_used.txt
new file mode 100644
index 0000000000..cbae2e1f51
--- /dev/null
+++ b/src/mainboard/google/brox/variants/brox/memory/mem_parts_used.txt
@@ -0,0 +1 @@
+MT62F512M32D2DR-031 WT:B
diff --git a/src/mainboard/google/brox/variants/brox/overridetree.cb b/src/mainboard/google/brox/variants/brox/overridetree.cb
new file mode 100644
index 0000000000..a5e2217fef
--- /dev/null
+++ b/src/mainboard/google/brox/variants/brox/overridetree.cb
@@ -0,0 +1,4 @@
+chip soc/intel/alderlake
+ device domain 0 on
+ end
+end
diff --git a/src/mainboard/google/brox/variants/brox/ramstage.c b/src/mainboard/google/brox/variants/brox/ramstage.c
new file mode 100644
index 0000000000..b468320356
--- /dev/null
+++ b/src/mainboard/google/brox/variants/brox/ramstage.c
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <baseboard/variants.h>
+#include <device/pci_ids.h>
+
+const struct cpu_power_limits limits[] = {
+ /* SKU_ID, TDP (Watts), pl1_min, pl1_max, pl2_min, pl2_max, pl4 */
+ /* All values are for performance config as per document #686872 */
+ { PCI_DID_INTEL_RPL_P_ID_1, 45, 18000, 45000, 115000, 115000, 210000 },
+ { PCI_DID_INTEL_RPL_P_ID_2, 28, 10000, 28000, 64000, 64000, 126000 },
+ { PCI_DID_INTEL_RPL_P_ID_3, 15, 6000, 15000, 55000, 55000, 114000 },
+};
+
+void variant_devtree_update(void)
+{
+ size_t total_entries = ARRAY_SIZE(limits);
+ variant_update_power_limits(limits, total_entries);
+}
diff --git a/src/mainboard/google/brox/variants/brox/variant.c b/src/mainboard/google/brox/variants/brox/variant.c
new file mode 100644
index 0000000000..acb5b66f6c
--- /dev/null
+++ b/src/mainboard/google/brox/variants/brox/variant.c
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <chip.h>
+#include <fw_config.h>
+#include <baseboard/variants.h>
+
+void variant_update_soc_chip_config(struct soc_intel_alderlake_config *config)
+{
+}
diff --git a/src/mainboard/google/brox/wwan_power.asl b/src/mainboard/google/brox/wwan_power.asl
new file mode 100644
index 0000000000..f19a5ef4e9
--- /dev/null
+++ b/src/mainboard/google/brox/wwan_power.asl
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <variant/gpio.h>
+
+Method (MPTS, 1)
+{
+#if CONFIG(HAVE_PCIE_WWAN)
+ \_SB.PCI0.CTXS(WWAN_PERST);
+ Sleep(T1_OFF_MS)
+#endif
+ \_SB.PCI0.CTXS(WWAN_RST);
+ Sleep(T2_OFF_MS)
+ \_SB.PCI0.CTXS(WWAN_FCPO);
+}