mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-15 19:51:37 +00:00
acpi: Add support for generating processor tables
ACPI has a number of CPU-related tables. Add utility functions to write out the basic packages. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
f37979e7b7
commit
15403289e5
3 changed files with 201 additions and 0 deletions
|
@ -64,7 +64,9 @@ enum {
|
|||
OR_OP = 0x7d,
|
||||
NOT_OP = 0x80,
|
||||
DEVICE_OP = 0x82,
|
||||
PROCESSOR_OP = 0x83,
|
||||
POWER_RES_OP = 0x84,
|
||||
NOTIFY_OP = 0x86,
|
||||
LEQUAL_OP = 0x93,
|
||||
TO_BUFFER_OP = 0x96,
|
||||
TO_INTEGER_OP = 0x99,
|
||||
|
@ -777,4 +779,41 @@ void acpigen_write_dsm_uuid_end(struct acpi_ctx *ctx);
|
|||
*/
|
||||
void acpigen_write_dsm_end(struct acpi_ctx *ctx);
|
||||
|
||||
/**
|
||||
* acpigen_write_processor() - Write a Processor package
|
||||
*
|
||||
* This emits a Processor package header with the required information. The
|
||||
* caller must complete the information and call acpigen_pop_len() at the end
|
||||
*
|
||||
* @ctx: ACPI context pointer
|
||||
* @cpuindex: CPU number
|
||||
* @pblock_addr: PBlk system IO address
|
||||
* @pblock_len: PBlk length
|
||||
*/
|
||||
void acpigen_write_processor(struct acpi_ctx *ctx, uint cpuindex,
|
||||
u32 pblock_addr, uint pblock_len);
|
||||
|
||||
/**
|
||||
* acpigen_write_processor_package() - Write a package containing the processors
|
||||
*
|
||||
* The package containins the name of each processor in the SoC
|
||||
*
|
||||
* @ctx: ACPI context pointer
|
||||
* @name: Package name (.e.g "PPKG")
|
||||
* @first_core: Number of the first core (e.g. 0)
|
||||
* @core_count: Number of cores (e.g. 4)
|
||||
*/
|
||||
void acpigen_write_processor_package(struct acpi_ctx *ctx, const char *name,
|
||||
uint first_core, uint core_count);
|
||||
|
||||
/**
|
||||
* acpigen_write_processor_cnot() - Write a processor notification method
|
||||
*
|
||||
* This writes a method that notifies all CPU cores
|
||||
*
|
||||
* @ctx: ACPI context pointer
|
||||
* @num_cores: Number of CPU cores
|
||||
*/
|
||||
void acpigen_write_processor_cnot(struct acpi_ctx *ctx, const uint num_cores);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
#include <acpi/acpi_table.h>
|
||||
#include <dm/acpi.h>
|
||||
|
||||
/* CPU path format */
|
||||
#define ACPI_CPU_STRING "\\_PR.CP%02d"
|
||||
|
||||
u8 *acpigen_get_current(struct acpi_ctx *ctx)
|
||||
{
|
||||
return ctx->current;
|
||||
|
@ -340,6 +343,58 @@ void acpigen_write_method_serialized(struct acpi_ctx *ctx, const char *name,
|
|||
ACPI_METHOD_SERIALIZED_MASK);
|
||||
}
|
||||
|
||||
void acpigen_write_processor(struct acpi_ctx *ctx, uint cpuindex,
|
||||
u32 pblock_addr, uint pblock_len)
|
||||
{
|
||||
/*
|
||||
* Processor (\_PR.CPnn, cpuindex, pblock_addr, pblock_len)
|
||||
* {
|
||||
*/
|
||||
char pscope[16];
|
||||
|
||||
acpigen_emit_ext_op(ctx, PROCESSOR_OP);
|
||||
acpigen_write_len_f(ctx);
|
||||
|
||||
snprintf(pscope, sizeof(pscope), ACPI_CPU_STRING, cpuindex);
|
||||
acpigen_emit_namestring(ctx, pscope);
|
||||
acpigen_emit_byte(ctx, cpuindex);
|
||||
acpigen_emit_dword(ctx, pblock_addr);
|
||||
acpigen_emit_byte(ctx, pblock_len);
|
||||
}
|
||||
|
||||
void acpigen_write_processor_package(struct acpi_ctx *ctx,
|
||||
const char *const name,
|
||||
const uint first_core,
|
||||
const uint core_count)
|
||||
{
|
||||
uint i;
|
||||
char pscope[16];
|
||||
|
||||
acpigen_write_name(ctx, name);
|
||||
acpigen_write_package(ctx, core_count);
|
||||
for (i = first_core; i < first_core + core_count; ++i) {
|
||||
snprintf(pscope, sizeof(pscope), ACPI_CPU_STRING, i);
|
||||
acpigen_emit_namestring(ctx, pscope);
|
||||
}
|
||||
acpigen_pop_len(ctx);
|
||||
}
|
||||
|
||||
void acpigen_write_processor_cnot(struct acpi_ctx *ctx, const uint num_cores)
|
||||
{
|
||||
int core_id;
|
||||
|
||||
acpigen_write_method(ctx, "\\_PR.CNOT", 1);
|
||||
for (core_id = 0; core_id < num_cores; core_id++) {
|
||||
char buffer[30];
|
||||
|
||||
snprintf(buffer, sizeof(buffer), ACPI_CPU_STRING, core_id);
|
||||
acpigen_emit_byte(ctx, NOTIFY_OP);
|
||||
acpigen_emit_namestring(ctx, buffer);
|
||||
acpigen_emit_byte(ctx, ARG0_OP);
|
||||
}
|
||||
acpigen_pop_len(ctx);
|
||||
}
|
||||
|
||||
void acpigen_write_device(struct acpi_ctx *ctx, const char *name)
|
||||
{
|
||||
acpigen_emit_ext_op(ctx, DEVICE_OP);
|
||||
|
|
|
@ -1343,3 +1343,110 @@ static int dm_test_acpi_write_i2c_dsm(struct unit_test_state *uts)
|
|||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_acpi_write_i2c_dsm, 0);
|
||||
|
||||
/* Test emitting a processor */
|
||||
static int dm_test_acpi_write_processor(struct unit_test_state *uts)
|
||||
{
|
||||
const int cpuindex = 6;
|
||||
const u32 pblock_addr = 0x12345600;
|
||||
const u32 pblock_len = 0x60;
|
||||
struct acpi_ctx *ctx;
|
||||
u8 *ptr;
|
||||
|
||||
ut_assertok(alloc_context(&ctx));
|
||||
|
||||
ptr = acpigen_get_current(ctx);
|
||||
acpigen_write_processor(ctx, cpuindex, pblock_addr, pblock_len);
|
||||
acpigen_pop_len(ctx);
|
||||
|
||||
ut_asserteq(EXT_OP_PREFIX, *ptr++);
|
||||
ut_asserteq(PROCESSOR_OP, *ptr++);
|
||||
ut_asserteq(0x13, acpi_test_get_length(ptr));
|
||||
ptr += 3;
|
||||
ut_asserteq_strn("\\._PR_CP06", (char *)ptr);
|
||||
ptr += 10;
|
||||
ut_asserteq(cpuindex, *ptr++);
|
||||
ut_asserteq(pblock_addr, get_unaligned((u32 *)ptr));
|
||||
ptr += 4;
|
||||
ut_asserteq(pblock_len, *ptr++);
|
||||
|
||||
ut_asserteq_ptr(ptr, ctx->current);
|
||||
|
||||
free_context(&ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_acpi_write_processor, 0);
|
||||
|
||||
/* Test emitting a processor package */
|
||||
static int dm_test_acpi_write_processor_package(struct unit_test_state *uts)
|
||||
{
|
||||
const int core_count = 3;
|
||||
struct acpi_ctx *ctx;
|
||||
u8 *ptr;
|
||||
|
||||
ut_assertok(alloc_context(&ctx));
|
||||
|
||||
ptr = acpigen_get_current(ctx);
|
||||
acpigen_write_processor_package(ctx, "XCPU", 0, core_count);
|
||||
|
||||
ut_asserteq(NAME_OP, *ptr++);
|
||||
ut_asserteq_strn("XCPU", (char *)ptr);
|
||||
ptr += 4;
|
||||
ut_asserteq(PACKAGE_OP, *ptr++);
|
||||
ptr += 3; /* skip length */
|
||||
ut_asserteq(core_count, *ptr++);
|
||||
|
||||
ut_asserteq_strn("\\._PR_CP00", (char *)ptr);
|
||||
ptr += 10;
|
||||
ut_asserteq_strn("\\._PR_CP01", (char *)ptr);
|
||||
ptr += 10;
|
||||
ut_asserteq_strn("\\._PR_CP02", (char *)ptr);
|
||||
ptr += 10;
|
||||
|
||||
ut_asserteq_ptr(ptr, ctx->current);
|
||||
|
||||
free_context(&ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_acpi_write_processor_package, 0);
|
||||
|
||||
/* Test emitting a processor notification package */
|
||||
static int dm_test_acpi_write_processor_cnot(struct unit_test_state *uts)
|
||||
{
|
||||
const int core_count = 3;
|
||||
struct acpi_ctx *ctx;
|
||||
u8 *ptr;
|
||||
|
||||
ut_assertok(alloc_context(&ctx));
|
||||
|
||||
ptr = acpigen_get_current(ctx);
|
||||
acpigen_write_processor_cnot(ctx, core_count);
|
||||
|
||||
ut_asserteq(METHOD_OP, *ptr++);
|
||||
ptr += 3; /* skip length */
|
||||
ut_asserteq_strn("\\._PR_CNOT", (char *)ptr);
|
||||
ptr += 10;
|
||||
ut_asserteq(1, *ptr++);
|
||||
|
||||
ut_asserteq(NOTIFY_OP, *ptr++);
|
||||
ut_asserteq_strn("\\._PR_CP00", (char *)ptr);
|
||||
ptr += 10;
|
||||
ut_asserteq(ARG0_OP, *ptr++);
|
||||
ut_asserteq(NOTIFY_OP, *ptr++);
|
||||
ut_asserteq_strn("\\._PR_CP01", (char *)ptr);
|
||||
ptr += 10;
|
||||
ut_asserteq(ARG0_OP, *ptr++);
|
||||
ut_asserteq(NOTIFY_OP, *ptr++);
|
||||
ut_asserteq_strn("\\._PR_CP02", (char *)ptr);
|
||||
ptr += 10;
|
||||
ut_asserteq(ARG0_OP, *ptr++);
|
||||
|
||||
ut_asserteq_ptr(ptr, ctx->current);
|
||||
|
||||
free_context(&ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_acpi_write_processor_cnot, 0);
|
||||
|
|
Loading…
Add table
Reference in a new issue