Embedded Controller

Embedded Controller

The embedded controller (EC) is present on most mobile PC platforms and is responsible for handling various things like power, battery, keyboard, fan, temperature sensors, etc.

The EC’s role includes:

  • AP power - the EC manages powering up the application processor, which involves the proper sequencing and timing of multiple power rails and monitoring power state signals from the application processor.

  • Keyboard - the EC scans the keyboard, sending key press information to the operating system over a dedicated communication channel.

  • Thermal management - the EC continuously monitors the temperature of the application processor, RAM, and charging circuitry, etc.

  • Power management - the EC monitors battery and charging.

ACPI Embedded Controller Interface

ACPI defines an embedded controller interface (ECI) to standardize the interface between OSPM and EC. This allows OS to provide a standard driver that can directly communicate with an embedded controller in the system, thus allowing other drivers within the system to communicate with and use the resources of system-embedded controllers.

The embedded controller interface (ECI) is currently defined only for Intel I/O Ports and doesn’t support Arm-based platforms yet.

Embedded Controller in Arm Platforms

Embedded controller is connected to the application processor using one of the serial interfaces like I2C, SPI, etc.

Embedded controller devices can be accessed from ASL using ACPI GenericSerialBus Operation Regions.

For example, to define the ACPI standard method _TMP property as part of a thermal zone to get the system's current temperature, we can use the following ASL code.

Scope (\_SB.I2C1) { Name (ECI1, ResourceTemplate () { I2cSerialBusV2 (0x1, ControllerInitiated, 400000, AddressingMode7Bit, "\\_SB.I2C1", 0x00, ResourceConsumer, , Exclusive, ) }) OperationRegion (ECRW, GenericSerialBus, Zero, 0x0100) Field (ECRW, BufferAcc, NoLock, Preserve) { Connection (ECI1), AccessAs (BufferAcc, AttribRawBytes (0x01)), REGR, 8, // read register AccessAs (BufferAcc, AttribRawBytes (0x04)), REGW, 8 // Write register } Name (ECRB, Buffer (0x0A) {}) CreateByteField (ECRB, 0, RSTA) CreateByteField (ECRB, 1, RLEN) CreateByteField (ECRB, 2, RVAL) Name (ECWB, Buffer (0x0A) {}) CreateByteField (ECWB, Zero, WSTA) CreateByteField (ECWB, One, WLEN) CreateByteField (ECWB, 0x02, ECW0) CreateByteField (ECWB, 0x03, ECW1) CreateByteField (ECWB, 0x04, ECW2) CreateByteField (ECWB, 0x05, ECW3) CreateByteField (ECWB, 0x06, ECW4) Method (ECMR, 1, NotSerialized) { WLEN = 0x04 ECW0 = Zero ECW1 = (Arg0 & 0xFF) ECW2 = ((Arg0 >> 0x08) & 0xFF) ECW3 = One ECWB = REGW = ECWB If ((WSTA == Zero)) { ECRB = REGR } Return (RVAL) } } ThermalZone (TZ0) { ... Method (_TMP, 0, Serialized) // _TMP: Temperature { Return ((\_SB.I2C1.ECMR (0x2020)) } ... }