blob: 910df6179587d7a4fb5c645a0f3991d2087b5531 [file] [log] [blame]
Angel Ponsf94ac9a2020-04-05 15:46:48 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Duncan Lauriec88c54c2014-04-30 16:36:13 -07003
4/*
5 * Helper functions for dealing with power management registers
6 * and the differences between PCH variants.
7 */
8
Joel Kitching1d93b882018-09-26 17:58:14 +08009#include <arch/acpi.h>
Duncan Lauriec88c54c2014-04-30 16:36:13 -070010#include <arch/io.h>
Bill XIE516c0a52020-02-24 23:08:35 +080011#include <bootmode.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020012#include <device/pci_ops.h>
Duncan Lauriec88c54c2014-04-30 16:36:13 -070013#include <device/device.h>
14#include <device/pci.h>
15#include <device/pci_def.h>
16#include <console/console.h>
Julius Werner4ee4bd52014-10-20 13:46:39 -070017#include <soc/iomap.h>
18#include <soc/lpc.h>
19#include <soc/pci_devs.h>
20#include <soc/pm.h>
21#include <soc/gpio.h>
Philipp Deppenwiesefea24292017-10-17 17:02:29 +020022#include <security/vboot/vbnv.h>
Duncan Lauriec88c54c2014-04-30 16:36:13 -070023
24/* Print status bits with descriptive names */
25static void print_status_bits(u32 status, const char *bit_names[])
26{
27 int i;
28
29 if (!status)
30 return;
31
Lee Leahy26b7cd02017-03-16 18:47:55 -070032 for (i = 31; i >= 0; i--) {
Duncan Lauriec88c54c2014-04-30 16:36:13 -070033 if (status & (1 << i)) {
34 if (bit_names[i])
35 printk(BIOS_DEBUG, "%s ", bit_names[i]);
36 else
37 printk(BIOS_DEBUG, "BIT%d ", i);
38 }
39 }
40}
41
42/* Print status bits as GPIO numbers */
43static void print_gpio_status(u32 status, int start)
44{
45 int i;
46
47 if (!status)
48 return;
49
Lee Leahy26b7cd02017-03-16 18:47:55 -070050 for (i = 31; i >= 0; i--) {
Duncan Lauriec88c54c2014-04-30 16:36:13 -070051 if (status & (1 << i))
52 printk(BIOS_DEBUG, "GPIO%d ", start + i);
53 }
54}
55
56
57/*
58 * PM1_CNT
59 */
60
61/* Enable events in PM1 control register */
62void enable_pm1_control(u32 mask)
63{
64 u32 pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
65 pm1_cnt |= mask;
66 outl(pm1_cnt, ACPI_BASE_ADDRESS + PM1_CNT);
67}
68
69/* Disable events in PM1 control register */
70void disable_pm1_control(u32 mask)
71{
72 u32 pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
73 pm1_cnt &= ~mask;
74 outl(pm1_cnt, ACPI_BASE_ADDRESS + PM1_CNT);
75}
76
77
78/*
79 * PM1
80 */
81
82/* Clear and return PM1 status register */
83static u16 reset_pm1_status(void)
84{
85 u16 pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS);
86 outw(pm1_sts, ACPI_BASE_ADDRESS + PM1_STS);
87 return pm1_sts;
88}
89
90/* Print PM1 status bits */
91static u16 print_pm1_status(u16 pm1_sts)
92{
93 const char *pm1_sts_bits[] = {
94 [0] = "TMROF",
95 [4] = "BM",
96 [5] = "GBL",
97 [8] = "PWRBTN",
98 [10] = "RTC",
99 [11] = "PRBTNOR",
100 [14] = "PCIEXPWAK",
101 [15] = "WAK",
102 };
103
104 if (!pm1_sts)
105 return 0;
106
107 printk(BIOS_SPEW, "PM1_STS: ");
108 print_status_bits(pm1_sts, pm1_sts_bits);
109 printk(BIOS_SPEW, "\n");
110
111 return pm1_sts;
112}
113
114/* Print, clear, and return PM1 status */
115u16 clear_pm1_status(void)
116{
117 return print_pm1_status(reset_pm1_status());
118}
119
120/* Set the PM1 register to events */
121void enable_pm1(u16 events)
122{
123 outw(events, ACPI_BASE_ADDRESS + PM1_EN);
124}
125
126
127/*
128 * SMI
129 */
130
131/* Clear and return SMI status register */
132static u32 reset_smi_status(void)
133{
134 u32 smi_sts = inl(ACPI_BASE_ADDRESS + SMI_STS);
135 outl(smi_sts, ACPI_BASE_ADDRESS + SMI_STS);
136 return smi_sts;
137}
138
139/* Print SMI status bits */
140static u32 print_smi_status(u32 smi_sts)
141{
142 const char *smi_sts_bits[] = {
143 [2] = "BIOS",
144 [3] = "LEGACY_USB",
145 [4] = "SLP_SMI",
146 [5] = "APM",
147 [6] = "SWSMI_TMR",
148 [8] = "PM1",
149 [9] = "GPE0",
150 [10] = "GPI",
151 [11] = "MCSMI",
152 [12] = "DEVMON",
153 [13] = "TCO",
154 [14] = "PERIODIC",
155 [15] = "SERIRQ_SMI",
156 [16] = "SMBUS_SMI",
157 [17] = "LEGACY_USB2",
158 [18] = "INTEL_USB2",
159 [20] = "PCI_EXP_SMI",
160 [21] = "MONITOR",
161 [26] = "SPI",
162 [27] = "GPIO_UNLOCK"
163 };
164
165 if (!smi_sts)
166 return 0;
167
168 printk(BIOS_DEBUG, "SMI_STS: ");
169 print_status_bits(smi_sts, smi_sts_bits);
170 printk(BIOS_DEBUG, "\n");
171
172 return smi_sts;
173}
174
175/* Print, clear, and return SMI status */
176u32 clear_smi_status(void)
177{
178 return print_smi_status(reset_smi_status());
179}
180
181/* Enable SMI event */
182void enable_smi(u32 mask)
183{
184 u32 smi_en = inl(ACPI_BASE_ADDRESS + SMI_EN);
185 smi_en |= mask;
186 outl(smi_en, ACPI_BASE_ADDRESS + SMI_EN);
187}
188
189/* Disable SMI event */
190void disable_smi(u32 mask)
191{
192 u32 smi_en = inl(ACPI_BASE_ADDRESS + SMI_EN);
193 smi_en &= ~mask;
194 outl(smi_en, ACPI_BASE_ADDRESS + SMI_EN);
195}
196
197
198/*
199 * ALT_GP_SMI
200 */
201
202/* Clear GPIO SMI status and return events that are enabled and active */
203static u32 reset_alt_smi_status(void)
204{
205 u32 alt_sts, alt_en;
206
207 /* Low Power variant moves this to GPIO region as dword */
208 alt_sts = inl(GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_STS);
209 outl(alt_sts, GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_STS);
210 alt_en = inl(GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_EN);
211
212 /* Only report enabled events */
213 return alt_sts & alt_en;
214}
215
216/* Print GPIO SMI status bits */
217static u32 print_alt_smi_status(u32 alt_sts)
218{
219 if (!alt_sts)
220 return 0;
221
222 printk(BIOS_DEBUG, "ALT_STS: ");
223
224 /* First 16 events are GPIO 32-47 */
225 print_gpio_status(alt_sts & 0xffff, 32);
226
227 printk(BIOS_DEBUG, "\n");
228
229 return alt_sts;
230}
231
232/* Print, clear, and return GPIO SMI status */
233u32 clear_alt_smi_status(void)
234{
235 return print_alt_smi_status(reset_alt_smi_status());
236}
237
238/* Enable GPIO SMI events */
239void enable_alt_smi(u32 mask)
240{
241 u32 alt_en;
242
243 alt_en = inl(GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_EN);
244 alt_en |= mask;
245 outl(alt_en, GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_EN);
246}
247
248
249/*
250 * TCO
251 */
252
253/* Clear TCO status and return events that are enabled and active */
254static u32 reset_tco_status(void)
255{
256 u32 tcobase = ACPI_BASE_ADDRESS + 0x60;
257 u32 tco_sts = inl(tcobase + 0x04);
258 u32 tco_en = inl(ACPI_BASE_ADDRESS + 0x68);
259
260 /* Don't clear BOOT_STS before SECOND_TO_STS */
261 outl(tco_sts & ~(1 << 18), tcobase + 0x04);
262
263 /* Clear BOOT_STS */
264 if (tco_sts & (1 << 18))
265 outl(tco_sts & (1 << 18), tcobase + 0x04);
266
267 return tco_sts & tco_en;
268}
269
270/* Print TCO status bits */
271static u32 print_tco_status(u32 tco_sts)
272{
273 const char *tco_sts_bits[] = {
274 [0] = "NMI2SMI",
275 [1] = "SW_TCO",
276 [2] = "TCO_INT",
277 [3] = "TIMEOUT",
278 [7] = "NEWCENTURY",
279 [8] = "BIOSWR",
280 [9] = "DMISCI",
281 [10] = "DMISMI",
282 [12] = "DMISERR",
283 [13] = "SLVSEL",
284 [16] = "INTRD_DET",
285 [17] = "SECOND_TO",
286 [18] = "BOOT",
287 [20] = "SMLINK_SLV"
288 };
289
290 if (!tco_sts)
291 return 0;
292
293 printk(BIOS_DEBUG, "TCO_STS: ");
294 print_status_bits(tco_sts, tco_sts_bits);
295 printk(BIOS_DEBUG, "\n");
296
297 return tco_sts;
298}
299
300/* Print, clear, and return TCO status */
301u32 clear_tco_status(void)
302{
303 return print_tco_status(reset_tco_status());
304}
305
306/* Enable TCO SCI */
307void enable_tco_sci(void)
308{
309 /* Clear pending events */
310 outl(ACPI_BASE_ADDRESS + GPE0_STS(3), TCOSCI_STS);
311
312 /* Enable TCO SCI events */
313 enable_gpe(TCOSCI_EN);
314}
315
316
317/*
318 * GPE0
319 */
320
321/* Clear a GPE0 status and return events that are enabled and active */
322static u32 reset_gpe(u16 sts_reg, u16 en_reg)
323{
324 u32 gpe0_sts = inl(ACPI_BASE_ADDRESS + sts_reg);
325 u32 gpe0_en = inl(ACPI_BASE_ADDRESS + en_reg);
326
327 outl(gpe0_sts, ACPI_BASE_ADDRESS + sts_reg);
328
329 /* Only report enabled events */
330 return gpe0_sts & gpe0_en;
331}
332
333/* Print GPE0 status bits */
334static u32 print_gpe_status(u32 gpe0_sts, const char *bit_names[])
335{
336 if (!gpe0_sts)
337 return 0;
338
339 printk(BIOS_DEBUG, "GPE0_STS: ");
340 print_status_bits(gpe0_sts, bit_names);
341 printk(BIOS_DEBUG, "\n");
342
343 return gpe0_sts;
344}
345
346/* Print GPE0 GPIO status bits */
347static u32 print_gpe_gpio(u32 gpe0_sts, int start)
348{
349 if (!gpe0_sts)
350 return 0;
351
352 printk(BIOS_DEBUG, "GPE0_STS: ");
353 print_gpio_status(gpe0_sts, start);
354 printk(BIOS_DEBUG, "\n");
355
356 return gpe0_sts;
357}
358
359/* Clear all GPE status and return "standard" GPE event status */
360u32 clear_gpe_status(void)
361{
362 const char *gpe0_sts_3_bits[] = {
363 [1] = "HOTPLUG",
364 [2] = "SWGPE",
365 [6] = "TCO_SCI",
366 [7] = "SMB_WAK",
367 [9] = "PCI_EXP",
368 [10] = "BATLOW",
369 [11] = "PME",
370 [12] = "ME",
371 [13] = "PME_B0",
372 [16] = "GPIO27",
373 [18] = "WADT"
374 };
375
376 print_gpe_gpio(reset_gpe(GPE0_STS(GPE_31_0), GPE0_EN(GPE_31_0)), 0);
377 print_gpe_gpio(reset_gpe(GPE0_STS(GPE_63_32), GPE0_EN(GPE_63_32)), 32);
378 print_gpe_gpio(reset_gpe(GPE0_STS(GPE_94_64), GPE0_EN(GPE_94_64)), 64);
379 return print_gpe_status(reset_gpe(GPE0_STS(GPE_STD), GPE0_EN(GPE_STD)),
380 gpe0_sts_3_bits);
381}
382
383/* Enable all requested GPE */
384void enable_all_gpe(u32 set1, u32 set2, u32 set3, u32 set4)
385{
386 outl(set1, ACPI_BASE_ADDRESS + GPE0_EN(GPE_31_0));
387 outl(set2, ACPI_BASE_ADDRESS + GPE0_EN(GPE_63_32));
388 outl(set3, ACPI_BASE_ADDRESS + GPE0_EN(GPE_94_64));
389 outl(set4, ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD));
390}
391
392/* Disable all GPE */
393void disable_all_gpe(void)
394{
395 enable_all_gpe(0, 0, 0, 0);
396}
397
398/* Enable a standard GPE */
399void enable_gpe(u32 mask)
400{
401 u32 gpe0_en = inl(ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD));
402 gpe0_en |= mask;
403 outl(gpe0_en, ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD));
404}
405
406/* Disable a standard GPE */
407void disable_gpe(u32 mask)
408{
409 u32 gpe0_en = inl(ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD));
410 gpe0_en &= ~mask;
411 outl(gpe0_en, ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD));
412}
413
414int acpi_sci_irq(void)
415{
416 int scis = pci_read_config32(PCH_DEV_LPC, ACPI_CNTL) & SCI_IRQ_SEL;
417 int sci_irq = 9;
418
419 /* Determine how SCI is routed. */
420 switch (scis) {
421 case SCIS_IRQ9:
422 case SCIS_IRQ10:
423 case SCIS_IRQ11:
424 sci_irq = scis - SCIS_IRQ9 + 9;
425 break;
426 case SCIS_IRQ20:
427 case SCIS_IRQ21:
428 case SCIS_IRQ22:
429 case SCIS_IRQ23:
430 sci_irq = scis - SCIS_IRQ20 + 20;
431 break;
432 default:
433 printk(BIOS_DEBUG, "Invalid SCI route! Defaulting to IRQ9.\n");
434 sci_irq = 9;
435 break;
436 }
437
438 printk(BIOS_DEBUG, "SCI is IRQ%d\n", sci_irq);
439 return sci_irq;
440}
Aaron Durbinb9d9b792017-09-15 11:51:58 -0600441
Bill XIE516c0a52020-02-24 23:08:35 +0800442int platform_is_resuming(void)
Joel Kitching1d93b882018-09-26 17:58:14 +0800443{
444 if (!(inw(ACPI_BASE_ADDRESS + PM1_STS) & WAK_STS))
445 return 0;
446
447 return acpi_sleep_from_pm1(inl(ACPI_BASE_ADDRESS + PM1_CNT)) == ACPI_S3;
448}
Eugene Myersebc84232020-01-21 16:46:16 -0500449
450/* STM Support */
451uint16_t get_pmbase(void)
452{
453 return (uint16_t) ACPI_BASE_ADDRESS;
454}