blob: ad324520a0595513c46c03cc8444b3644e92489a [file] [log] [blame]
Martin Roth433659a2014-05-12 21:55:00 -06001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2009 coresystems GmbH
5 * Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
6 * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; version 2 of
11 * the License.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
Martin Roth433659a2014-05-12 21:55:00 -060017 */
18
19#include <types.h>
20#include <console/console.h>
21#include <arch/acpi.h>
22#include <arch/acpigen.h>
23#include <arch/cpu.h>
24#include <cpu/x86/msr.h>
Martin Rothbd88fa02015-11-26 17:46:45 -070025#include <cpu/x86/smm.h>
Martin Roth433659a2014-05-12 21:55:00 -060026#include <cpu/intel/speedstep.h>
27#include <cpu/intel/turbo.h>
28#include <arch/smp/mpspec.h>
29#include <device/device.h>
30#include <device/pci.h>
Ben Gardnerfa6014a2015-12-08 21:20:25 -060031#include <soc/baytrail.h>
Ben Gardnerfa6014a2015-12-08 21:20:25 -060032#include <soc/pci_devs.h>
33#include <soc/acpi.h>
Martin Roth433659a2014-05-12 21:55:00 -060034#include <string.h>
Ben Gardnerfa6014a2015-12-08 21:20:25 -060035#include <soc/iomap.h>
36#include <soc/lpc.h>
Ben Gardnerfa6014a2015-12-08 21:20:25 -060037#include <soc/pmc.h>
38#include <soc/irq.h>
39#include <soc/iosf.h>
Martin Roth433659a2014-05-12 21:55:00 -060040#include <arch/io.h>
Ben Gardnerfa6014a2015-12-08 21:20:25 -060041#include <soc/msr.h>
42#include <soc/pattrs.h>
Martin Roth433659a2014-05-12 21:55:00 -060043#include <cbmem.h>
Elyes HAOUAS26071aa2019-02-15 08:21:33 +010044#include <version.h>
Martin Roth433659a2014-05-12 21:55:00 -060045
46#include "chip.h"
47
48#define MWAIT_RES(state, sub_state) \
49 { \
50 .addrl = (((state) << 4) | (sub_state)), \
51 .space_id = ACPI_ADDRESS_SPACE_FIXED, \
52 .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, \
53 .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, \
54 .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD, \
55 }
56
57/* C-state map without S0ix */
58static acpi_cstate_t cstate_map[] = {
59 {
60 /* C1 */
61 .ctype = 1, /* ACPI C1 */
62 .latency = 1,
63 .power = 1000,
64 .resource = MWAIT_RES(0, 0),
65 },
66 {
67 /* C6NS with no L2 shrink */
68 /* NOTE: this substate is above CPUID limit */
69 .ctype = 2, /* ACPI C2 */
70 .latency = 500,
71 .power = 10,
72 .resource = MWAIT_RES(5, 1),
73 },
74 {
75 /* C6FS with full L2 shrink */
76 .ctype = 3, /* ACPI C3 */
77 .latency = 1500, /* 1.5ms worst case */
78 .power = 10,
79 .resource = MWAIT_RES(5, 2),
80 }
81};
82
83void acpi_init_gnvs(global_nvs_t *gnvs)
84{
Martin Roth433659a2014-05-12 21:55:00 -060085 /* CPU core count */
86 gnvs->pcnt = dev_count_cpu();
87
88 /* Top of Low Memory (start of resource allocation) */
89 gnvs->tolm = nc_read_top_of_low_memory();
90
91#if IS_ENABLED(CONFIG_CONSOLE_CBMEM)
92 /* Update the mem console pointer. */
93 gnvs->cbmc = (u32)cbmem_find(CBMEM_ID_CONSOLE);
94#endif
95}
96
97static int acpi_sci_irq(void)
98{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080099 u32 *actl = (u32 *)(ILB_BASE_ADDRESS + ACTL);
Martin Roth433659a2014-05-12 21:55:00 -0600100 int scis;
101 static int sci_irq;
102
103 if (sci_irq)
104 return sci_irq;
105
106 /* Determine how SCI is routed. */
107 scis = read32(actl) & SCIS_MASK;
108 switch (scis) {
109 case SCIS_IRQ9:
110 case SCIS_IRQ10:
111 case SCIS_IRQ11:
112 sci_irq = scis - SCIS_IRQ9 + 9;
113 break;
114 case SCIS_IRQ20:
115 case SCIS_IRQ21:
116 case SCIS_IRQ22:
117 case SCIS_IRQ23:
118 sci_irq = scis - SCIS_IRQ20 + 20;
119 break;
120 default:
121 printk(BIOS_DEBUG, "Invalid SCI route! Defaulting to IRQ9.\n");
122 sci_irq = 9;
123 break;
124 }
125
126 printk(BIOS_DEBUG, "SCI is IRQ%d\n", sci_irq);
127 return sci_irq;
128}
129
130void acpi_create_intel_hpet(acpi_hpet_t * hpet)
131{
132 acpi_header_t *header = &(hpet->header);
133 acpi_addr_t *addr = &(hpet->addr);
134
135 memset((void *) hpet, 0, sizeof(acpi_hpet_t));
136
137 /* fill out header fields */
138 memcpy(header->signature, "HPET", 4);
139 memcpy(header->oem_id, OEM_ID, 6);
140 memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
141 memcpy(header->asl_compiler_id, ASLC, 4);
142
143 header->length = sizeof(acpi_hpet_t);
Marc Jones8abf6ae2018-08-22 19:08:52 -0600144 header->revision = get_acpi_table_revision(HPET);
Martin Roth433659a2014-05-12 21:55:00 -0600145
146 /* fill out HPET address */
147 addr->space_id = 0; /* Memory */
148 addr->bit_width = 64;
149 addr->bit_offset = 0;
150 addr->addrl = (unsigned long long)HPET_BASE_ADDRESS & 0xffffffff;
151 addr->addrh = (unsigned long long)HPET_BASE_ADDRESS >> 32;
152
153 hpet->id = 0x8086a201; /* Intel */
154 hpet->number = 0x00;
155 hpet->min_tick = 0x0080;
156
157 header->checksum =
158 acpi_checksum((void *) hpet, sizeof(acpi_hpet_t));
159}
160
161unsigned long acpi_fill_mcfg(unsigned long current)
162{
163 current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current,
164 MCFG_BASE_ADDRESS, 0, 0, 255);
165 return current;
166}
167
168/**
169 * Fill in the fadt with generic values that can be overridden later.
170 */
171
172typedef struct soc_intel_fsp_baytrail_config config_t;
173
174void acpi_fill_in_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt)
175{
176 acpi_header_t *header = &(fadt->header);
Kyösti Mälkkie7377552018-06-21 16:20:55 +0300177 struct device *lpcdev = pcidev_path_on_root(FADT_SOC_LPC_DEVFN);
Martin Roth433659a2014-05-12 21:55:00 -0600178 u16 pmbase = pci_read_config16(lpcdev, ABASE) & 0xfff0;
179 config_t *config = lpcdev->chip_info;
180
181 memset((void *) fadt, 0, sizeof(acpi_fadt_t));
182
183 /*
184 * Reference section 5.2.9 Fixed ACPI Description Table (FADT)
185 * in the ACPI 3.0b specification.
186 */
187
188 /* FADT Header Structure */
189 memcpy(header->signature, "FACP", 4);
190 header->length = sizeof(acpi_fadt_t);
Marc Jonesf9ea7ed2018-08-22 18:59:26 -0600191 header->revision = get_acpi_table_revision(FADT);
Martin Roth433659a2014-05-12 21:55:00 -0600192 memcpy(header->oem_id, OEM_ID, 6);
193 memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
194 memcpy(header->asl_compiler_id, ASLC, 4);
Elyes HAOUAS26071aa2019-02-15 08:21:33 +0100195 header->asl_compiler_revision = asl_revision;
Martin Roth433659a2014-05-12 21:55:00 -0600196
197 /* ACPI Pointers */
198 fadt->firmware_ctrl = (unsigned long) facs;
199 fadt->dsdt = (unsigned long) dsdt;
200
201 fadt->model = 0; /* reserved, should be 0 ACPI 3.0 */
202 fadt->preferred_pm_profile = config->fadt_pm_profile; /* unknown is default */
203
204 /* System Management */
205 fadt->sci_int = acpi_sci_irq();
Martin Rothbd88fa02015-11-26 17:46:45 -0700206
Martin Roth433659a2014-05-12 21:55:00 -0600207 fadt->smi_cmd = APM_CNT;
208 fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
209 fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
Martin Roth433659a2014-05-12 21:55:00 -0600210
211 /* Power Control */
212 fadt->s4bios_req = 0x00;
213 fadt->pstate_cnt = 0x00;
214
215 /* Control Registers - Base Address */
216 fadt->pm1a_evt_blk = pmbase + PM1_STS;
217 fadt->pm1b_evt_blk = 0x00; /* Not Used */
218 fadt->pm1a_cnt_blk = pmbase + PM1_CNT;
219 fadt->pm1b_cnt_blk = 0x00; /* Not Used */
220 fadt->pm2_cnt_blk = pmbase + PM2A_CNT_BLK;
221 fadt->pm_tmr_blk = pmbase + PM1_TMR;
222 fadt->gpe0_blk = pmbase + GPE0_STS;
223 fadt->gpe1_blk = 0x00; /* Not Used */
224
225 /* Control Registers - Length */
226 fadt->pm1_evt_len = 4; /* 32 bits */
227 fadt->pm1_cnt_len = 2; /* 32 bit register, 16 bits used */
228 fadt->pm2_cnt_len = 1; /* 8 bits */
229 fadt->pm_tmr_len = 4; /* 32 bits */
230 fadt->gpe0_blk_len = 8; /* 64 bits */
231 fadt->gpe1_blk_len = 0;
232 fadt->gpe1_base = 0;
233 fadt->cst_cnt = 0;
234 fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
235 fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED;
236 fadt->flush_size = 0; /* set to 0 if WBINVD is 1 in flags */
237 fadt->flush_stride = 0; /* set to 0 if WBINVD is 1 in flags */
238 fadt->duty_offset = 1;
239 fadt->duty_width = 0;
240
241 /* RTC Registers */
242 fadt->day_alrm = 0x0D;
243 fadt->mon_alrm = 0x00;
244 fadt->century = 0x00;
245 fadt->iapc_boot_arch = config->fadt_boot_arch; /* legacy free default */
246
247 fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
248 ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON |
249 ACPI_FADT_RESET_REGISTER | ACPI_FADT_SLEEP_TYPE |
250 ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK;
251
252 /* Reset Register */
253 fadt->reset_reg.space_id = ACPI_ADDRESS_SPACE_IO;
254 fadt->reset_reg.bit_width = 8;
255 fadt->reset_reg.bit_offset = 0;
256 fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
257 fadt->reset_reg.addrl = 0xCF9;
258 fadt->reset_reg.addrh = 0x00;
259 fadt->reset_value = 6;
260
Elyes HAOUASf5b974e2018-11-10 20:29:08 +0100261 fadt->ARM_boot_arch = 0; /* MUST be 0 ACPI 3.0 */
262 fadt->FADT_MinorVersion = 0; /* MUST be 0 ACPI 3.0 */
Martin Roth433659a2014-05-12 21:55:00 -0600263
264 /* Extended ACPI Pointers */
265 fadt->x_firmware_ctl_l = (unsigned long)facs;
266 fadt->x_firmware_ctl_h = 0x00;
267 fadt->x_dsdt_l = (unsigned long)dsdt;
268 fadt->x_dsdt_h = 0x00;
269
270 /* PM1 Status & PM1 Enable */
271 fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
272 fadt->x_pm1a_evt_blk.bit_width = 32;
273 fadt->x_pm1a_evt_blk.bit_offset = 0;
274 fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
275 fadt->x_pm1a_evt_blk.addrl = fadt->pm1a_evt_blk;
276 fadt->x_pm1a_evt_blk.addrh = 0x00;
277
278 fadt->x_pm1b_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
279 fadt->x_pm1b_evt_blk.bit_width = 0;
280 fadt->x_pm1b_evt_blk.bit_offset = 0;
281 fadt->x_pm1b_evt_blk.access_size = 0;
282 fadt->x_pm1b_evt_blk.addrl = fadt->pm1b_evt_blk;
283 fadt->x_pm1b_evt_blk.addrh = 0x00;
284
285 /* PM1 Control Registers */
286 fadt->x_pm1a_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
287 fadt->x_pm1a_cnt_blk.bit_width = 16;
288 fadt->x_pm1a_cnt_blk.bit_offset = 0;
289 fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
290 fadt->x_pm1a_cnt_blk.addrl = fadt->pm1a_cnt_blk;
291 fadt->x_pm1a_cnt_blk.addrh = 0x00;
292
293 fadt->x_pm1b_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
294 fadt->x_pm1b_cnt_blk.bit_width = 0;
295 fadt->x_pm1b_cnt_blk.bit_offset = 0;
296 fadt->x_pm1b_cnt_blk.access_size = 0;
297 fadt->x_pm1b_cnt_blk.addrl = fadt->pm1b_cnt_blk;
298 fadt->x_pm1b_cnt_blk.addrh = 0x00;
299
300 /* PM2 Control Registers */
301 fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
302 fadt->x_pm2_cnt_blk.bit_width = 8;
303 fadt->x_pm2_cnt_blk.bit_offset = 0;
304 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
305 fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
306 fadt->x_pm2_cnt_blk.addrh = 0x00;
307
308 /* PM1 Timer Register */
309 fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
310 fadt->x_pm_tmr_blk.bit_width = 32;
311 fadt->x_pm_tmr_blk.bit_offset = 0;
312 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
313 fadt->x_pm_tmr_blk.addrl = fadt->pm_tmr_blk;
314 fadt->x_pm_tmr_blk.addrh = 0x00;
315
316 /* General-Purpose Event Registers */
317 fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO;
318 fadt->x_gpe0_blk.bit_width = 64; /* EventStatus + EventEnable */
319 fadt->x_gpe0_blk.bit_offset = 0;
320 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
321 fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
322 fadt->x_gpe0_blk.addrh = 0x00;
323
324 fadt->x_gpe1_blk.space_id = ACPI_ADDRESS_SPACE_IO;
325 fadt->x_gpe1_blk.bit_width = 0;
326 fadt->x_gpe1_blk.bit_offset = 0;
327 fadt->x_gpe1_blk.access_size = 0;
328 fadt->x_gpe1_blk.addrl = fadt->gpe1_blk;
329 fadt->x_gpe1_blk.addrh = 0x00;
330
331 header->checksum =
332 acpi_checksum((void *) fadt, sizeof(acpi_fadt_t));
333}
334static acpi_tstate_t baytrail_tss_table[] = {
335 { 100, 1000, 0, 0x00, 0 },
336 { 88, 875, 0, 0x1e, 0 },
337 { 75, 750, 0, 0x1c, 0 },
338 { 63, 625, 0, 0x1a, 0 },
339 { 50, 500, 0, 0x18, 0 },
340 { 38, 375, 0, 0x16, 0 },
341 { 25, 250, 0, 0x14, 0 },
342 { 13, 125, 0, 0x12, 0 },
343};
344
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100345static void generate_T_state_entries(int core, int cores_per_package)
Martin Roth433659a2014-05-12 21:55:00 -0600346{
Martin Roth433659a2014-05-12 21:55:00 -0600347 /* Indicate SW_ALL coordination for T-states */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100348 acpigen_write_TSD_package(core, cores_per_package, SW_ALL);
Martin Roth433659a2014-05-12 21:55:00 -0600349
350 /* Indicate FFixedHW so OS will use MSR */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100351 acpigen_write_empty_PTC();
Martin Roth433659a2014-05-12 21:55:00 -0600352
353 /* Set NVS controlled T-state limit */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100354 acpigen_write_TPC("\\TLVL");
Martin Roth433659a2014-05-12 21:55:00 -0600355
356 /* Write TSS table for MSR access */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100357 acpigen_write_TSS_package(
Martin Roth433659a2014-05-12 21:55:00 -0600358 ARRAY_SIZE(baytrail_tss_table), baytrail_tss_table);
Martin Roth433659a2014-05-12 21:55:00 -0600359}
360
361static int calculate_power(int tdp, int p1_ratio, int ratio)
362{
363 u32 m;
364 u32 power;
365
366 /*
367 * M = ((1.1 - ((p1_ratio - ratio) * 0.00625)) / 1.1) ^ 2
368 *
369 * Power = (ratio / p1_ratio) * m * tdp
370 */
371
372 m = (110000 - ((p1_ratio - ratio) * 625)) / 11;
373 m = (m * m) / 1000;
374
375 power = ((ratio * 100000 / p1_ratio) / 100);
376 power *= (m / 100) * (tdp / 1000);
377 power /= 1000;
378
379 return (int)power;
380}
381
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200382static void generate_P_state_entries(int core, int cores_per_package)
Martin Roth433659a2014-05-12 21:55:00 -0600383{
Martin Roth433659a2014-05-12 21:55:00 -0600384 int ratio_min, ratio_max, ratio_turbo, ratio_step, ratio_range_2;
385 int coord_type, power_max, power_unit, num_entries;
386 int ratio, power, clock, clock_max;
387 int vid, vid_turbo, vid_min, vid_max, vid_range_2;
388 u32 control_status;
389 const struct pattrs *pattrs = pattrs_get();
390 msr_t msr;
391
392 /* Inputs from CPU attributes */
393 ratio_max = pattrs->iacore_ratios[IACORE_MAX];
394 ratio_min = pattrs->iacore_ratios[IACORE_LFM];
395 vid_max = pattrs->iacore_vids[IACORE_MAX];
396 vid_min = pattrs->iacore_vids[IACORE_LFM];
397
398 /* Hardware coordination of P-states */
399 coord_type = HW_ALL;
400
401 /* Max Non-Turbo Frequency */
402 clock_max = (ratio_max * pattrs->bclk_khz) / 1000;
403
404 /* Calculate CPU TDP in mW */
405 msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
406 power_unit = 1 << (msr.lo & 0xf);
407 msr = rdmsr(MSR_PKG_POWER_LIMIT);
408 power_max = ((msr.lo & 0x7fff) / power_unit) * 1000;
409
410 /* Write _PCT indicating use of FFixedHW */
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200411 acpigen_write_empty_PCT();
Martin Roth433659a2014-05-12 21:55:00 -0600412
413 /* Write _PPC with NVS specified limit on supported P-state */
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200414 acpigen_write_PPC_NVS();
Martin Roth433659a2014-05-12 21:55:00 -0600415
416 /* Write PSD indicating configured coordination type */
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200417 acpigen_write_PSD_package(core, 1, coord_type);
Martin Roth433659a2014-05-12 21:55:00 -0600418
419 /* Add P-state entries in _PSS table */
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200420 acpigen_write_name("_PSS");
Martin Roth433659a2014-05-12 21:55:00 -0600421
422 /* Determine ratio points */
423 ratio_step = 1;
424 num_entries = (ratio_max - ratio_min) / ratio_step;
425 while (num_entries > 15) { /* ACPI max is 15 ratios */
426 ratio_step <<= 1;
427 num_entries >>= 1;
428 }
429
430 /* P[T] is Turbo state if enabled */
431 if (get_turbo_state() == TURBO_ENABLED) {
432 /* _PSS package count including Turbo */
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200433 acpigen_write_package(num_entries + 2);
Martin Roth433659a2014-05-12 21:55:00 -0600434
435 ratio_turbo = pattrs->iacore_ratios[IACORE_TURBO];
436 vid_turbo = pattrs->iacore_vids[IACORE_TURBO];
437 control_status = (ratio_turbo << 8) | vid_turbo;
438
439 /* Add entry for Turbo ratio */
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200440 acpigen_write_PSS_package(
Martin Roth433659a2014-05-12 21:55:00 -0600441 clock_max + 1, /*MHz*/
442 power_max, /*mW*/
443 10, /*lat1*/
444 10, /*lat2*/
445 control_status, /*control*/
446 control_status); /*status*/
447 } else {
448 /* _PSS package count without Turbo */
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200449 acpigen_write_package(num_entries + 1);
Martin Roth433659a2014-05-12 21:55:00 -0600450 ratio_turbo = ratio_max;
451 vid_turbo = vid_max;
452 }
453
454 /* First regular entry is max non-turbo ratio */
455 control_status = (ratio_max << 8) | vid_max;
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200456 acpigen_write_PSS_package(
Martin Roth433659a2014-05-12 21:55:00 -0600457 clock_max, /*MHz*/
458 power_max, /*mW*/
459 10, /*lat1*/
460 10, /*lat2*/
461 control_status, /*control */
462 control_status); /*status*/
463
464 /* Set up ratio and vid ranges for VID calculation */
465 ratio_range_2 = (ratio_turbo - ratio_min) * 2;
466 vid_range_2 = (vid_turbo - vid_min) * 2;
467
468 /* Generate the remaining entries */
469 for (ratio = ratio_min + ((num_entries - 1) * ratio_step);
470 ratio >= ratio_min; ratio -= ratio_step) {
471
472 /* Calculate VID for this ratio */
473 vid = ((ratio - ratio_min) * vid_range_2) /
474 ratio_range_2 + vid_min;
475 /* Round up if remainder */
476 if (((ratio - ratio_min) * vid_range_2) % ratio_range_2)
477 vid++;
478
479 /* Calculate power at this ratio */
480 power = calculate_power(power_max, ratio_max, ratio);
481 clock = (ratio * pattrs->bclk_khz) / 1000;
482 control_status = (ratio << 8) | (vid & 0xff);
483
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200484 acpigen_write_PSS_package(
Martin Roth433659a2014-05-12 21:55:00 -0600485 clock, /*MHz*/
486 power, /*mW*/
487 10, /*lat1*/
488 10, /*lat2*/
489 control_status, /*control*/
490 control_status); /*status*/
491 }
492
493 /* Fix package length */
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200494 acpigen_pop_len();
Martin Roth433659a2014-05-12 21:55:00 -0600495}
496
Elyes HAOUAS509edac2018-05-27 17:48:32 +0200497void generate_cpu_entries(struct device *device)
Martin Roth433659a2014-05-12 21:55:00 -0600498{
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200499 int core;
Martin Roth433659a2014-05-12 21:55:00 -0600500 int pcontrol_blk = get_pmbase(), plen = 6;
501 const struct pattrs *pattrs = pattrs_get();
502
503 for (core=0; core<pattrs->num_cpus; core++) {
504 if (core > 0) {
505 pcontrol_blk = 0;
506 plen = 0;
507 }
508
509 /* Generate processor \_PR.CPUx */
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200510 acpigen_write_processor(
Martin Roth433659a2014-05-12 21:55:00 -0600511 core, pcontrol_blk, plen);
512
513 /* Generate P-state tables */
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200514 generate_P_state_entries(
Martin Roth433659a2014-05-12 21:55:00 -0600515 core, pattrs->num_cpus);
516
517 /* Generate C-state tables */
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200518 acpigen_write_CST_package(
Martin Roth433659a2014-05-12 21:55:00 -0600519 cstate_map, ARRAY_SIZE(cstate_map));
520
521 /* Generate T-state tables */
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200522 generate_T_state_entries(
Martin Roth433659a2014-05-12 21:55:00 -0600523 core, pattrs->num_cpus);
524
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200525 acpigen_pop_len();
Martin Roth433659a2014-05-12 21:55:00 -0600526 }
Arthur Heymanscf9fc1d2018-11-28 13:58:57 +0100527
528 /* PPKG is usually used for thermal management
529 of the first and only package. */
530 acpigen_write_processor_package("PPKG", 0, pattrs->num_cpus);
531
532 /* Add a method to notify processor nodes */
533 acpigen_write_processor_cnot(pattrs->num_cpus);
Martin Roth433659a2014-05-12 21:55:00 -0600534}
535
536unsigned long acpi_madt_irq_overrides(unsigned long current)
537{
538 int sci_irq = acpi_sci_irq();
539 acpi_madt_irqoverride_t *irqovr;
540 uint16_t sci_flags = MP_IRQ_TRIGGER_LEVEL;
541
542 /* INT_SRC_OVR */
543 irqovr = (void *)current;
544 current += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
545
546 if (sci_irq >= 20)
547 sci_flags |= MP_IRQ_POLARITY_LOW;
548 else
549 sci_flags |= MP_IRQ_POLARITY_HIGH;
550
551 irqovr = (void *)current;
552 current += acpi_create_madt_irqoverride(irqovr, 0, sci_irq, sci_irq,
553 sci_flags);
554
555 return current;
556}
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200557
Elyes HAOUAS509edac2018-05-27 17:48:32 +0200558unsigned long southcluster_write_acpi_tables(struct device *device,
Alexander Couzens83fc32f2015-04-12 22:28:37 +0200559 unsigned long current,
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200560 struct acpi_rsdp *rsdp)
561{
562 acpi_header_t *ssdt2;
563
Alexander Couzens83fc32f2015-04-12 22:28:37 +0200564 current = acpi_write_hpet(device, current, rsdp);
Aaron Durbin07a1b282015-12-10 17:07:38 -0600565 current = acpi_align_current(current);
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200566
567 ssdt2 = (acpi_header_t *)current;
568 memset(ssdt2, 0, sizeof(acpi_header_t));
569 acpi_create_serialio_ssdt(ssdt2);
570 if (ssdt2->length) {
571 current += ssdt2->length;
572 acpi_add_table(rsdp, ssdt2);
573 printk(BIOS_DEBUG, "ACPI: * SSDT2 @ %p Length %x\n",ssdt2,
574 ssdt2->length);
Aaron Durbin07a1b282015-12-10 17:07:38 -0600575 current = acpi_align_current(current);
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200576 } else {
577 ssdt2 = NULL;
578 printk(BIOS_DEBUG, "ACPI: * SSDT2 not generated.\n");
579 }
580
581 printk(BIOS_DEBUG, "current = %lx\n", current);
582
583 return current;
584}
585
Elyes HAOUAS509edac2018-05-27 17:48:32 +0200586void southcluster_inject_dsdt(struct device *device)
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200587{
588 global_nvs_t *gnvs;
589
590 gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
591 if (!gnvs) {
592 gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof (*gnvs));
593 if (gnvs)
594 memset(gnvs, 0, sizeof(*gnvs));
595 }
596
597 if (gnvs) {
598 acpi_create_gnvs(gnvs);
Vladimir Serbinenko7fb149d2014-10-08 22:56:27 +0200599 /* And tell SMI about it */
600 smm_setup_structures(gnvs, NULL, NULL);
601
602 /* Add it to DSDT. */
603 acpigen_write_scope("\\");
604 acpigen_write_name_dword("NVSA", (u32) gnvs);
605 acpigen_pop_len();
606 }
607}