summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mainboard/google/brya/Kconfig5
-rw-r--r--src/mainboard/google/brya/acpi/gpu_defines.h44
-rw-r--r--src/mainboard/google/brya/acpi/gpu_top.asl46
-rw-r--r--src/mainboard/google/brya/acpi/nvjt.asl129
-rw-r--r--src/mainboard/google/brya/acpi/nvop.asl69
-rw-r--r--src/mainboard/google/brya/acpi/peg.asl95
-rw-r--r--src/mainboard/google/brya/acpi/power.asl297
-rw-r--r--src/mainboard/google/brya/acpi/utility.asl30
-rw-r--r--src/mainboard/google/brya/dsdt.asl4
9 files changed, 719 insertions, 0 deletions
diff --git a/src/mainboard/google/brya/Kconfig b/src/mainboard/google/brya/Kconfig
index 9bc07c4925..67995b5d77 100644
--- a/src/mainboard/google/brya/Kconfig
+++ b/src/mainboard/google/brya/Kconfig
@@ -264,4 +264,9 @@ config MEMORY_SOLDERDOWN
config HAVE_SLP_S0_GATE
def_bool n
+config INCLUDE_NVIDIA_GPU_ASL
+ def_bool n
+ help
+ Select this if the variant has an Nvidia GN20 GPU attached to PEG1
+
endif # BOARD_GOOGLE_BRYA_COMMON
diff --git a/src/mainboard/google/brya/acpi/gpu_defines.h b/src/mainboard/google/brya/acpi/gpu_defines.h
new file mode 100644
index 0000000000..65a8ee942e
--- /dev/null
+++ b/src/mainboard/google/brya/acpi/gpu_defines.h
@@ -0,0 +1,44 @@
+/* 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 REVISION_MIN_NVOP 0x100
+#define REVISION_MIN_NVJT 0x100
+#define REVISION_MIN_NBCI 0x102
diff --git a/src/mainboard/google/brya/acpi/gpu_top.asl b/src/mainboard/google/brya/acpi/gpu_top.asl
new file mode 100644
index 0000000000..c23a0ce003
--- /dev/null
+++ b/src/mainboard/google/brya/acpi/gpu_top.asl
@@ -0,0 +1,46 @@
+/* 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"
+
+ 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))
+ }
+ }
+
+ Return (NV_ERROR_UNSUPPORTED)
+ }
+ }
+}
diff --git a/src/mainboard/google/brya/acpi/nvjt.asl b/src/mainboard/google/brya/acpi/nvjt.asl
new file mode 100644
index 0000000000..9c422d4644
--- /dev/null
+++ b/src/mainboard/google/brya/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 2
+#define JT_FUNC_PLATPOLICY 3
+
+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 (^_STA () != 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/brya/acpi/nvop.asl b/src/mainboard/google/brya/acpi/nvop.asl
new file mode 100644
index 0000000000..2cf84c697d
--- /dev/null
+++ b/src/mainboard/google/brya/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 (\_SB.PCI0.PEG0.PGPR._STA == 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/brya/acpi/peg.asl b/src/mainboard/google/brya/acpi/peg.asl
new file mode 100644
index 0000000000..55551bc714
--- /dev/null
+++ b/src/mainboard/google/brya/acpi/peg.asl
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+External (\_SB.PCI0.DGPU, DeviceObj)
+External (\_SB.PCI0.PEG0.PEGP._OFF, MethodObj)
+External (\_SB.PCI0.PEG0.PEGP._ON, MethodObj)
+
+OperationRegion (PCIC, PCI_Config, 0x00, 0x100)
+Field (PCIC, AnyAcc, NoLock, Preserve)
+{
+ Offset (0x52),
+ , 13,
+ LASX, 1, /* Link Active Status */
+ 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 (16)
+ 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 (16)
+ Local0--
+ }
+
+ NCB7 = 0
+ Local0 = 8
+ While (Local0 > 0)
+ {
+ If (LASX == 1)
+ {
+ Break
+ }
+
+ Sleep (16)
+ 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._ON ()
+ _STA = 1
+ }
+ Method (_OFF, 0, Serialized)
+ {
+ /* Power down GPU to GCOFF (or GC6 entry if deferred) */
+ _STA = 0
+ \_SB.PCI0.PEG0.PEGP._OFF ()
+ }
+ Name (_STA, 0)
+}
+
+Name (_PR0, Package() { PGPR })
+Name (_PR2, Package() { PGPR })
+Name (_PR3, Package() { PGPR })
diff --git a/src/mainboard/google/brya/acpi/power.asl b/src/mainboard/google/brya/acpi/power.asl
new file mode 100644
index 0000000000..b5822fcf9b
--- /dev/null
+++ b/src/mainboard/google/brya/acpi/power.asl
@@ -0,0 +1,297 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+
+/* Voltage rail control signals */
+#define GPIO_1V8_PWR_EN GPP_E18
+#define GPIO_1V8_PG GPP_E20
+#define GPIO_NV33_PWR_EN GPP_A21
+#define GPIO_NV33_PG GPP_A22
+#define GPIO_NVVDD_PWR_EN GPP_E0
+#define GPIO_NVVDD_PG GPP_E16
+#define GPIO_PEXVDD_PWR_EN GPP_E10
+#define GPIO_PEXVDD_PG GPP_E17
+#define GPIO_FBVDD_PWR_EN GPP_A17
+#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_A19
+
+#define GC6_DEFER_TYPE_EXIT_GC6 3
+
+/* Optimus Power Control State */
+Name (OPCS, OPTIMUS_POWER_CONTROL_DISABLE)
+
+/* PCI configuration space Owner */
+Name (PCIO, PCI_OWNER_SBIOS)
+
+/* 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)
+
+/* 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)
+
+/* "GC6 In", i.e. GC6 Entry Sequence */
+Method (GC6I, 0, Serialized)
+{
+ GC6E = GC6_STATE_TRANSITION
+
+ /* Put PCIe link into L2/3 */
+ \_SB.PCI0.PEG0.DL23 ()
+
+ /* Assert GPU_PERST_L */
+ \_SB.PCI0.STXS (GPIO_GPU_PERST_L)
+
+ /* Deassert PG_GPU_ALLRAILS */
+ \_SB.PCI0.CTXS (GPIO_GPU_ALLRAILS_PG)
+
+ /* Deassert EN_PP0950_GPU_X */
+ \_SB.PCI0.CTXS (GPIO_PEXVDD_PWR_EN)
+
+ /* Wait for de-assertion of PG_PP0950_GPU */
+ GPPL (GPIO_PEXVDD_PG, 0, 20)
+
+ /* Deassert EN_PPVAR_GPU_NVVDD */
+ \_SB.PCI0.CTXS (GPIO_NVVDD_PWR_EN)
+
+ /* Wait for de-assertion of PG_PPVAR_GPU_NVVDD */
+ GPPL (GPIO_NVVDD_PG, 0, 20)
+
+ /* Deassert EN_PCH_PPVAR_GPU_FBVDDQ */
+ \_SB.PCI0.CTXS (GPIO_FBVDD_PWR_EN)
+
+ /* Deassert EN_PP3300_GPU */
+ \_SB.PCI0.CTXS (GPIO_NV33_PWR_EN)
+
+ /* Wait for de-assertion of PG_PP3300_GPU */
+ GPPL (GPIO_NV33_PG, 0, 20)
+
+ GC6E = GC6_STATE_ENTERED
+}
+
+/* "GC6 Out", i.e. GC6 Exit Sequence */
+Method (GC6O, 0, Serialized)
+{
+ GC6E = GC6_STATE_TRANSITION
+
+ /* Assert EN_PP3300_GPU */
+ \_SB.PCI0.STXS (GPIO_NV33_PWR_EN)
+
+ /* Wait for assertion of PG_PP3300_GPU */
+ GPPL (GPIO_NV33_PG, 1, 20)
+
+ /* Deassert GPU_PERST_L */
+ \_SB.PCI0.CTXS (GPIO_GPU_PERST_L)
+
+ /* Put PCIe link into L0 state */
+ \_SB.PCI0.PEG0.LD23 ()
+
+ /* Wait for GPU to assert GPU_NVVDD_EN */
+ GPPL (GPIO_GPU_NVVDD_EN, 1, 20)
+
+ /*
+ * There is a 4ms window once the GPU asserts GPU_NVVDD_EN to
+ * perform the following:
+ * 1. Enable GPU_NVVDD
+ * 2. Enable GPU_PEX
+ * 3. Wait for all PG
+ * 4. Assert FBVDD
+ * At the end of the 4ms window, the GPU will deassert its
+ * GPIO1_GC6_FB_EN signal that is used to keep the FBVDD
+ * rail up during GC6.
+ */
+ \_SB.PCI0.STXS (GPIO_NVVDD_PWR_EN)
+ Stall (20)
+ \_SB.PCI0.STXS (GPIO_PEXVDD_PWR_EN)
+ GPPL (GPIO_NVVDD_PG, 1, 4)
+ GPPL (GPIO_PEXVDD_PG, 1, 4)
+ \_SB.PCI0.STXS (GPIO_FBVDD_PWR_EN)
+
+ /* Assert PG_GPU_ALLRAILS */
+ \_SB.PCI0.STXS (GPIO_GPU_ALLRAILS_PG)
+
+ GC6E = GC6_STATE_EXITED
+}
+
+/* GCOFF exit sequence */
+Method (PGON, 0, Serialized)
+{
+ /* Assert PERST# */
+ \_SB.PCI0.CTXS (GPIO_GPU_PERST_L)
+
+ /* Ramp up 1.8V rail */
+ \_SB.PCI0.STXS (GPIO_1V8_PWR_EN)
+ GPPL (GPIO_1V8_PG, 1, 20)
+
+ /* Ramp up NV33 rail */
+ \_SB.PCI0.STXS (GPIO_NV33_PWR_EN)
+ GPPL (GPIO_NV33_PG, 1, 20)
+
+ /* Ramp up NVVDD rail */
+ \_SB.PCI0.STXS (GPIO_NVVDD_PWR_EN)
+ GPPL (GPIO_NVVDD_PG, 1, 5)
+
+ /* Ramp up PEXVDD rail */
+ \_SB.PCI0.STXS (GPIO_PEXVDD_PWR_EN)
+ GPPL (GPIO_PEXVDD_PG, 1, 5)
+
+ /* Ramp up FBVDD rail */
+ \_SB.PCI0.STXS (GPIO_FBVDD_PWR_EN)
+ GPPL (GPIO_FBVDD_PG, 1, 5)
+
+ /* All rails are good */
+ \_SB.PCI0.STXS (GPIO_GPU_ALLRAILS_PG)
+ Sleep (1)
+
+ /* Deassert PERST# */
+ \_SB.PCI0.STXS (GPIO_GPU_PERST_L)
+}
+
+/* GCOFF entry sequence */
+Method (PGOF, 0, Serialized)
+{
+ /* Assert PERST# */
+ \_SB.PCI0.CTXS (GPIO_GPU_PERST_L)
+ Sleep (5)
+
+ /* All rails are about to go down */
+ \_SB.PCI0.CTXS (GPIO_GPU_ALLRAILS_PG)
+
+ /* Ramp down FBVDD */
+ \_SB.PCI0.CTXS (GPIO_FBVDD_PWR_EN)
+ GPPL (GPIO_FBVDD_PG, 0, 20)
+
+ /* Ramp down PEXVDD */
+ \_SB.PCI0.CTXS (GPIO_PEXVDD_PWR_EN)
+ GPPL (GPIO_PEXVDD_PG, 0, 20)
+
+ /* Ramp down NVVDD */
+ \_SB.PCI0.CTXS (GPIO_NVVDD_PWR_EN)
+ GPPL (GPIO_NVVDD_PG, 0, 20)
+
+ /* Ramp down NV33 */
+ \_SB.PCI0.CTXS (GPIO_NV33_PWR_EN)
+ GPPL (GPIO_NV33_PG, 0, 20)
+
+ /* Ramp down 1.8V */
+ \_SB.PCI0.CTXS (GPIO_1V8_PWR_EN)
+ GPPL (GPIO_1V8_PG, 0, 20)
+}
+
+/* Handle deferred GC6 vs. poweron request */
+Method (NPON, 0, Serialized)
+{
+ If (DFEN == GC6_DEFER_ENABLE) /* 1 */
+ {
+ If (DFCO == GC6_DEFER_TYPE_EXIT_GC6) /* 3 */
+ {
+ GC6O ()
+ }
+
+ DFEN = GC6_DEFER_DISABLE
+ }
+ Else
+ {
+ PGON ()
+ }
+}
+
+/* Handle deferred GC6 vs. poweroff request */
+Method (NPOF, 0, Serialized)
+{
+ If (DFEN == GC6_DEFER_ENABLE)
+ {
+ /* Deferred GC6 entry */
+ If (DFCI == NVJT_GPC_EGNS || DFCI == NVJT_GPC_EGIS)
+ {
+ GC6I ()
+ }
+
+ DFEN = GC6_DEFER_DISABLE
+ }
+ Else
+ {
+ PGOF ()
+ }
+}
+
+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 _OFF, _PS0 must run _ON */
+ OPS0 = OPTIMUS_CONTROL_RUN_PS0
+
+ /* OPCS is one-shot, so reset it */
+ OPCS = OPTIMUS_POWER_CONTROL_DISABLE
+ }
+}
+
+/*
+ * Normally, _ON and _OFF of the power resources listed in _PRx will be
+ * evaluated before entering D0/D3. However, for Optimus, the package
+ * should refer to the PCIe controller itself, not a dependent device.
+ */
+Name (_PR0, Package() { \_SB.PCI0.PEG0 })
+Name (_PR3, Package() { \_SB.PCI0.PEG0 })
+
+Method (_STA, 0, Serialized)
+{
+ If (GC6E == GC6_STATE_EXITED &&
+ \_SB.PCI0.GTXS(GPIO_GPU_ALLRAILS_PG) == 1)
+ {
+ Return (0xF)
+ }
+ Else
+ {
+ Return (0)
+ }
+}
diff --git a/src/mainboard/google/brya/acpi/utility.asl b/src/mainboard/google/brya/acpi/utility.asl
new file mode 100644
index 0000000000..4fc03e83e1
--- /dev/null
+++ b/src/mainboard/google/brya/acpi/utility.asl
@@ -0,0 +1,30 @@
+/* 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 = GRXS (Arg0)
+ Local7 = Arg2 * 10000
+ Local7 = Timer + Local7
+ While (Local0 != Arg1 && Timer < Local7)
+ {
+ Stall (10)
+ Local0 = \_SB.PCI0.GRXS (Arg0)
+ }
+}
+
+/* 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)
+}
diff --git a/src/mainboard/google/brya/dsdt.asl b/src/mainboard/google/brya/dsdt.asl
index 82cafcfbf5..f86b28995b 100644
--- a/src/mainboard/google/brya/dsdt.asl
+++ b/src/mainboard/google/brya/dsdt.asl
@@ -44,4 +44,8 @@ DefinitionBlock(
/* ACPI code for EC functions */
#include <ec/google/chromeec/acpi/ec.asl>
}
+
+#if CONFIG(INCLUDE_NVIDIA_GPU_ASL)
+ #include "acpi/gpu_top.asl"
+#endif
}