blob: a278e55742c04f2391c66f716d3f578fcc61339a [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
Kyösti Mälkkiae1b2d42023-04-10 16:45:39 +030084static u8 soc_madt_sci_irq_polarity(u8 sci_irq)
85{
86 if (sci_irq >= 20)
87 return MP_IRQ_POLARITY_LOW;
88 else
89 return MP_IRQ_POLARITY_HIGH;
90}
91
92#define ACPI_SCI_IRQ 9
93
94void ioapic_get_sci_pin(u8 *gsi, u8 *irq, u8 *flags)
Lee Leahy77ff0b12015-05-05 15:07:29 -070095{
96 u32 *actl = (u32 *)(ILB_BASE_ADDRESS + ACTL);
Kyösti Mälkkiae1b2d42023-04-10 16:45:39 +030097 int sci_irq = ACPI_SCI_IRQ;
Lee Leahy77ff0b12015-05-05 15:07:29 -070098 int scis;
Lee Leahy77ff0b12015-05-05 15:07:29 -070099
100 /* Determine how SCI is routed. */
101 scis = read32(actl) & SCIS_MASK;
102 switch (scis) {
103 case SCIS_IRQ9:
104 case SCIS_IRQ10:
105 case SCIS_IRQ11:
106 sci_irq = scis - SCIS_IRQ9 + 9;
107 break;
108 case SCIS_IRQ20:
109 case SCIS_IRQ21:
110 case SCIS_IRQ22:
111 case SCIS_IRQ23:
112 sci_irq = scis - SCIS_IRQ20 + 20;
113 break;
114 default:
Kyösti Mälkkiae1b2d42023-04-10 16:45:39 +0300115 printk(BIOS_DEBUG, "Invalid SCI route! Defaulting to IRQ%d.\n", sci_irq);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700116 break;
117 }
118
Kyösti Mälkkiae1b2d42023-04-10 16:45:39 +0300119 *gsi = sci_irq;
120 *irq = (sci_irq < 16) ? sci_irq : ACPI_SCI_IRQ;
121 *flags = MP_IRQ_TRIGGER_LEVEL | soc_madt_sci_irq_polarity(sci_irq);
122
123 printk(BIOS_DEBUG, "SCI is IRQ %d, GSI %d\n", *irq, *gsi);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700124}
125
Lee Leahy32471722015-04-20 15:20:28 -0700126static acpi_tstate_t soc_tss_table[] = {
Lee Leahy77ff0b12015-05-05 15:07:29 -0700127 { 100, 1000, 0, 0x00, 0 },
Angel Ponsaee7ab22020-03-19 00:31:58 +0100128 { 88, 875, 0, 0x1e, 0 },
129 { 75, 750, 0, 0x1c, 0 },
130 { 63, 625, 0, 0x1a, 0 },
131 { 50, 500, 0, 0x18, 0 },
132 { 38, 375, 0, 0x16, 0 },
133 { 25, 250, 0, 0x14, 0 },
134 { 13, 125, 0, 0x12, 0 },
Lee Leahy77ff0b12015-05-05 15:07:29 -0700135};
136
Lee Leahyacb9c0b2015-07-02 11:55:18 -0700137static void generate_t_state_entries(int core, int cores_per_package)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700138{
Lee Leahy77ff0b12015-05-05 15:07:29 -0700139 /* Indicate SW_ALL coordination for T-states */
Lee Leahy32471722015-04-20 15:20:28 -0700140 acpigen_write_TSD_package(core, cores_per_package, SW_ALL);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700141
142 /* Indicate FFixedHW so OS will use MSR */
Lee Leahy32471722015-04-20 15:20:28 -0700143 acpigen_write_empty_PTC();
Lee Leahy77ff0b12015-05-05 15:07:29 -0700144
145 /* Set NVS controlled T-state limit */
Lee Leahy32471722015-04-20 15:20:28 -0700146 acpigen_write_TPC("\\TLVL");
Lee Leahy77ff0b12015-05-05 15:07:29 -0700147
148 /* Write TSS table for MSR access */
Angel Ponsaee7ab22020-03-19 00:31:58 +0100149 acpigen_write_TSS_package(ARRAY_SIZE(soc_tss_table), soc_tss_table);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700150}
151
152static int calculate_power(int tdp, int p1_ratio, int ratio)
153{
Angel Ponsaee7ab22020-03-19 00:31:58 +0100154 u32 m, power;
Lee Leahy77ff0b12015-05-05 15:07:29 -0700155
156 /*
157 * M = ((1.1 - ((p1_ratio - ratio) * 0.00625)) / 1.1) ^ 2
Lee Leahy77ff0b12015-05-05 15:07:29 -0700158 */
159
160 m = (110000 - ((p1_ratio - ratio) * 625)) / 11;
161 m = (m * m) / 1000;
162
Angel Ponsaee7ab22020-03-19 00:31:58 +0100163 /*
164 * Power = (ratio / p1_ratio) * m * TDP
165 */
Lee Leahy77ff0b12015-05-05 15:07:29 -0700166 power = ((ratio * 100000 / p1_ratio) / 100);
167 power *= (m / 100) * (tdp / 1000);
168 power /= 1000;
169
170 return (int)power;
171}
172
Kyösti Mälkkid521b962023-04-12 21:44:49 +0300173static void generate_p_state_entries(int core)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700174{
Lee Leahy77ff0b12015-05-05 15:07:29 -0700175 int ratio_min, ratio_max, ratio_turbo, ratio_step, ratio_range_2;
176 int coord_type, power_max, power_unit, num_entries;
177 int ratio, power, clock, clock_max;
178 int vid, vid_turbo, vid_min, vid_max, vid_range_2;
179 u32 control_status;
180 const struct pattrs *pattrs = pattrs_get();
181 msr_t msr;
182
183 /* Inputs from CPU attributes */
184 ratio_max = pattrs->iacore_ratios[IACORE_MAX];
185 ratio_min = pattrs->iacore_ratios[IACORE_LFM];
186 vid_max = pattrs->iacore_vids[IACORE_MAX];
187 vid_min = pattrs->iacore_vids[IACORE_LFM];
188
189 /* Set P-states coordination type based on MSR disable bit */
190 coord_type = (pattrs->num_cpus > 2) ? SW_ALL : HW_ALL;
191
192 /* Max Non-Turbo Frequency */
193 clock_max = (ratio_max * pattrs->bclk_khz) / 1000;
194
195 /* Calculate CPU TDP in mW */
196 msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
197 power_unit = 1 << (msr.lo & 0xf);
198 msr = rdmsr(MSR_PKG_POWER_LIMIT);
199 power_max = ((msr.lo & 0x7fff) / power_unit) * 1000;
200
201 /* Write _PCT indicating use of FFixedHW */
Lee Leahy32471722015-04-20 15:20:28 -0700202 acpigen_write_empty_PCT();
Lee Leahy77ff0b12015-05-05 15:07:29 -0700203
204 /* Write _PPC with NVS specified limit on supported P-state */
Lee Leahy32471722015-04-20 15:20:28 -0700205 acpigen_write_PPC_NVS();
Lee Leahy77ff0b12015-05-05 15:07:29 -0700206
207 /* Write PSD indicating configured coordination type */
Lee Leahy32471722015-04-20 15:20:28 -0700208 acpigen_write_PSD_package(core, 1, coord_type);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700209
210 /* Add P-state entries in _PSS table */
Lee Leahy32471722015-04-20 15:20:28 -0700211 acpigen_write_name("_PSS");
Lee Leahy77ff0b12015-05-05 15:07:29 -0700212
213 /* Determine ratio points */
214 ratio_step = 1;
215 num_entries = (ratio_max - ratio_min) / ratio_step;
216 while (num_entries > 15) { /* ACPI max is 15 ratios */
217 ratio_step <<= 1;
218 num_entries >>= 1;
219 }
220
221 /* P[T] is Turbo state if enabled */
222 if (get_turbo_state() == TURBO_ENABLED) {
223 /* _PSS package count including Turbo */
Lee Leahy32471722015-04-20 15:20:28 -0700224 acpigen_write_package(num_entries + 2);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700225
226 ratio_turbo = pattrs->iacore_ratios[IACORE_TURBO];
227 vid_turbo = pattrs->iacore_vids[IACORE_TURBO];
228 control_status = (ratio_turbo << 8) | vid_turbo;
229
230 /* Add entry for Turbo ratio */
Lee Leahy32471722015-04-20 15:20:28 -0700231 acpigen_write_PSS_package(
232 clock_max + 1, /* MHz */
233 power_max, /* mW */
234 10, /* lat1 */
235 10, /* lat2 */
236 control_status, /* control */
237 control_status); /* status */
Lee Leahy77ff0b12015-05-05 15:07:29 -0700238 } else {
239 /* _PSS package count without Turbo */
Lee Leahy32471722015-04-20 15:20:28 -0700240 acpigen_write_package(num_entries + 1);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700241 ratio_turbo = ratio_max;
242 vid_turbo = vid_max;
243 }
244
245 /* First regular entry is max non-turbo ratio */
246 control_status = (ratio_max << 8) | vid_max;
Lee Leahy32471722015-04-20 15:20:28 -0700247 acpigen_write_PSS_package(
248 clock_max, /* MHz */
249 power_max, /* mW */
250 10, /* lat1 */
251 10, /* lat2 */
252 control_status, /* control */
253 control_status); /* status */
Lee Leahy77ff0b12015-05-05 15:07:29 -0700254
255 /* Set up ratio and vid ranges for VID calculation */
256 ratio_range_2 = (ratio_turbo - ratio_min) * 2;
257 vid_range_2 = (vid_turbo - vid_min) * 2;
258
259 /* Generate the remaining entries */
260 for (ratio = ratio_min + ((num_entries - 1) * ratio_step);
261 ratio >= ratio_min; ratio -= ratio_step) {
262
263 /* Calculate VID for this ratio */
Angel Ponsaee7ab22020-03-19 00:31:58 +0100264 vid = ((ratio - ratio_min) * vid_range_2) / ratio_range_2 + vid_min;
265
Lee Leahy77ff0b12015-05-05 15:07:29 -0700266 /* Round up if remainder */
267 if (((ratio - ratio_min) * vid_range_2) % ratio_range_2)
268 vid++;
269
270 /* Calculate power at this ratio */
271 power = calculate_power(power_max, ratio_max, ratio);
272 clock = (ratio * pattrs->bclk_khz) / 1000;
273 control_status = (ratio << 8) | (vid & 0xff);
274
Lee Leahy32471722015-04-20 15:20:28 -0700275 acpigen_write_PSS_package(
276 clock, /* MHz */
277 power, /* mW */
278 10, /* lat1 */
279 10, /* lat2 */
280 control_status, /* control */
281 control_status); /* status */
Lee Leahy77ff0b12015-05-05 15:07:29 -0700282 }
283
284 /* Fix package length */
Lee Leahy32471722015-04-20 15:20:28 -0700285 acpigen_pop_len();
Lee Leahy77ff0b12015-05-05 15:07:29 -0700286}
287
Kyösti Mälkkid521b962023-04-12 21:44:49 +0300288static void generate_cpu_entry(int core, int cores_per_package)
289{
290 /* Generate Scope(\_SB) { Device(CPUx */
291 acpigen_write_processor_device(core);
292
293 /* Generate P-state tables */
294 generate_p_state_entries(core);
295
296 /* Generate C-state tables */
297 acpigen_write_CST_package(cstate_map, ARRAY_SIZE(cstate_map));
298
299 /* Generate T-state tables */
300 generate_t_state_entries(core, cores_per_package);
301
302 acpigen_write_processor_device_end();
303}
304
Furquan Shaikh7536a392020-04-24 21:59:21 -0700305void generate_cpu_entries(const struct device *device)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700306{
Lee Leahy32471722015-04-20 15:20:28 -0700307 int core;
Lee Leahy77ff0b12015-05-05 15:07:29 -0700308 const struct pattrs *pattrs = pattrs_get();
309
Kyösti Mälkkid521b962023-04-12 21:44:49 +0300310 for (core = 0; core < pattrs->num_cpus; core++)
311 generate_cpu_entry(core, pattrs->num_cpus);
Arthur Heymans1a9efe32018-11-28 12:20:43 +0100312
313 /* PPKG is usually used for thermal management
314 of the first and only package. */
315 acpigen_write_processor_package("PPKG", 0, pattrs->num_cpus);
316
317 /* Add a method to notify processor nodes */
318 acpigen_write_processor_cnot(pattrs->num_cpus);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700319}
320
Furquan Shaikh0f007d82020-04-24 06:41:18 -0700321unsigned long southcluster_write_acpi_tables(const struct device *device, unsigned long current,
Lee Leahy2bc9cee2015-06-30 15:25:44 -0700322 struct acpi_rsdp *rsdp)
323{
324 acpi_header_t *ssdt2;
325
Julius Wernercd49cce2019-03-05 16:53:33 -0800326 if (!CONFIG(DISABLE_HPET)) {
Frans Hendriksf2af7022018-11-16 12:08:41 +0100327 current = acpi_write_hpet(device, current, rsdp);
328 current = acpi_align_current(current);
329 }
Lee Leahy2bc9cee2015-06-30 15:25:44 -0700330
Lee Leahy2bc9cee2015-06-30 15:25:44 -0700331 ssdt2 = (acpi_header_t *)current;
332 memset(ssdt2, 0, sizeof(acpi_header_t));
333 acpi_create_serialio_ssdt(ssdt2);
334 if (ssdt2->length) {
335 current += ssdt2->length;
336 acpi_add_table(rsdp, ssdt2);
Angel Ponsaee7ab22020-03-19 00:31:58 +0100337 printk(BIOS_DEBUG, "ACPI: * SSDT2 @ %p Length %x\n", ssdt2, ssdt2->length);
Aaron Durbin07a1b282015-12-10 17:07:38 -0600338 current = acpi_align_current(current);
Angel Ponsaee7ab22020-03-19 00:31:58 +0100339
Lee Leahy2bc9cee2015-06-30 15:25:44 -0700340 } else {
341 ssdt2 = NULL;
342 printk(BIOS_DEBUG, "ACPI: * SSDT2 not generated.\n");
343 }
344
345 printk(BIOS_DEBUG, "current = %lx\n", current);
346
347 return current;
348}
349
Aaron Durbin64031672018-04-21 14:45:32 -0600350__weak void acpi_create_serialio_ssdt(acpi_header_t *ssdt)
Lee Leahy2bc9cee2015-06-30 15:25:44 -0700351{
352}