blob: 46115108ffdf7d79c775aef6cd453e7f2bdeaf65 [file] [log] [blame]
Lee Leahy77ff0b12015-05-05 15:07:29 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2013 Google Inc.
Lee Leahy32471722015-04-20 15:20:28 -07005 * Copyright (C) 2015 Intel Corp.
Lee Leahy77ff0b12015-05-05 15:07:29 -07006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of 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.
Lee Leahy77ff0b12015-05-05 15:07:29 -070015 */
16
Lee Leahy77ff0b12015-05-05 15:07:29 -070017#include <arch/io.h>
18#include <console/console.h>
Lee Leahyacb9c0b2015-07-02 11:55:18 -070019#include <rules.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070020#include <soc/iomap.h>
21#include <soc/lpc.h>
22#include <soc/pci_devs.h>
Lee Leahy32471722015-04-20 15:20:28 -070023#include <soc/pm.h>
24#include <stdint.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070025
Lee Leahyacb9c0b2015-07-02 11:55:18 -070026#if ENV_SMM
Lee Leahy77ff0b12015-05-05 15:07:29 -070027
28static const device_t pcu_dev = PCI_DEV(0, PCU_DEV, 0);
29
30static inline device_t get_pcu_dev(void)
31{
32 return pcu_dev;
33}
34
Lee Leahyacb9c0b2015-07-02 11:55:18 -070035#else /* ENV_SMM */
Lee Leahy77ff0b12015-05-05 15:07:29 -070036#include <device/device.h>
37#include <device/pci.h>
38
39static device_t pcu_dev;
40static device_t get_pcu_dev(void)
41{
42 if (pcu_dev == NULL)
43 pcu_dev = dev_find_slot(0, PCI_DEVFN(PCU_DEV, 0));
44 return pcu_dev;
45}
Lee Leahyacb9c0b2015-07-02 11:55:18 -070046#endif /* ENV_SMM */
Lee Leahy77ff0b12015-05-05 15:07:29 -070047
48uint16_t get_pmbase(void)
49{
50 return pci_read_config16(get_pcu_dev(), ABASE) & 0xfff8;
51}
52
53static void print_num_status_bits(int num_bits, uint32_t status,
Lee Leahy32471722015-04-20 15:20:28 -070054 const char * const bit_names[])
Lee Leahy77ff0b12015-05-05 15:07:29 -070055{
56 int i;
57
58 if (!status)
59 return;
60
61 for (i = num_bits - 1; i >= 0; i--) {
62 if (status & (1 << i)) {
63 if (bit_names[i])
64 printk(BIOS_DEBUG, "%s ", bit_names[i]);
65 else
66 printk(BIOS_DEBUG, "BIT%d ", i);
67 }
68 }
69}
70
Lee Leahy32471722015-04-20 15:20:28 -070071static void print_status_bits(uint32_t status, const char * const bit_names[])
Lee Leahy77ff0b12015-05-05 15:07:29 -070072{
73 print_num_status_bits(32, status, bit_names);
74}
75
76static uint32_t print_smi_status(uint32_t smi_sts)
77{
Lee Leahy32471722015-04-20 15:20:28 -070078 static const char * const smi_sts_bits[] = {
Lee Leahy77ff0b12015-05-05 15:07:29 -070079 [2] = "BIOS",
80 [4] = "SLP_SMI",
81 [5] = "APM",
82 [6] = "SWSMI_TMR",
83 [8] = "PM1",
84 [9] = "GPE0",
85 [12] = "DEVMON",
86 [13] = "TCO",
87 [14] = "PERIODIC",
88 [15] = "ILB",
89 [16] = "SMBUS_SMI",
90 [17] = "LEGACY_USB2",
91 [18] = "INTEL_USB2",
92 [20] = "PCI_EXP_SMI",
93 [26] = "SPI",
94 [28] = "PUNIT",
95 [29] = "GUNIT",
96 };
97
98 if (!smi_sts)
99 return 0;
100
101 printk(BIOS_DEBUG, "SMI_STS: ");
102 print_status_bits(smi_sts, smi_sts_bits);
103 printk(BIOS_DEBUG, "\n");
104
105 return smi_sts;
106}
107
108static uint32_t reset_smi_status(void)
109{
110 uint16_t pmbase = get_pmbase();
111 uint32_t smi_sts = inl(pmbase + SMI_STS);
112 outl(smi_sts, pmbase + SMI_STS);
113 return smi_sts;
114}
115
116uint32_t clear_smi_status(void)
117{
118 return print_smi_status(reset_smi_status());
119}
120
121void enable_smi(uint32_t mask)
122{
123 uint16_t pmbase = get_pmbase();
124 uint32_t smi_en = inl(pmbase + SMI_EN);
125 smi_en |= mask;
126 outl(smi_en, pmbase + SMI_EN);
127}
128
129void disable_smi(uint32_t mask)
130{
131 uint16_t pmbase = get_pmbase();
132 uint32_t smi_en = inl(pmbase + SMI_EN);
133 smi_en &= ~mask;
134 outl(smi_en, pmbase + SMI_EN);
135}
136
137void enable_pm1_control(uint32_t mask)
138{
139 uint16_t pmbase = get_pmbase();
140 uint32_t pm1_cnt = inl(pmbase + PM1_CNT);
141 pm1_cnt |= mask;
142 outl(pm1_cnt, pmbase + PM1_CNT);
143}
144
145void disable_pm1_control(uint32_t mask)
146{
147 uint16_t pmbase = get_pmbase();
148 uint32_t pm1_cnt = inl(pmbase + PM1_CNT);
149 pm1_cnt &= ~mask;
150 outl(pm1_cnt, pmbase + PM1_CNT);
151}
152
153static uint16_t reset_pm1_status(void)
154{
155 uint16_t pmbase = get_pmbase();
156 uint16_t pm1_sts = inw(pmbase + PM1_STS);
157 outw(pm1_sts, pmbase + PM1_STS);
158 return pm1_sts;
159}
160
161static uint16_t print_pm1_status(uint16_t pm1_sts)
162{
Lee Leahy32471722015-04-20 15:20:28 -0700163 static const char * const pm1_sts_bits[] = {
Lee Leahy77ff0b12015-05-05 15:07:29 -0700164 [0] = "TMROF",
165 [5] = "GBL",
166 [8] = "PWRBTN",
167 [10] = "RTC",
168 [11] = "PRBTNOR",
169 [13] = "USB",
170 [14] = "PCIEXPWAK",
171 [15] = "WAK",
172 };
173
174 if (!pm1_sts)
175 return 0;
176
177 printk(BIOS_SPEW, "PM1_STS: ");
178 print_status_bits(pm1_sts, pm1_sts_bits);
179 printk(BIOS_SPEW, "\n");
180
181 return pm1_sts;
182}
183
184uint16_t clear_pm1_status(void)
185{
186 return print_pm1_status(reset_pm1_status());
187}
188
189void enable_pm1(uint16_t events)
190{
191 outw(events, get_pmbase() + PM1_EN);
192}
193
194static uint32_t print_tco_status(uint32_t tco_sts)
195{
Lee Leahy32471722015-04-20 15:20:28 -0700196 static const char * const tco_sts_bits[] = {
Lee Leahy77ff0b12015-05-05 15:07:29 -0700197 [3] = "TIMEOUT",
198 [17] = "SECOND_TO",
199 };
200
201 if (!tco_sts)
202 return 0;
203
204 printk(BIOS_DEBUG, "TCO_STS: ");
205 print_status_bits(tco_sts, tco_sts_bits);
206 printk(BIOS_DEBUG, "\n");
207
208 return tco_sts;
209}
210
211static uint32_t reset_tco_status(void)
212{
213 uint16_t pmbase = get_pmbase();
214 uint32_t tco_sts = inl(pmbase + TCO_STS);
215 uint32_t tco_en = inl(pmbase + TCO1_CNT);
216
217 outl(tco_sts, pmbase + TCO_STS);
218 return tco_sts & tco_en;
219}
220
221uint32_t clear_tco_status(void)
222{
223 return print_tco_status(reset_tco_status());
224}
225
226void enable_gpe(uint32_t mask)
227{
228 uint16_t pmbase = get_pmbase();
229 uint32_t gpe0_en = inl(pmbase + GPE0_EN);
230 gpe0_en |= mask;
231 outl(gpe0_en, pmbase + GPE0_EN);
232}
233
234void disable_gpe(uint32_t mask)
235{
236 uint16_t pmbase = get_pmbase();
237 uint32_t gpe0_en = inl(pmbase + GPE0_EN);
238 gpe0_en &= ~mask;
239 outl(gpe0_en, pmbase + GPE0_EN);
240}
241
242void disable_all_gpe(void)
243{
244 disable_gpe(~0);
245}
246
247
248static uint32_t reset_gpe_status(void)
249{
250 uint16_t pmbase = get_pmbase();
251 uint32_t gpe_sts = inl(pmbase + GPE0_STS);
252 outl(gpe_sts, pmbase + GPE0_STS);
253 return gpe_sts;
254}
255
256static uint32_t print_gpe_sts(uint32_t gpe_sts)
257{
Lee Leahy32471722015-04-20 15:20:28 -0700258 static const char * const gpe_sts_bits[] = {
Lee Leahy77ff0b12015-05-05 15:07:29 -0700259 [1] = "HOTPLUG",
260 [2] = "SWGPE",
261 [3] = "PCIE_WAKE0",
262 [4] = "PUNIT",
263 [5] = "GUNIT",
264 [6] = "PCIE_WAKE1",
265 [7] = "PCIE_WAKE2",
266 [8] = "PCIE_WAKE3",
267 [9] = "PCI_EXP",
268 [10] = "BATLOW",
269 [13] = "PME_B0",
270 [16] = "SUS_GPIO_0",
271 [17] = "SUS_GPIO_1",
272 [18] = "SUS_GPIO_2",
273 [19] = "SUS_GPIO_3",
274 [20] = "SUS_GPIO_4",
275 [21] = "SUS_GPIO_5",
276 [22] = "SUS_GPIO_6",
277 [23] = "SUS_GPIO_7",
278 [24] = "CORE_GPIO_0",
279 [25] = "CORE_GPIO_1",
280 [26] = "CORE_GPIO_2",
281 [27] = "CORE_GPIO_3",
282 [28] = "CORE_GPIO_4",
283 [29] = "CORE_GPIO_5",
284 [30] = "CORE_GPIO_6",
285 [31] = "CORE_GPIO_7",
286 };
287
288 if (!gpe_sts)
289 return gpe_sts;
290
291 printk(BIOS_DEBUG, "GPE0a_STS: ");
292 print_status_bits(gpe_sts, gpe_sts_bits);
293 printk(BIOS_DEBUG, "\n");
294
295 return gpe_sts;
296}
297
298uint32_t clear_gpe_status(void)
299{
300 return print_gpe_sts(reset_gpe_status());
301}
302
303static uint32_t reset_alt_status(void)
304{
305 uint16_t pmbase = get_pmbase();
306 uint32_t alt_gpio_smi = inl(pmbase + ALT_GPIO_SMI);
307 outl(alt_gpio_smi, pmbase + ALT_GPIO_SMI);
308 return alt_gpio_smi;
309}
310
311static uint32_t print_alt_sts(uint32_t alt_gpio_smi)
312{
313 uint32_t alt_gpio_sts;
Lee Leahy32471722015-04-20 15:20:28 -0700314 static const char * const alt_gpio_smi_sts_bits[] = {
Lee Leahy77ff0b12015-05-05 15:07:29 -0700315 [0] = "SUS_GPIO_0",
316 [1] = "SUS_GPIO_1",
317 [2] = "SUS_GPIO_2",
318 [3] = "SUS_GPIO_3",
319 [4] = "SUS_GPIO_4",
320 [5] = "SUS_GPIO_5",
321 [6] = "SUS_GPIO_6",
322 [7] = "SUS_GPIO_7",
323 [8] = "CORE_GPIO_0",
324 [9] = "CORE_GPIO_1",
325 [10] = "CORE_GPIO_2",
326 [11] = "CORE_GPIO_3",
327 [12] = "CORE_GPIO_4",
328 [13] = "CORE_GPIO_5",
329 [14] = "CORE_GPIO_6",
330 [15] = "CORE_GPIO_7",
331 };
332
333 /* Status bits are in the upper 16 bits. */
334 alt_gpio_sts = alt_gpio_smi >> 16;
335 if (!alt_gpio_sts)
336 return alt_gpio_smi;
337
338 printk(BIOS_DEBUG, "ALT_GPIO_SMI: ");
339 print_num_status_bits(16, alt_gpio_sts, alt_gpio_smi_sts_bits);
340 printk(BIOS_DEBUG, "\n");
341
342 return alt_gpio_smi;
343}
344
345uint32_t clear_alt_status(void)
346{
347 return print_alt_sts(reset_alt_status());
348}
349
350void clear_pmc_status(void)
351{
352 uint32_t prsts;
353 uint32_t gen_pmcon1;
354
Lee Leahy32471722015-04-20 15:20:28 -0700355 prsts = read32((void *)(PMC_BASE_ADDRESS + PRSTS));
356 gen_pmcon1 = read32((void *)(PMC_BASE_ADDRESS + GEN_PMCON1));
Lee Leahy77ff0b12015-05-05 15:07:29 -0700357
358 /* Clear the status bits. The RPS field is cleared on a 0 write. */
Lee Leahy32471722015-04-20 15:20:28 -0700359 write32((void *)(PMC_BASE_ADDRESS + GEN_PMCON1), gen_pmcon1 & ~RPS);
360 write32((void *)(PMC_BASE_ADDRESS + PRSTS), prsts);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700361}