blob: 1c9eb4e31b16135376b9df79f521e5b0c2098b0b [file] [log] [blame]
Angel Ponsba38f372020-04-05 15:46:45 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Lee Leahy77ff0b12015-05-05 15:07:29 -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>
Furquan Shaikh76cedd22020-05-02 10:24:23 -07005#include <acpi/acpigen.h>
Angel Pons18edd002021-01-28 12:22:52 +01006#include <arch/ioapic.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -07007#include <arch/smp/mpspec.h>
Angel Pons18edd002021-01-28 12:22:52 +01008#include <device/mmio.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -07009#include <console/console.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070010#include <cpu/intel/turbo.h>
Lee Leahy32471722015-04-20 15:20:28 -070011#include <cpu/x86/msr.h>
12#include <cpu/x86/smm.h>
Lee Leahy32471722015-04-20 15:20:28 -070013#include <device/pci.h>
Patrick Rudolphc7edf182017-09-26 19:34:35 +020014#include <drivers/intel/gma/opregion.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070015#include <soc/acpi.h>
Kyösti Mälkki4bd91872021-03-16 19:02:26 +020016#include <soc/device_nvs.h>
Lee Leahy32471722015-04-20 15:20:28 -070017#include <soc/gfx.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070018#include <soc/iomap.h>
19#include <soc/irq.h>
20#include <soc/msr.h>
Kyösti Mälkkid6c57142020-12-21 15:17:01 +020021#include <soc/nvs.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070022#include <soc/pattrs.h>
Lee Leahy32471722015-04-20 15:20:28 -070023#include <soc/pci_devs.h>
24#include <soc/pm.h>
25#include <string.h>
26#include <types.h>
Felix Durairaj15184e02015-11-23 14:07:40 -080027#include <wrdd.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070028
Angel Pons8d5b6742021-09-27 13:04:28 +020029#include "chip.h"
30
Lee Leahy77ff0b12015-05-05 15:07:29 -070031#define MWAIT_RES(state, sub_state) \
32 { \
33 .addrl = (((state) << 4) | (sub_state)), \
34 .space_id = ACPI_ADDRESS_SPACE_FIXED, \
35 .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, \
36 .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, \
37 .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD, \
38 }
39
40/* C-state map without S0ix */
Angel Ponsd2794ce2021-10-17 12:59:43 +020041static const acpi_cstate_t cstate_map[] = {
Lee Leahy77ff0b12015-05-05 15:07:29 -070042 {
43 /* C1 */
44 .ctype = 1, /* ACPI C1 */
45 .latency = 1,
46 .power = 1000,
47 .resource = MWAIT_RES(0, 0),
48 },
49 {
50 /* C6NS with no L2 shrink */
51 /* NOTE: this substate is above CPUID limit */
52 .ctype = 2, /* ACPI C2 */
53 .latency = 500,
54 .power = 10,
55 .resource = MWAIT_RES(5, 1),
56 },
57 {
58 /* C6FS with full L2 shrink */
59 .ctype = 3, /* ACPI C3 */
60 .latency = 1500, /* 1.5ms worst case */
61 .power = 1,
62 .resource = MWAIT_RES(5, 2),
63 }
64};
65
Kyösti Mälkki4bd91872021-03-16 19:02:26 +020066size_t size_of_dnvs(void)
67{
68 return sizeof(struct device_nvs);
69}
70
Kyösti Mälkki999e4412020-06-28 21:56:46 +030071void soc_fill_gnvs(struct global_nvs *gnvs)
Lee Leahy77ff0b12015-05-05 15:07:29 -070072{
Angel Pons8d5b6742021-09-27 13:04:28 +020073 const struct soc_intel_braswell_config *config = config_of_soc();
74
75 gnvs->dpte = config->dptf_enable;
76
Kyösti Mälkki46e37c62020-06-29 02:47:45 +030077 /* Fill in the Wi-Fi Region ID */
78 if (CONFIG(HAVE_REGULATORY_DOMAIN))
79 gnvs->cid1 = wifi_regulatory_domain();
80 else
81 gnvs->cid1 = WRDD_DEFAULT_REGULATORY_DOMAIN;
Lee Leahy77ff0b12015-05-05 15:07:29 -070082}
83
Angel Pons6ee77512020-07-12 15:47:07 +020084int acpi_sci_irq(void)
Lee Leahy77ff0b12015-05-05 15:07:29 -070085{
86 u32 *actl = (u32 *)(ILB_BASE_ADDRESS + ACTL);
87 int scis;
88 static int sci_irq;
89
90 if (sci_irq)
91 return sci_irq;
92
93 /* Determine how SCI is routed. */
94 scis = read32(actl) & SCIS_MASK;
95 switch (scis) {
96 case SCIS_IRQ9:
97 case SCIS_IRQ10:
98 case SCIS_IRQ11:
99 sci_irq = scis - SCIS_IRQ9 + 9;
100 break;
101 case SCIS_IRQ20:
102 case SCIS_IRQ21:
103 case SCIS_IRQ22:
104 case SCIS_IRQ23:
105 sci_irq = scis - SCIS_IRQ20 + 20;
106 break;
107 default:
108 printk(BIOS_DEBUG, "Invalid SCI route! Defaulting to IRQ9.\n");
109 sci_irq = 9;
110 break;
111 }
112
113 printk(BIOS_DEBUG, "SCI is IRQ%d\n", sci_irq);
114 return sci_irq;
115}
116
Lee Leahy32471722015-04-20 15:20:28 -0700117static acpi_tstate_t soc_tss_table[] = {
Lee Leahy77ff0b12015-05-05 15:07:29 -0700118 { 100, 1000, 0, 0x00, 0 },
Angel Ponsaee7ab22020-03-19 00:31:58 +0100119 { 88, 875, 0, 0x1e, 0 },
120 { 75, 750, 0, 0x1c, 0 },
121 { 63, 625, 0, 0x1a, 0 },
122 { 50, 500, 0, 0x18, 0 },
123 { 38, 375, 0, 0x16, 0 },
124 { 25, 250, 0, 0x14, 0 },
125 { 13, 125, 0, 0x12, 0 },
Lee Leahy77ff0b12015-05-05 15:07:29 -0700126};
127
Lee Leahyacb9c0b2015-07-02 11:55:18 -0700128static void generate_t_state_entries(int core, int cores_per_package)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700129{
Lee Leahy77ff0b12015-05-05 15:07:29 -0700130 /* Indicate SW_ALL coordination for T-states */
Lee Leahy32471722015-04-20 15:20:28 -0700131 acpigen_write_TSD_package(core, cores_per_package, SW_ALL);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700132
133 /* Indicate FFixedHW so OS will use MSR */
Lee Leahy32471722015-04-20 15:20:28 -0700134 acpigen_write_empty_PTC();
Lee Leahy77ff0b12015-05-05 15:07:29 -0700135
136 /* Set NVS controlled T-state limit */
Lee Leahy32471722015-04-20 15:20:28 -0700137 acpigen_write_TPC("\\TLVL");
Lee Leahy77ff0b12015-05-05 15:07:29 -0700138
139 /* Write TSS table for MSR access */
Angel Ponsaee7ab22020-03-19 00:31:58 +0100140 acpigen_write_TSS_package(ARRAY_SIZE(soc_tss_table), soc_tss_table);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700141}
142
143static int calculate_power(int tdp, int p1_ratio, int ratio)
144{
Angel Ponsaee7ab22020-03-19 00:31:58 +0100145 u32 m, power;
Lee Leahy77ff0b12015-05-05 15:07:29 -0700146
147 /*
148 * M = ((1.1 - ((p1_ratio - ratio) * 0.00625)) / 1.1) ^ 2
Lee Leahy77ff0b12015-05-05 15:07:29 -0700149 */
150
151 m = (110000 - ((p1_ratio - ratio) * 625)) / 11;
152 m = (m * m) / 1000;
153
Angel Ponsaee7ab22020-03-19 00:31:58 +0100154 /*
155 * Power = (ratio / p1_ratio) * m * TDP
156 */
Lee Leahy77ff0b12015-05-05 15:07:29 -0700157 power = ((ratio * 100000 / p1_ratio) / 100);
158 power *= (m / 100) * (tdp / 1000);
159 power /= 1000;
160
161 return (int)power;
162}
163
Lee Leahyacb9c0b2015-07-02 11:55:18 -0700164static void generate_p_state_entries(int core, int cores_per_package)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700165{
Lee Leahy77ff0b12015-05-05 15:07:29 -0700166 int ratio_min, ratio_max, ratio_turbo, ratio_step, ratio_range_2;
167 int coord_type, power_max, power_unit, num_entries;
168 int ratio, power, clock, clock_max;
169 int vid, vid_turbo, vid_min, vid_max, vid_range_2;
170 u32 control_status;
171 const struct pattrs *pattrs = pattrs_get();
172 msr_t msr;
173
174 /* Inputs from CPU attributes */
175 ratio_max = pattrs->iacore_ratios[IACORE_MAX];
176 ratio_min = pattrs->iacore_ratios[IACORE_LFM];
177 vid_max = pattrs->iacore_vids[IACORE_MAX];
178 vid_min = pattrs->iacore_vids[IACORE_LFM];
179
180 /* Set P-states coordination type based on MSR disable bit */
181 coord_type = (pattrs->num_cpus > 2) ? SW_ALL : HW_ALL;
182
183 /* Max Non-Turbo Frequency */
184 clock_max = (ratio_max * pattrs->bclk_khz) / 1000;
185
186 /* Calculate CPU TDP in mW */
187 msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
188 power_unit = 1 << (msr.lo & 0xf);
189 msr = rdmsr(MSR_PKG_POWER_LIMIT);
190 power_max = ((msr.lo & 0x7fff) / power_unit) * 1000;
191
192 /* Write _PCT indicating use of FFixedHW */
Lee Leahy32471722015-04-20 15:20:28 -0700193 acpigen_write_empty_PCT();
Lee Leahy77ff0b12015-05-05 15:07:29 -0700194
195 /* Write _PPC with NVS specified limit on supported P-state */
Lee Leahy32471722015-04-20 15:20:28 -0700196 acpigen_write_PPC_NVS();
Lee Leahy77ff0b12015-05-05 15:07:29 -0700197
198 /* Write PSD indicating configured coordination type */
Lee Leahy32471722015-04-20 15:20:28 -0700199 acpigen_write_PSD_package(core, 1, coord_type);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700200
201 /* Add P-state entries in _PSS table */
Lee Leahy32471722015-04-20 15:20:28 -0700202 acpigen_write_name("_PSS");
Lee Leahy77ff0b12015-05-05 15:07:29 -0700203
204 /* Determine ratio points */
205 ratio_step = 1;
206 num_entries = (ratio_max - ratio_min) / ratio_step;
207 while (num_entries > 15) { /* ACPI max is 15 ratios */
208 ratio_step <<= 1;
209 num_entries >>= 1;
210 }
211
212 /* P[T] is Turbo state if enabled */
213 if (get_turbo_state() == TURBO_ENABLED) {
214 /* _PSS package count including Turbo */
Lee Leahy32471722015-04-20 15:20:28 -0700215 acpigen_write_package(num_entries + 2);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700216
217 ratio_turbo = pattrs->iacore_ratios[IACORE_TURBO];
218 vid_turbo = pattrs->iacore_vids[IACORE_TURBO];
219 control_status = (ratio_turbo << 8) | vid_turbo;
220
221 /* Add entry for Turbo ratio */
Lee Leahy32471722015-04-20 15:20:28 -0700222 acpigen_write_PSS_package(
223 clock_max + 1, /* MHz */
224 power_max, /* mW */
225 10, /* lat1 */
226 10, /* lat2 */
227 control_status, /* control */
228 control_status); /* status */
Lee Leahy77ff0b12015-05-05 15:07:29 -0700229 } else {
230 /* _PSS package count without Turbo */
Lee Leahy32471722015-04-20 15:20:28 -0700231 acpigen_write_package(num_entries + 1);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700232 ratio_turbo = ratio_max;
233 vid_turbo = vid_max;
234 }
235
236 /* First regular entry is max non-turbo ratio */
237 control_status = (ratio_max << 8) | vid_max;
Lee Leahy32471722015-04-20 15:20:28 -0700238 acpigen_write_PSS_package(
239 clock_max, /* MHz */
240 power_max, /* mW */
241 10, /* lat1 */
242 10, /* lat2 */
243 control_status, /* control */
244 control_status); /* status */
Lee Leahy77ff0b12015-05-05 15:07:29 -0700245
246 /* Set up ratio and vid ranges for VID calculation */
247 ratio_range_2 = (ratio_turbo - ratio_min) * 2;
248 vid_range_2 = (vid_turbo - vid_min) * 2;
249
250 /* Generate the remaining entries */
251 for (ratio = ratio_min + ((num_entries - 1) * ratio_step);
252 ratio >= ratio_min; ratio -= ratio_step) {
253
254 /* Calculate VID for this ratio */
Angel Ponsaee7ab22020-03-19 00:31:58 +0100255 vid = ((ratio - ratio_min) * vid_range_2) / ratio_range_2 + vid_min;
256
Lee Leahy77ff0b12015-05-05 15:07:29 -0700257 /* Round up if remainder */
258 if (((ratio - ratio_min) * vid_range_2) % ratio_range_2)
259 vid++;
260
261 /* Calculate power at this ratio */
262 power = calculate_power(power_max, ratio_max, ratio);
263 clock = (ratio * pattrs->bclk_khz) / 1000;
264 control_status = (ratio << 8) | (vid & 0xff);
265
Lee Leahy32471722015-04-20 15:20:28 -0700266 acpigen_write_PSS_package(
267 clock, /* MHz */
268 power, /* mW */
269 10, /* lat1 */
270 10, /* lat2 */
271 control_status, /* control */
272 control_status); /* status */
Lee Leahy77ff0b12015-05-05 15:07:29 -0700273 }
274
275 /* Fix package length */
Lee Leahy32471722015-04-20 15:20:28 -0700276 acpigen_pop_len();
Lee Leahy77ff0b12015-05-05 15:07:29 -0700277}
278
Furquan Shaikh7536a392020-04-24 21:59:21 -0700279void generate_cpu_entries(const struct device *device)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700280{
Lee Leahy32471722015-04-20 15:20:28 -0700281 int core;
Lee Leahy77ff0b12015-05-05 15:07:29 -0700282 const struct pattrs *pattrs = pattrs_get();
283
Lee Leahy32471722015-04-20 15:20:28 -0700284 for (core = 0; core < pattrs->num_cpus; core++) {
Christian Walterbe3979c2019-12-18 15:07:59 +0100285 /* Generate processor \_SB.CPUx */
Michael Niewöhner2353cd92021-10-04 16:59:49 +0200286 acpigen_write_processor(core, 0, 0);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700287
288 /* Generate P-state tables */
Angel Ponsaee7ab22020-03-19 00:31:58 +0100289 generate_p_state_entries(core, pattrs->num_cpus);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700290
291 /* Generate C-state tables */
Angel Ponsaee7ab22020-03-19 00:31:58 +0100292 acpigen_write_CST_package(cstate_map, ARRAY_SIZE(cstate_map));
Lee Leahy77ff0b12015-05-05 15:07:29 -0700293
294 /* Generate T-state tables */
Angel Ponsaee7ab22020-03-19 00:31:58 +0100295 generate_t_state_entries(core, pattrs->num_cpus);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700296
Lee Leahy32471722015-04-20 15:20:28 -0700297 acpigen_pop_len();
Lee Leahy77ff0b12015-05-05 15:07:29 -0700298 }
Arthur Heymans1a9efe32018-11-28 12:20:43 +0100299
300 /* PPKG is usually used for thermal management
301 of the first and only package. */
302 acpigen_write_processor_package("PPKG", 0, pattrs->num_cpus);
303
304 /* Add a method to notify processor nodes */
305 acpigen_write_processor_cnot(pattrs->num_cpus);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700306}
307
Angel Pons18edd002021-01-28 12:22:52 +0100308static unsigned long acpi_madt_irq_overrides(unsigned long current)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700309{
310 int sci_irq = acpi_sci_irq();
311 acpi_madt_irqoverride_t *irqovr;
312 uint16_t sci_flags = MP_IRQ_TRIGGER_LEVEL;
313
314 /* INT_SRC_OVR */
315 irqovr = (void *)current;
316 current += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
317
318 if (sci_irq >= 20)
319 sci_flags |= MP_IRQ_POLARITY_LOW;
320 else
321 sci_flags |= MP_IRQ_POLARITY_HIGH;
322
323 irqovr = (void *)current;
Angel Ponsaee7ab22020-03-19 00:31:58 +0100324 current += acpi_create_madt_irqoverride(irqovr, 0, sci_irq, sci_irq, sci_flags);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700325
326 return current;
327}
Lee Leahy32471722015-04-20 15:20:28 -0700328
Angel Pons18edd002021-01-28 12:22:52 +0100329unsigned long acpi_fill_madt(unsigned long current)
330{
331 /* Local APICs */
332 current = acpi_create_madt_lapics(current);
333
334 /* IOAPIC */
Kyösti Mälkkic0457352021-06-08 06:12:25 +0300335 current += acpi_create_madt_ioapic_from_hw((acpi_madt_ioapic_t *)current, IO_APIC_ADDR);
Angel Pons18edd002021-01-28 12:22:52 +0100336
337 current = acpi_madt_irq_overrides(current);
338
339 return current;
340}
341
Furquan Shaikh0f007d82020-04-24 06:41:18 -0700342unsigned long southcluster_write_acpi_tables(const struct device *device, unsigned long current,
Lee Leahy2bc9cee2015-06-30 15:25:44 -0700343 struct acpi_rsdp *rsdp)
344{
345 acpi_header_t *ssdt2;
346
Julius Wernercd49cce2019-03-05 16:53:33 -0800347 if (!CONFIG(DISABLE_HPET)) {
Frans Hendriksf2af7022018-11-16 12:08:41 +0100348 current = acpi_write_hpet(device, current, rsdp);
349 current = acpi_align_current(current);
350 }
Lee Leahy2bc9cee2015-06-30 15:25:44 -0700351
Lee Leahy2bc9cee2015-06-30 15:25:44 -0700352 ssdt2 = (acpi_header_t *)current;
353 memset(ssdt2, 0, sizeof(acpi_header_t));
354 acpi_create_serialio_ssdt(ssdt2);
355 if (ssdt2->length) {
356 current += ssdt2->length;
357 acpi_add_table(rsdp, ssdt2);
Angel Ponsaee7ab22020-03-19 00:31:58 +0100358 printk(BIOS_DEBUG, "ACPI: * SSDT2 @ %p Length %x\n", ssdt2, ssdt2->length);
Aaron Durbin07a1b282015-12-10 17:07:38 -0600359 current = acpi_align_current(current);
Angel Ponsaee7ab22020-03-19 00:31:58 +0100360
Lee Leahy2bc9cee2015-06-30 15:25:44 -0700361 } else {
362 ssdt2 = NULL;
363 printk(BIOS_DEBUG, "ACPI: * SSDT2 not generated.\n");
364 }
365
366 printk(BIOS_DEBUG, "current = %lx\n", current);
367
368 return current;
369}
370
Aaron Durbin64031672018-04-21 14:45:32 -0600371__weak void acpi_create_serialio_ssdt(acpi_header_t *ssdt)
Lee Leahy2bc9cee2015-06-30 15:25:44 -0700372{
373}