diff --git a/src/mainboard/novacustom/mtl-h/acpi/dgpu/gps.asl b/src/mainboard/novacustom/mtl-h/acpi/dgpu/gps.asl new file mode 100644 index 0000000000..8bf8954b82 --- /dev/null +++ b/src/mainboard/novacustom/mtl-h/acpi/dgpu/gps.asl @@ -0,0 +1,96 @@ +/* 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 + +/* GPS return Package */ +Name (GPSP, Buffer (0x24) {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)) + } + Case (GPS_FUNC_PSHAREPARAMS) + { + CreateField (Arg1, 0, 4, QUTY) /* Query type */ + + /* Version of return value */ + VRV1 = 0x10000 + RETN = QUTY + + Switch (ToInteger (QUTY)) + { + Case (QUERY_GET_STATUS) + { + Return (GPSP) + } + Case (QUERY_GET_SUPPORTED_FIELDS) + { + RETN = 0x300 | ToInteger (QUTY) + CreateDWordField (GPSP, 0x0C, PDTS) + PDTS = 0x03e8 + Return (GPSP) + } + Case (QUERY_GET_CURRENT_LIMITS) + { + /* No limits */ + Return (GPSP) + } + } + } + Case (GPS_FUNC_REQUESTDXSTATE) + { + Local0 = ToInteger(\_SB.PCI0.LPCB.EC0.GPUD) + \_SB.PCI0.RP12.PXSX.DNOT (Local0, 1) + Return (NV_ERROR_SUCCESS) + } + } + + Return (NV_ERROR_UNSUPPORTED) +} diff --git a/src/mainboard/novacustom/mtl-h/acpi/dgpu/gpu_defines.h b/src/mainboard/novacustom/mtl-h/acpi/dgpu/gpu_defines.h new file mode 100644 index 0000000000..1cb03145b0 --- /dev/null +++ b/src/mainboard/novacustom/mtl-h/acpi/dgpu/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/novacustom/mtl-h/acpi/dgpu/gpu_ec.asl b/src/mainboard/novacustom/mtl-h/acpi/dgpu/gpu_ec.asl new file mode 100644 index 0000000000..13b04294b6 --- /dev/null +++ b/src/mainboard/novacustom/mtl-h/acpi/dgpu/gpu_ec.asl @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +Scope (\_SB.PCI0.LPCB.EC0) +{ + /* EC has data for GPU in memmap */ + Method (_QA0, 0, Serialized) + { + Local0 = ToInteger(GPUD) + \_SB.PCI0.RP12.PXSX.DNOT (Local0, 0) + } +} diff --git a/src/mainboard/novacustom/mtl-h/acpi/dgpu/gpu_top.asl b/src/mainboard/novacustom/mtl-h/acpi/dgpu/gpu_top.asl new file mode 100644 index 0000000000..baee47dcca --- /dev/null +++ b/src/mainboard/novacustom/mtl-h/acpi/dgpu/gpu_top.asl @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_defines.h" + +Scope (\_SB.PCI0.RP12) +{ + #include "peg.asl" + + Device (PXSX) + { + Name (_ADR, 0x0) + OperationRegion (PCIC, PCI_Config, 0x00, 0x100) + Field (PCIC, DWordAcc, NoLock, Preserve) + { + NVID, 16, + NDID, 16, + Offset (0x40), + NVSS, 32 + } + + #include "utility.asl" + #include "power.asl" + #include "nvop.asl" + #include "nvjt.asl" + #include "nbci.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.RP12.PXSX, 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_GPS)) + { + If (ToInteger (Arg1) >= REVISION_MIN_GPS) + { + Return (GPS (Arg2, Arg3)) + } + } + + Return (NV_ERROR_UNSUPPORTED) + } + } +} diff --git a/src/mainboard/novacustom/mtl-h/acpi/dgpu/nbci.asl b/src/mainboard/novacustom/mtl-h/acpi/dgpu/nbci.asl new file mode 100644 index 0000000000..1546928aef --- /dev/null +++ b/src/mainboard/novacustom/mtl-h/acpi/dgpu/nbci.asl @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#define NBCI_FUNC_SUPPORT 0 +#define NBCI_FUNC_GETOBJBYTYPE 16 +#define NBCI_FUNC_GETCALLBACKS 19 + +#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_GETCALLBACKS))) + } + Case (NBCI_FUNC_GETCALLBACKS) + { + /* Re-use the GPS subfunction's GETCALLBACKS Method */ + Return (GPS (GPS_FUNC_GETCALLBACKS, Arg1)) + } + } + + Return (NV_ERROR_UNSUPPORTED) +} diff --git a/src/mainboard/novacustom/mtl-h/acpi/dgpu/nvjt.asl b/src/mainboard/novacustom/mtl-h/acpi/dgpu/nvjt.asl new file mode 100644 index 0000000000..0526dc92a4 --- /dev/null +++ b/src/mainboard/novacustom/mtl-h/acpi/dgpu/nvjt.asl @@ -0,0 +1,128 @@ +/* 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))) + } + Case (JT_FUNC_CAPS) + { + Return (ITOB( + (1 << 0) | /* JTE: G-Sync NVSR Power Features Enabled */ + (1 << 1) | /* NVSE: NVSR Disabled */ + (2 << 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) */ + (1 << 14) | /* RPC: Root Port Control */ + (2 << 15) | /* GC6 Version (GC6-R) */ + (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/novacustom/mtl-h/acpi/dgpu/nvop.asl b/src/mainboard/novacustom/mtl-h/acpi/dgpu/nvop.asl new file mode 100644 index 0000000000..1f534be549 --- /dev/null +++ b/src/mainboard/novacustom/mtl-h/acpi/dgpu/nvop.asl @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#define NVOP_FUNC_SUPPORT 0x00 +#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 */ + (1 << 6) | /* Shared Discrete GPU Hotplug Capabilities */ + (0 << 7) | /* MUXed DDC/Aux Capabilities */ + (PCIO << 8) | /* PCIe Configuration Space Owner */ + (1 << 24) | /* Platform Optimus Power Capabilities */ + (3 << 27))) /* Optimus HD Audio Codec Capabilities */ + } + Case (NVOP_FUNC_OPTIMUS_STATUS) + { + Return (ITOB ( + (1 << 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/novacustom/mtl-h/acpi/dgpu/peg.asl b/src/mainboard/novacustom/mtl-h/acpi/dgpu/peg.asl new file mode 100644 index 0000000000..ac0c17cbb2 --- /dev/null +++ b/src/mainboard/novacustom/mtl-h/acpi/dgpu/peg.asl @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +External (\_SB.PCI0.RP12.PXSX.NPON, MethodObj) +External (\_SB.PCI0.RP12.PXSX.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.RP12.PXSX.NPON () + _STA = 1 + } + Method (_OFF, 0, Serialized) + { + /* Power down GPU to GCOFF (or GC6 entry if deferred) */ + _STA = 0 + \_SB.PCI0.RP12.PXSX.NPOF () + } + Name (_STA, 0) +} + +Name (_PR0, Package() { PGPR }) +Name (_PR2, Package() { PGPR }) +Name (_PR3, Package() { PGPR }) diff --git a/src/mainboard/novacustom/mtl-h/acpi/dgpu/power.asl b/src/mainboard/novacustom/mtl-h/acpi/dgpu/power.asl new file mode 100644 index 0000000000..496fd2c147 --- /dev/null +++ b/src/mainboard/novacustom/mtl-h/acpi/dgpu/power.asl @@ -0,0 +1,315 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include + +External (\_SB.PCI0.SPCO, MethodObj) + + +/* Board specific defines */ + +/* PCI Subsystem ID to restore after wake */ +#define GPU_SSID 0xa7611558 + +/* Power control signals */ +#define GPIO_GPU_PERST_L GPP_B09 +#define GPIO_GPU_PWR_EN GPP_D03 +#define GPIO_GPU_PWR_GD GPP_C15 +#define GPIO_GPU_NVVDD_EN GPP_F16 + +/* GPU clock pin */ +#define GPU_SRCCLK_PIN 0x6 + +#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 + +/* Optimus Power Control State */ +Name (OPCS, OPTIMUS_POWER_CONTROL_DISABLE) + +/* PCI configuration space Owner */ +Name (PCIO, PCI_OWNER_SBIOS) + +/* 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) + +/* Copy of LTR enable bit from PEG port */ +Name (SLTR, 0) + +/* Control the PCIe SRCCLK# for dGPU */ +Method (SRCC, 1, Serialized) +{ + /* Control clock via P2SB interface */ + \_SB.PCI0.SPCO (GPU_SRCCLK_PIN, Arg0) +} + +/* "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.RP12.DL23 () + + /* Wait for GPU to deassert its GPIO4, i.e. GPU_NVVDD_EN */ + GPPL (GPIO_GPU_NVVDD_EN, 0, 20) + + /* 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) + + /* Restore PCIe link back to L0 state */ + \_SB.PCI0.RP12.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) + + /* Enable power rails */ + STXS (GPIO_GPU_PWR_EN) + + /* Wait 200ms for PWRGD */ + GPPL (GPIO_GPU_PWR_GD, 1, 200) + + /* 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) + + /* Disable power rails */ + CTXS (GPIO_GPU_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.RP12.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.RP12.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 () + } + NVSS = GPU_SSID +} + +/* 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 () + NVSS = GPU_SSID +} + +Method (_OFF, 0, Serialized) +{ + PGOF () +} + +/* Put device into D0 */ +Method (_PS0, 0, NotSerialized) +{ + If (OPS0 == OPTIMUS_CONTROL_RUN_PS0) + { + /* 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) + { + /* 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_PWR_GD) == 1) + { + Return (1) + } + Else + { + Return (0) + } +} + +Method (_STA, 0, Serialized) +{ + Return (0xF) +} diff --git a/src/mainboard/novacustom/mtl-h/acpi/dgpu/utility.asl b/src/mainboard/novacustom/mtl-h/acpi/dgpu/utility.asl new file mode 100644 index 0000000000..7bf97d4af4 --- /dev/null +++ b/src/mainboard/novacustom/mtl-h/acpi/dgpu/utility.asl @@ -0,0 +1,58 @@ +/* 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/novacustom/mtl-h/dsdt.asl b/src/mainboard/novacustom/mtl-h/dsdt.asl index 06e7263d07..2b2bcb8fc8 100644 --- a/src/mainboard/novacustom/mtl-h/dsdt.asl +++ b/src/mainboard/novacustom/mtl-h/dsdt.asl @@ -31,4 +31,8 @@ DefinitionBlock( } #include "acpi/mainboard.asl" + +#if CONFIG(BOARD_NOVACUSTOM_V5X0TNX_BASE) + #include "acpi/dgpu/gpu_top.asl" +#endif }