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