Skip to content

EC Driver Documentation

thom_tl edited this page Aug 2, 2020 · 3 revisions

EC Driver

The EC (Embedded Controller) is a device that might be accessed by AML code, and is used commonly by laptops. It controls HW events and in some cases power management. LAI provides an optional driver for this in drivers/ec.c, however that is not all that is needed to initialize it, here is some example code to initialize all ECs.

This code includes <lai/core.h>, <acpispec/tables.h>, and <lai/drivers/ec.h>

LAI_CLEANUP_STATE lai_state_t state;
lai_init_state(&state);
 
LAI_CLEANUP_VAR lai_variable_t pnp_id = LAI_VAR_INITIALIZER;
lai_eisaid(&pnp_id, ACPI_EC_PNP_ID);
 
struct lai_ns_iterator it = LAI_NS_ITERATOR_INITIALIZER;
lai_nsnode_t *node = NULL;
while((node = lai_ns_iterate(&it))){
    if(lai_check_device_pnp_id(node, &pnp_id, &state)) // This is not an EC
        continue;
 
    // Found one
    struct lai_ec_driver *driver = malloc(sizeof(struct lai_ec_driver)); // Dynamically allocate the memory since -
    lai_init_ec(node, driver);                                           // we dont know how many ECs there could be
 
    struct lai_ns_child_iterator child_it = LAI_NS_CHILD_ITERATOR_INITIALIZER(node);
    lai_nsnode_t *child_node;
    while((child_node = lai_ns_child_iterate(&child_it))){
        if(lai_ns_get_node_type(child_node) == LAI_NODETYPE_OPREGION){
            if(lai_ns_get_opregion_address_space(child_node) == OPREGION_EC){
                lai_ns_override_opregion(child_node, &lai_ec_opregion_override, driver);
            }
        }
    }

    lai_nsnode_t* reg = lai_resolve_path(node, "_REG");
    if(reg) {
        LAI_CLEANUP_VAR lai_variable_t address_space = LAI_VAR_INITIALIZER;
        LAI_CLEANUP_VAR lai_variable_t enable = LAI_VAR_INITIALIZER;

        address_space.type = LAI_INTEGER;
        address_space.integer = 3; // EmbeddedControl

        enable.type = LAI_INTEGER;
        enable.integer = 1; // Enable

        lai_api_error_t error = lai_eval_largs(NULL, reg, &state, &address_space, &enable, NULL);
        if(error != LAI_ERROR_NONE) {
            // Handle error
        }
    }
}

EC on early boot

In some cases it might be needed to initialize an EC before full enumeration of the AML code is completed, ACPI provides the ECDT table for this, LAI here provides a function to search for this table and initialize a struct lai_ec_driver with it.

// Search for ECDT table and initialize driver struct with it
void lai_early_init_ec(struct lai_ec_driver *driver);
Clone this wiki locally