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