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 <arch/io.h>
7 #include <console/console.h>
8 #include <device/pci.h>
9 #include <intelblocks/pmclib.h>
10 #include <soc/iomap.h>
11 #include <soc/pci_devs.h>
12 #include <soc/pm.h>
13 #include <soc/soc_util.h>
14 
15 static void print_num_status_bits(int num_bits, uint32_t status,
16  const char *const bit_names[])
17 {
18  int i;
19 
20  if (!status)
21  return;
22 
23  for (i = num_bits - 1; i >= 0; i--) {
24  if (status & (1 << i)) {
25  if (bit_names[i])
26  printk(BIOS_DEBUG, "%s ", bit_names[i]);
27  else
28  printk(BIOS_DEBUG, "BIT%d ", i);
29  }
30  }
31 }
32 
34 {
35  static const char *const smi_sts_bits[] = {
36  [2] = "BIOS",
37  [4] = "SLP_SMI",
38  [5] = "APM",
39  [6] = "SWSMI_TMR",
40  [8] = "PM1",
41  [9] = "GPE0",
42  [10] = "GPE1",
43  [11] = "MC_SMI",
44  [12] = "DEVMON",
45  [13] = "TCO",
46  [14] = "PERIODIC",
47  [15] = "SERIRQ",
48  [16] = "SMBUS_SMI",
49  [17] = "LEGACY_USB2",
50  [18] = "INTEL_USB2",
51  [19] = "PATCH",
52  [20] = "PCI_EXP_SMI",
53  [21] = "MONITOR",
54  [26] = "SPI",
55  [27] = "GPIO_UNLOCK",
56  [31] = "LEGACY_USB3",
57  };
58 
59  if (!smi_sts)
60  return 0;
61 
62  printk(BIOS_DEBUG, "SMI_STS: ");
63  print_num_status_bits(ARRAY_SIZE(smi_sts_bits), smi_sts, smi_sts_bits);
64  printk(BIOS_DEBUG, "\n");
65 
66  return smi_sts;
67 }
68 
70 {
72  uint32_t smi_sts = inl((uint16_t)(pmbase + SMI_STS));
73  outl(smi_sts, (uint16_t)(pmbase + SMI_STS));
74  return smi_sts;
75 }
76 
78 
80 {
82  uint32_t smi_en = inl((uint16_t)(pmbase + SMI_EN));
83  smi_en |= mask;
84  outl(smi_en, (uint16_t)(pmbase + SMI_EN));
85 }
86 
88 {
89  uint32_t reg32;
90 
92 
93  /* 4KiB alignment. */
94  reg32 &= ~0xfff;
95 
96  return (void *)(uintptr_t) reg32;
97 }
98 
100 {
102  uint32_t smi_en = inl((uint16_t)(pmbase + SMI_EN));
103  smi_en &= ~mask;
104  outl(smi_en, (uint16_t)(pmbase + SMI_EN));
105 }
106 
108 {
110  uint32_t pm1_cnt = inl((uint16_t)(pmbase + PM1_CNT));
111  pm1_cnt |= mask;
112  outl(pm1_cnt, (uint16_t)(pmbase + PM1_CNT));
113 }
114 
116 {
118  uint32_t pm1_cnt = inl((uint16_t)(pmbase + PM1_CNT));
119  pm1_cnt &= ~mask;
120  outl(pm1_cnt, (uint16_t)(pmbase + PM1_CNT));
121 }
122 
124 {
126  uint16_t pm1_sts = inw((uint16_t)(pmbase + PM1_STS));
127  outw(pm1_sts, (uint16_t)(pmbase + PM1_STS));
128  return pm1_sts;
129 }
130 
132 {
133  static const char *const pm1_sts_bits[] = {
134  [0] = "TMROF", [4] = "BM", [5] = "GBL",
135  [8] = "PWRBTN", [10] = "RTC", [11] = "PRBTNOR",
136  [15] = "WAK",
137  };
138 
139  if (!pm1_sts)
140  return 0;
141 
142  printk(BIOS_DEBUG, "PM1_STS: ");
143  print_num_status_bits(ARRAY_SIZE(pm1_sts_bits), pm1_sts, pm1_sts_bits);
144  printk(BIOS_DEBUG, "\n");
145 
146  return pm1_sts;
147 }
148 
150 
151 void enable_pm1(uint16_t events)
152 {
154  outw(events, (uint16_t)(pmbase + PM1_EN));
155 }
156 
158 {
159  static const char *const tco_sts_bits[] = {
160  [0] = "NMI2SMI", [1] = "OS_TCO_SMI",
161  [2] = "TCO_INIT", [3] = "TIMEOUT",
162  [7] = "NEWCENTURY ", [8] = "BIOSWR ",
163  [9] = "CPUSCI ", [10] = "CPUSMI ",
164  [12] = "CPUSERR ", [16] = "INTRD_DET ",
165  [17] = "SECOND_TO", [20] = "SMLINK_SLV_SMI",
166  };
167 
168  if (!tco_sts)
169  return 0;
170 
171  printk(BIOS_DEBUG, "TCO_STS: ");
172  print_num_status_bits(ARRAY_SIZE(tco_sts_bits), tco_sts, tco_sts_bits);
173  printk(BIOS_DEBUG, "\n");
174 
175  return tco_sts;
176 }
177 
179 {
180  uint16_t tcobase = get_tcobase();
181  uint32_t tco_sts = inl((uint16_t)(tcobase + TCO1_STS));
182  uint32_t tco_en = inl((uint16_t)(tcobase + TCO1_CNT));
183 
184  outl(tco_sts, (uint16_t)(tcobase + TCO1_STS));
185  return tco_sts & tco_en;
186 }
187 
189 
191 {
193  uint32_t gpe0_en = inl((uint16_t)(pmbase + GPE0_EN(GPE_STD)));
194  gpe0_en |= mask;
195  outl(gpe0_en, (uint16_t)(pmbase + GPE0_EN(GPE_STD)));
196 }
197 
199 {
201  uint32_t gpe0_en = inl((uint16_t)(pmbase + GPE0_EN(GPE_STD)));
202  gpe0_en &= ~mask;
203  outl(gpe0_en, (uint16_t)(pmbase + GPE0_EN(GPE_STD)));
204 }
205 
206 void disable_all_gpe(void) { disable_gpe(~0); }
207 
209 {
211  uint32_t gpe_sts = inl((uint16_t)(pmbase + GPE0_STS(GPE_STD)));
212  outl(gpe_sts, (uint16_t)(pmbase + GPE0_STS(GPE_STD)));
213  return gpe_sts;
214 }
215 
217 {
218  static const char *const gpe_sts_bits[] = {
219  [0] = "GPIO_0", [1] = "GPIO_1",
220  [2] = "GPIO_2", [3] = "GPIO_3",
221  [4] = "GPIO_4", [5] = "GPIO_5",
222  [6] = "GPIO_6", [7] = "GPIO_7",
223  [8] = "GPIO_8", [9] = "GPIO_9",
224  [10] = "GPIO_10", [11] = "GPIO_11",
225  [12] = "GPIO_12", [13] = "GPIO_13",
226  [14] = "GPIO_14", [15] = "GPIO_15",
227  [16] = "GPIO_16", [17] = "GPIO_17",
228  [18] = "GPIO_18", [19] = "GPIO_19",
229  [20] = "GPIO_20", [21] = "GPIO_21",
230  [22] = "GPIO_22", [23] = "GPIO_23",
231  [24] = "GPIO_24", [25] = "GPIO_25",
232  [26] = "GPIO_26", [27] = "GPIO_27",
233  [28] = "GPIO_28", [29] = "GPIO_29",
234  [30] = "GPIO_30", [31] = "GPIO_31",
235  };
236 
237  if (!gpe_sts)
238  return gpe_sts;
239 
240  printk(BIOS_DEBUG, "GPE0a_STS: ");
241  print_num_status_bits(ARRAY_SIZE(gpe_sts_bits), gpe_sts, gpe_sts_bits);
242  printk(BIOS_DEBUG, "\n");
243 
244  return gpe_sts;
245 }
246 
248 
249 void clear_pmc_status(void) { /* TODO */ }
#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 GPE_STD
Definition: pm.h:85
#define GPE0_EN(x)
Definition: pm.h:99
#define PM1_CNT
Definition: pm.h:27
#define SMI_EN
Definition: pm.h:32
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#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)
static __always_inline u32 pci_read_config32(const struct device *dev, u16 reg)
Definition: pci_ops.h:58
#define PMC_PWRM_BASE
Definition: pmc.h:33
uint16_t get_tcobase(void)
Definition: soc_util.c:200
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define PCH_DEV_PMC
Definition: pci_devs.h:236
uint16_t get_pmbase(void)
Definition: pmutil.c:254
uint8_t * pmc_mmio_regs(void)
Definition: pmutil.c:142
#define TCO1_CNT
Definition: smbus.h:12
#define TCO1_STS
Definition: smbus.h:7
void enable_pm1(uint16_t events)
Definition: pmutil.c:157
uint16_t clear_pm1_status(void)
Definition: pmutil.c:152
void enable_pm1_control(uint32_t mask)
Definition: pmutil.c:105
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
uint32_t clear_gpe_status(void)
Definition: pmutil.c:265
void disable_pm1_control(uint32_t mask)
Definition: pmutil.c:113
void disable_all_gpe(void)
Definition: pmutil.c:210
uint32_t clear_tco_status(void)
Definition: pmutil.c:189
uint32_t clear_smi_status(void)
Definition: pmutil.c:84
void disable_gpe(uint32_t mask)
Definition: pmutil.c:202
static const int mask[4]
Definition: gpio.c:308
static uint16_t reset_pm1_status(void)
Definition: pmutil.c:123
static uint32_t reset_gpe_status(void)
Definition: pmutil.c:208
static uint16_t print_pm1_status(uint16_t pm1_sts)
Definition: pmutil.c:131
static uint32_t reset_smi_status(void)
Definition: pmutil.c:69
static void print_num_status_bits(int num_bits, uint32_t status, const char *const bit_names[])
Definition: pmutil.c:15
static uint32_t print_tco_status(uint32_t tco_sts)
Definition: pmutil.c:157
static uint32_t reset_tco_status(void)
Definition: pmutil.c:178
static uint32_t print_gpe_sts(uint32_t gpe_sts)
Definition: pmutil.c:216
static uint32_t print_smi_status(uint32_t smi_sts)
Definition: pmutil.c:33
static u16 pmbase
Definition: smi.c:27
unsigned short uint16_t
Definition: stdint.h:11
unsigned int uint32_t
Definition: stdint.h:14
unsigned long uintptr_t
Definition: stdint.h:21
unsigned char uint8_t
Definition: stdint.h:8