coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
acpi.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <acpi/acpi.h>
4 #include <acpi/acpi_gnvs.h>
5 #include <acpi/acpi_pm.h>
6 #include <acpi/acpigen.h>
7 #include <arch/cpu.h>
8 #include <arch/ioapic.h>
9 #include <arch/smp/mpspec.h>
10 #include <console/console.h>
12 #include <intelblocks/acpi.h>
14 #include <intelblocks/cpulib.h>
15 #include <intelblocks/pmclib.h>
16 #include <soc/cpu.h>
17 #include <soc/msr.h>
18 #include <soc/pm.h>
19 #include <soc/ramstage.h>
20 #include <soc/systemagent.h>
21 #include <string.h>
22 #include <types.h>
23 
24 #include "chip.h"
25 
26 /*
27  * List of supported C-states in this processor.
28  */
29 enum {
30  C_STATE_C0, /* 0 */
31  C_STATE_C1, /* 1 */
32  C_STATE_C1E, /* 2 */
33  C_STATE_C3, /* 3 */
40  C_STATE_C8, /* 10 */
41  C_STATE_C9, /* 11 */
42  C_STATE_C10, /* 12 */
44 };
45 #define MWAIT_RES(state, sub_state) \
46  { \
47  .addrl = (((state) << 4) | (sub_state)), \
48  .space_id = ACPI_ADDRESS_SPACE_FIXED, \
49  .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, \
50  .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, \
51  .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD, \
52  }
53 
55  [C_STATE_C0] = { },
56  [C_STATE_C1] = {
57  .latency = 0,
58  .power = C1_POWER,
59  .resource = MWAIT_RES(0, 0),
60  },
61  [C_STATE_C1E] = {
62  .latency = 0,
63  .power = C1_POWER,
64  .resource = MWAIT_RES(0, 1),
65  },
66  [C_STATE_C3] = {
67  .latency = C_STATE_LATENCY_FROM_LAT_REG(0),
68  .power = C3_POWER,
69  .resource = MWAIT_RES(1, 0),
70  },
72  .latency = C_STATE_LATENCY_FROM_LAT_REG(1),
73  .power = C6_POWER,
74  .resource = MWAIT_RES(2, 0),
75  },
77  .latency = C_STATE_LATENCY_FROM_LAT_REG(2),
78  .power = C6_POWER,
79  .resource = MWAIT_RES(2, 1),
80  },
82  .latency = C_STATE_LATENCY_FROM_LAT_REG(1),
83  .power = C7_POWER,
84  .resource = MWAIT_RES(3, 0),
85  },
87  .latency = C_STATE_LATENCY_FROM_LAT_REG(2),
88  .power = C7_POWER,
89  .resource = MWAIT_RES(3, 1),
90  },
92  .latency = C_STATE_LATENCY_FROM_LAT_REG(1),
93  .power = C7_POWER,
94  .resource = MWAIT_RES(3, 2),
95  },
97  .latency = C_STATE_LATENCY_FROM_LAT_REG(2),
98  .power = C7_POWER,
99  .resource = MWAIT_RES(3, 3),
100  },
101  [C_STATE_C8] = {
102  .latency = C_STATE_LATENCY_FROM_LAT_REG(3),
103  .power = C8_POWER,
104  .resource = MWAIT_RES(4, 0),
105  },
106  [C_STATE_C9] = {
107  .latency = C_STATE_LATENCY_FROM_LAT_REG(4),
108  .power = C9_POWER,
109  .resource = MWAIT_RES(5, 0),
110  },
111  [C_STATE_C10] = {
112  .latency = C_STATE_LATENCY_FROM_LAT_REG(5),
113  .power = C10_POWER,
114  .resource = MWAIT_RES(6, 0),
115  },
116 };
117 
118 static int cstate_set_s0ix[] = {
119  C_STATE_C1E,
122 };
123 
124 static int cstate_set_non_s0ix[] = {
125  C_STATE_C1E,
126  C_STATE_C3,
128 };
129 
130 const acpi_cstate_t *soc_get_cstate_map(size_t *entries)
131 {
134  int *set;
135  int i;
136 
138 
139  int is_s0ix_enable = config->s0ix_enable;
140 
141  if (is_s0ix_enable) {
142  *entries = ARRAY_SIZE(cstate_set_s0ix);
143  set = cstate_set_s0ix;
144  } else {
145  *entries = ARRAY_SIZE(cstate_set_non_s0ix);
146  set = cstate_set_non_s0ix;
147  }
148 
149  for (i = 0; i < *entries; i++) {
150  memcpy(&map[i], &cstate_map[set[i]], sizeof(acpi_cstate_t));
151  map[i].ctype = i + 1;
152  }
153  return map;
154 }
155 
156 void soc_power_states_generation(int core_id, int cores_per_package)
157 {
159 
160  /* Generate P-state tables */
161  if (config->eist_enable)
162  generate_p_state_entries(core_id, cores_per_package);
163 }
164 
166 {
167  return read32p(soc_read_pmc_base() + IRQ_REG);
168 }
169 
171 {
173 
174  /* Enable DPTF based on mainboard configuration */
175  gnvs->dpte = config->dptf_enable;
176 
177  /* Set USB2/USB3 wake enable bitmaps. */
178  gnvs->u2we = config->usb2_wake_enable_bitmap;
179  gnvs->u3we = config->usb3_wake_enable_bitmap;
180 
181  /* Fill in Above 4GB MMIO resource */
183 }
184 
185 static unsigned long soc_fill_dmar(unsigned long current)
186 {
187  const u32 gfx_vtbar = MCHBAR32(GFXVTBAR) & ~0xfff;
188  const bool gfxvten = MCHBAR32(GFXVTBAR) & 1;
189 
190  /* iGFX has to be enabled, GFXVTBAR set and in 32-bit space. */
191  const bool emit_igd =
193  gfx_vtbar && gfxvten &&
194  !MCHBAR32(GFXVTBAR + 4);
195 
196  /* First, add DRHD entries */
197  if (emit_igd) {
198  const unsigned long tmp = current;
199 
200  current += acpi_create_dmar_drhd(current, 0, 0, gfx_vtbar);
201  current += acpi_create_dmar_ds_pci(current, 0, 2, 0);
202 
203  acpi_dmar_drhd_fixup(tmp, current);
204  }
205 
206  const u32 vtvc0bar = MCHBAR32(VTVC0BAR) & ~0xfff;
207  const bool vtvc0en = MCHBAR32(VTVC0BAR) & 1;
208 
209  /* General VTBAR has to be set and in 32-bit space. */
210  if (vtvc0bar && vtvc0en && !MCHBAR32(VTVC0BAR + 4)) {
211  const unsigned long tmp = current;
212 
213  current += acpi_create_dmar_drhd(current, DRHD_INCLUDE_PCI_ALL, 0, vtvc0bar);
214 
215  current += acpi_create_dmar_ds_ioapic(current, 2, V_P2SB_IBDF_BUS,
217 
218  current += acpi_create_dmar_ds_msi_hpet(current, 0, V_P2SB_HBDF_BUS,
220 
221  acpi_dmar_drhd_fixup(tmp, current);
222  }
223 
224  /* Then, add RMRR entries after all DRHD entries */
225  if (emit_igd) {
226  const unsigned long tmp = current;
227 
228  current += acpi_create_dmar_rmrr(current, 0,
230  current += acpi_create_dmar_ds_pci(current, 0, 2, 0);
231  acpi_dmar_rmrr_fixup(tmp, current);
232  }
233 
234  return current;
235 }
236 
237 unsigned long sa_write_acpi_tables(const struct device *const dev,
238  unsigned long current,
239  struct acpi_rsdp *const rsdp)
240 {
241  acpi_dmar_t *const dmar = (acpi_dmar_t *)current;
242 
243  /* Create DMAR table only if we have VT-d capability. */
244  if (!soc_vtd_enabled())
245  return current;
246 
247  printk(BIOS_DEBUG, "ACPI: * DMAR\n");
249  current += dmar->header.length;
250  current = acpi_align_current(current);
251  acpi_add_table(rsdp, dmar);
252 
253  return current;
254 }
255 
257 {
258  if (sci >= 20)
259  return MP_IRQ_POLARITY_LOW;
260  else
261  return MP_IRQ_POLARITY_HIGH;
262 }
263 
264 void acpi_fill_soc_wake(uint32_t *pm1_en, uint32_t *gpe0_en,
265  const struct chipset_power_state *ps)
266 {
268 
269  if (ps->prev_sleep_state == ACPI_S3 && deep_s3_enabled()) {
270  if (config->deep_sx_config & DSX_EN_LAN_WAKE_PIN)
271  gpe0_en[GPE_STD] |= LAN_WAK_EN;
272  if (config->deep_sx_config & DSX_EN_WAKE_PIN)
273  *pm1_en |= PCIEXPWAK_STS;
274  }
275 }
unsigned long acpi_create_dmar_ds_ioapic(unsigned long current, u8 enumeration_id, u8 bus, u8 dev, u8 fn)
Definition: acpi.c:775
unsigned long acpi_create_dmar_rmrr(unsigned long current, u16 segment, u64 bar, u64 limit)
Definition: acpi.c:652
void acpi_dmar_drhd_fixup(unsigned long base, unsigned long current)
Definition: acpi.c:719
void acpi_add_table(acpi_rsdp_t *rsdp, void *table)
Add an ACPI table to the RSDT (and XSDT) structure, recalculate length and checksum.
Definition: acpi.c:49
unsigned long acpi_create_dmar_ds_msi_hpet(unsigned long current, u8 enumeration_id, u8 bus, u8 dev, u8 fn)
Definition: acpi.c:782
unsigned long acpi_create_dmar_ds_pci(unsigned long current, u8 bus, u8 dev, u8 fn)
Definition: acpi.c:768
void acpi_create_dmar(acpi_dmar_t *dmar, enum dmar_flags flags, unsigned long(*acpi_fill_dmar)(unsigned long))
Definition: acpi.c:607
void acpi_dmar_rmrr_fixup(unsigned long base, unsigned long current)
Definition: acpi.c:725
unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags, u16 segment, u64 bar)
Definition: acpi.c:638
#define GPE_STD
Definition: pm.h:85
void * memcpy(void *dest, const void *src, size_t n)
Definition: memcpy.c:7
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define MAX(a, b)
Definition: helpers.h:40
#define PCIEXPWAK_STS
Definition: southbridge.h:28
#define MCHBAR32(x)
Definition: systemagent.h:23
void sa_fill_gnvs(struct global_nvs *gnvs)
Definition: systemagent.c:140
uintptr_t sa_get_tolud_base(void)
uintptr_t sa_get_gsm_base(void)
#define printk(level,...)
Definition: stdlib.h:16
#define C_STATE_LATENCY_FROM_LAT_REG(reg)
Definition: haswell.h:119
bool is_devfn_enabled(unsigned int devfn)
Definition: device_const.c:382
#define VTVC0BAR
Definition: mchbar.h:20
#define GFXVTBAR
Definition: mchbar.h:18
static uintptr_t acpi_align_current(uintptr_t current)
Definition: acpi.h:1435
@ DRHD_INCLUDE_PCI_ALL
Definition: acpi.h:515
@ DMAR_INTR_REMAP
Definition: acpi.h:523
@ ACPI_S3
Definition: acpi.h:1383
#define config_of_soc()
Definition: device.h:394
static __always_inline uint32_t read32p(const uintptr_t addr)
Definition: mmio.h:220
#define DSX_EN_LAN_WAKE_PIN
Definition: pmc.h:100
#define IRQ_REG
Definition: pmc.h:142
#define DSX_EN_WAKE_PIN
Definition: pmc.h:98
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
enum board_config config
Definition: memory.c:448
#define MP_IRQ_POLARITY_LOW
Definition: mpspec.h:125
#define MP_IRQ_POLARITY_HIGH
Definition: mpspec.h:124
#define LAN_WAK_EN
Definition: pm.h:110
#define V_P2SB_HBDF_BUS
Definition: systemagent.h:56
#define V_P2SB_HBDF_DEV
Definition: systemagent.h:57
#define V_P2SB_HBDF_FUN
Definition: systemagent.h:58
#define V_P2SB_IBDF_BUS
Definition: systemagent.h:51
#define V_P2SB_IBDF_DEV
Definition: systemagent.h:52
bool soc_vtd_enabled(void)
Definition: systemagent.c:18
#define V_P2SB_IBDF_FUN
Definition: systemagent.h:53
struct global_nvs * gnvs
const acpi_cstate_t * soc_get_cstate_map(size_t *entries)
Definition: acpi.c:113
@ C_STATE_C0
Definition: acpi.c:27
@ C_STATE_C7S_LONG_LAT
Definition: acpi.c:35
@ C_STATE_C1E
Definition: acpi.c:29
@ C_STATE_C7S_SHORT_LAT
Definition: acpi.c:34
@ C_STATE_C7_LONG_LAT
Definition: acpi.c:33
@ C_STATE_C6_LONG_LAT
Definition: acpi.c:31
@ C_STATE_C9
Definition: acpi.c:37
@ C_STATE_C10
Definition: acpi.c:38
@ C_STATE_C7_SHORT_LAT
Definition: acpi.c:32
@ C_STATE_C1
Definition: acpi.c:28
@ C_STATE_C8
Definition: acpi.c:36
@ NUM_C_STATES
Definition: acpi.c:39
@ C_STATE_C6_SHORT_LAT
Definition: acpi.c:30
unsigned long sa_write_acpi_tables(const struct device *dev, unsigned long current, struct acpi_rsdp *rsdp)
Definition: acpi.c:245
int soc_madt_sci_irq_polarity(int sci)
Definition: acpi.c:282
void soc_power_states_generation(int core_id, int cores_per_package)
Definition: acpi.c:139
void soc_fill_gnvs(struct global_nvs *gnvs)
Definition: acpi.c:267
uint32_t soc_read_sci_irq_select(void)
Definition: acpi.c:167
#define C7_POWER
Definition: cpu.h:17
#define C1_POWER
Definition: cpu.h:15
#define C6_POWER
Definition: cpu.h:16
#define C9_POWER
Definition: cpu.h:19
#define C10_POWER
Definition: cpu.h:20
#define C8_POWER
Definition: cpu.h:18
#define SA_DEVFN_IGD
Definition: pci_devs.h:32
static int deep_s3_enabled(void)
Definition: pmutil.c:189
uintptr_t soc_read_pmc_base(void)
Definition: pmutil.c:147
void generate_p_state_entries(int core, int cores_per_package)
Definition: acpi.c:259
__weak void acpi_fill_soc_wake(uint32_t *pm1_en, uint32_t *gpe0_en, const struct chipset_power_state *ps)
Definition: acpi.c:185
static unsigned long soc_fill_dmar(unsigned long current)
Definition: acpi.c:185
static int cstate_set_non_s0ix[]
Definition: acpi.c:124
#define MWAIT_RES(state, sub_state)
Definition: acpi.c:45
@ C_STATE_C3
Definition: acpi.c:33
static int cstate_set_s0ix[]
Definition: acpi.c:118
static acpi_cstate_t cstate_map[NUM_C_STATES]
Definition: acpi.c:54
#define C3_POWER
Definition: cpu.h:18
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
u8 ctype
Definition: acpi.h:984
u16 latency
Definition: acpi.h:985
acpi_header_t header
Definition: acpi.h:580
Definition: acpi.h:82
uint32_t prev_sleep_state
Definition: pm.h:153
Definition: device.h:107
Definition: nvs.h:14
u16 u2we
Definition: nvs.h:24
u16 u3we
Definition: nvs.h:25
uint8_t dpte
Definition: nvs.h:20