blob: a880183b82bf8cb5b8b7e10679fbc5ca8c20211e [file] [log] [blame]
Angel Ponsba38f372020-04-05 15:46:45 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Lee Leahy77ff0b12015-05-05 15:07:29 -07002
Angel Pons5595a202021-04-17 12:28:53 +02003#define __SIMPLE_DEVICE__
4
Furquan Shaikh76cedd22020-05-02 10:24:23 -07005#include <acpi/acpi.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -07006#include <arch/io.h>
Frans Hendriks20989632019-05-16 11:46:22 +02007#include <assert.h>
Bill XIE516c0a52020-02-24 23:08:35 +08008#include <bootmode.h>
Kyösti Mälkki21d6a272019-11-05 18:50:38 +02009#include <device/device.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020010#include <device/mmio.h>
Kyösti Mälkki21d6a272019-11-05 18:50:38 +020011#include <device/pci.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020012#include <device/pci_ops.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070013#include <console/console.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070014#include <soc/iomap.h>
15#include <soc/lpc.h>
16#include <soc/pci_devs.h>
Lee Leahy32471722015-04-20 15:20:28 -070017#include <soc/pm.h>
18#include <stdint.h>
Philipp Deppenwiesefea24292017-10-17 17:02:29 +020019#include <security/vboot/vbnv.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070020
Lee Leahy77ff0b12015-05-05 15:07:29 -070021uint16_t get_pmbase(void)
22{
Angel Pons5595a202021-04-17 12:28:53 +020023 return pci_read_config16(PCI_DEV(0, PCU_DEV, 0), ABASE) & 0xfff8;
Lee Leahy77ff0b12015-05-05 15:07:29 -070024}
25
Angel Ponsaee7ab22020-03-19 00:31:58 +010026static void print_num_status_bits(int num_bits, uint32_t status, const char *const bit_names[])
Lee Leahy77ff0b12015-05-05 15:07:29 -070027{
28 int i;
29
30 if (!status)
31 return;
32
33 for (i = num_bits - 1; i >= 0; i--) {
34 if (status & (1 << i)) {
35 if (bit_names[i])
36 printk(BIOS_DEBUG, "%s ", bit_names[i]);
37 else
38 printk(BIOS_DEBUG, "BIT%d ", i);
39 }
40 }
41}
42
Lee Leahy77ff0b12015-05-05 15:07:29 -070043static uint32_t print_smi_status(uint32_t smi_sts)
44{
Elyes HAOUAS39303d52018-07-08 12:40:45 +020045 static const char *const smi_sts_bits[] = {
Lee Leahy77ff0b12015-05-05 15:07:29 -070046 [2] = "BIOS",
47 [4] = "SLP_SMI",
48 [5] = "APM",
49 [6] = "SWSMI_TMR",
50 [8] = "PM1",
51 [9] = "GPE0",
52 [12] = "DEVMON",
53 [13] = "TCO",
54 [14] = "PERIODIC",
55 [15] = "ILB",
56 [16] = "SMBUS_SMI",
57 [17] = "LEGACY_USB2",
58 [18] = "INTEL_USB2",
59 [20] = "PCI_EXP_SMI",
60 [26] = "SPI",
61 [28] = "PUNIT",
62 [29] = "GUNIT",
63 };
64
65 if (!smi_sts)
66 return 0;
67
68 printk(BIOS_DEBUG, "SMI_STS: ");
Ravi Sarawadid077b582015-09-09 14:12:16 -070069 print_num_status_bits(30, smi_sts, smi_sts_bits);
Lee Leahy77ff0b12015-05-05 15:07:29 -070070 printk(BIOS_DEBUG, "\n");
71
72 return smi_sts;
73}
74
75static uint32_t reset_smi_status(void)
76{
77 uint16_t pmbase = get_pmbase();
78 uint32_t smi_sts = inl(pmbase + SMI_STS);
79 outl(smi_sts, pmbase + SMI_STS);
80 return smi_sts;
81}
82
83uint32_t clear_smi_status(void)
84{
85 return print_smi_status(reset_smi_status());
86}
87
88void enable_smi(uint32_t mask)
89{
90 uint16_t pmbase = get_pmbase();
91 uint32_t smi_en = inl(pmbase + SMI_EN);
92 smi_en |= mask;
93 outl(smi_en, pmbase + SMI_EN);
94}
95
96void disable_smi(uint32_t mask)
97{
98 uint16_t pmbase = get_pmbase();
99 uint32_t smi_en = inl(pmbase + SMI_EN);
100 smi_en &= ~mask;
101 outl(smi_en, pmbase + SMI_EN);
102}
103
104void enable_pm1_control(uint32_t mask)
105{
106 uint16_t pmbase = get_pmbase();
107 uint32_t pm1_cnt = inl(pmbase + PM1_CNT);
108 pm1_cnt |= mask;
109 outl(pm1_cnt, pmbase + PM1_CNT);
110}
111
112void disable_pm1_control(uint32_t mask)
113{
114 uint16_t pmbase = get_pmbase();
115 uint32_t pm1_cnt = inl(pmbase + PM1_CNT);
116 pm1_cnt &= ~mask;
117 outl(pm1_cnt, pmbase + PM1_CNT);
118}
119
120static uint16_t reset_pm1_status(void)
121{
122 uint16_t pmbase = get_pmbase();
123 uint16_t pm1_sts = inw(pmbase + PM1_STS);
124 outw(pm1_sts, pmbase + PM1_STS);
125 return pm1_sts;
126}
127
128static uint16_t print_pm1_status(uint16_t pm1_sts)
129{
Elyes HAOUAS39303d52018-07-08 12:40:45 +0200130 static const char *const pm1_sts_bits[] = {
Lee Leahy77ff0b12015-05-05 15:07:29 -0700131 [0] = "TMROF",
132 [5] = "GBL",
133 [8] = "PWRBTN",
134 [10] = "RTC",
135 [11] = "PRBTNOR",
136 [13] = "USB",
137 [14] = "PCIEXPWAK",
138 [15] = "WAK",
139 };
140
141 if (!pm1_sts)
142 return 0;
143
144 printk(BIOS_SPEW, "PM1_STS: ");
Ravi Sarawadid077b582015-09-09 14:12:16 -0700145 print_num_status_bits(16, pm1_sts, pm1_sts_bits);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700146 printk(BIOS_SPEW, "\n");
147
148 return pm1_sts;
149}
150
151uint16_t clear_pm1_status(void)
152{
153 return print_pm1_status(reset_pm1_status());
154}
155
156void enable_pm1(uint16_t events)
157{
158 outw(events, get_pmbase() + PM1_EN);
159}
160
161static uint32_t print_tco_status(uint32_t tco_sts)
162{
Elyes HAOUAS39303d52018-07-08 12:40:45 +0200163 static const char *const tco_sts_bits[] = {
Lee Leahy77ff0b12015-05-05 15:07:29 -0700164 [3] = "TIMEOUT",
165 [17] = "SECOND_TO",
166 };
167
168 if (!tco_sts)
169 return 0;
170
171 printk(BIOS_DEBUG, "TCO_STS: ");
Ravi Sarawadid077b582015-09-09 14:12:16 -0700172 print_num_status_bits(18, tco_sts, tco_sts_bits);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700173 printk(BIOS_DEBUG, "\n");
174
175 return tco_sts;
176}
177
178static uint32_t reset_tco_status(void)
179{
180 uint16_t pmbase = get_pmbase();
181 uint32_t tco_sts = inl(pmbase + TCO_STS);
182 uint32_t tco_en = inl(pmbase + TCO1_CNT);
183
184 outl(tco_sts, pmbase + TCO_STS);
185 return tco_sts & tco_en;
186}
187
188uint32_t clear_tco_status(void)
189{
190 return print_tco_status(reset_tco_status());
191}
192
193void enable_gpe(uint32_t mask)
194{
195 uint16_t pmbase = get_pmbase();
196 uint32_t gpe0_en = inl(pmbase + GPE0_EN);
197 gpe0_en |= mask;
198 outl(gpe0_en, pmbase + GPE0_EN);
199}
200
201void disable_gpe(uint32_t mask)
202{
203 uint16_t pmbase = get_pmbase();
204 uint32_t gpe0_en = inl(pmbase + GPE0_EN);
205 gpe0_en &= ~mask;
206 outl(gpe0_en, pmbase + GPE0_EN);
207}
208
209void disable_all_gpe(void)
210{
211 disable_gpe(~0);
212}
213
Lee Leahy77ff0b12015-05-05 15:07:29 -0700214static uint32_t reset_gpe_status(void)
215{
216 uint16_t pmbase = get_pmbase();
217 uint32_t gpe_sts = inl(pmbase + GPE0_STS);
218 outl(gpe_sts, pmbase + GPE0_STS);
219 return gpe_sts;
220}
221
222static uint32_t print_gpe_sts(uint32_t gpe_sts)
223{
Elyes HAOUAS39303d52018-07-08 12:40:45 +0200224 static const char *const gpe_sts_bits[] = {
Lee Leahy77ff0b12015-05-05 15:07:29 -0700225 [1] = "HOTPLUG",
226 [2] = "SWGPE",
227 [3] = "PCIE_WAKE0",
228 [4] = "PUNIT",
229 [5] = "GUNIT",
230 [6] = "PCIE_WAKE1",
231 [7] = "PCIE_WAKE2",
232 [8] = "PCIE_WAKE3",
233 [9] = "PCI_EXP",
234 [10] = "BATLOW",
235 [13] = "PME_B0",
236 [16] = "SUS_GPIO_0",
237 [17] = "SUS_GPIO_1",
238 [18] = "SUS_GPIO_2",
239 [19] = "SUS_GPIO_3",
240 [20] = "SUS_GPIO_4",
241 [21] = "SUS_GPIO_5",
242 [22] = "SUS_GPIO_6",
243 [23] = "SUS_GPIO_7",
244 [24] = "CORE_GPIO_0",
245 [25] = "CORE_GPIO_1",
246 [26] = "CORE_GPIO_2",
247 [27] = "CORE_GPIO_3",
248 [28] = "CORE_GPIO_4",
249 [29] = "CORE_GPIO_5",
250 [30] = "CORE_GPIO_6",
251 [31] = "CORE_GPIO_7",
252 };
253
254 if (!gpe_sts)
255 return gpe_sts;
256
257 printk(BIOS_DEBUG, "GPE0a_STS: ");
Ravi Sarawadid077b582015-09-09 14:12:16 -0700258 print_num_status_bits(32, gpe_sts, gpe_sts_bits);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700259 printk(BIOS_DEBUG, "\n");
260
261 return gpe_sts;
262}
263
264uint32_t clear_gpe_status(void)
265{
266 return print_gpe_sts(reset_gpe_status());
267}
268
269static uint32_t reset_alt_status(void)
270{
271 uint16_t pmbase = get_pmbase();
272 uint32_t alt_gpio_smi = inl(pmbase + ALT_GPIO_SMI);
273 outl(alt_gpio_smi, pmbase + ALT_GPIO_SMI);
274 return alt_gpio_smi;
275}
276
277static uint32_t print_alt_sts(uint32_t alt_gpio_smi)
278{
279 uint32_t alt_gpio_sts;
Elyes HAOUAS39303d52018-07-08 12:40:45 +0200280 static const char *const alt_gpio_smi_sts_bits[] = {
Angel Ponsaee7ab22020-03-19 00:31:58 +0100281 [0] = "SUS_GPIO_0",
282 [1] = "SUS_GPIO_1",
283 [2] = "SUS_GPIO_2",
284 [3] = "SUS_GPIO_3",
285 [4] = "SUS_GPIO_4",
286 [5] = "SUS_GPIO_5",
287 [6] = "SUS_GPIO_6",
288 [7] = "SUS_GPIO_7",
289 [8] = "CORE_GPIO_0",
290 [9] = "CORE_GPIO_1",
Lee Leahy77ff0b12015-05-05 15:07:29 -0700291 [10] = "CORE_GPIO_2",
292 [11] = "CORE_GPIO_3",
293 [12] = "CORE_GPIO_4",
294 [13] = "CORE_GPIO_5",
295 [14] = "CORE_GPIO_6",
296 [15] = "CORE_GPIO_7",
297 };
298
299 /* Status bits are in the upper 16 bits. */
300 alt_gpio_sts = alt_gpio_smi >> 16;
301 if (!alt_gpio_sts)
302 return alt_gpio_smi;
303
304 printk(BIOS_DEBUG, "ALT_GPIO_SMI: ");
305 print_num_status_bits(16, alt_gpio_sts, alt_gpio_smi_sts_bits);
306 printk(BIOS_DEBUG, "\n");
307
308 return alt_gpio_smi;
309}
310
311uint32_t clear_alt_status(void)
312{
313 return print_alt_sts(reset_alt_status());
314}
315
316void clear_pmc_status(void)
317{
318 uint32_t prsts;
319 uint32_t gen_pmcon1;
320
Lee Leahy32471722015-04-20 15:20:28 -0700321 prsts = read32((void *)(PMC_BASE_ADDRESS + PRSTS));
322 gen_pmcon1 = read32((void *)(PMC_BASE_ADDRESS + GEN_PMCON1));
Lee Leahy77ff0b12015-05-05 15:07:29 -0700323
324 /* Clear the status bits. The RPS field is cleared on a 0 write. */
Lee Leahy32471722015-04-20 15:20:28 -0700325 write32((void *)(PMC_BASE_ADDRESS + GEN_PMCON1), gen_pmcon1 & ~RPS);
326 write32((void *)(PMC_BASE_ADDRESS + PRSTS), prsts);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700327}
Aaron Durbinb19e33f2017-09-15 14:32:13 -0600328
329int rtc_failure(void)
330{
331 uint32_t gen_pmcon1;
332 int rtc_fail;
Aaron Durbinb19e33f2017-09-15 14:32:13 -0600333
Frans Hendriks20989632019-05-16 11:46:22 +0200334 /* not usable in ramstage as GEN_PMCON1 gets reset */
335 if (ENV_RAMSTAGE)
336 dead_code();
337
338 gen_pmcon1 = read32((u32 *)(PMC_BASE_ADDRESS + GEN_PMCON1));
Aaron Durbinb19e33f2017-09-15 14:32:13 -0600339
340 rtc_fail = !!(gen_pmcon1 & RPS);
Aaron Durbinb19e33f2017-09-15 14:32:13 -0600341 if (rtc_fail)
342 printk(BIOS_DEBUG, "RTC failure.\n");
343
344 return rtc_fail;
345}
Aaron Durbin0990fbf2017-09-15 15:23:04 -0600346
347int vbnv_cmos_failed(void)
348{
349 return rtc_failure();
350}
Joel Kitching1d93b882018-09-26 17:58:14 +0800351
Bill XIE516c0a52020-02-24 23:08:35 +0800352int platform_is_resuming(void)
Joel Kitching1d93b882018-09-26 17:58:14 +0800353{
354 if (!(inw(ACPI_BASE_ADDRESS + PM1_STS) & WAK_STS))
355 return 0;
356
357 return acpi_sleep_from_pm1(inl(ACPI_BASE_ADDRESS + PM1_CNT)) == ACPI_S3;
358}