blob: d8af0c92445e925d7366e95d5652ac030a9f7cce [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
#include <acpi/acpi.h>
#include <acpi/acpigen.h>
#include <amdblocks/cpu.h>
#include <console/console.h>
#include <cpu/amd/msr.h>
#include <cpu/x86/msr.h>
#include <types.h>
static void write_cstate_entry(acpi_cstate_t *entry, const acpi_cstate_t *data,
uint32_t cstate_io_base_address)
{
if (!data->ctype) {
printk(BIOS_WARNING, "Invalid C-state data; skipping entry.\n");
return;
}
entry->ctype = data->ctype;
entry->latency = data->latency;
entry->power = data->power;
if (data->ctype == 1) {
entry->resource = (acpi_addr_t){
.space_id = ACPI_ADDRESS_SPACE_FIXED,
.bit_width = 2,
.bit_offset = 2,
.addrl = 0,
.addrh = 0,
};
} else {
entry->resource = (acpi_addr_t){
.space_id = ACPI_ADDRESS_SPACE_IO,
.bit_width = 8,
.bit_offset = 0,
/* ctype is 1-indexed while the offset into cstate_io_base_address is
0-indexed */
.addrl = cstate_io_base_address + data->ctype - 1,
.addrh = 0,
.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS,
};
}
}
size_t get_cstate_info(acpi_cstate_t *cstate_values)
{
size_t i;
size_t cstate_count;
uint32_t cstate_io_base_address =
rdmsr(MSR_CSTATE_ADDRESS).lo & MSR_CSTATE_ADDRESS_MASK;
const acpi_cstate_t *cstate_config = get_cstate_config_data(&cstate_count);
if (cstate_count > MAX_CSTATE_COUNT) {
printk(BIOS_WARNING, "cstate_info array has too many entries. "
"Skipping last %zu entries.\n",
cstate_count - MAX_CSTATE_COUNT);
cstate_count = MAX_CSTATE_COUNT;
}
for (i = 0; i < cstate_count; i++) {
write_cstate_entry(&cstate_values[i], &cstate_config[i], cstate_io_base_address);
}
return i;
}