arch/x86/acpigen: Add support for _DSM method generation

Add acpigen_write_dsm that generates ACPI AML code for _DSM
method. Caller should provide set of callbacks with callback[i]
corresponding to function index i of DSM method. Local0 and Local1
should not be used in any of the callbacks.

BUG=chrome-os-partner:57846

Change-Id: Ie18cba080424488fe00cc626ea50aa92c1dbb199
Signed-off-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: https://review.coreboot.org/17090
Tested-by: build bot (Jenkins)
Reviewed-by: Alexander Couzens <lynxis@fe80.eu>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
Furquan Shaikh 2016-10-21 16:37:41 -07:00 committed by Furquan Shaikh
parent 1d33488968
commit c00bd18b13
2 changed files with 94 additions and 0 deletions

View File

@ -1046,6 +1046,92 @@ void acpigen_write_return_byte(uint8_t arg)
acpigen_write_byte(arg);
}
/*
* Generate ACPI AML code for _DSM method.
* This function takes as input uuid for the device, set of callbacks and
* argument to pass into the callbacks. Callbacks should ensure that Local0 and
* Local1 are left untouched. Use of Local2-Local7 is permitted in callbacks.
*
* Arguments passed into _DSM method:
* Arg0 = UUID
* Arg1 = Revision
* Arg2 = Function index
* Arg3 = Function specific arguments
*
* AML code generated would look like:
* Method (_DSM, 4, Serialized) {
* ToBuffer (Arg0, Local0)
* If (LEqual (Local0, ToUUID(uuid))) {
* ToInteger (Arg2, Local1)
* If (LEqual (Local1, 0)) {
* <acpigen by callback[0]>
* } Else {
* ...
* If (LEqual (Local1, n)) {
* <acpigen by callback[n]>
* } Else {
* Return (Buffer (One) { 0x0 })
* }
* }
* } Else {
* Return (Buffer (One) { 0x0 })
* }
* }
*/
void acpigen_write_dsm(const char *uuid, void (*callbacks[])(void *),
size_t count, void *arg)
{
size_t i;
/* Method (_DSM, 4, Serialized) */
acpigen_write_method_serialized("_DSM", 0x4);
/* ToBuffer (Arg0, Local0) */
acpigen_write_to_buffer(ARG0_OP, LOCAL0_OP);
/* If (LEqual (Local0, ToUUID(uuid))) */
acpigen_write_if();
acpigen_emit_byte(LEQUAL_OP);
acpigen_emit_byte(LOCAL0_OP);
acpigen_write_uuid(uuid);
/* ToInteger (Arg2, Local1) */
acpigen_write_to_integer(ARG2_OP, LOCAL1_OP);
acpigen_write_debug_op(LOCAL1_OP);
for (i = 0; i < count; i++) {
/* If (Lequal (Local1, i)) */
acpigen_write_if_lequal(LOCAL1_OP, i);
/* Callback to write if handler. */
if (callbacks[i])
callbacks[i](arg);
acpigen_pop_len(); /* If */
/* Else */
acpigen_write_else();
}
/* Default case: Return (Buffer (One) { 0x0 }) */
acpigen_write_return_singleton_buffer(0x0);
/* Pop lengths for all the else clauses. */
for (i = 0; i < count; i++)
acpigen_pop_len();
acpigen_pop_len(); /* If (LEqual (Local0, ToUUID(uuid))) */
/* Else */
acpigen_write_else();
/* Return (Buffer (One) { 0x0 }) */
acpigen_write_return_singleton_buffer(0x0);
acpigen_pop_len(); /* Else */
acpigen_pop_len(); /* Method _DSM */
}
/* Soc-implemented functions -- weak definitions. */
int __attribute__((weak)) acpigen_soc_read_rx_gpio(unsigned int gpio_num)
{

View File

@ -167,6 +167,14 @@ void acpigen_write_byte_buffer(uint8_t *arr, uint8_t size);
void acpigen_write_return_byte_buffer(uint8_t *arr, uint8_t size);
void acpigen_write_return_singleton_buffer(uint8_t arg);
void acpigen_write_return_byte(uint8_t arg);
/*
* Generate ACPI AML code for _DSM method.
* This function takes as input uuid for the device, set of callbacks and
* argument to pass into the callbacks. Callbacks should ensure that Local0 and
* Local1 are left untouched. Use of Local2-Local7 is permitted in callbacks.
*/
void acpigen_write_dsm(const char *uuid, void (*callbacks[])(void *),
size_t count, void *arg);
int get_cst_entries(acpi_cstate_t **);