1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <device/pci_ids.h>
5 External (\_SB.PCI0.PMC.IPCS, MethodObj)
7 /* Voltage rail control signals */
9 #if CONFIG(BOARD_GOOGLE_AGAH)
10 #define GPIO_1V8_PWR_EN GPP_F12
12 #define GPIO_NV33_PWR_EN GPP_A21
13 #define GPIO_NV33_PG GPP_A22
15 #define GPIO_1V8_PWR_EN GPP_E11
17 #define GPIO_NV33_PWR_EN GPP_E1
18 #define GPIO_NV33_PG GPP_E2
21 #define GPIO_1V8_PG GPP_E20
22 #define GPIO_NV12_PWR_EN GPP_D0
23 #define GPIO_NV12_PG GPP_D1
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
31 #define GPIO_GPU_PERST_L GPP_B3
32 #define GPIO_GPU_ALLRAILS_PG GPP_E5
33 #define GPIO_GPU_NVVDD_EN GPP_A17
35 #define GC6_DEFER_TYPE_EXIT_GC6 3
37 /* 250ms in "Timer" units (i.e. 100ns increments) */
38 #define MIN_OFF_TIME_TIMERS 2500000
40 #define SRCCLK_DISABLE 0
41 #define SRCCLK_ENABLE 1
43 #define GPU_POWER_STATE_OFF 0
44 #define GPU_POWER_STATE_ON 1
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
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.
55 /* Dynamically-assigned NVVDD PG GPIO, set in _INI in SSDT */
59 /* Optimus Power Control State */
60 Name (OPCS, OPTIMUS_POWER_CONTROL_DISABLE)
62 /* PCI configuration space Owner */
63 Name (PCIO, PCI_OWNER_DRIVER)
65 /* Saved PCI configuration space memory (VGA Buffer) */
66 Name (VGAB, Buffer (0xfb) { 0x00 })
68 /* Deferred GPU State */
69 Name (OPS0, OPTIMUS_CONTROL_NO_RUN_PS0)
71 /* GC6 Entry/Exit state */
72 Name (GC6E, GC6_STATE_EXITED)
74 /* Power State, GCOFF, GCON */
75 Name (GPPS, GPU_POWER_STATE_ON)
77 /* Defer GC6 entry / exit until D3-cold request */
79 /* Deferred GC6 Enter control */
81 /* Deferred GC6 Exit control */
86 #define PMC_SRCCLK_PIN 0x1
87 #define PMC_SRCCLK_ENABLE 0x1
88 #define PMC_SRCCLK_DISABLE 0x0
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 */
96 /* Control the PCIe SRCCLK# for dGPU */
97 Method (SRCC, 1, Serialized)
101 Local0 = PMC_SRCCLK_DISABLE
102 Local1 = PMC_RP_DISABLE
106 Local0 = PMC_SRCCLK_ENABLE
107 Local1 = PMC_RP_ENABLE
110 \_SB.PCI0.PMC.IPCS (0xac, 0, 16, PMC_SRCCLK_PIN,
111 Local0, PMC_RP_IDX, Local1)
114 /* "GC6 In", i.e. GC6 Entry Sequence */
115 Method (GC6I, 0, Serialized)
117 GC6E = GC6_STATE_TRANSITION
119 /* Save the PEG port's LTR setting */
122 /* Put PCIe link into L2/3 */
123 \_SB.PCI0.PEG0.DL23 ()
125 /* Wait for GPU to deassert its GPIO4, i.e. GPU_NVVDD_EN */
126 GPPL (GPIO_GPU_NVVDD_EN, 0, 20)
128 /* Deassert PG_GPU_ALLRAILS */
129 CTXS (GPIO_GPU_ALLRAILS_PG)
131 /* Ramp down FBVDD - TODO: Remove Agah when board is dropped */
132 #if CONFIG(BOARD_GOOGLE_AGAH)
133 STXS (GPIO_FBVDD_PWR_EN)
135 CTXS (GPIO_FBVDD_PWR_EN)
138 /* Ramp down PEXVDD */
139 CTXS (GPIO_PEXVDD_PWR_EN)
140 #if CONFIG(BOARD_GOOGLE_AGAH)
146 /* Deassert EN_PPVAR_GPU_NVVDD */
147 CTXS (GPIO_NVVDD_PWR_EN)
150 /* Assert GPU_PERST_L */
151 CTXS (GPIO_GPU_PERST_L)
153 /* Disable PCIe SRCCLK# */
154 SRCC (SRCCLK_DISABLE)
156 GC6E = GC6_STATE_ENTERED
159 /* "GC6 Out", i.e. GC6 Exit Sequence */
160 Method (GC6O, 0, Serialized)
162 GC6E = GC6_STATE_TRANSITION
164 /* Re-enable PCIe SRCCLK# */
167 /* Deassert GPU_PERST_L */
168 STXS (GPIO_GPU_PERST_L)
170 /* Wait for GPU to assert GPU_NVVDD_EN */
171 GPPL (GPIO_GPU_NVVDD_EN, 1, 20)
174 STXS (GPIO_NVVDD_PWR_EN)
178 STXS (GPIO_PEXVDD_PWR_EN)
179 GPPL (GPIO_PEXVDD_PG, 1, 4)
181 /* Ramp up FBVDD - TODO: Remove Agah when board is dropped */
182 #if CONFIG(BOARD_GOOGLE_AGAH)
183 CTXS (GPIO_FBVDD_PWR_EN)
185 STXS (GPIO_FBVDD_PWR_EN)
189 /* Assert PG_GPU_ALLRAILS */
190 STXS (GPIO_GPU_ALLRAILS_PG)
192 /* Restore PCIe link back to L0 state */
193 \_SB.PCI0.PEG0.LD23 ()
195 /* Wait for dGPU to reappear on the bus */
197 While (NVID != PCI_VID_NVIDIA)
207 /* Restore the PEG LTR enable bit */
210 /* Clear recoverable errors detected bit */
213 GC6E = GC6_STATE_EXITED
216 /* GCOFF exit sequence */
217 Method (PGON, 0, Serialized)
219 Local0 = Timer - GCOT
220 If (Local0 < MIN_OFF_TIME_TIMERS)
222 Local1 = (MIN_OFF_TIME_TIMERS - Local0) / 10000
223 Printf("Sleeping %o to ensure min GCOFF time", Local1)
228 CTXS (GPIO_GPU_PERST_L)
230 /* Ramp up 1.2V rail on boards with support */
231 STXS (GPIO_NV12_PWR_EN)
232 GPPL (GPIO_NV12_PG, 1, 5)
234 /* Ramp up 1.8V rail */
236 GPPL (GPIO_1V8_PG, 1, 20)
238 /* Ramp up NV33 rail */
239 STXS (GPIO_NV33_PWR_EN)
240 GPPL (GPIO_NV33_PG, 1, 20)
242 /* Ramp up NVVDD rail */
243 STXS (GPIO_NVVDD_PWR_EN)
246 /* Ramp up PEXVDD rail */
247 STXS (GPIO_PEXVDD_PWR_EN)
248 GPPL (GPIO_PEXVDD_PG, 1, 5)
250 /* Ramp up FBVDD rail */
251 #if CONFIG(BOARD_GOOGLE_AGAH)
252 CTXS (GPIO_FBVDD_PWR_EN)
254 STXS (GPIO_FBVDD_PWR_EN)
257 GPPL (GPIO_FBVDD_PG, 1, 5)
259 /* All rails are good */
260 STXS (GPIO_GPU_ALLRAILS_PG)
263 /* Deassert PERST# */
264 STXS (GPIO_GPU_PERST_L)
267 GC6E = GC6_STATE_EXITED
268 GPPS = GPU_POWER_STATE_ON
271 /* GCOFF entry sequence */
272 Method (PGOF, 0, Serialized)
275 CTXS (GPIO_GPU_PERST_L)
277 /* All rails are about to go down */
278 CTXS (GPIO_GPU_ALLRAILS_PG)
281 /* Ramp down FBVDD */
282 #if CONFIG(BOARD_GOOGLE_AGAH)
283 STXS (GPIO_FBVDD_PWR_EN)
285 CTXS (GPIO_FBVDD_PWR_EN)
288 /* Ramp down PEXVDD and let rail discharge to <10% */
289 CTXS (GPIO_PEXVDD_PWR_EN)
290 #if CONFIG(BOARD_GOOGLE_AGAH)
296 /* Ramp down NVVDD */
297 CTXS (GPIO_NVVDD_PWR_EN)
301 CTXS (GPIO_NV33_PWR_EN)
307 /* Ramp down 1.2V rail on boards with support */
308 CTXS (GPIO_NV12_PWR_EN)
312 GPPS = GPU_POWER_STATE_OFF
315 /* GCOFF Out, i.e. full power-on sequence */
316 Method (GCOO, 0, Serialized)
318 If (GPPS == GPU_POWER_STATE_ON)
320 Printf ("PGON: GPU already on")
326 \_SB.PCI0.PEG0.LD23 ()
328 /* Wait for dGPU to reappear on the bus */
330 While (NVID != PCI_VID_NVIDIA)
340 /* Restore the PEG LTR enable bit */
343 /* Clear recoverable errors detected bit */
346 /* Restore the PEG LTR enable bit */
349 /* Clear recoverable errors detected bit */
353 /* GCOFF In, i.e. full power-off sequence */
354 Method (GCOI, 0, Serialized)
356 If (GPPS == GPU_POWER_STATE_OFF)
358 Printf ("GPU already off")
362 /* Save the PEG port's LTR setting */
364 \_SB.PCI0.PEG0.DL23 ()
366 SRCC (SRCCLK_DISABLE)
369 /* Handle deferred GC6 vs. poweron request */
370 Method (NPON, 0, Serialized)
372 If (DFEN == GC6_DEFER_ENABLE)
374 If (DFCO == GC6_DEFER_TYPE_EXIT_GC6)
379 DFEN = GC6_DEFER_DISABLE
387 /* Handle deferred GC6 vs. poweroff request */
388 Method (NPOF, 0, Serialized)
390 /* Don't touch the `DFEN` flag until the GC6 exit. */
391 If (DFEN == GC6_DEFER_ENABLE)
393 /* Deferred GC6 entry */
394 If (DFCI == NVJT_GPC_EGNS || DFCI == NVJT_GPC_EGIS)
405 Method (_ON, 0, Serialized)
410 Method (_OFF, 0, Serialized)
415 /* Put device into D0 */
416 Method (_PS0, 0, NotSerialized)
418 If (OPS0 == OPTIMUS_CONTROL_RUN_PS0)
420 /* Restore PCI config space */
421 If (PCIO == PCI_OWNER_SBIOS)
426 /* Poweron or deferred GC6 exit */
429 OPS0 = OPTIMUS_CONTROL_NO_RUN_PS0
433 /* Put device into D3 */
434 Method (_PS3, 0, NotSerialized)
436 If (OPCS == OPTIMUS_POWER_CONTROL_ENABLE)
438 /* Save PCI config space to ACPI buffer */
439 If (PCIO == PCI_OWNER_SBIOS)
444 /* Poweroff or deferred GC6 entry */
447 /* Because _PS3 ran NPOF, _PS0 must run NPON */
448 OPS0 = OPTIMUS_CONTROL_RUN_PS0
450 /* OPCS is one-shot, so reset it */
451 OPCS = OPTIMUS_POWER_CONTROL_DISABLE
455 Method (PSTA, 0, Serialized)
457 If (GC6E == GC6_STATE_EXITED &&
458 \_SB.PCI0.GTXS(GPIO_GPU_ALLRAILS_PG) == 1)
468 Method (_STA, 0, Serialized)