1 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <acpi/acpi_gnvs.h>
5 #include <acpi/acpigen.h>
6 #include <arch/ioapic.h>
7 #include <arch/smp/mpspec.h>
8 #include <device/mmio.h>
9 #include <console/console.h>
10 #include <cpu/intel/turbo.h>
11 #include <cpu/x86/msr.h>
12 #include <cpu/x86/smm.h>
13 #include <device/pci.h>
14 #include <drivers/intel/gma/opregion.h>
16 #include <soc/device_nvs.h>
18 #include <soc/iomap.h>
22 #include <soc/pattrs.h>
23 #include <soc/pci_devs.h>
31 #define MWAIT_RES(state, sub_state) \
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, \
40 /* C-state map without S0ix */
41 static const acpi_cstate_t cstate_map
[] = {
44 .ctype
= 1, /* ACPI C1 */
47 .resource
= MWAIT_RES(0, 0),
50 /* C6NS with no L2 shrink */
51 /* NOTE: this substate is above CPUID limit */
52 .ctype
= 2, /* ACPI C2 */
55 .resource
= MWAIT_RES(5, 1),
58 /* C6FS with full L2 shrink */
59 .ctype
= 3, /* ACPI C3 */
60 .latency
= 1500, /* 1.5ms worst case */
62 .resource
= MWAIT_RES(5, 2),
66 size_t size_of_dnvs(void)
68 return sizeof(struct device_nvs
);
71 void soc_fill_gnvs(struct global_nvs
*gnvs
)
73 gnvs
->dpte
= is_devfn_enabled(PCI_DEVFN(PUNIT_DEV
, 0));
75 /* Fill in the Wi-Fi Region ID */
76 if (CONFIG(HAVE_REGULATORY_DOMAIN
))
77 gnvs
->cid1
= wifi_regulatory_domain();
79 gnvs
->cid1
= WRDD_DEFAULT_REGULATORY_DOMAIN
;
82 static u8
soc_madt_sci_irq_polarity(u8 sci_irq
)
85 return MP_IRQ_POLARITY_LOW
;
87 return MP_IRQ_POLARITY_HIGH
;
90 #define ACPI_SCI_IRQ 9
92 void ioapic_get_sci_pin(u8
*gsi
, u8
*irq
, u8
*flags
)
94 u32
*actl
= (u32
*)(ILB_BASE_ADDRESS
+ ACTL
);
95 int sci_irq
= ACPI_SCI_IRQ
;
98 /* Determine how SCI is routed. */
99 scis
= read32(actl
) & SCIS_MASK
;
104 sci_irq
= scis
- SCIS_IRQ9
+ 9;
110 sci_irq
= scis
- SCIS_IRQ20
+ 20;
113 printk(BIOS_DEBUG
, "Invalid SCI route! Defaulting to IRQ%d.\n", sci_irq
);
118 *irq
= (sci_irq
< 16) ? sci_irq
: ACPI_SCI_IRQ
;
119 *flags
= MP_IRQ_TRIGGER_LEVEL
| soc_madt_sci_irq_polarity(sci_irq
);
121 printk(BIOS_DEBUG
, "SCI is IRQ %d, GSI %d\n", *irq
, *gsi
);
124 static acpi_tstate_t soc_tss_table
[] = {
125 { 100, 1000, 0, 0x00, 0 },
126 { 88, 875, 0, 0x1e, 0 },
127 { 75, 750, 0, 0x1c, 0 },
128 { 63, 625, 0, 0x1a, 0 },
129 { 50, 500, 0, 0x18, 0 },
130 { 38, 375, 0, 0x16, 0 },
131 { 25, 250, 0, 0x14, 0 },
132 { 13, 125, 0, 0x12, 0 },
135 static void generate_t_state_entries(int core
, int cores_per_package
)
137 /* Indicate SW_ALL coordination for T-states */
138 acpigen_write_TSD_package(core
, cores_per_package
, SW_ALL
);
140 /* Indicate FFixedHW so OS will use MSR */
141 acpigen_write_empty_PTC();
143 /* Set NVS controlled T-state limit */
144 acpigen_write_TPC("\\TLVL");
146 /* Write TSS table for MSR access */
147 acpigen_write_TSS_package(ARRAY_SIZE(soc_tss_table
), soc_tss_table
);
150 static int calculate_power(int tdp
, int p1_ratio
, int ratio
)
155 * M = ((1.1 - ((p1_ratio - ratio) * 0.00625)) / 1.1) ^ 2
158 m
= (110000 - ((p1_ratio
- ratio
) * 625)) / 11;
162 * Power = (ratio / p1_ratio) * m * TDP
164 power
= ((ratio
* 100000 / p1_ratio
) / 100);
165 power
*= (m
/ 100) * (tdp
/ 1000);
171 static void generate_p_state_entries(int core
)
173 int ratio_min
, ratio_max
, ratio_turbo
, ratio_step
, ratio_range_2
;
174 int coord_type
, power_max
, power_unit
, num_entries
;
175 int ratio
, power
, clock
, clock_max
;
176 int vid
, vid_turbo
, vid_min
, vid_max
, vid_range_2
;
178 const struct pattrs
*pattrs
= pattrs_get();
181 /* Inputs from CPU attributes */
182 ratio_max
= pattrs
->iacore_ratios
[IACORE_MAX
];
183 ratio_min
= pattrs
->iacore_ratios
[IACORE_LFM
];
184 vid_max
= pattrs
->iacore_vids
[IACORE_MAX
];
185 vid_min
= pattrs
->iacore_vids
[IACORE_LFM
];
187 /* Set P-states coordination type based on MSR disable bit */
188 coord_type
= (pattrs
->num_cpus
> 2) ? SW_ALL
: HW_ALL
;
190 /* Max Non-Turbo Frequency */
191 clock_max
= (ratio_max
* pattrs
->bclk_khz
) / 1000;
193 /* Calculate CPU TDP in mW */
194 msr
= rdmsr(MSR_PKG_POWER_SKU_UNIT
);
195 power_unit
= 1 << (msr
.lo
& 0xf);
196 msr
= rdmsr(MSR_PKG_POWER_LIMIT
);
197 power_max
= ((msr
.lo
& 0x7fff) / power_unit
) * 1000;
199 /* Write _PCT indicating use of FFixedHW */
200 acpigen_write_empty_PCT();
202 /* Write _PPC with NVS specified limit on supported P-state */
203 acpigen_write_PPC_NVS();
205 /* Write PSD indicating configured coordination type */
206 acpigen_write_PSD_package(core
, 1, coord_type
);
208 /* Add P-state entries in _PSS table */
209 acpigen_write_name("_PSS");
211 /* Determine ratio points */
213 num_entries
= (ratio_max
- ratio_min
) / ratio_step
;
214 while (num_entries
> 15) { /* ACPI max is 15 ratios */
219 /* P[T] is Turbo state if enabled */
220 if (get_turbo_state() == TURBO_ENABLED
) {
221 /* _PSS package count including Turbo */
222 acpigen_write_package(num_entries
+ 2);
224 ratio_turbo
= pattrs
->iacore_ratios
[IACORE_TURBO
];
225 vid_turbo
= pattrs
->iacore_vids
[IACORE_TURBO
];
226 control_status
= (ratio_turbo
<< 8) | vid_turbo
;
228 /* Add entry for Turbo ratio */
229 acpigen_write_PSS_package(
230 clock_max
+ 1, /* MHz */
234 control_status
, /* control */
235 control_status
); /* status */
237 /* _PSS package count without Turbo */
238 acpigen_write_package(num_entries
+ 1);
239 ratio_turbo
= ratio_max
;
243 /* First regular entry is max non-turbo ratio */
244 control_status
= (ratio_max
<< 8) | vid_max
;
245 acpigen_write_PSS_package(
250 control_status
, /* control */
251 control_status
); /* status */
253 /* Set up ratio and vid ranges for VID calculation */
254 ratio_range_2
= (ratio_turbo
- ratio_min
) * 2;
255 vid_range_2
= (vid_turbo
- vid_min
) * 2;
257 /* Generate the remaining entries */
258 for (ratio
= ratio_min
+ ((num_entries
- 1) * ratio_step
);
259 ratio
>= ratio_min
; ratio
-= ratio_step
) {
260 /* Calculate VID for this ratio */
261 vid
= ((ratio
- ratio_min
) * vid_range_2
) / ratio_range_2
+ vid_min
;
263 /* Round up if remainder */
264 if (((ratio
- ratio_min
) * vid_range_2
) % ratio_range_2
)
267 /* Calculate power at this ratio */
268 power
= calculate_power(power_max
, ratio_max
, ratio
);
269 clock
= (ratio
* pattrs
->bclk_khz
) / 1000;
270 control_status
= (ratio
<< 8) | (vid
& 0xff);
272 acpigen_write_PSS_package(
277 control_status
, /* control */
278 control_status
); /* status */
281 /* Fix package length */
285 static void generate_cpu_entry(int core
, int cores_per_package
)
287 /* Generate Scope(\_SB) { Device(CPUx */
288 acpigen_write_processor_device(core
);
290 /* Generate P-state tables */
291 generate_p_state_entries(core
);
293 /* Generate C-state tables */
294 acpigen_write_CST_package(cstate_map
, ARRAY_SIZE(cstate_map
));
296 /* Generate T-state tables */
297 generate_t_state_entries(core
, cores_per_package
);
299 acpigen_write_processor_device_end();
302 void generate_cpu_entries(const struct device
*device
)
305 const struct pattrs
*pattrs
= pattrs_get();
307 for (core
= 0; core
< pattrs
->num_cpus
; core
++)
308 generate_cpu_entry(core
, pattrs
->num_cpus
);
310 /* PPKG is usually used for thermal management
311 of the first and only package. */
312 acpigen_write_processor_package("PPKG", 0, pattrs
->num_cpus
);
314 /* Add a method to notify processor nodes */
315 acpigen_write_processor_cnot(pattrs
->num_cpus
);
318 unsigned long southcluster_write_acpi_tables(const struct device
*device
, unsigned long current
,
319 struct acpi_rsdp
*rsdp
)
321 acpi_header_t
*ssdt2
;
323 if (!CONFIG(DISABLE_HPET
)) {
324 current
= acpi_write_hpet(device
, current
, rsdp
);
325 current
= acpi_align_current(current
);
328 ssdt2
= (acpi_header_t
*)current
;
329 memset(ssdt2
, 0, sizeof(acpi_header_t
));
330 acpi_create_serialio_ssdt(ssdt2
);
332 current
+= ssdt2
->length
;
333 acpi_add_table(rsdp
, ssdt2
);
334 printk(BIOS_DEBUG
, "ACPI: * SSDT2 @ %p Length %x\n", ssdt2
, ssdt2
->length
);
335 current
= acpi_align_current(current
);
339 printk(BIOS_DEBUG
, "ACPI: * SSDT2 not generated.\n");
342 printk(BIOS_DEBUG
, "current = %lx\n", current
);
347 __weak
void acpi_create_serialio_ssdt(acpi_header_t
*ssdt
)