blob: 51fea18bf93544780767dcf4cc0f28af05b8fadc [file] [log] [blame]
Angel Pons3bd1e3d2020-04-05 15:47:17 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Lee Leahyb0005132015-05-12 18:19:47 -07002
Furquan Shaikh76cedd22020-05-02 10:24:23 -07003#include <acpi/acpi.h>
Kyösti Mälkki0c1dd9c2020-06-17 23:37:49 +03004#include <acpi/acpi_gnvs.h>
Kyösti Mälkki27872372021-01-21 16:05:26 +02005#include <acpi/acpi_pm.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -07006#include <acpi/acpigen.h>
robbie zhangb45dde02015-10-01 17:21:33 -07007#include <arch/cpu.h>
Duncan Lauriedb54a672015-09-04 14:19:35 -07008#include <arch/ioapic.h>
Lee Leahyb0005132015-05-12 18:19:47 -07009#include <arch/smp/mpspec.h>
Lee Leahyb0005132015-05-12 18:19:47 -070010#include <console/console.h>
11#include <cpu/x86/smm.h>
Lee Leahyb0005132015-05-12 18:19:47 -070012#include <cpu/x86/msr.h>
Matt Delco9084c3c2018-07-27 14:17:29 -070013#include <cpu/intel/common/common.h>
Lee Leahyb0005132015-05-12 18:19:47 -070014#include <cpu/intel/turbo.h>
Kyösti Mälkkica71e132021-01-15 05:06:35 +020015#include <intelblocks/acpi_wake_source.h>
Barnali Sarkar0a203d12017-05-04 18:02:17 +053016#include <intelblocks/cpulib.h>
Ravi Sarawadi1483d1f2017-09-28 17:06:01 -070017#include <intelblocks/lpc_lib.h>
Pratik Prajapati418535e2017-10-11 16:12:21 -070018#include <intelblocks/sgx.h>
Duncan Laurie93bbd412017-11-11 20:03:29 -080019#include <intelblocks/uart.h>
Nico Huberc37b0e32017-09-18 20:03:46 +020020#include <intelblocks/systemagent.h>
Lee Leahyb0005132015-05-12 18:19:47 -070021#include <soc/acpi.h>
22#include <soc/cpu.h>
23#include <soc/iomap.h>
Lee Leahyb0005132015-05-12 18:19:47 -070024#include <soc/msr.h>
Kyösti Mälkkid6c57142020-12-21 15:17:01 +020025#include <soc/nvs.h>
Lee Leahyb0005132015-05-12 18:19:47 -070026#include <soc/pci_devs.h>
27#include <soc/pm.h>
Naresh G Solankia2d40622016-08-30 20:47:13 +053028#include <soc/ramstage.h>
Nico Huberc37b0e32017-09-18 20:03:46 +020029#include <soc/systemagent.h>
robbie zhangb45dde02015-10-01 17:21:33 -070030#include <string.h>
31#include <types.h>
Patrick Rudolphe56189c2018-04-18 10:11:59 +020032#include <device/pci_ops.h>
Lee Leahyb0005132015-05-12 18:19:47 -070033
Elyes HAOUASc3385072019-03-21 15:38:06 +010034#include "chip.h"
35
Michael Niewöhnerd5a45472020-10-15 00:27:59 +020036#define CPUID_6_EAX_ISST (1 << 7)
37
Lee Leahyb0005132015-05-12 18:19:47 -070038/*
Lee Leahy1d14b3e2015-05-12 18:23:27 -070039 * List of suported C-states in this processor.
Lee Leahyb0005132015-05-12 18:19:47 -070040 */
41enum {
Lee Leahy1d14b3e2015-05-12 18:23:27 -070042 C_STATE_C0, /* 0 */
43 C_STATE_C1, /* 1 */
44 C_STATE_C1E, /* 2 */
45 C_STATE_C3, /* 3 */
46 C_STATE_C6_SHORT_LAT, /* 4 */
47 C_STATE_C6_LONG_LAT, /* 5 */
48 C_STATE_C7_SHORT_LAT, /* 6 */
49 C_STATE_C7_LONG_LAT, /* 7 */
50 C_STATE_C7S_SHORT_LAT, /* 8 */
51 C_STATE_C7S_LONG_LAT, /* 9 */
52 C_STATE_C8, /* 10 */
53 C_STATE_C9, /* 11 */
54 C_STATE_C10, /* 12 */
Lee Leahyb0005132015-05-12 18:19:47 -070055 NUM_C_STATES
56};
Lee Leahy1d14b3e2015-05-12 18:23:27 -070057#define MWAIT_RES(state, sub_state) \
58 { \
59 .addrl = (((state) << 4) | (sub_state)), \
60 .space_id = ACPI_ADDRESS_SPACE_FIXED, \
61 .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, \
62 .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, \
63 .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD, \
Lee Leahyb0005132015-05-12 18:19:47 -070064 }
65
66static acpi_cstate_t cstate_map[NUM_C_STATES] = {
67 [C_STATE_C0] = { },
68 [C_STATE_C1] = {
69 .latency = 0,
robbie zhangc16b1fd2015-09-11 14:25:15 -070070 .power = C1_POWER,
Lee Leahy1d14b3e2015-05-12 18:23:27 -070071 .resource = MWAIT_RES(0, 0),
Lee Leahyb0005132015-05-12 18:19:47 -070072 },
73 [C_STATE_C1E] = {
74 .latency = 0,
robbie zhangc16b1fd2015-09-11 14:25:15 -070075 .power = C1_POWER,
Lee Leahy1d14b3e2015-05-12 18:23:27 -070076 .resource = MWAIT_RES(0, 1),
Lee Leahyb0005132015-05-12 18:19:47 -070077 },
78 [C_STATE_C3] = {
79 .latency = C_STATE_LATENCY_FROM_LAT_REG(0),
robbie zhangc16b1fd2015-09-11 14:25:15 -070080 .power = C3_POWER,
Lee Leahyb0005132015-05-12 18:19:47 -070081 .resource = MWAIT_RES(1, 0),
82 },
83 [C_STATE_C6_SHORT_LAT] = {
84 .latency = C_STATE_LATENCY_FROM_LAT_REG(1),
robbie zhangc16b1fd2015-09-11 14:25:15 -070085 .power = C6_POWER,
Lee Leahyb0005132015-05-12 18:19:47 -070086 .resource = MWAIT_RES(2, 0),
87 },
88 [C_STATE_C6_LONG_LAT] = {
89 .latency = C_STATE_LATENCY_FROM_LAT_REG(2),
robbie zhangc16b1fd2015-09-11 14:25:15 -070090 .power = C6_POWER,
Lee Leahyb0005132015-05-12 18:19:47 -070091 .resource = MWAIT_RES(2, 1),
92 },
93 [C_STATE_C7_SHORT_LAT] = {
94 .latency = C_STATE_LATENCY_FROM_LAT_REG(1),
robbie zhangc16b1fd2015-09-11 14:25:15 -070095 .power = C7_POWER,
Lee Leahyb0005132015-05-12 18:19:47 -070096 .resource = MWAIT_RES(3, 0),
97 },
98 [C_STATE_C7_LONG_LAT] = {
99 .latency = C_STATE_LATENCY_FROM_LAT_REG(2),
robbie zhangc16b1fd2015-09-11 14:25:15 -0700100 .power = C7_POWER,
Lee Leahyb0005132015-05-12 18:19:47 -0700101 .resource = MWAIT_RES(3, 1),
102 },
103 [C_STATE_C7S_SHORT_LAT] = {
104 .latency = C_STATE_LATENCY_FROM_LAT_REG(1),
robbie zhangc16b1fd2015-09-11 14:25:15 -0700105 .power = C7_POWER,
Lee Leahyb0005132015-05-12 18:19:47 -0700106 .resource = MWAIT_RES(3, 2),
107 },
108 [C_STATE_C7S_LONG_LAT] = {
109 .latency = C_STATE_LATENCY_FROM_LAT_REG(2),
robbie zhangc16b1fd2015-09-11 14:25:15 -0700110 .power = C7_POWER,
Lee Leahyb0005132015-05-12 18:19:47 -0700111 .resource = MWAIT_RES(3, 3),
112 },
113 [C_STATE_C8] = {
114 .latency = C_STATE_LATENCY_FROM_LAT_REG(3),
robbie zhangc16b1fd2015-09-11 14:25:15 -0700115 .power = C8_POWER,
Lee Leahyb0005132015-05-12 18:19:47 -0700116 .resource = MWAIT_RES(4, 0),
117 },
118 [C_STATE_C9] = {
119 .latency = C_STATE_LATENCY_FROM_LAT_REG(4),
robbie zhangc16b1fd2015-09-11 14:25:15 -0700120 .power = C9_POWER,
Lee Leahyb0005132015-05-12 18:19:47 -0700121 .resource = MWAIT_RES(5, 0),
122 },
123 [C_STATE_C10] = {
124 .latency = C_STATE_LATENCY_FROM_LAT_REG(5),
robbie zhangc16b1fd2015-09-11 14:25:15 -0700125 .power = C10_POWER,
Lee Leahyb0005132015-05-12 18:19:47 -0700126 .resource = MWAIT_RES(6, 0),
127 },
128};
129
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700130static int cstate_set_s0ix[] = {
Lee Leahyb0005132015-05-12 18:19:47 -0700131 C_STATE_C1E,
132 C_STATE_C7S_LONG_LAT,
133 C_STATE_C10
134};
135
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700136static int cstate_set_non_s0ix[] = {
Lee Leahyb0005132015-05-12 18:19:47 -0700137 C_STATE_C1E,
138 C_STATE_C3,
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700139 C_STATE_C7S_LONG_LAT,
Lee Leahyb0005132015-05-12 18:19:47 -0700140};
141
142static int get_cores_per_package(void)
143{
144 struct cpuinfo_x86 c;
145 struct cpuid_result result;
146 int cores = 1;
147
148 get_fms(&c, cpuid_eax(1));
149 if (c.x86 != 6)
150 return 1;
151
152 result = cpuid_ext(0xb, 1);
153 cores = result.ebx & 0xff;
154
155 return cores;
156}
157
Kyösti Mälkkic2b0a4f2020-06-28 22:39:59 +0300158void soc_fill_gnvs(struct global_nvs *gnvs)
Lee Leahyb0005132015-05-12 18:19:47 -0700159{
Kyösti Mälkkid5f645c2019-09-28 00:20:27 +0300160 const struct soc_intel_skylake_config *config = config_of_soc();
Duncan Laurie7fce30c2015-09-04 13:53:14 -0700161
Duncan Laurie7fce30c2015-09-04 13:53:14 -0700162 /* Enable DPTF based on mainboard configuration */
163 gnvs->dpte = config->dptf_enable;
Duncan Laurie3d3b76b2016-02-25 08:45:43 -0800164
Furquan Shaikh3bfe3402016-10-18 14:25:25 -0700165 /* Set USB2/USB3 wake enable bitmaps. */
166 gnvs->u2we = config->usb2_wake_enable_bitmap;
167 gnvs->u3we = config->usb3_wake_enable_bitmap;
Pratik Prajapati418535e2017-10-11 16:12:21 -0700168
Michael Niewöhner7736bfc2019-10-22 23:05:06 +0200169 if (CONFIG(SOC_INTEL_COMMON_BLOCK_SGX_ENABLE))
Pratik Prajapati418535e2017-10-11 16:12:21 -0700170 sgx_fill_gnvs(gnvs);
Subrata Banikb6df6b02020-01-03 15:29:02 +0530171
172 /* Fill in Above 4GB MMIO resource */
173 sa_fill_gnvs(gnvs);
Lee Leahyb0005132015-05-12 18:19:47 -0700174}
175
Lee Leahyb0005132015-05-12 18:19:47 -0700176unsigned long acpi_fill_mcfg(unsigned long current)
177{
178 current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current,
Duncan Laurie50f06a12018-03-02 14:56:38 -0800179 CONFIG_MMCONF_BASE_ADDRESS, 0, 0,
Angel Pons98494882021-01-29 11:35:16 +0100180 CONFIG_MMCONF_BUS_NUMBER - 1);
Lee Leahyb0005132015-05-12 18:19:47 -0700181 return current;
182}
183
Duncan Lauriedb54a672015-09-04 14:19:35 -0700184unsigned long acpi_fill_madt(unsigned long current)
185{
186 /* Local APICs */
187 current = acpi_create_madt_lapics(current);
188
189 /* IOAPIC */
190 current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
191 2, IO_APIC_ADDR, 0);
192
193 return acpi_madt_irq_overrides(current);
194}
195
Jacob Garber9172b692019-06-26 16:18:16 -0600196static void write_c_state_entries(acpi_cstate_t *map, const int *set, size_t max_c_state)
Lee Leahyb0005132015-05-12 18:19:47 -0700197{
Jacob Garber9172b692019-06-26 16:18:16 -0600198 for (size_t i = 0; i < max_c_state; i++) {
Lee Leahyb0005132015-05-12 18:19:47 -0700199 memcpy(&map[i], &cstate_map[set[i]], sizeof(acpi_cstate_t));
200 map[i].ctype = i + 1;
201 }
202
203 /* Generate C-state tables */
Jacob Garber9172b692019-06-26 16:18:16 -0600204 acpigen_write_CST_package(map, max_c_state);
205}
206
207static void generate_c_state_entries(int s0ix_enable)
208{
209 if (s0ix_enable) {
210 acpi_cstate_t map[ARRAY_SIZE(cstate_set_s0ix)];
211 write_c_state_entries(map, cstate_set_s0ix, ARRAY_SIZE(map));
212 } else {
213 acpi_cstate_t map[ARRAY_SIZE(cstate_set_non_s0ix)];
214 write_c_state_entries(map, cstate_set_non_s0ix, ARRAY_SIZE(map));
215 }
Lee Leahyb0005132015-05-12 18:19:47 -0700216}
217
218static int calculate_power(int tdp, int p1_ratio, int ratio)
219{
220 u32 m;
221 u32 power;
222
223 /*
224 * M = ((1.1 - ((p1_ratio - ratio) * 0.00625)) / 1.1) ^ 2
225 *
226 * Power = (ratio / p1_ratio) * m * tdp
227 */
228
229 m = (110000 - ((p1_ratio - ratio) * 625)) / 11;
230 m = (m * m) / 1000;
231
232 power = ((ratio * 100000 / p1_ratio) / 100);
233 power *= (m / 100) * (tdp / 1000);
234 power /= 1000;
235
236 return (int)power;
237}
238
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700239static void generate_p_state_entries(int core, int cores_per_package)
Lee Leahyb0005132015-05-12 18:19:47 -0700240{
241 int ratio_min, ratio_max, ratio_turbo, ratio_step;
242 int coord_type, power_max, power_unit, num_entries;
243 int ratio, power, clock, clock_max;
244 msr_t msr;
245
246 /* Determine P-state coordination type from MISC_PWR_MGMT[0] */
247 msr = rdmsr(MSR_MISC_PWR_MGMT);
248 if (msr.lo & MISC_PWR_MGMT_EIST_HW_DIS)
249 coord_type = SW_ANY;
250 else
251 coord_type = HW_ALL;
252
253 /* Get bus ratio limits and calculate clock speeds */
254 msr = rdmsr(MSR_PLATFORM_INFO);
255 ratio_min = (msr.hi >> (40-32)) & 0xff; /* Max Efficiency Ratio */
256
257 /* Determine if this CPU has configurable TDP */
258 if (cpu_config_tdp_levels()) {
259 /* Set max ratio to nominal TDP ratio */
260 msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
261 ratio_max = msr.lo & 0xff;
262 } else {
263 /* Max Non-Turbo Ratio */
264 ratio_max = (msr.lo >> 8) & 0xff;
265 }
Aamir Bohra1041d392017-06-02 11:56:14 +0530266 clock_max = ratio_max * CONFIG_CPU_BCLK_MHZ;
Lee Leahyb0005132015-05-12 18:19:47 -0700267
268 /* Calculate CPU TDP in mW */
269 msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
270 power_unit = 2 << ((msr.lo & 0xf) - 1);
271 msr = rdmsr(MSR_PKG_POWER_SKU);
272 power_max = ((msr.lo & 0x7fff) / power_unit) * 1000;
273
274 /* Write _PCT indicating use of FFixedHW */
275 acpigen_write_empty_PCT();
276
277 /* Write _PPC with no limit on supported P-state */
278 acpigen_write_PPC_NVS();
279
280 /* Write PSD indicating configured coordination type */
281 acpigen_write_PSD_package(core, 1, coord_type);
282
283 /* Add P-state entries in _PSS table */
284 acpigen_write_name("_PSS");
285
286 /* Determine ratio points */
287 ratio_step = PSS_RATIO_STEP;
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700288 num_entries = ((ratio_max - ratio_min) / ratio_step) + 1;
289 if (num_entries > PSS_MAX_ENTRIES) {
290 ratio_step += 1;
291 num_entries = ((ratio_max - ratio_min) / ratio_step) + 1;
Lee Leahyb0005132015-05-12 18:19:47 -0700292 }
293
294 /* P[T] is Turbo state if enabled */
295 if (get_turbo_state() == TURBO_ENABLED) {
296 /* _PSS package count including Turbo */
297 acpigen_write_package(num_entries + 2);
298
299 msr = rdmsr(MSR_TURBO_RATIO_LIMIT);
300 ratio_turbo = msr.lo & 0xff;
301
302 /* Add entry for Turbo ratio */
303 acpigen_write_PSS_package(
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700304 clock_max + 1, /* MHz */
305 power_max, /* mW */
306 PSS_LATENCY_TRANSITION, /* lat1 */
307 PSS_LATENCY_BUSMASTER, /* lat2 */
308 ratio_turbo << 8, /* control */
309 ratio_turbo << 8); /* status */
Lee Leahyb0005132015-05-12 18:19:47 -0700310 } else {
311 /* _PSS package count without Turbo */
312 acpigen_write_package(num_entries + 1);
313 }
314
315 /* First regular entry is max non-turbo ratio */
316 acpigen_write_PSS_package(
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700317 clock_max, /* MHz */
318 power_max, /* mW */
319 PSS_LATENCY_TRANSITION, /* lat1 */
320 PSS_LATENCY_BUSMASTER, /* lat2 */
321 ratio_max << 8, /* control */
322 ratio_max << 8); /* status */
Lee Leahyb0005132015-05-12 18:19:47 -0700323
324 /* Generate the remaining entries */
325 for (ratio = ratio_min + ((num_entries - 1) * ratio_step);
326 ratio >= ratio_min; ratio -= ratio_step) {
327
328 /* Calculate power at this ratio */
329 power = calculate_power(power_max, ratio_max, ratio);
Aamir Bohra1041d392017-06-02 11:56:14 +0530330 clock = ratio * CONFIG_CPU_BCLK_MHZ;
Lee Leahyb0005132015-05-12 18:19:47 -0700331
332 acpigen_write_PSS_package(
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700333 clock, /* MHz */
334 power, /* mW */
335 PSS_LATENCY_TRANSITION, /* lat1 */
336 PSS_LATENCY_BUSMASTER, /* lat2 */
337 ratio << 8, /* control */
338 ratio << 8); /* status */
Lee Leahyb0005132015-05-12 18:19:47 -0700339 }
340
341 /* Fix package length */
342 acpigen_pop_len();
343}
344
Michael Niewöhnerb20aac02020-10-14 19:30:46 +0200345static void generate_cppc_entries(int core_id)
346{
347 /* Generate GCPC table in first logical core */
348 if (core_id == 0) {
349 struct cppc_config cppc_config;
350 cpu_init_cppc_config(&cppc_config, CPPC_VERSION_2);
351 acpigen_write_CPPC_package(&cppc_config);
352 }
353
354 /* Write _CST entry for each logical core */
355 acpigen_write_CPPC_method();
356}
357
Furquan Shaikh7536a392020-04-24 21:59:21 -0700358void generate_cpu_entries(const struct device *device)
Lee Leahyb0005132015-05-12 18:19:47 -0700359{
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700360 int core_id, cpu_id, pcontrol_blk = ACPI_BASE_ADDRESS, plen = 6;
Lee Leahyb0005132015-05-12 18:19:47 -0700361 int totalcores = dev_count_cpu();
362 int cores_per_package = get_cores_per_package();
363 int numcpus = totalcores/cores_per_package;
Kyösti Mälkkid5f645c2019-09-28 00:20:27 +0300364 config_t *config = config_of_soc();
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700365 int is_s0ix_enable = config->s0ix_enable;
Michael Niewöhnerb20aac02020-10-14 19:30:46 +0200366 const bool isst_supported = cpuid_eax(6) & CPUID_6_EAX_ISST;
Lee Leahyb0005132015-05-12 18:19:47 -0700367
368 printk(BIOS_DEBUG, "Found %d CPU(s) with %d core(s) each.\n",
369 numcpus, cores_per_package);
370
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700371 for (cpu_id = 0; cpu_id < numcpus; cpu_id++) {
372 for (core_id = 0; core_id < cores_per_package; core_id++) {
373 if (core_id > 0) {
Lee Leahyb0005132015-05-12 18:19:47 -0700374 pcontrol_blk = 0;
375 plen = 0;
376 }
377
Christian Walterbe3979c2019-12-18 15:07:59 +0100378 /* Generate processor \_SB.CPUx */
Lee Leahyb0005132015-05-12 18:19:47 -0700379 acpigen_write_processor(
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700380 cpu_id*cores_per_package+core_id,
Lee Leahyb0005132015-05-12 18:19:47 -0700381 pcontrol_blk, plen);
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700382 /* Generate C-state tables */
Jacob Garber9172b692019-06-26 16:18:16 -0600383 generate_c_state_entries(is_s0ix_enable);
Lee Leahyb0005132015-05-12 18:19:47 -0700384
Matt Delco9084c3c2018-07-27 14:17:29 -0700385 if (config->eist_enable) {
Subrata Banik6b45ee42017-05-12 11:43:57 +0530386 /* Generate P-state tables */
387 generate_p_state_entries(core_id,
388 cores_per_package);
Matt Delco9084c3c2018-07-27 14:17:29 -0700389 }
Michael Niewöhner30c5d212020-08-03 15:01:18 +0200390
Michael Niewöhnerb20aac02020-10-14 19:30:46 +0200391 if (isst_supported)
392 generate_cppc_entries(core_id);
Michael Niewöhner30c5d212020-08-03 15:01:18 +0200393
Lee Leahyb0005132015-05-12 18:19:47 -0700394 acpigen_pop_len();
395 }
396 }
Arthur Heymans8afc1352018-11-28 12:07:19 +0100397
398 /* PPKG is usually used for thermal management
399 of the first and only package. */
400 acpigen_write_processor_package("PPKG", 0, cores_per_package);
401
402 /* Add a method to notify processor nodes */
403 acpigen_write_processor_cnot(cores_per_package);
Lee Leahyb0005132015-05-12 18:19:47 -0700404}
405
Nico Huberc37b0e32017-09-18 20:03:46 +0200406static unsigned long acpi_fill_dmar(unsigned long current)
407{
Kyösti Mälkki903b40a2019-07-03 07:25:59 +0300408 struct device *const igfx_dev = pcidev_path_on_root(SA_DEVFN_IGD);
Nico Huberc37b0e32017-09-18 20:03:46 +0200409 const u32 gfx_vtbar = MCHBAR32(GFXVTBAR) & ~0xfff;
410 const bool gfxvten = MCHBAR32(GFXVTBAR) & 1;
411
412 /* iGFX has to be enabled, GFXVTBAR set and in 32-bit space. */
Angel Pons96a80132020-08-03 12:29:41 +0200413 const bool emit_igd =
414 igfx_dev && igfx_dev->enabled &&
415 gfx_vtbar && gfxvten &&
416 !MCHBAR32(GFXVTBAR + 4);
417
418 /* First, add DRHD entries */
419 if (emit_igd) {
420 const unsigned long tmp = current;
Nico Huberc37b0e32017-09-18 20:03:46 +0200421
422 current += acpi_create_dmar_drhd(current, 0, 0, gfx_vtbar);
Matt DeVillier7866d492018-03-29 14:59:57 +0200423 current += acpi_create_dmar_ds_pci(current, 0, 2, 0);
Nico Huberc37b0e32017-09-18 20:03:46 +0200424
425 acpi_dmar_drhd_fixup(tmp, current);
426 }
427
Nico Huberc37b0e32017-09-18 20:03:46 +0200428 const u32 vtvc0bar = MCHBAR32(VTVC0BAR) & ~0xfff;
429 const bool vtvc0en = MCHBAR32(VTVC0BAR) & 1;
430
431 /* General VTBAR has to be set and in 32-bit space. */
Angel Ponsef879a82019-08-30 19:42:23 +0200432 if (vtvc0bar && vtvc0en && !MCHBAR32(VTVC0BAR + 4)) {
Nico Huberc37b0e32017-09-18 20:03:46 +0200433 const unsigned long tmp = current;
434
Angel Ponsef879a82019-08-30 19:42:23 +0200435 current += acpi_create_dmar_drhd(current, DRHD_INCLUDE_PCI_ALL, 0, vtvc0bar);
Nico Huberc37b0e32017-09-18 20:03:46 +0200436
Angel Ponsef879a82019-08-30 19:42:23 +0200437 current += acpi_create_dmar_ds_ioapic(current, 2, V_P2SB_IBDF_BUS,
438 V_P2SB_IBDF_DEV, V_P2SB_IBDF_FUN);
Nico Huberc37b0e32017-09-18 20:03:46 +0200439
Angel Ponsef879a82019-08-30 19:42:23 +0200440 current += acpi_create_dmar_ds_msi_hpet(current, 0, V_P2SB_HBDF_BUS,
441 V_P2SB_HBDF_DEV, V_P2SB_HBDF_FUN);
Nico Huberc37b0e32017-09-18 20:03:46 +0200442
443 acpi_dmar_drhd_fixup(tmp, current);
444 }
445
Angel Pons96a80132020-08-03 12:29:41 +0200446 /* Then, add RMRR entries after all DRHD entries */
447 if (emit_igd) {
448 const unsigned long tmp = current;
449
450 current += acpi_create_dmar_rmrr(current, 0,
451 sa_get_gsm_base(), sa_get_tolud_base() - 1);
452 current += acpi_create_dmar_ds_pci(current, 0, 2, 0);
453 acpi_dmar_rmrr_fixup(tmp, current);
454 }
455
Nico Huberc37b0e32017-09-18 20:03:46 +0200456 return current;
457}
458
Furquan Shaikh0f007d82020-04-24 06:41:18 -0700459unsigned long northbridge_write_acpi_tables(const struct device *const dev,
Nico Huberc37b0e32017-09-18 20:03:46 +0200460 unsigned long current,
461 struct acpi_rsdp *const rsdp)
462{
Nico Huberc37b0e32017-09-18 20:03:46 +0200463 acpi_dmar_t *const dmar = (acpi_dmar_t *)current;
464
465 /* Create DMAR table only if we have VT-d capability. */
Angel Pons00f53a82021-04-05 12:03:08 +0200466 if (!soc_is_vtd_capable())
Nico Huberc37b0e32017-09-18 20:03:46 +0200467 return current;
468
469 printk(BIOS_DEBUG, "ACPI: * DMAR\n");
470 acpi_create_dmar(dmar, DMAR_INTR_REMAP, acpi_fill_dmar);
471 current += dmar->header.length;
472 current = acpi_align_current(current);
473 acpi_add_table(rsdp, dmar);
474
475 return current;
476}
477
Angel Ponse4844ce2021-04-17 12:49:08 +0200478int acpi_sci_irq(void)
479{
480 int scis = pci_read_config32(PCH_DEV_PMC, ACTL) & SCI_IRQ_SEL;
481 int sci_irq = 9;
482
483 /* Determine how SCI is routed. */
484 switch (scis) {
485 case SCIS_IRQ9:
486 case SCIS_IRQ10:
487 case SCIS_IRQ11:
488 sci_irq = scis - SCIS_IRQ9 + 9;
489 break;
490 case SCIS_IRQ20:
491 case SCIS_IRQ21:
492 case SCIS_IRQ22:
493 case SCIS_IRQ23:
494 sci_irq = scis - SCIS_IRQ20 + 20;
495 break;
496 default:
497 printk(BIOS_DEBUG, "Invalid SCI route! Defaulting to IRQ9.\n");
498 sci_irq = 9;
499 break;
500 }
501
502 printk(BIOS_DEBUG, "SCI is IRQ%d\n", sci_irq);
503 return sci_irq;
504}
505
Lee Leahyb0005132015-05-12 18:19:47 -0700506unsigned long acpi_madt_irq_overrides(unsigned long current)
507{
508 int sci = acpi_sci_irq();
509 acpi_madt_irqoverride_t *irqovr;
510 uint16_t flags = MP_IRQ_TRIGGER_LEVEL;
511
512 /* INT_SRC_OVR */
513 irqovr = (void *)current;
514 current += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
515
516 if (sci >= 20)
517 flags |= MP_IRQ_POLARITY_LOW;
518 else
519 flags |= MP_IRQ_POLARITY_HIGH;
520
521 /* SCI */
522 irqovr = (void *)current;
523 current += acpi_create_madt_irqoverride(irqovr, 0, sci, sci, flags);
524
Michael Niewöhner14512f92020-11-23 15:53:28 +0100525 /* NMI */
526 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)current, 0xff, 5, 1);
527
Lee Leahyb0005132015-05-12 18:19:47 -0700528 return current;
529}
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700530
Furquan Shaikh0f007d82020-04-24 06:41:18 -0700531unsigned long southbridge_write_acpi_tables(const struct device *device,
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700532 unsigned long current,
533 struct acpi_rsdp *rsdp)
534{
Duncan Laurie93bbd412017-11-11 20:03:29 -0800535 current = acpi_write_dbg2_pci_uart(rsdp, current,
Subrata Banikafa07f72018-05-24 12:21:06 +0530536 uart_get_device(),
Duncan Laurie93bbd412017-11-11 20:03:29 -0800537 ACPI_ACCESS_SIZE_DWORD_ACCESS);
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700538 current = acpi_write_hpet(device, current, rsdp);
Aaron Durbin07a1b282015-12-10 17:07:38 -0600539 return acpi_align_current(current);
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700540}
541
Duncan Lauriea1c8b34d2015-09-08 16:12:44 -0700542/* Save wake source information for calculating ACPI _SWS values */
Kyösti Mälkkif67e67512021-01-22 19:59:07 +0200543int soc_fill_acpi_wake(const struct chipset_power_state *ps, uint32_t *pm1, uint32_t **gpe0)
Duncan Lauriea1c8b34d2015-09-08 16:12:44 -0700544{
Kyösti Mälkkid5f645c2019-09-28 00:20:27 +0300545 const struct soc_intel_skylake_config *config = config_of_soc();
Duncan Lauriea1c8b34d2015-09-08 16:12:44 -0700546 static uint32_t gpe0_sts[GPE0_REG_MAX];
547 uint32_t pm1_en;
Duncan Laurie95f90202016-10-25 20:07:22 -0700548 uint32_t gpe0_std;
Duncan Lauriea1c8b34d2015-09-08 16:12:44 -0700549 int i;
Aaron Durbin64606ce2016-10-27 09:53:17 -0500550 const int last_index = GPE0_REG_MAX - 1;
Duncan Lauriea1c8b34d2015-09-08 16:12:44 -0700551
Duncan Laurie95f90202016-10-25 20:07:22 -0700552 pm1_en = ps->pm1_en;
553 gpe0_std = ps->gpe0_en[3];
554
555 /*
556 * Chipset state in the suspend well (but not RTC) is lost in Deep S3
557 * so enable Deep S3 wake events that are configured by the mainboard
558 */
Duncan Laurie1fe32d62017-04-10 21:02:13 -0700559 if (ps->prev_sleep_state == ACPI_S3 &&
560 (config->deep_s3_enable_ac || config->deep_s3_enable_dc)) {
Duncan Laurie95f90202016-10-25 20:07:22 -0700561 pm1_en |= PWRBTN_STS; /* Always enabled as wake source */
562 if (config->deep_sx_config & DSX_EN_LAN_WAKE_PIN)
563 gpe0_std |= LAN_WAK_EN;
564 if (config->deep_sx_config & DSX_EN_WAKE_PIN)
565 pm1_en |= PCIEXPWAK_STS;
566 }
567
Duncan Lauriea1c8b34d2015-09-08 16:12:44 -0700568 *pm1 = ps->pm1_sts & pm1_en;
569
570 /* Mask off GPE0 status bits that are not enabled */
571 *gpe0 = &gpe0_sts[0];
Aaron Durbin64606ce2016-10-27 09:53:17 -0500572 for (i = 0; i < last_index; i++)
Duncan Lauriea1c8b34d2015-09-08 16:12:44 -0700573 gpe0_sts[i] = ps->gpe0_sts[i] & ps->gpe0_en[i];
Aaron Durbin64606ce2016-10-27 09:53:17 -0500574 gpe0_sts[last_index] = ps->gpe0_sts[last_index] & gpe0_std;
Duncan Lauriea1c8b34d2015-09-08 16:12:44 -0700575
576 return GPE0_REG_MAX;
577}