1/* SPDX-License-Identifier: GPL-2.0-or-later */ 2 3#include <device/pci_ids.h> 4 5External (\_SB.PCI0.PMC.IPCS, MethodObj) 6 7/* Voltage rail control signals */ 8 9#define GPIO_1V8_PWR_EN GPP_E11 10 11#define GPIO_NV33_PWR_EN GPP_E1 12#define GPIO_NV33_PG GPP_E2 13 14#define GPIO_1V8_PG GPP_E20 15#define GPIO_NV12_PWR_EN GPP_D0 16#define GPIO_NV12_PG GPP_D1 17 18#define GPIO_NVVDD_PWR_EN GPP_E0 19#define GPIO_PEXVDD_PWR_EN GPP_E10 20#define GPIO_PEXVDD_PG GPP_E17 21#define GPIO_FBVDD_PWR_EN GPP_A19 22#define GPIO_FBVDD_PG GPP_E4 23 24#define GPIO_GPU_PERST_L GPP_B3 25#define GPIO_GPU_ALLRAILS_PG GPP_E5 26#define GPIO_GPU_NVVDD_EN GPP_A17 27 28#define GC6_DEFER_TYPE_EXIT_GC6 3 29 30/* 250ms in "Timer" units (i.e. 100ns increments) */ 31#define MIN_OFF_TIME_TIMERS 2500000 32 33#define SRCCLK_DISABLE 0 34#define SRCCLK_ENABLE 1 35 36#define GPU_POWER_STATE_OFF 0 37#define GPU_POWER_STATE_ON 1 38 39/* Dynamically-assigned NVVDD PG GPIO, set in _INI in SSDT */ 40Name (NVPG, 0) 41Name (GPEN, 0) 42 43/* Optimus Power Control State */ 44Name (OPCS, OPTIMUS_POWER_CONTROL_DISABLE) 45 46/* PCI configuration space Owner */ 47Name (PCIO, PCI_OWNER_DRIVER) 48 49/* Saved PCI configuration space memory (VGA Buffer) */ 50Name (VGAB, Buffer (0xfb) { 0x00 }) 51 52/* Deferred GPU State */ 53Name (OPS0, OPTIMUS_CONTROL_NO_RUN_PS0) 54 55/* GC6 Entry/Exit state */ 56Name (GC6E, GC6_STATE_EXITED) 57 58/* Power State, GCOFF, GCON */ 59Name (GPPS, GPU_POWER_STATE_ON) 60 61/* Defer GC6 entry / exit until D3-cold request */ 62Name (DFEN, 0) 63/* Deferred GC6 Enter control */ 64Name (DFCI, 0) 65/* Deferred GC6 Exit control */ 66Name (DFCO, 0) 67/* GCOFF Timer */ 68Name (GCOT, 0) 69 70#define PMC_SRCCLK_PIN 0x1 71#define PMC_SRCCLK_ENABLE 0x1 72#define PMC_SRCCLK_DISABLE 0x0 73 74#define PMC_RP_IDX (1 << 27) 75#define PMC_RP_ENABLE (1 << 27) 76#define PMC_RP_DISABLE 0x0 77/* Copy of LTR enable bit from PEG port */ 78Name (SLTR, 0) 79 80/* Control the PCIe SRCCLK# for dGPU */ 81Method (SRCC, 1, Serialized) 82{ 83 If (!Arg0) 84 { 85 Local0 = PMC_SRCCLK_DISABLE 86 Local1 = PMC_RP_DISABLE 87 } 88 Else 89 { 90 Local0 = PMC_SRCCLK_ENABLE 91 Local1 = PMC_RP_ENABLE 92 } 93 94 \_SB.PCI0.PMC.IPCS (0xac, 0, 16, PMC_SRCCLK_PIN, 95 Local0, PMC_RP_IDX, Local1) 96} 97 98/* "GC6 In", i.e. GC6 Entry Sequence */ 99Method (GC6I, 0, Serialized) 100{ 101 GC6E = GC6_STATE_TRANSITION 102 103 /* Save the PEG port's LTR setting */ 104 SLTR = LREN 105 106 /* Put PCIe link into L2/3 */ 107 \_SB.PCI0.PEG0.DL23 () 108 109 /* Wait for GPU to deassert its GPIO4, i.e. GPU_NVVDD_EN */ 110 GPPL (GPIO_GPU_NVVDD_EN, 0, 20) 111 112 /* Deassert PG_GPU_ALLRAILS */ 113 CTXS (GPIO_GPU_ALLRAILS_PG) 114 115 /* Ramp down FBVDD - TODO: Remove Agah when board is dropped */ 116 CTXS (GPIO_FBVDD_PWR_EN) 117 118 /* Ramp down PEXVDD */ 119 CTXS (GPIO_PEXVDD_PWR_EN) 120 Sleep (2) 121 122 /* Deassert EN_PPVAR_GPU_NVVDD */ 123 CTXS (GPIO_NVVDD_PWR_EN) 124 Sleep (2) 125 126 /* Assert GPU_PERST_L */ 127 CTXS (GPIO_GPU_PERST_L) 128 129 /* Disable PCIe SRCCLK# */ 130 SRCC (SRCCLK_DISABLE) 131 132 GC6E = GC6_STATE_ENTERED 133} 134 135/* "GC6 Out", i.e. GC6 Exit Sequence */ 136Method (GC6O, 0, Serialized) 137{ 138 GC6E = GC6_STATE_TRANSITION 139 140 /* Re-enable PCIe SRCCLK# */ 141 SRCC (SRCCLK_ENABLE) 142 143 /* Deassert GPU_PERST_L */ 144 STXS (GPIO_GPU_PERST_L) 145 146 /* Wait for GPU to assert GPU_NVVDD_EN */ 147 GPPL (GPIO_GPU_NVVDD_EN, 1, 20) 148 149 /* Ramp up NVVDD */ 150 STXS (GPIO_NVVDD_PWR_EN) 151 GPPL (NVPG, 1, 4) 152 153 /* Ramp up PEXVDD */ 154 STXS (GPIO_PEXVDD_PWR_EN) 155 GPPL (GPIO_PEXVDD_PG, 1, 4) 156 157 /* Ramp up FBVDD - TODO: Remove Agah when board is dropped */ 158 STXS (GPIO_FBVDD_PWR_EN) 159 160 161 /* Assert PG_GPU_ALLRAILS */ 162 STXS (GPIO_GPU_ALLRAILS_PG) 163 164 /* Restore PCIe link back to L0 state */ 165 \_SB.PCI0.PEG0.LD23 () 166 167 /* Wait for dGPU to reappear on the bus */ 168 Local0 = 50 169 While (NVID != PCI_VID_NVIDIA) 170 { 171 Stall (100) 172 Local0-- 173 If (Local0 == 0) 174 { 175 Break 176 } 177 } 178 179 /* Restore the PEG LTR enable bit */ 180 LREN = SLTR 181 182 /* Clear recoverable errors detected bit */ 183 CEDR = 1 184 185 GC6E = GC6_STATE_EXITED 186} 187 188/* GCOFF exit sequence */ 189Method (PGON, 0, Serialized) 190{ 191 Local0 = Timer - GCOT 192 If (Local0 < MIN_OFF_TIME_TIMERS) 193 { 194 Local1 = (MIN_OFF_TIME_TIMERS - Local0) / 10000 195 Printf("Sleeping %o to ensure min GCOFF time", Local1) 196 Sleep (Local1) 197 } 198 199 /* Assert PERST# */ 200 CTXS (GPIO_GPU_PERST_L) 201 202 /* Ramp up 1.2V rail on boards with support */ 203 STXS (GPIO_NV12_PWR_EN) 204 GPPL (GPIO_NV12_PG, 1, 5) 205 206 /* Ramp up 1.8V rail */ 207 STXS (GPEN) 208 GPPL (GPIO_1V8_PG, 1, 20) 209 210 /* Ramp up NV33 rail */ 211 STXS (GPIO_NV33_PWR_EN) 212 GPPL (GPIO_NV33_PG, 1, 20) 213 214 /* Ramp up NVVDD rail */ 215 STXS (GPIO_NVVDD_PWR_EN) 216 GPPL (NVPG, 1, 5) 217 218 /* Ramp up PEXVDD rail */ 219 STXS (GPIO_PEXVDD_PWR_EN) 220 GPPL (GPIO_PEXVDD_PG, 1, 5) 221 222 /* Ramp up FBVDD rail */ 223 STXS (GPIO_FBVDD_PWR_EN) 224 225 GPPL (GPIO_FBVDD_PG, 1, 5) 226 227 /* All rails are good */ 228 STXS (GPIO_GPU_ALLRAILS_PG) 229 Sleep (1) 230 231 /* Deassert PERST# */ 232 STXS (GPIO_GPU_PERST_L) 233 234 235 GC6E = GC6_STATE_EXITED 236 GPPS = GPU_POWER_STATE_ON 237} 238 239/* GCOFF entry sequence */ 240Method (PGOF, 0, Serialized) 241{ 242 /* Assert PERST# */ 243 CTXS (GPIO_GPU_PERST_L) 244 245 /* All rails are about to go down */ 246 CTXS (GPIO_GPU_ALLRAILS_PG) 247 Sleep (1) 248 249 /* Ramp down FBVDD */ 250 CTXS (GPIO_FBVDD_PWR_EN) 251 252 /* Ramp down PEXVDD and let rail discharge to <10% */ 253 CTXS (GPIO_PEXVDD_PWR_EN) 254 Sleep (2) 255 256 /* Ramp down NVVDD */ 257 CTXS (GPIO_NVVDD_PWR_EN) 258 Sleep (2) 259 260 /* Ramp down NV33 */ 261 CTXS (GPIO_NV33_PWR_EN) 262 Sleep (4) 263 264 /* Ramp down 1.8V */ 265 CTXS (GPEN) 266 267 /* Ramp down 1.2V rail on boards with support */ 268 CTXS (GPIO_NV12_PWR_EN) 269 270 GCOT = Timer 271 272 GPPS = GPU_POWER_STATE_OFF 273} 274 275/* GCOFF Out, i.e. full power-on sequence */ 276Method (GCOO, 0, Serialized) 277{ 278 If (GPPS == GPU_POWER_STATE_ON) 279 { 280 Printf ("PGON: GPU already on") 281 Return 282 } 283 284 SRCC (SRCCLK_ENABLE) 285 PGON () 286 \_SB.PCI0.PEG0.LD23 () 287 288 /* Wait for dGPU to reappear on the bus */ 289 Local0 = 50 290 While (NVID != PCI_VID_NVIDIA) 291 { 292 Stall (100) 293 Local0-- 294 If (Local0 == 0) 295 { 296 Break 297 } 298 } 299 300 /* Restore the PEG LTR enable bit */ 301 LREN = SLTR 302 303 /* Clear recoverable errors detected bit */ 304 CEDR = 1 305 306 /* Restore the PEG LTR enable bit */ 307 LREN = SLTR 308 309 /* Clear recoverable errors detected bit */ 310 CEDR = 1 311} 312 313/* GCOFF In, i.e. full power-off sequence */ 314Method (GCOI, 0, Serialized) 315{ 316 If (GPPS == GPU_POWER_STATE_OFF) 317 { 318 Printf ("GPU already off") 319 Return 320 } 321 322 /* Save the PEG port's LTR setting */ 323 SLTR = LREN 324 \_SB.PCI0.PEG0.DL23 () 325 PGOF () 326 SRCC (SRCCLK_DISABLE) 327} 328 329/* Handle deferred GC6 vs. poweron request */ 330Method (NPON, 0, Serialized) 331{ 332 If (DFEN == GC6_DEFER_ENABLE) 333 { 334 If (DFCO == GC6_DEFER_TYPE_EXIT_GC6) 335 { 336 GC6O () 337 } 338 339 DFEN = GC6_DEFER_DISABLE 340 } 341 Else 342 { 343 GCOO () 344 } 345} 346 347/* Handle deferred GC6 vs. poweroff request */ 348Method (NPOF, 0, Serialized) 349{ 350 /* Don't touch the `DFEN` flag until the GC6 exit. */ 351 If (DFEN == GC6_DEFER_ENABLE) 352 { 353 /* Deferred GC6 entry */ 354 If (DFCI == NVJT_GPC_EGNS || DFCI == NVJT_GPC_EGIS) 355 { 356 GC6I () 357 } 358 } 359 Else 360 { 361 GCOI () 362 } 363} 364 365Method (_ON, 0, Serialized) 366{ 367 PGON () 368} 369 370Method (_OFF, 0, Serialized) 371{ 372 PGOF () 373} 374 375/* Put device into D0 */ 376Method (_PS0, 0, NotSerialized) 377{ 378 If (OPS0 == OPTIMUS_CONTROL_RUN_PS0) 379 { 380 /* Restore PCI config space */ 381 If (PCIO == PCI_OWNER_SBIOS) 382 { 383 VGAR = VGAB 384 } 385 386 /* Poweron or deferred GC6 exit */ 387 NPON () 388 389 OPS0 = OPTIMUS_CONTROL_NO_RUN_PS0 390 } 391} 392 393/* Put device into D3 */ 394Method (_PS3, 0, NotSerialized) 395{ 396 If (OPCS == OPTIMUS_POWER_CONTROL_ENABLE) 397 { 398 /* Save PCI config space to ACPI buffer */ 399 If (PCIO == PCI_OWNER_SBIOS) 400 { 401 VGAB = VGAR 402 } 403 404 /* Poweroff or deferred GC6 entry */ 405 NPOF () 406 407 /* Because _PS3 ran NPOF, _PS0 must run NPON */ 408 OPS0 = OPTIMUS_CONTROL_RUN_PS0 409 410 /* OPCS is one-shot, so reset it */ 411 OPCS = OPTIMUS_POWER_CONTROL_DISABLE 412 } 413} 414 415Method (PSTA, 0, Serialized) 416{ 417 If (GC6E == GC6_STATE_EXITED && 418 \_SB.PCI0.GTXS(GPIO_GPU_ALLRAILS_PG) == 1) 419 { 420 Return (1) 421 } 422 Else 423 { 424 Return (0) 425 } 426} 427 428Method (_STA, 0, Serialized) 429{ 430 Return (0xF) 431} 432