coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
pmutil.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #define __SIMPLE_DEVICE__
4 
5 #include <stdint.h>
6 #include <acpi/acpi.h>
7 #include <acpi/acpi_pm.h>
8 #include <arch/io.h>
9 #include <bootmode.h>
10 #include <device/device.h>
11 #include <device/mmio.h>
12 #include <device/pci.h>
13 #include <device/pci_ops.h>
14 #include <console/console.h>
15 
16 #include <soc/iomap.h>
17 #include <soc/lpc.h>
18 #include <soc/pci_devs.h>
19 #include <soc/pm.h>
20 #include <security/vboot/vbnv.h>
21 
23 {
24  return pci_read_config16(PCI_DEV(0, PCU_DEV, 0), ABASE) & 0xfff8;
25 }
26 
27 static void print_num_status_bits(int num_bits, uint32_t status, const char *const bit_names[])
28 {
29  int i;
30 
31  if (!status)
32  return;
33 
34  for (i = num_bits - 1; i >= 0; i--) {
35  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 
45 {
46  static const char *const smi_sts_bits[] = {
47  [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: ");
70  print_num_status_bits(30, smi_sts, smi_sts_bits);
71  printk(BIOS_DEBUG, "\n");
72 
73  return smi_sts;
74 }
75 
77 {
79  uint32_t smi_sts = inl(pmbase + SMI_STS);
80  outl(smi_sts, pmbase + SMI_STS);
81  return smi_sts;
82 }
83 
85 {
87 }
88 
90 {
92  uint32_t smi_en = inl(pmbase + SMI_EN);
93  smi_en |= mask;
94  outl(smi_en, pmbase + SMI_EN);
95 }
96 
98 {
100  uint32_t smi_en = inl(pmbase + SMI_EN);
101  smi_en &= ~mask;
102  outl(smi_en, pmbase + SMI_EN);
103 }
104 
106 {
108  uint32_t pm1_cnt = inl(pmbase + PM1_CNT);
109  pm1_cnt |= mask;
110  outl(pm1_cnt, pmbase + PM1_CNT);
111 }
112 
114 {
116  uint32_t pm1_cnt = inl(pmbase + PM1_CNT);
117  pm1_cnt &= ~mask;
118  outl(pm1_cnt, pmbase + PM1_CNT);
119 }
120 
122 {
124  uint16_t pm1_sts = inw(pmbase + PM1_STS);
125  outw(pm1_sts, pmbase + PM1_STS);
126  return pm1_sts;
127 }
128 
130 {
131  static const char *const pm1_sts_bits[] = {
132  [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: ");
146  print_num_status_bits(16, pm1_sts, pm1_sts_bits);
147  printk(BIOS_SPEW, "\n");
148 
149  return pm1_sts;
150 }
151 
153 {
155 }
156 
157 void enable_pm1(uint16_t events)
158 {
159  outw(events, get_pmbase() + PM1_EN);
160 }
161 
163 {
164  static const char *const tco_sts_bits[] = {
165  [3] = "TIMEOUT",
166  [17] = "SECOND_TO",
167  };
168 
169  if (!tco_sts)
170  return 0;
171 
172  printk(BIOS_DEBUG, "TCO_STS: ");
173  print_num_status_bits(18, tco_sts, tco_sts_bits);
174  printk(BIOS_DEBUG, "\n");
175 
176  return tco_sts;
177 }
178 
180 {
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 
190 {
192 }
193 
195 {
197  uint32_t gpe0_en = inl(pmbase + GPE0_EN);
198  gpe0_en |= mask;
199  outl(gpe0_en, pmbase + GPE0_EN);
200 }
201 
203 {
205  uint32_t gpe0_en = inl(pmbase + GPE0_EN);
206  gpe0_en &= ~mask;
207  outl(gpe0_en, pmbase + GPE0_EN);
208 }
209 
210 void disable_all_gpe(void)
211 {
212  disable_gpe(~0);
213 }
214 
216 {
218  uint32_t gpe_sts = inl(pmbase + GPE0_STS);
219  outl(gpe_sts, pmbase + GPE0_STS);
220  return gpe_sts;
221 }
222 
224 {
225  static const char *const gpe_sts_bits[] = {
226  [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: ");
259  print_num_status_bits(32, gpe_sts, gpe_sts_bits);
260  printk(BIOS_DEBUG, "\n");
261 
262  return gpe_sts;
263 }
264 
266 {
268 }
269 
271 {
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 
278 static uint32_t print_alt_sts(uint32_t alt_gpio_smi)
279 {
280  uint32_t alt_gpio_sts;
281  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",
292  [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 
313 {
315 }
316 
318 {
319  uint32_t prsts;
320  uint32_t gen_pmcon1;
321 
322  prsts = read32((void *)(PMC_BASE_ADDRESS + PRSTS));
323  gen_pmcon1 = read32((void *)(PMC_BASE_ADDRESS + GEN_PMCON1));
324 
325  /* Clear the status bits. The RPS field is cleared on a 0 write. */
326  write32((void *)(PMC_BASE_ADDRESS + GEN_PMCON1), gen_pmcon1 & ~RPS);
327  write32((void *)(PMC_BASE_ADDRESS + PRSTS), prsts);
328 }
329 
330 int rtc_failure(void)
331 {
332  uint32_t gen_pmcon1;
333  int rtc_fail;
334  struct chipset_power_state *ps = acpi_get_pm_state();
335 
336  if (ps != NULL)
337  gen_pmcon1 = ps->gen_pmcon1;
338  else
340 
341  rtc_fail = !!(gen_pmcon1 & RPS);
342  if (rtc_fail)
343  printk(BIOS_DEBUG, "RTC failure.\n");
344 
345  return rtc_fail;
346 }
347 
349 {
350  return rtc_failure();
351 }
352 
354 {
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 }
struct chipset_power_state * acpi_get_pm_state(void)
Definition: acpi_pm.c:31
#define PM1_EN
Definition: pm.h:21
#define SMI_STS
Definition: pm.h:50
#define GPE0_STS(x)
Definition: pm.h:81
#define PM1_STS
Definition: pm.h:12
#define GPE0_EN(x)
Definition: pm.h:99
#define PM1_CNT
Definition: pm.h:27
#define SMI_EN
Definition: pm.h:32
#define GEN_PMCON1
Definition: pm.h:154
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
#define ALT_GPIO_SMI
Definition: pm.h:220
#define TCO_STS
Definition: pm.h:226
#define WAK_STS
Definition: southbridge.h:27
#define printk(level,...)
Definition: stdlib.h:16
u16 inw(u16 port)
u32 inl(u16 port)
void outl(u32 val, u16 port)
void outw(u16 val, u16 port)
#define RPS
Definition: i440bx.h:45
@ ACPI_S3
Definition: acpi.h:1383
static __always_inline u16 pci_read_config16(const struct device *dev, u16 reg)
Definition: pci_ops.h:52
#define ACPI_BASE_ADDRESS
Definition: iomap.h:99
#define PRSTS
Definition: pmc.h:77
#define ABASE
Definition: pmc.h:11
#define PMC_BASE_ADDRESS
Definition: iomap.h:15
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_SPEW
BIOS_SPEW - Excessively verbose output.
Definition: loglevel.h:142
#define PCI_DEV(SEGBUS, DEV, FN)
Definition: pci_type.h:14
#define PCU_DEV
Definition: pci_devs.h:121
int platform_is_resuming(void)
Definition: pmutil.c:8
uint16_t get_pmbase(void)
Definition: pmutil.c:254
int vbnv_cmos_failed(void)
Definition: pmutil.c:184
#define TCO1_CNT
Definition: smbus.h:12
void enable_pm1(uint16_t events)
Definition: pmutil.c:157
uint16_t clear_pm1_status(void)
Definition: pmutil.c:152
static uint16_t reset_pm1_status(void)
Definition: pmutil.c:121
static uint32_t reset_gpe_status(void)
Definition: pmutil.c:215
void enable_pm1_control(uint32_t mask)
Definition: pmutil.c:105
static uint16_t print_pm1_status(uint16_t pm1_sts)
Definition: pmutil.c:129
uint32_t clear_alt_status(void)
Definition: pmutil.c:312
static uint32_t reset_smi_status(void)
Definition: pmutil.c:76
void disable_smi(uint32_t mask)
Definition: pmutil.c:97
void enable_smi(uint32_t mask)
Definition: pmutil.c:89
void enable_gpe(uint32_t mask)
Definition: pmutil.c:194
void clear_pmc_status(void)
Definition: pmutil.c:317
static uint32_t reset_alt_status(void)
Definition: pmutil.c:270
static void print_num_status_bits(int num_bits, uint32_t status, const char *const bit_names[])
Definition: pmutil.c:27
uint32_t clear_gpe_status(void)
Definition: pmutil.c:265
static uint32_t print_tco_status(uint32_t tco_sts)
Definition: pmutil.c:162
void disable_pm1_control(uint32_t mask)
Definition: pmutil.c:113
static uint32_t reset_tco_status(void)
Definition: pmutil.c:179
void disable_all_gpe(void)
Definition: pmutil.c:210
uint32_t clear_tco_status(void)
Definition: pmutil.c:189
static uint32_t print_gpe_sts(uint32_t gpe_sts)
Definition: pmutil.c:223
uint32_t clear_smi_status(void)
Definition: pmutil.c:84
static uint32_t print_smi_status(uint32_t smi_sts)
Definition: pmutil.c:44
int rtc_failure(void)
Definition: pmutil.c:330
static uint32_t print_alt_sts(uint32_t alt_gpio_smi)
Definition: pmutil.c:278
void disable_gpe(uint32_t mask)
Definition: pmutil.c:202
static const int mask[4]
Definition: gpio.c:308
static u16 pmbase
Definition: smi.c:27
#define NULL
Definition: stddef.h:19
unsigned short uint16_t
Definition: stdint.h:11
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
uint32_t gen_pmcon1
Definition: pm.h:231