mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-09-28 23:50:26 +09:00
acpi: Add support for various misc ACPI opcodes
Add more functions to handle some miscellaneous ACPI opcodes. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Wolfgang Wallner <wolfgang.wallner@br-automation.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
parent
0667900049
commit
9c70e7e556
@ -17,6 +17,9 @@ struct acpi_ctx;
|
|||||||
/* Top 4 bits of the value used to indicate a three-byte length value */
|
/* Top 4 bits of the value used to indicate a three-byte length value */
|
||||||
#define ACPI_PKG_LEN_3_BYTES 0x80
|
#define ACPI_PKG_LEN_3_BYTES 0x80
|
||||||
|
|
||||||
|
#define ACPI_METHOD_NARGS_MASK 0x7
|
||||||
|
#define ACPI_METHOD_SERIALIZED_MASK BIT(3)
|
||||||
|
|
||||||
/* ACPI Op/Prefix codes */
|
/* ACPI Op/Prefix codes */
|
||||||
enum {
|
enum {
|
||||||
ZERO_OP = 0x00,
|
ZERO_OP = 0x00,
|
||||||
@ -29,9 +32,26 @@ enum {
|
|||||||
QWORD_PREFIX = 0x0e,
|
QWORD_PREFIX = 0x0e,
|
||||||
BUFFER_OP = 0x11,
|
BUFFER_OP = 0x11,
|
||||||
PACKAGE_OP = 0x12,
|
PACKAGE_OP = 0x12,
|
||||||
|
METHOD_OP = 0x14,
|
||||||
|
SLEEP_OP = 0x22,
|
||||||
DUAL_NAME_PREFIX = 0x2e,
|
DUAL_NAME_PREFIX = 0x2e,
|
||||||
MULTI_NAME_PREFIX = 0x2f,
|
MULTI_NAME_PREFIX = 0x2f,
|
||||||
|
DEBUG_OP = 0x31,
|
||||||
|
EXT_OP_PREFIX = 0x5b,
|
||||||
ROOT_PREFIX = 0x5c,
|
ROOT_PREFIX = 0x5c,
|
||||||
|
LOCAL0_OP = 0x60,
|
||||||
|
LOCAL1_OP = 0x61,
|
||||||
|
LOCAL2_OP = 0x62,
|
||||||
|
LOCAL3_OP = 0x63,
|
||||||
|
LOCAL4_OP = 0x64,
|
||||||
|
LOCAL5_OP = 0x65,
|
||||||
|
LOCAL6_OP = 0x66,
|
||||||
|
LOCAL7_OP = 0x67,
|
||||||
|
STORE_OP = 0x70,
|
||||||
|
AND_OP = 0x7b,
|
||||||
|
OR_OP = 0x7d,
|
||||||
|
NOT_OP = 0x80,
|
||||||
|
RETURN_OP = 0xa4,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -204,4 +224,101 @@ void acpigen_write_name(struct acpi_ctx *ctx, const char *namepath);
|
|||||||
*/
|
*/
|
||||||
int acpigen_write_uuid(struct acpi_ctx *ctx, const char *uuid);
|
int acpigen_write_uuid(struct acpi_ctx *ctx, const char *uuid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* acpigen_emit_ext_op() - Emit an extended op with the EXT_OP_PREFIX prefix
|
||||||
|
*
|
||||||
|
* @ctx: ACPI context pointer
|
||||||
|
* @op: Operation code (e.g. SLEEP_OP)
|
||||||
|
*/
|
||||||
|
void acpigen_emit_ext_op(struct acpi_ctx *ctx, uint op);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* acpigen_write_method() - Write a method header
|
||||||
|
*
|
||||||
|
* @ctx: ACPI context pointer
|
||||||
|
* @name: Method name (4 characters)
|
||||||
|
* @nargs: Number of method arguments (0 if none)
|
||||||
|
*/
|
||||||
|
void acpigen_write_method(struct acpi_ctx *ctx, const char *name, int nargs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* acpigen_write_method_serialized() - Write a method header
|
||||||
|
*
|
||||||
|
* This sets the 'serialized' flag so that the method is thread-safe
|
||||||
|
*
|
||||||
|
* @ctx: ACPI context pointer
|
||||||
|
* @name: Method name (4 characters)
|
||||||
|
* @nargs: Number of method arguments (0 if none)
|
||||||
|
*/
|
||||||
|
void acpigen_write_method_serialized(struct acpi_ctx *ctx, const char *name,
|
||||||
|
int nargs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* acpigen_write_sta() - Write a _STA method
|
||||||
|
*
|
||||||
|
* @ctx: ACPI context pointer
|
||||||
|
* @status: Status value to return
|
||||||
|
*/
|
||||||
|
void acpigen_write_sta(struct acpi_ctx *ctx, uint status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* acpigen_write_sleep() - Write a sleep operation
|
||||||
|
*
|
||||||
|
* @ctx: ACPI context pointer
|
||||||
|
* @sleep_ms: Number of milliseconds to sleep for
|
||||||
|
*/
|
||||||
|
void acpigen_write_sleep(struct acpi_ctx *ctx, u64 sleep_ms);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* acpigen_write_store() - Write a store operation
|
||||||
|
*
|
||||||
|
* @ctx: ACPI context pointer
|
||||||
|
*/
|
||||||
|
void acpigen_write_store(struct acpi_ctx *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* acpigen_write_debug_string() - Write a debug string
|
||||||
|
*
|
||||||
|
* This writes a debug operation with an associated string
|
||||||
|
*
|
||||||
|
* @ctx: ACPI context pointer
|
||||||
|
* @str: String to write
|
||||||
|
*/
|
||||||
|
void acpigen_write_debug_string(struct acpi_ctx *ctx, const char *str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* acpigen_write_or() - Write a bitwise OR operation
|
||||||
|
*
|
||||||
|
* res = arg1 | arg2
|
||||||
|
*
|
||||||
|
* @ctx: ACPI context pointer
|
||||||
|
* @arg1: ACPI opcode for operand 1 (e.g. LOCAL0_OP)
|
||||||
|
* @arg2: ACPI opcode for operand 2 (e.g. LOCAL1_OP)
|
||||||
|
* @res: ACPI opcode for result (e.g. LOCAL2_OP)
|
||||||
|
*/
|
||||||
|
void acpigen_write_or(struct acpi_ctx *ctx, u8 arg1, u8 arg2, u8 res);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* acpigen_write_and() - Write a bitwise AND operation
|
||||||
|
*
|
||||||
|
* res = arg1 & arg2
|
||||||
|
*
|
||||||
|
* @ctx: ACPI context pointer
|
||||||
|
* @arg1: ACPI opcode for operand 1 (e.g. LOCAL0_OP)
|
||||||
|
* @arg2: ACPI opcode for operand 2 (e.g. LOCAL1_OP)
|
||||||
|
* @res: ACPI opcode for result (e.g. LOCAL2_OP)
|
||||||
|
*/
|
||||||
|
void acpigen_write_and(struct acpi_ctx *ctx, u8 arg1, u8 arg2, u8 res);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* acpigen_write_not() - Write a bitwise NOT operation
|
||||||
|
*
|
||||||
|
* res = ~arg1
|
||||||
|
*
|
||||||
|
* @ctx: ACPI context pointer
|
||||||
|
* @arg: ACPI opcode for operand (e.g. LOCAL0_OP)
|
||||||
|
* @res: ACPI opcode for result (e.g. LOCAL2_OP)
|
||||||
|
*/
|
||||||
|
void acpigen_write_not(struct acpi_ctx *ctx, u8 arg, u8 res);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -72,6 +72,12 @@ void acpigen_pop_len(struct acpi_ctx *ctx)
|
|||||||
p[2] = len >> 12 & 0xff;
|
p[2] = len >> 12 & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void acpigen_emit_ext_op(struct acpi_ctx *ctx, uint op)
|
||||||
|
{
|
||||||
|
acpigen_emit_byte(ctx, EXT_OP_PREFIX);
|
||||||
|
acpigen_emit_byte(ctx, op);
|
||||||
|
}
|
||||||
|
|
||||||
char *acpigen_write_package(struct acpi_ctx *ctx, int nr_el)
|
char *acpigen_write_package(struct acpi_ctx *ctx, int nr_el)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
@ -251,6 +257,40 @@ void acpigen_write_name(struct acpi_ctx *ctx, const char *namepath)
|
|||||||
acpigen_emit_namestring(ctx, namepath);
|
acpigen_emit_namestring(ctx, namepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void acpigen_write_method_internal(struct acpi_ctx *ctx,
|
||||||
|
const char *name, uint flags)
|
||||||
|
{
|
||||||
|
acpigen_emit_byte(ctx, METHOD_OP);
|
||||||
|
acpigen_write_len_f(ctx);
|
||||||
|
acpigen_emit_namestring(ctx, name);
|
||||||
|
acpigen_emit_byte(ctx, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Method (name, nargs, NotSerialized) */
|
||||||
|
void acpigen_write_method(struct acpi_ctx *ctx, const char *name, int nargs)
|
||||||
|
{
|
||||||
|
acpigen_write_method_internal(ctx, name,
|
||||||
|
nargs & ACPI_METHOD_NARGS_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Method (name, nargs, Serialized) */
|
||||||
|
void acpigen_write_method_serialized(struct acpi_ctx *ctx, const char *name,
|
||||||
|
int nargs)
|
||||||
|
{
|
||||||
|
acpigen_write_method_internal(ctx, name,
|
||||||
|
(nargs & ACPI_METHOD_NARGS_MASK) |
|
||||||
|
ACPI_METHOD_SERIALIZED_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void acpigen_write_sta(struct acpi_ctx *ctx, uint status)
|
||||||
|
{
|
||||||
|
/* Method (_STA, 0, NotSerialized) { Return (status) } */
|
||||||
|
acpigen_write_method(ctx, "_STA", 0);
|
||||||
|
acpigen_emit_byte(ctx, RETURN_OP);
|
||||||
|
acpigen_write_byte(ctx, status);
|
||||||
|
acpigen_pop_len(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ToUUID(uuid)
|
* ToUUID(uuid)
|
||||||
*
|
*
|
||||||
@ -287,3 +327,49 @@ int acpigen_write_uuid(struct acpi_ctx *ctx, const char *uuid)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sleep (ms) */
|
||||||
|
void acpigen_write_sleep(struct acpi_ctx *ctx, u64 sleep_ms)
|
||||||
|
{
|
||||||
|
acpigen_emit_ext_op(ctx, SLEEP_OP);
|
||||||
|
acpigen_write_integer(ctx, sleep_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void acpigen_write_store(struct acpi_ctx *ctx)
|
||||||
|
{
|
||||||
|
acpigen_emit_byte(ctx, STORE_OP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Or (arg1, arg2, res) */
|
||||||
|
void acpigen_write_or(struct acpi_ctx *ctx, u8 arg1, u8 arg2, u8 res)
|
||||||
|
{
|
||||||
|
acpigen_emit_byte(ctx, OR_OP);
|
||||||
|
acpigen_emit_byte(ctx, arg1);
|
||||||
|
acpigen_emit_byte(ctx, arg2);
|
||||||
|
acpigen_emit_byte(ctx, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And (arg1, arg2, res) */
|
||||||
|
void acpigen_write_and(struct acpi_ctx *ctx, u8 arg1, u8 arg2, u8 res)
|
||||||
|
{
|
||||||
|
acpigen_emit_byte(ctx, AND_OP);
|
||||||
|
acpigen_emit_byte(ctx, arg1);
|
||||||
|
acpigen_emit_byte(ctx, arg2);
|
||||||
|
acpigen_emit_byte(ctx, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not (arg, res) */
|
||||||
|
void acpigen_write_not(struct acpi_ctx *ctx, u8 arg, u8 res)
|
||||||
|
{
|
||||||
|
acpigen_emit_byte(ctx, NOT_OP);
|
||||||
|
acpigen_emit_byte(ctx, arg);
|
||||||
|
acpigen_emit_byte(ctx, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store (str, DEBUG) */
|
||||||
|
void acpigen_write_debug_string(struct acpi_ctx *ctx, const char *str)
|
||||||
|
{
|
||||||
|
acpigen_write_store(ctx);
|
||||||
|
acpigen_write_string(ctx, str);
|
||||||
|
acpigen_emit_ext_op(ctx, DEBUG_OP);
|
||||||
|
}
|
||||||
|
@ -626,3 +626,78 @@ static int dm_test_acpi_uuid(struct unit_test_state *uts)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
DM_TEST(dm_test_acpi_uuid, 0);
|
DM_TEST(dm_test_acpi_uuid, 0);
|
||||||
|
|
||||||
|
/* Test writing misc ACPI codes */
|
||||||
|
static int dm_test_acpi_misc(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct acpi_ctx *ctx;
|
||||||
|
const int flags = 3;
|
||||||
|
const int nargs = 4;
|
||||||
|
u8 *ptr;
|
||||||
|
|
||||||
|
ut_assertok(alloc_context(&ctx));
|
||||||
|
|
||||||
|
ptr = acpigen_get_current(ctx);
|
||||||
|
acpigen_write_sleep(ctx, TEST_INT64);
|
||||||
|
ut_asserteq_64(TEST_INT64, get_unaligned((u64 *)(ptr + 3)));
|
||||||
|
ptr += 11;
|
||||||
|
|
||||||
|
acpigen_write_store(ctx);
|
||||||
|
ut_asserteq(STORE_OP, *ptr);
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
acpigen_write_debug_string(ctx, TEST_STRING);
|
||||||
|
ut_asserteq_str(TEST_STRING, (char *)ptr + 2);
|
||||||
|
ptr += 2 + sizeof(TEST_STRING);
|
||||||
|
ut_asserteq(EXT_OP_PREFIX, ptr[0]);
|
||||||
|
ut_asserteq(DEBUG_OP, ptr[1]);
|
||||||
|
ptr += 2;
|
||||||
|
|
||||||
|
acpigen_write_sta(ctx, flags);
|
||||||
|
ut_asserteq(METHOD_OP, ptr[0]);
|
||||||
|
ut_asserteq(11, acpi_test_get_length(ptr + 1));
|
||||||
|
ut_asserteq_strn("_STA", (char *)ptr + 4);
|
||||||
|
ut_asserteq(0, ptr[8]);
|
||||||
|
ut_asserteq(RETURN_OP, ptr[9]);
|
||||||
|
ut_asserteq(BYTE_PREFIX, ptr[10]);
|
||||||
|
ut_asserteq(flags, ptr[11]);
|
||||||
|
ptr += 12;
|
||||||
|
|
||||||
|
acpigen_write_sleep(ctx, TEST_INT16);
|
||||||
|
ut_asserteq(SLEEP_OP, ptr[1]);
|
||||||
|
ut_asserteq(TEST_INT16, get_unaligned((u16 *)(ptr + 3)));
|
||||||
|
ptr += 5;
|
||||||
|
|
||||||
|
acpigen_write_method_serialized(ctx, "FRED", nargs);
|
||||||
|
ut_asserteq(METHOD_OP, ptr[0]);
|
||||||
|
ut_asserteq_strn("FRED", (char *)ptr + 4);
|
||||||
|
ut_asserteq(1 << 3 | nargs, ptr[8]);
|
||||||
|
ut_asserteq(1, ctx->ltop); /* method is unfinished */
|
||||||
|
|
||||||
|
ptr += 9;
|
||||||
|
acpigen_write_or(ctx, LOCAL0_OP, LOCAL1_OP, LOCAL2_OP);
|
||||||
|
acpigen_write_and(ctx, LOCAL3_OP, LOCAL4_OP, LOCAL5_OP);
|
||||||
|
acpigen_write_not(ctx, LOCAL6_OP, LOCAL7_OP);
|
||||||
|
ut_asserteq(OR_OP, ptr[0]);
|
||||||
|
ut_asserteq(LOCAL0_OP, ptr[1]);
|
||||||
|
ut_asserteq(LOCAL1_OP, ptr[2]);
|
||||||
|
ut_asserteq(LOCAL2_OP, ptr[3]);
|
||||||
|
|
||||||
|
ptr += 4;
|
||||||
|
ut_asserteq(AND_OP, ptr[0]);
|
||||||
|
ut_asserteq(LOCAL3_OP, ptr[1]);
|
||||||
|
ut_asserteq(LOCAL4_OP, ptr[2]);
|
||||||
|
ut_asserteq(LOCAL5_OP, ptr[3]);
|
||||||
|
|
||||||
|
ptr += 4;
|
||||||
|
ut_asserteq(NOT_OP, ptr[0]);
|
||||||
|
ut_asserteq(LOCAL6_OP, ptr[1]);
|
||||||
|
ut_asserteq(LOCAL7_OP, ptr[2]);
|
||||||
|
ptr += 3;
|
||||||
|
ut_asserteq_ptr(ptr, ctx->current);
|
||||||
|
|
||||||
|
free_context(&ctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DM_TEST(dm_test_acpi_misc, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user