• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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