blob: 3a0b70b0b301c0eec1a59f736855db2ad97cd68c [file] [log] [blame]
Duncan Laurie55cdf552013-03-08 16:01:44 -08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2013 Google Inc.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
9 * the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
19 * MA 02110-1301 USA
20 */
21
22/*
23 * Helper functions for dealing with power management registers
24 * and the differences between LynxPoint-H and LynxPoint-LP.
25 */
26
27#include <arch/io.h>
Duncan Laurie55cdf552013-03-08 16:01:44 -080028#include <device/device.h>
29#include <device/pci.h>
Stefan Reinauer5605f1b2013-03-21 18:43:51 -070030#include <device/pci_def.h>
Duncan Laurie55cdf552013-03-08 16:01:44 -080031#include <console/console.h>
32#include "pch.h"
33
34#if CONFIG_INTEL_LYNXPOINT_LP
35#include "lp_gpio.h"
36#endif
37
38/* These defines are here to handle the LP variant code dynamically. If these
39 * values are defined in lp_gpio.h but when a non-LP board is being built, the
40 * build will fail. */
41#define GPIO_ALT_GPI_SMI_STS 0x50
42#define GPIO_ALT_GPI_SMI_EN 0x54
43
44/* Print status bits with descriptive names */
45static void print_status_bits(u32 status, const char *bit_names[])
46{
47 int i;
48
49 if (!status)
50 return;
51
52 for (i=31; i>=0; i--) {
53 if (status & (1 << i)) {
54 if (bit_names[i])
55 printk(BIOS_DEBUG, "%s ", bit_names[i]);
56 else
57 printk(BIOS_DEBUG, "BIT%d ", i);
58 }
59 }
60}
61
62/* Print status bits as GPIO numbers */
63static void print_gpio_status(u32 status, int start)
64{
65 int i;
66
67 if (!status)
68 return;
69
70 for (i=31; i>=0; i--) {
71 if (status & (1 << i))
72 printk(BIOS_DEBUG, "GPIO%d ", start + i);
73 }
74}
75
76
77/*
78 * PM1_CNT
79 */
80
81/* Enable events in PM1 control register */
82void enable_pm1_control(u32 mask)
83{
84 u32 pm1_cnt = inl(get_pmbase() + PM1_CNT);
85 pm1_cnt |= mask;
86 outl(pm1_cnt, get_pmbase() + PM1_CNT);
87}
88
89/* Disable events in PM1 control register */
90void disable_pm1_control(u32 mask)
91{
92 u32 pm1_cnt = inl(get_pmbase() + PM1_CNT);
93 pm1_cnt &= ~mask;
94 outl(pm1_cnt, get_pmbase() + PM1_CNT);
95}
96
97
98/*
99 * PM1
100 */
101
102/* Clear and return PM1 status register */
103static u16 reset_pm1_status(void)
104{
105 u16 pm1_sts = inw(get_pmbase() + PM1_STS);
106 outw(pm1_sts, get_pmbase() + PM1_STS);
107 return pm1_sts;
108}
109
110/* Print PM1 status bits */
111static u16 print_pm1_status(u16 pm1_sts)
112{
113 const char *pm1_sts_bits[] = {
114 [0] = "TMROF",
115 [4] = "BM",
116 [5] = "GBL",
117 [8] = "PWRBTN",
118 [10] = "RTC",
119 [11] = "PRBTNOR",
120 [14] = "PCIEXPWAK",
121 [15] = "WAK",
122 };
123
124 if (!pm1_sts)
125 return 0;
126
127 printk(BIOS_SPEW, "PM1_STS: ");
128 print_status_bits(pm1_sts, pm1_sts_bits);
129 printk(BIOS_SPEW, "\n");
130
131 return pm1_sts;
132}
133
134/* Print, clear, and return PM1 status */
135u16 clear_pm1_status(void)
136{
137 return print_pm1_status(reset_pm1_status());
138}
139
140/* Enable PM1 event */
141void enable_pm1(u32 mask)
142{
143 u32 pm1_en = inl(get_pmbase() + PM1_EN);
144 pm1_en |= mask;
145 outl(pm1_en, get_pmbase() + PM1_EN);
146}
147
148
149/*
150 * SMI
151 */
152
153/* Clear and return SMI status register */
154static u32 reset_smi_status(void)
155{
156 u32 smi_sts = inl(get_pmbase() + SMI_STS);
157 outl(smi_sts, get_pmbase() + SMI_STS);
158 return smi_sts;
159}
160
161/* Print SMI status bits */
162static u32 print_smi_status(u32 smi_sts)
163{
164 const char *smi_sts_bits[] = {
165 [2] = "BIOS",
166 [3] = "LEGACY_USB",
167 [4] = "SLP_SMI",
168 [5] = "APM",
169 [6] = "SWSMI_TMR",
170 [8] = "PM1",
171 [9] = "GPE0",
172 [10] = "GPI",
173 [11] = "MCSMI",
174 [12] = "DEVMON",
175 [13] = "TCO",
176 [14] = "PERIODIC",
177 [15] = "SERIRQ_SMI",
178 [16] = "SMBUS_SMI",
179 [17] = "LEGACY_USB2",
180 [18] = "INTEL_USB2",
181 [20] = "PCI_EXP_SMI",
182 [21] = "MONITOR",
183 [26] = "SPI",
184 [27] = "GPIO_UNLOCK"
185 };
186
187 if (!smi_sts)
188 return 0;
189
190 printk(BIOS_DEBUG, "SMI_STS: ");
191 print_status_bits(smi_sts, smi_sts_bits);
192 printk(BIOS_DEBUG, "\n");
193
194 return smi_sts;
195}
196
197/* Print, clear, and return SMI status */
198u32 clear_smi_status(void)
199{
200 return print_smi_status(reset_smi_status());
201}
202
203/* Enable SMI event */
204void enable_smi(u32 mask)
205{
206 u32 smi_en = inl(get_pmbase() + SMI_EN);
207 smi_en |= mask;
208 outl(smi_en, get_pmbase() + SMI_EN);
209}
210
211/* Disable SMI event */
212void disable_smi(u32 mask)
213{
214 u32 smi_en = inl(get_pmbase() + SMI_EN);
215 smi_en &= ~mask;
216 outl(smi_en, get_pmbase() + SMI_EN);
217}
218
219
220/*
221 * ALT_GP_SMI
222 */
223
224/* Clear GPIO SMI status and return events that are enabled and active */
225static u32 reset_alt_smi_status(void)
226{
227 u32 alt_sts, alt_en;
228
229 if (pch_is_lp()) {
230 /* LynxPoint-LP moves this to GPIO region as dword */
231 alt_sts = inl(get_gpiobase() + GPIO_ALT_GPI_SMI_STS);
232 outl(alt_sts, get_gpiobase() + GPIO_ALT_GPI_SMI_STS);
233
234 alt_en = inl(get_gpiobase() + GPIO_ALT_GPI_SMI_EN);
235 } else {
236 u16 pmbase = get_pmbase();
237
238 /* LynxPoint-H adds a second enable/status word */
239 alt_sts = inw(pmbase + ALT_GP_SMI_STS2);
240 outw(alt_sts & 0xffff, pmbase + ALT_GP_SMI_STS2);
241
242 alt_sts <<= 16;
243 alt_sts |= inw(pmbase + ALT_GP_SMI_STS);
244 outw(alt_sts & 0xffff, pmbase + ALT_GP_SMI_STS);
245
246 alt_en = inw(pmbase + ALT_GP_SMI_EN2);
247 alt_en <<= 16;
248 alt_en |= inw(pmbase + ALT_GP_SMI_EN);
249 }
250
251 /* Only report enabled events */
252 return alt_sts & alt_en;
253}
254
255/* Print GPIO SMI status bits */
256static u32 print_alt_smi_status(u32 alt_sts)
257{
258 if (!alt_sts)
259 return 0;
260
261 printk(BIOS_DEBUG, "ALT_STS: ");
262
263 if (pch_is_lp()) {
264 /* First 16 events are GPIO 32-47 */
265 print_gpio_status(alt_sts & 0xffff, 32);
266 } else {
267 const char *alt_sts_bits_high[] = {
268 [0] = "GPIO17",
269 [1] = "GPIO19",
270 [2] = "GPIO21",
271 [3] = "GPIO22",
272 [4] = "GPIO43",
273 [5] = "GPIO56",
274 [6] = "GPIO57",
275 [7] = "GPIO60",
276 };
277
278 /* First 16 events are GPIO 0-15 */
279 print_gpio_status(alt_sts & 0xffff, 0);
280 print_status_bits(alt_sts >> 16, alt_sts_bits_high);
281 }
282
283 printk(BIOS_DEBUG, "\n");
284
285 return alt_sts;
286}
287
288/* Print, clear, and return GPIO SMI status */
289u32 clear_alt_smi_status(void)
290{
291 return print_alt_smi_status(reset_alt_smi_status());
292}
293
294/* Enable GPIO SMI events */
295void enable_alt_smi(u32 mask)
296{
297 if (pch_is_lp()) {
298 u32 alt_en;
299
300 alt_en = inl(get_gpiobase() + GPIO_ALT_GPI_SMI_EN);
301 alt_en |= mask;
302 outl(alt_en, get_gpiobase() + GPIO_ALT_GPI_SMI_EN);
303 } else {
304 u16 pmbase = get_pmbase();
305 u16 alt_en;
306
307 /* Lower enable register */
308 alt_en = inw(pmbase + ALT_GP_SMI_EN);
309 alt_en |= mask & 0xffff;
310 outw(alt_en, pmbase + ALT_GP_SMI_EN);
311
312 /* Upper enable register */
313 alt_en = inw(pmbase + ALT_GP_SMI_EN2);
314 alt_en |= (mask >> 16) & 0xffff;
315 outw(alt_en, pmbase + ALT_GP_SMI_EN2);
316 }
317}
318
319
320/*
321 * TCO
322 */
323
324/* Clear TCO status and return events that are enabled and active */
325static u32 reset_tco_status(void)
326{
327 u32 tcobase = get_pmbase() + 0x60;
328 u32 tco_sts = inl(tcobase + 0x04);
329 u32 tco_en = inl(get_pmbase() + 0x68);
330
331 /* Don't clear BOOT_STS before SECOND_TO_STS */
332 outl(tco_sts & ~(1 << 18), tcobase + 0x04);
333
334 /* Clear BOOT_STS */
335 if (tco_sts & (1 << 18))
336 outl(tco_sts & (1 << 18), tcobase + 0x04);
337
338 return tco_sts & tco_en;
339}
340
341/* Print TCO status bits */
342static u32 print_tco_status(u32 tco_sts)
343{
344 const char *tco_sts_bits[] = {
345 [0] = "NMI2SMI",
346 [1] = "SW_TCO",
347 [2] = "TCO_INT",
348 [3] = "TIMEOUT",
349 [7] = "NEWCENTURY",
350 [8] = "BIOSWR",
351 [9] = "DMISCI",
352 [10] = "DMISMI",
353 [12] = "DMISERR",
354 [13] = "SLVSEL",
355 [16] = "INTRD_DET",
356 [17] = "SECOND_TO",
357 [18] = "BOOT",
358 [20] = "SMLINK_SLV"
359 };
360
361 if (!tco_sts)
362 return 0;
363
364 printk(BIOS_DEBUG, "TCO_STS: ");
365 print_status_bits(tco_sts, tco_sts_bits);
366 printk(BIOS_DEBUG, "\n");
367
368 return tco_sts;
369}
370
371/* Print, clear, and return TCO status */
372u32 clear_tco_status(void)
373{
374 return print_tco_status(reset_tco_status());
375}
376
377/* Enable TCO SCI */
378void enable_tco_sci(void)
379{
380 u16 gpe0_sts = pch_is_lp() ? LP_GPE0_STS_4 : GPE0_STS;
381
382 /* Clear pending events */
383 outl(get_pmbase() + gpe0_sts, TCOSCI_STS);
384
385 /* Enable TCO SCI events */
386 enable_gpe(TCOSCI_EN);
387}
388
389
390/*
391 * GPE0
392 */
393
394/* Clear a GPE0 status and return events that are enabled and active */
395static u32 reset_gpe_status(u16 sts_reg, u16 en_reg)
396{
397 u32 gpe0_sts = inl(get_pmbase() + sts_reg);
398 u32 gpe0_en = inl(get_pmbase() + en_reg);
399
400 outl(gpe0_sts, get_pmbase() + sts_reg);
401
402 /* Only report enabled events */
403 return gpe0_sts & gpe0_en;
404}
405
406/* Print GPE0 status bits */
407static u32 print_gpe_status(u32 gpe0_sts, const char *bit_names[])
408{
409 if (!gpe0_sts)
410 return 0;
411
412 printk(BIOS_DEBUG, "GPE0_STS: ");
413 print_status_bits(gpe0_sts, bit_names);
414 printk(BIOS_DEBUG, "\n");
415
416 return gpe0_sts;
417}
418
419/* Print GPE0 GPIO status bits */
420static u32 print_gpe_gpio(u32 gpe0_sts, int start)
421{
422 if (!gpe0_sts)
423 return 0;
424
425 printk(BIOS_DEBUG, "GPE0_STS: ");
426 print_gpio_status(gpe0_sts, start);
427 printk(BIOS_DEBUG, "\n");
428
429 return gpe0_sts;
430}
431
432/* Print, clear, and return LynxPoint-H GPE0 status */
433static u32 clear_lpt_gpe_status(void)
434{
435 const char *gpe0_sts_bits_low[] = {
436 [1] = "HOTPLUG",
437 [2] = "SWGPE",
438 [6] = "TCO_SCI",
439 [7] = "SMB_WAK",
440 [8] = "RI",
441 [9] = "PCI_EXP",
442 [10] = "BATLOW",
443 [11] = "PME",
444 [13] = "PME_B0",
445 [16] = "GPIO0",
446 [17] = "GPIO1",
447 [18] = "GPIO2",
448 [19] = "GPIO3",
449 [20] = "GPIO4",
450 [21] = "GPIO5",
451 [22] = "GPIO6",
452 [23] = "GPIO7",
453 [24] = "GPIO8",
454 [25] = "GPIO9",
455 [26] = "GPIO10",
456 [27] = "GPIO11",
457 [28] = "GPIO12",
458 [29] = "GPIO13",
459 [30] = "GPIO14",
460 [31] = "GPIO15",
461 };
462 const char *gpe0_sts_bits_high[] = {
463 [3] = "GPIO27",
464 [6] = "WADT",
465 [24] = "GPIO17",
466 [25] = "GPIO19",
467 [26] = "GPIO21",
468 [27] = "GPIO22",
469 [28] = "GPIO43",
470 [29] = "GPIO56",
471 [30] = "GPIO57",
472 [31] = "GPIO60",
473 };
474
475 /* High bits */
476 print_gpe_status(reset_gpe_status(GPE0_STS_2, GPE0_EN_2),
477 gpe0_sts_bits_high);
478
479 /* Standard GPE and GPIO 0-31 */
480 return print_gpe_status(reset_gpe_status(GPE0_STS, GPE0_EN),
481 gpe0_sts_bits_low);
482}
483
484/* Print, clear, and return LynxPoint-LP GPE0 status */
485static u32 clear_lpt_lp_gpe_status(void)
486{
487 const char *gpe0_sts_4_bits[] = {
488 [1] = "HOTPLUG",
489 [2] = "SWGPE",
490 [6] = "TCO_SCI",
491 [7] = "SMB_WAK",
492 [9] = "PCI_EXP",
493 [10] = "BATLOW",
494 [11] = "PME",
495 [12] = "ME",
496 [13] = "PME_B0",
497 [16] = "GPIO27",
498 [18] = "WADT"
499 };
500
501 /* GPIO 0-31 */
502 print_gpe_gpio(reset_gpe_status(LP_GPE0_STS_1, LP_GPE0_EN_1), 0);
503
504 /* GPIO 32-63 */
505 print_gpe_gpio(reset_gpe_status(LP_GPE0_STS_2, LP_GPE0_EN_2), 32);
506
507 /* GPIO 64-94 */
508 print_gpe_gpio(reset_gpe_status(LP_GPE0_STS_3, LP_GPE0_EN_3), 64);
509
510 /* Standard GPE */
511 return print_gpe_status(reset_gpe_status(LP_GPE0_STS_4, LP_GPE0_EN_4),
512 gpe0_sts_4_bits);
513}
514
515/* Clear all GPE status and return "standard" GPE event status */
516u32 clear_gpe_status(void)
517{
518 if (pch_is_lp())
519 return clear_lpt_lp_gpe_status();
520 else
521 return clear_lpt_gpe_status();
522}
523
524/* Enable all requested GPE */
525void enable_all_gpe(u32 set1, u32 set2, u32 set3, u32 set4)
526{
527 u16 pmbase = get_pmbase();
528
529 if (pch_is_lp()) {
530 outl(set1, pmbase + LP_GPE0_EN_1);
531 outl(set2, pmbase + LP_GPE0_EN_2);
532 outl(set3, pmbase + LP_GPE0_EN_3);
533 outl(set4, pmbase + LP_GPE0_EN_4);
534 } else {
535 outl(set1, pmbase + GPE0_EN);
536 outl(set2, pmbase + GPE0_EN_2);
537 }
538}
539
540/* Disable all GPE */
541void disable_all_gpe(void)
542{
543 enable_all_gpe(0, 0, 0, 0);
544}
545
546/* Enable a standard GPE */
547void enable_gpe(u32 mask)
548{
549 u32 gpe0_reg = pch_is_lp() ? LP_GPE0_EN_4 : GPE0_EN;
550 u32 gpe0_en = inl(get_pmbase() + gpe0_reg);
551 gpe0_en |= mask;
552 outl(gpe0_en, get_pmbase() + gpe0_reg);
553}
554
555/* Disable a standard GPE */
556void disable_gpe(u32 mask)
557{
558 u32 gpe0_reg = pch_is_lp() ? LP_GPE0_EN_4 : GPE0_EN;
559 u32 gpe0_en = inl(get_pmbase() + gpe0_reg);
560 gpe0_en &= ~mask;
561 outl(gpe0_en, get_pmbase() + gpe0_reg);
562}