blob: 4497166c6b5a4830a55ecc63d8f2934f70b29ecb [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
Furquan Shaikh76cedd22020-05-02 10:24:23 -07003#include <acpi/acpi.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -07004#include <arch/io.h>
Frans Hendriks20989632019-05-16 11:46:22 +02005#include <assert.h>
Bill XIE516c0a52020-02-24 23:08:35 +08006#include <bootmode.h>
Kyösti Mälkki21d6a272019-11-05 18:50:38 +02007#include <device/device.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02008#include <device/mmio.h>
Kyösti Mälkki21d6a272019-11-05 18:50:38 +02009#include <device/pci.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020010#include <device/pci_ops.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070011#include <console/console.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070012#include <soc/iomap.h>
13#include <soc/lpc.h>
14#include <soc/pci_devs.h>
Lee Leahy32471722015-04-20 15:20:28 -070015#include <soc/pm.h>
16#include <stdint.h>
Philipp Deppenwiesefea24292017-10-17 17:02:29 +020017#include <security/vboot/vbnv.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070018
Aaron Durbinb19e33f2017-09-15 14:32:13 -060019#if defined(__SIMPLE_DEVICE__)
Lee Leahy77ff0b12015-05-05 15:07:29 -070020
Elyes HAOUASc8a649c2018-06-10 23:36:44 +020021static const pci_devfn_t pcu_dev = PCI_DEV(0, PCU_DEV, 0);
Lee Leahy77ff0b12015-05-05 15:07:29 -070022
Elyes HAOUASc8a649c2018-06-10 23:36:44 +020023static inline pci_devfn_t get_pcu_dev(void)
Lee Leahy77ff0b12015-05-05 15:07:29 -070024{
25 return pcu_dev;
26}
27
Kyösti Mälkki21d6a272019-11-05 18:50:38 +020028#else /* __SIMPLE_DEVICE__ */
Lee Leahy77ff0b12015-05-05 15:07:29 -070029
Elyes HAOUASc8a649c2018-06-10 23:36:44 +020030static struct device *pcu_dev;
31static struct device *get_pcu_dev(void)
Lee Leahy77ff0b12015-05-05 15:07:29 -070032{
33 if (pcu_dev == NULL)
Kyösti Mälkkic70eed12018-05-22 02:18:00 +030034 pcu_dev = pcidev_on_root(PCU_DEV, 0);
Lee Leahy77ff0b12015-05-05 15:07:29 -070035 return pcu_dev;
36}
Kyösti Mälkki21d6a272019-11-05 18:50:38 +020037#endif /* __SIMPLE_DEVICE__ */
Lee Leahy77ff0b12015-05-05 15:07:29 -070038
39uint16_t get_pmbase(void)
40{
41 return pci_read_config16(get_pcu_dev(), ABASE) & 0xfff8;
42}
43
Angel Ponsaee7ab22020-03-19 00:31:58 +010044static void print_num_status_bits(int num_bits, uint32_t status, const char *const bit_names[])
Lee Leahy77ff0b12015-05-05 15:07:29 -070045{
46 int i;
47
48 if (!status)
49 return;
50
51 for (i = num_bits - 1; i >= 0; i--) {
52 if (status & (1 << i)) {
53 if (bit_names[i])
54 printk(BIOS_DEBUG, "%s ", bit_names[i]);
55 else
56 printk(BIOS_DEBUG, "BIT%d ", i);
57 }
58 }
59}
60
Lee Leahy77ff0b12015-05-05 15:07:29 -070061static uint32_t print_smi_status(uint32_t smi_sts)
62{
Elyes HAOUAS39303d52018-07-08 12:40:45 +020063 static const char *const smi_sts_bits[] = {
Lee Leahy77ff0b12015-05-05 15:07:29 -070064 [2] = "BIOS",
65 [4] = "SLP_SMI",
66 [5] = "APM",
67 [6] = "SWSMI_TMR",
68 [8] = "PM1",
69 [9] = "GPE0",
70 [12] = "DEVMON",
71 [13] = "TCO",
72 [14] = "PERIODIC",
73 [15] = "ILB",
74 [16] = "SMBUS_SMI",
75 [17] = "LEGACY_USB2",
76 [18] = "INTEL_USB2",
77 [20] = "PCI_EXP_SMI",
78 [26] = "SPI",
79 [28] = "PUNIT",
80 [29] = "GUNIT",
81 };
82
83 if (!smi_sts)
84 return 0;
85
86 printk(BIOS_DEBUG, "SMI_STS: ");
Ravi Sarawadid077b582015-09-09 14:12:16 -070087 print_num_status_bits(30, smi_sts, smi_sts_bits);
Lee Leahy77ff0b12015-05-05 15:07:29 -070088 printk(BIOS_DEBUG, "\n");
89
90 return smi_sts;
91}
92
93static uint32_t reset_smi_status(void)
94{
95 uint16_t pmbase = get_pmbase();
96 uint32_t smi_sts = inl(pmbase + SMI_STS);
97 outl(smi_sts, pmbase + SMI_STS);
98 return smi_sts;
99}
100
101uint32_t clear_smi_status(void)
102{
103 return print_smi_status(reset_smi_status());
104}
105
106void enable_smi(uint32_t mask)
107{
108 uint16_t pmbase = get_pmbase();
109 uint32_t smi_en = inl(pmbase + SMI_EN);
110 smi_en |= mask;
111 outl(smi_en, pmbase + SMI_EN);
112}
113
114void disable_smi(uint32_t mask)
115{
116 uint16_t pmbase = get_pmbase();
117 uint32_t smi_en = inl(pmbase + SMI_EN);
118 smi_en &= ~mask;
119 outl(smi_en, pmbase + SMI_EN);
120}
121
122void enable_pm1_control(uint32_t mask)
123{
124 uint16_t pmbase = get_pmbase();
125 uint32_t pm1_cnt = inl(pmbase + PM1_CNT);
126 pm1_cnt |= mask;
127 outl(pm1_cnt, pmbase + PM1_CNT);
128}
129
130void disable_pm1_control(uint32_t mask)
131{
132 uint16_t pmbase = get_pmbase();
133 uint32_t pm1_cnt = inl(pmbase + PM1_CNT);
134 pm1_cnt &= ~mask;
135 outl(pm1_cnt, pmbase + PM1_CNT);
136}
137
138static uint16_t reset_pm1_status(void)
139{
140 uint16_t pmbase = get_pmbase();
141 uint16_t pm1_sts = inw(pmbase + PM1_STS);
142 outw(pm1_sts, pmbase + PM1_STS);
143 return pm1_sts;
144}
145
146static uint16_t print_pm1_status(uint16_t pm1_sts)
147{
Elyes HAOUAS39303d52018-07-08 12:40:45 +0200148 static const char *const pm1_sts_bits[] = {
Lee Leahy77ff0b12015-05-05 15:07:29 -0700149 [0] = "TMROF",
150 [5] = "GBL",
151 [8] = "PWRBTN",
152 [10] = "RTC",
153 [11] = "PRBTNOR",
154 [13] = "USB",
155 [14] = "PCIEXPWAK",
156 [15] = "WAK",
157 };
158
159 if (!pm1_sts)
160 return 0;
161
162 printk(BIOS_SPEW, "PM1_STS: ");
Ravi Sarawadid077b582015-09-09 14:12:16 -0700163 print_num_status_bits(16, pm1_sts, pm1_sts_bits);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700164 printk(BIOS_SPEW, "\n");
165
166 return pm1_sts;
167}
168
169uint16_t clear_pm1_status(void)
170{
171 return print_pm1_status(reset_pm1_status());
172}
173
174void enable_pm1(uint16_t events)
175{
176 outw(events, get_pmbase() + PM1_EN);
177}
178
179static uint32_t print_tco_status(uint32_t tco_sts)
180{
Elyes HAOUAS39303d52018-07-08 12:40:45 +0200181 static const char *const tco_sts_bits[] = {
Lee Leahy77ff0b12015-05-05 15:07:29 -0700182 [3] = "TIMEOUT",
183 [17] = "SECOND_TO",
184 };
185
186 if (!tco_sts)
187 return 0;
188
189 printk(BIOS_DEBUG, "TCO_STS: ");
Ravi Sarawadid077b582015-09-09 14:12:16 -0700190 print_num_status_bits(18, tco_sts, tco_sts_bits);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700191 printk(BIOS_DEBUG, "\n");
192
193 return tco_sts;
194}
195
196static uint32_t reset_tco_status(void)
197{
198 uint16_t pmbase = get_pmbase();
199 uint32_t tco_sts = inl(pmbase + TCO_STS);
200 uint32_t tco_en = inl(pmbase + TCO1_CNT);
201
202 outl(tco_sts, pmbase + TCO_STS);
203 return tco_sts & tco_en;
204}
205
206uint32_t clear_tco_status(void)
207{
208 return print_tco_status(reset_tco_status());
209}
210
211void enable_gpe(uint32_t mask)
212{
213 uint16_t pmbase = get_pmbase();
214 uint32_t gpe0_en = inl(pmbase + GPE0_EN);
215 gpe0_en |= mask;
216 outl(gpe0_en, pmbase + GPE0_EN);
217}
218
219void disable_gpe(uint32_t mask)
220{
221 uint16_t pmbase = get_pmbase();
222 uint32_t gpe0_en = inl(pmbase + GPE0_EN);
223 gpe0_en &= ~mask;
224 outl(gpe0_en, pmbase + GPE0_EN);
225}
226
227void disable_all_gpe(void)
228{
229 disable_gpe(~0);
230}
231
Lee Leahy77ff0b12015-05-05 15:07:29 -0700232static uint32_t reset_gpe_status(void)
233{
234 uint16_t pmbase = get_pmbase();
235 uint32_t gpe_sts = inl(pmbase + GPE0_STS);
236 outl(gpe_sts, pmbase + GPE0_STS);
237 return gpe_sts;
238}
239
240static uint32_t print_gpe_sts(uint32_t gpe_sts)
241{
Elyes HAOUAS39303d52018-07-08 12:40:45 +0200242 static const char *const gpe_sts_bits[] = {
Lee Leahy77ff0b12015-05-05 15:07:29 -0700243 [1] = "HOTPLUG",
244 [2] = "SWGPE",
245 [3] = "PCIE_WAKE0",
246 [4] = "PUNIT",
247 [5] = "GUNIT",
248 [6] = "PCIE_WAKE1",
249 [7] = "PCIE_WAKE2",
250 [8] = "PCIE_WAKE3",
251 [9] = "PCI_EXP",
252 [10] = "BATLOW",
253 [13] = "PME_B0",
254 [16] = "SUS_GPIO_0",
255 [17] = "SUS_GPIO_1",
256 [18] = "SUS_GPIO_2",
257 [19] = "SUS_GPIO_3",
258 [20] = "SUS_GPIO_4",
259 [21] = "SUS_GPIO_5",
260 [22] = "SUS_GPIO_6",
261 [23] = "SUS_GPIO_7",
262 [24] = "CORE_GPIO_0",
263 [25] = "CORE_GPIO_1",
264 [26] = "CORE_GPIO_2",
265 [27] = "CORE_GPIO_3",
266 [28] = "CORE_GPIO_4",
267 [29] = "CORE_GPIO_5",
268 [30] = "CORE_GPIO_6",
269 [31] = "CORE_GPIO_7",
270 };
271
272 if (!gpe_sts)
273 return gpe_sts;
274
275 printk(BIOS_DEBUG, "GPE0a_STS: ");
Ravi Sarawadid077b582015-09-09 14:12:16 -0700276 print_num_status_bits(32, gpe_sts, gpe_sts_bits);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700277 printk(BIOS_DEBUG, "\n");
278
279 return gpe_sts;
280}
281
282uint32_t clear_gpe_status(void)
283{
284 return print_gpe_sts(reset_gpe_status());
285}
286
287static uint32_t reset_alt_status(void)
288{
289 uint16_t pmbase = get_pmbase();
290 uint32_t alt_gpio_smi = inl(pmbase + ALT_GPIO_SMI);
291 outl(alt_gpio_smi, pmbase + ALT_GPIO_SMI);
292 return alt_gpio_smi;
293}
294
295static uint32_t print_alt_sts(uint32_t alt_gpio_smi)
296{
297 uint32_t alt_gpio_sts;
Elyes HAOUAS39303d52018-07-08 12:40:45 +0200298 static const char *const alt_gpio_smi_sts_bits[] = {
Angel Ponsaee7ab22020-03-19 00:31:58 +0100299 [0] = "SUS_GPIO_0",
300 [1] = "SUS_GPIO_1",
301 [2] = "SUS_GPIO_2",
302 [3] = "SUS_GPIO_3",
303 [4] = "SUS_GPIO_4",
304 [5] = "SUS_GPIO_5",
305 [6] = "SUS_GPIO_6",
306 [7] = "SUS_GPIO_7",
307 [8] = "CORE_GPIO_0",
308 [9] = "CORE_GPIO_1",
Lee Leahy77ff0b12015-05-05 15:07:29 -0700309 [10] = "CORE_GPIO_2",
310 [11] = "CORE_GPIO_3",
311 [12] = "CORE_GPIO_4",
312 [13] = "CORE_GPIO_5",
313 [14] = "CORE_GPIO_6",
314 [15] = "CORE_GPIO_7",
315 };
316
317 /* Status bits are in the upper 16 bits. */
318 alt_gpio_sts = alt_gpio_smi >> 16;
319 if (!alt_gpio_sts)
320 return alt_gpio_smi;
321
322 printk(BIOS_DEBUG, "ALT_GPIO_SMI: ");
323 print_num_status_bits(16, alt_gpio_sts, alt_gpio_smi_sts_bits);
324 printk(BIOS_DEBUG, "\n");
325
326 return alt_gpio_smi;
327}
328
329uint32_t clear_alt_status(void)
330{
331 return print_alt_sts(reset_alt_status());
332}
333
334void clear_pmc_status(void)
335{
336 uint32_t prsts;
337 uint32_t gen_pmcon1;
338
Lee Leahy32471722015-04-20 15:20:28 -0700339 prsts = read32((void *)(PMC_BASE_ADDRESS + PRSTS));
340 gen_pmcon1 = read32((void *)(PMC_BASE_ADDRESS + GEN_PMCON1));
Lee Leahy77ff0b12015-05-05 15:07:29 -0700341
342 /* Clear the status bits. The RPS field is cleared on a 0 write. */
Lee Leahy32471722015-04-20 15:20:28 -0700343 write32((void *)(PMC_BASE_ADDRESS + GEN_PMCON1), gen_pmcon1 & ~RPS);
344 write32((void *)(PMC_BASE_ADDRESS + PRSTS), prsts);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700345}
Aaron Durbinb19e33f2017-09-15 14:32:13 -0600346
347int rtc_failure(void)
348{
349 uint32_t gen_pmcon1;
350 int rtc_fail;
Aaron Durbinb19e33f2017-09-15 14:32:13 -0600351
Frans Hendriks20989632019-05-16 11:46:22 +0200352 /* not usable in ramstage as GEN_PMCON1 gets reset */
353 if (ENV_RAMSTAGE)
354 dead_code();
355
356 gen_pmcon1 = read32((u32 *)(PMC_BASE_ADDRESS + GEN_PMCON1));
Aaron Durbinb19e33f2017-09-15 14:32:13 -0600357
358 rtc_fail = !!(gen_pmcon1 & RPS);
Aaron Durbinb19e33f2017-09-15 14:32:13 -0600359 if (rtc_fail)
360 printk(BIOS_DEBUG, "RTC failure.\n");
361
362 return rtc_fail;
363}
Aaron Durbin0990fbf2017-09-15 15:23:04 -0600364
365int vbnv_cmos_failed(void)
366{
367 return rtc_failure();
368}
Joel Kitching1d93b882018-09-26 17:58:14 +0800369
Bill XIE516c0a52020-02-24 23:08:35 +0800370int platform_is_resuming(void)
Joel Kitching1d93b882018-09-26 17:58:14 +0800371{
372 if (!(inw(ACPI_BASE_ADDRESS + PM1_STS) & WAK_STS))
373 return 0;
374
375 return acpi_sleep_from_pm1(inl(ACPI_BASE_ADDRESS + PM1_CNT)) == ACPI_S3;
376}