• 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#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