blob: d00166047dd1ed5faba494c9f1a9e2d84090769c [file] [log] [blame]
Angel Ponsc3f58f62020-04-05 15:46:41 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Aaron Durbin7837be62013-10-21 22:32:00 -05002
Angel Pons0db4b272021-04-17 12:30:12 +02003#define __SIMPLE_DEVICE__
4
Aaron Durbin7837be62013-10-21 22:32:00 -05005#include <stdint.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -07006#include <acpi/acpi.h>
Kyösti Mälkki27872372021-01-21 16:05:26 +02007#include <acpi/acpi_pm.h>
Aaron Durbin7837be62013-10-21 22:32:00 -05008#include <arch/io.h>
Bill XIE516c0a52020-02-24 23:08:35 +08009#include <bootmode.h>
Kyösti Mälkki21d6a272019-11-05 18:50:38 +020010#include <device/device.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020011#include <device/mmio.h>
Kyösti Mälkki21d6a272019-11-05 18:50:38 +020012#include <device/pci.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020013#include <device/pci_ops.h>
Aaron Durbin7837be62013-10-21 22:32:00 -050014#include <console/console.h>
15
Julius Werner18ea2d32014-10-07 16:42:17 -070016#include <soc/iomap.h>
17#include <soc/lpc.h>
18#include <soc/pci_devs.h>
Angel Ponsb5320b22020-07-07 18:27:30 +020019#include <soc/pm.h>
Philipp Deppenwiesefea24292017-10-17 17:02:29 +020020#include <security/vboot/vbnv.h>
Aaron Durbin7837be62013-10-21 22:32:00 -050021
Aaron Durbin7837be62013-10-21 22:32:00 -050022uint16_t get_pmbase(void)
23{
Angel Pons0db4b272021-04-17 12:30:12 +020024 return pci_read_config16(PCI_DEV(0, PCU_DEV, 0), ABASE) & 0xfff8;
Aaron Durbin7837be62013-10-21 22:32:00 -050025}
26
Angel Ponsa5c970d2020-07-07 18:09:45 +020027static void print_num_status_bits(int num_bits, uint32_t status, const char *const bit_names[])
Aaron Durbin7837be62013-10-21 22:32:00 -050028{
29 int i;
30
31 if (!status)
32 return;
33
Aaron Durbin9f83e872013-11-11 14:45:27 -060034 for (i = num_bits - 1; i >= 0; i--) {
Aaron Durbin7837be62013-10-21 22:32:00 -050035 if (status & (1 << i)) {
36 if (bit_names[i])
37 printk(BIOS_DEBUG, "%s ", bit_names[i]);
38 else
39 printk(BIOS_DEBUG, "BIT%d ", i);
40 }
41 }
42}
43
44static uint32_t print_smi_status(uint32_t smi_sts)
45{
Angel Ponsa5c970d2020-07-07 18:09:45 +020046 static const char *const smi_sts_bits[] = {
Aaron Durbin7837be62013-10-21 22:32:00 -050047 [2] = "BIOS",
48 [4] = "SLP_SMI",
49 [5] = "APM",
50 [6] = "SWSMI_TMR",
51 [8] = "PM1",
52 [9] = "GPE0",
53 [12] = "DEVMON",
54 [13] = "TCO",
55 [14] = "PERIODIC",
56 [15] = "ILB",
57 [16] = "SMBUS_SMI",
58 [17] = "LEGACY_USB2",
59 [18] = "INTEL_USB2",
60 [20] = "PCI_EXP_SMI",
61 [26] = "SPI",
62 [28] = "PUNIT",
63 [29] = "GUNIT",
64 };
65
66 if (!smi_sts)
67 return 0;
68
69 printk(BIOS_DEBUG, "SMI_STS: ");
Angel Pons61dee5c2020-07-07 18:01:46 +020070 print_num_status_bits(30, smi_sts, smi_sts_bits);
Aaron Durbin7837be62013-10-21 22:32:00 -050071 printk(BIOS_DEBUG, "\n");
72
73 return smi_sts;
74}
75
76static uint32_t reset_smi_status(void)
77{
78 uint16_t pmbase = get_pmbase();
79 uint32_t smi_sts = inl(pmbase + SMI_STS);
80 outl(smi_sts, pmbase + SMI_STS);
81 return smi_sts;
82}
83
84uint32_t clear_smi_status(void)
85{
86 return print_smi_status(reset_smi_status());
87}
88
89void enable_smi(uint32_t mask)
90{
91 uint16_t pmbase = get_pmbase();
92 uint32_t smi_en = inl(pmbase + SMI_EN);
93 smi_en |= mask;
94 outl(smi_en, pmbase + SMI_EN);
95}
96
97void disable_smi(uint32_t mask)
98{
99 uint16_t pmbase = get_pmbase();
100 uint32_t smi_en = inl(pmbase + SMI_EN);
101 smi_en &= ~mask;
102 outl(smi_en, pmbase + SMI_EN);
103}
104
105void enable_pm1_control(uint32_t mask)
106{
107 uint16_t pmbase = get_pmbase();
108 uint32_t pm1_cnt = inl(pmbase + PM1_CNT);
109 pm1_cnt |= mask;
110 outl(pm1_cnt, pmbase + PM1_CNT);
111}
112
113void disable_pm1_control(uint32_t mask)
114{
115 uint16_t pmbase = get_pmbase();
116 uint32_t pm1_cnt = inl(pmbase + PM1_CNT);
117 pm1_cnt &= ~mask;
118 outl(pm1_cnt, pmbase + PM1_CNT);
119}
120
121static uint16_t reset_pm1_status(void)
122{
123 uint16_t pmbase = get_pmbase();
124 uint16_t pm1_sts = inw(pmbase + PM1_STS);
125 outw(pm1_sts, pmbase + PM1_STS);
126 return pm1_sts;
127}
128
129static uint16_t print_pm1_status(uint16_t pm1_sts)
130{
Angel Ponsa5c970d2020-07-07 18:09:45 +0200131 static const char *const pm1_sts_bits[] = {
Aaron Durbin7837be62013-10-21 22:32:00 -0500132 [0] = "TMROF",
133 [5] = "GBL",
134 [8] = "PWRBTN",
135 [10] = "RTC",
136 [11] = "PRBTNOR",
137 [13] = "USB",
138 [14] = "PCIEXPWAK",
139 [15] = "WAK",
140 };
141
142 if (!pm1_sts)
143 return 0;
144
145 printk(BIOS_SPEW, "PM1_STS: ");
Angel Pons61dee5c2020-07-07 18:01:46 +0200146 print_num_status_bits(16, pm1_sts, pm1_sts_bits);
Aaron Durbin7837be62013-10-21 22:32:00 -0500147 printk(BIOS_SPEW, "\n");
148
149 return pm1_sts;
150}
151
152uint16_t clear_pm1_status(void)
153{
154 return print_pm1_status(reset_pm1_status());
155}
156
157void enable_pm1(uint16_t events)
158{
159 outw(events, get_pmbase() + PM1_EN);
160}
161
162static uint32_t print_tco_status(uint32_t tco_sts)
163{
Angel Ponsa5c970d2020-07-07 18:09:45 +0200164 static const char *const tco_sts_bits[] = {
Aaron Durbin7837be62013-10-21 22:32:00 -0500165 [3] = "TIMEOUT",
166 [17] = "SECOND_TO",
167 };
168
169 if (!tco_sts)
170 return 0;
171
172 printk(BIOS_DEBUG, "TCO_STS: ");
Angel Pons61dee5c2020-07-07 18:01:46 +0200173 print_num_status_bits(18, tco_sts, tco_sts_bits);
Aaron Durbin7837be62013-10-21 22:32:00 -0500174 printk(BIOS_DEBUG, "\n");
175
176 return tco_sts;
177}
178
179static uint32_t reset_tco_status(void)
180{
181 uint16_t pmbase = get_pmbase();
182 uint32_t tco_sts = inl(pmbase + TCO_STS);
183 uint32_t tco_en = inl(pmbase + TCO1_CNT);
184
185 outl(tco_sts, pmbase + TCO_STS);
186 return tco_sts & tco_en;
187}
188
189uint32_t clear_tco_status(void)
190{
191 return print_tco_status(reset_tco_status());
192}
193
194void enable_gpe(uint32_t mask)
195{
196 uint16_t pmbase = get_pmbase();
197 uint32_t gpe0_en = inl(pmbase + GPE0_EN);
198 gpe0_en |= mask;
199 outl(gpe0_en, pmbase + GPE0_EN);
200}
201
202void disable_gpe(uint32_t mask)
203{
204 uint16_t pmbase = get_pmbase();
205 uint32_t gpe0_en = inl(pmbase + GPE0_EN);
206 gpe0_en &= ~mask;
207 outl(gpe0_en, pmbase + GPE0_EN);
208}
209
210void disable_all_gpe(void)
211{
212 disable_gpe(~0);
213}
214
Aaron Durbin7837be62013-10-21 22:32:00 -0500215static uint32_t reset_gpe_status(void)
216{
217 uint16_t pmbase = get_pmbase();
218 uint32_t gpe_sts = inl(pmbase + GPE0_STS);
219 outl(gpe_sts, pmbase + GPE0_STS);
220 return gpe_sts;
221}
222
223static uint32_t print_gpe_sts(uint32_t gpe_sts)
224{
Angel Ponsa5c970d2020-07-07 18:09:45 +0200225 static const char *const gpe_sts_bits[] = {
Aaron Durbin7837be62013-10-21 22:32:00 -0500226 [1] = "HOTPLUG",
227 [2] = "SWGPE",
228 [3] = "PCIE_WAKE0",
229 [4] = "PUNIT",
230 [5] = "GUNIT",
231 [6] = "PCIE_WAKE1",
232 [7] = "PCIE_WAKE2",
233 [8] = "PCIE_WAKE3",
234 [9] = "PCI_EXP",
235 [10] = "BATLOW",
236 [13] = "PME_B0",
237 [16] = "SUS_GPIO_0",
238 [17] = "SUS_GPIO_1",
239 [18] = "SUS_GPIO_2",
240 [19] = "SUS_GPIO_3",
241 [20] = "SUS_GPIO_4",
242 [21] = "SUS_GPIO_5",
243 [22] = "SUS_GPIO_6",
244 [23] = "SUS_GPIO_7",
245 [24] = "CORE_GPIO_0",
246 [25] = "CORE_GPIO_1",
247 [26] = "CORE_GPIO_2",
248 [27] = "CORE_GPIO_3",
249 [28] = "CORE_GPIO_4",
250 [29] = "CORE_GPIO_5",
251 [30] = "CORE_GPIO_6",
252 [31] = "CORE_GPIO_7",
253 };
254
255 if (!gpe_sts)
256 return gpe_sts;
257
258 printk(BIOS_DEBUG, "GPE0a_STS: ");
Angel Pons61dee5c2020-07-07 18:01:46 +0200259 print_num_status_bits(32, gpe_sts, gpe_sts_bits);
Aaron Durbin7837be62013-10-21 22:32:00 -0500260 printk(BIOS_DEBUG, "\n");
261
262 return gpe_sts;
263}
264
265uint32_t clear_gpe_status(void)
266{
267 return print_gpe_sts(reset_gpe_status());
268}
Aaron Durbin9f83e872013-11-11 14:45:27 -0600269
270static uint32_t reset_alt_status(void)
271{
272 uint16_t pmbase = get_pmbase();
273 uint32_t alt_gpio_smi = inl(pmbase + ALT_GPIO_SMI);
274 outl(alt_gpio_smi, pmbase + ALT_GPIO_SMI);
275 return alt_gpio_smi;
276}
277
278static uint32_t print_alt_sts(uint32_t alt_gpio_smi)
279{
280 uint32_t alt_gpio_sts;
Angel Ponsa5c970d2020-07-07 18:09:45 +0200281 static const char *const alt_gpio_smi_sts_bits[] = {
282 [0] = "SUS_GPIO_0",
283 [1] = "SUS_GPIO_1",
284 [2] = "SUS_GPIO_2",
285 [3] = "SUS_GPIO_3",
286 [4] = "SUS_GPIO_4",
287 [5] = "SUS_GPIO_5",
288 [6] = "SUS_GPIO_6",
289 [7] = "SUS_GPIO_7",
290 [8] = "CORE_GPIO_0",
291 [9] = "CORE_GPIO_1",
Aaron Durbin9f83e872013-11-11 14:45:27 -0600292 [10] = "CORE_GPIO_2",
293 [11] = "CORE_GPIO_3",
294 [12] = "CORE_GPIO_4",
295 [13] = "CORE_GPIO_5",
296 [14] = "CORE_GPIO_6",
297 [15] = "CORE_GPIO_7",
298 };
299
300 /* Status bits are in the upper 16 bits. */
301 alt_gpio_sts = alt_gpio_smi >> 16;
302 if (!alt_gpio_sts)
303 return alt_gpio_smi;
304
305 printk(BIOS_DEBUG, "ALT_GPIO_SMI: ");
306 print_num_status_bits(16, alt_gpio_sts, alt_gpio_smi_sts_bits);
307 printk(BIOS_DEBUG, "\n");
308
309 return alt_gpio_smi;
310}
311
312uint32_t clear_alt_status(void)
313{
314 return print_alt_sts(reset_alt_status());
315}
Aaron Durbin19edc3a2014-01-09 11:17:37 -0600316
317void clear_pmc_status(void)
318{
319 uint32_t prsts;
320 uint32_t gen_pmcon1;
321
Angel Ponse80d17f2020-07-07 17:25:38 +0200322 prsts = read32((void *)(PMC_BASE_ADDRESS + PRSTS));
323 gen_pmcon1 = read32((void *)(PMC_BASE_ADDRESS + GEN_PMCON1));
Aaron Durbin19edc3a2014-01-09 11:17:37 -0600324
Shawn Nematbakhsh51d787a2014-01-16 17:52:21 -0800325 /* Clear the status bits. The RPS field is cleared on a 0 write. */
Angel Ponse80d17f2020-07-07 17:25:38 +0200326 write32((void *)(PMC_BASE_ADDRESS + GEN_PMCON1), gen_pmcon1 & ~RPS);
327 write32((void *)(PMC_BASE_ADDRESS + PRSTS), prsts);
Aaron Durbin19edc3a2014-01-09 11:17:37 -0600328}
Aaron Durbin64b4bdd2017-09-15 14:24:03 -0600329
330int rtc_failure(void)
331{
332 uint32_t gen_pmcon1;
333 int rtc_fail;
Kyösti Mälkki27872372021-01-21 16:05:26 +0200334 struct chipset_power_state *ps = acpi_get_pm_state();
Aaron Durbin64b4bdd2017-09-15 14:24:03 -0600335
336 if (ps != NULL)
337 gen_pmcon1 = ps->gen_pmcon1;
338 else
339 gen_pmcon1 = read32((u32 *)(PMC_BASE_ADDRESS + GEN_PMCON1));
340
341 rtc_fail = !!(gen_pmcon1 & RPS);
Aaron Durbin64b4bdd2017-09-15 14:24:03 -0600342 if (rtc_fail)
343 printk(BIOS_DEBUG, "RTC failure.\n");
344
345 return rtc_fail;
346}
Aaron Durbin0990fbf2017-09-15 15:23:04 -0600347
348int vbnv_cmos_failed(void)
349{
350 return rtc_failure();
351}
Joel Kitching1d93b882018-09-26 17:58:14 +0800352
Bill XIE516c0a52020-02-24 23:08:35 +0800353int platform_is_resuming(void)
Joel Kitching1d93b882018-09-26 17:58:14 +0800354{
355 if (!(inw(ACPI_BASE_ADDRESS + PM1_STS) & WAK_STS))
356 return 0;
357
358 return acpi_sleep_from_pm1(inl(ACPI_BASE_ADDRESS + PM1_CNT)) == ACPI_S3;
359}