Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Legacy EC Interface

ACPI specification has a definition for an embedded controller, however this implementation is tied very closely to the eSPI bus and x86 architecture.

The following is an example of legacy EC interface definition from ACPI

11.7. Thermal Zone Examples — ACPI Specification 6.4 documentation

Scope(\\_SB.PCI0.ISA0) {
  Device(EC0) {
    Name(_HID, EISAID("PNP0C09")) // ID for this EC

    // current resource description for this EC
    Name(_CRS, ResourceTemplate() {
      IO(Decode16,0x62,0x62,0,1)
      IO(Decode16,0x66,0x66,0,1)
    })

    Name(_GPE, 0) // GPE index for this EC
    
    // create EC's region and field for thermal support
    OperationRegion(EC0, EmbeddedControl, 0, 0xFF)
    Field(EC0, ByteAcc, Lock, Preserve) {
      MODE, 1, // thermal policy (quiet/perform)
      FAN, 1, // fan power (on/off)
      , 6, // reserved
      TMP, 16, // current temp
      AC0, 16, // active cooling temp (fan high)
      , 16, // reserved
      PSV, 16, // passive cooling temp
      HOT 16, // critical S4 temp
      CRT, 16 // critical temp
    }

    // following is a method that OSPM will schedule after
    // it receives an SCI and queries the EC to receive value 7
    Method(_Q07) {
      Notify (\\_SB.PCI0.ISA0.EC0.TZ0, 0x80)
    } // end of Notify method

    // fan cooling on/off - engaged at AC0 temp
    PowerResource(PFAN, 0, 0) {
      Method(_STA) { Return (\\_SB.PCI0.ISA0.EC0.FAN) } // check power state
      Method(_ON) { Store (One, \\\\_SB.PCI0.ISA0.EC0.FAN) } // turn on fan
      Method(_OFF) { Store ( Zero, \\\\_SB.PCI0.ISA0.EC0.FAN) }// turn off
fan
    }

    // Create FAN device object
    Device (FAN) {
    // Device ID for the FAN
    Name(_HID, EISAID("PNP0C0B"))
    // list power resource for the fan
    Name(_PR0, Package(){PFAN})
    }

    // create a thermal zone
    ThermalZone (TZ0) {
      Method(_TMP) { Return (\\_SB.PCI0.ISA0.EC0.TMP )} // get current temp
      Method(_AC0) { Return (\\_SB.PCI0.ISA0.EC0.AC0) } // fan high temp
      Name(_AL0, Package(){\\_SB.PCI0.ISA0.EC0.FAN}) // fan is act cool dev
      Method(_PSV) { Return (\\_SB.PCI0.ISA0.EC0.PSV) } // passive cooling
temp
      Name(_PSL, Package (){\\_SB.CPU0}) // passive cooling devices
      Method(_HOT) { Return (\\_SB.PCI0.ISA0.EC0.HOT) } // get critical S4
temp
      Method(_CRT) { Return (\\_SB.PCI0.ISA0.EC0.CRT) } // get critical temp
      Method(_SCP, 1) { Store (Arg1, \\\\_SB.PCI0.ISA0.EC0.MODE) } // set
cooling mode

      Name(_TSP, 150) // passive sampling = 15 sec
      Name(_TZP, 0) // polling not required
      Name (_STR, Unicode ("System thermal zone"))
    } // end of TZ0
  } // end of ECO
} // end of \\\\_SB.PCI0.ISA0 scope-

On platforms that do not support IO port access there is an option to define MMIO regions to simulate the IO port transactions.

In the above example you can see that the operation region directly maps to features on the EC and you can change the EC behavior by writing to a byte in the region or reading the latest data from the EC.

For a system with the EC connected via eSPI and that needs a simple non-secure interface to the EC the above mapping works very well and keeps the code simple. The eSPI protocol itself has details on port accesses and uses the peripheral channel to easily read/write memory mapped regions.

As the EC features evolve there are several requirements that do no work well with this interface:

  • Different buses such as I3C, SPI, UART target a packet request/response rather than a memory mapped interface

  • Protected or restricted access and validation of request/response

  • Firmware update, large data driven requests that require larger data response the 256-byte region is limited

  • Discoverability of features available and OEM customizations

  • Out of order completion of requests, concurrency, routing and priority handling

As we try to address these limitations and move to a more packet based protocol described in this document. The following section covers details on how to adopt existing operation region to new ACPI functionality.

Adopting EC Operation Region

The new OS frameworks such as MPTF still use ACPI methods as primary interface. Instead of defining devices such as FAN or ThermalZone in the EC region you can simply define the EC region itself and then map all the other ACPI functions to operate on this region. This will allow you to maintain backwards compatibility with existing EC definitions.

Device(EC0) {
  Name(_HID, EISAID("PNP0C09")) // ID for this EC
  // current resource description for this EC
  Name(_CRS, ResourceTemplate() {
    IO(Decode16,0x62,0x62,0,1)
    IO(Decode16,0x66,0x66,0,1)
  })

  // create EC's region and field for thermal support
  OperationRegion(EC0, EmbeddedControl, 0, 0xFF)
  Field(EC0, ByteAcc, Lock, Preserve) {
    MODE, 1, // thermal policy (quiet/perform)
    FAN, 1, // fan power (on/off)
    , 6, // reserved
    TMP, 16, // current temp
    AC0, 16, // active cooling temp (fan high)
    , 16, // reserved
    PSV, 16, // passive cooling temp
    HOT 16, // critical S4 temp
    CRT, 16 // critical temp
  }
}

Device(SKIN) {
  Name(_HID, "MSFT000A") // New MPTF HID Temperature Device
  Method(_TMP, 0x0, Serialized) {
      Return( \\_SB.PCI0.ISA0.EC0.TMP)
  }
}

For more complicated functions that take a package some of the data may be constructed within ACPI and some of the data pulled from the OperationRegion. For example BIX for battery information may have a combination of static and dynamic data like this:

Method (_BIX) {
  Name (BAT0, Package (0x12)
  {
    0x01, // Revision
    0x02, // Power Unit
    0x03, // Design Capacity
    \\_SB.PCI0.ISA0.EC0.BFCC, // Last Full Charge Capacity
    0x05, // Battery Technology
    0x06, // Design Voltage
    0x07, // Design capacity of Warning
    0x08, // Design Capacity of Low
    \\_SB.PCI0.ISA0.EC0.BCYL, // Cycle Count
    0x0A, // Measurement Accuracy
    0x0B, // Max Sampling Time
    0x0C, // Min Sampling Time
    0x0D, // Max Averaging Interval
    0x0E, // Min Averaging Interval
    0x0F, // Battery Capacity Granularity 1
    0x10, // Battery Capacity Granularity 2
    "Model123", // Model Number
    "Serial456", // Serial Number
    "Li-Ion", // Battery Type
    "OEMName" // OEM Information
  })
  Return(BAT0)
}

Limitations for using Legacy EC

Before using the Legacy EC definition OEM’s should be aware of several use cases that may limit you ability to use it.

ACPI support for eSPI master

In the case of Legacy EC the communication to the EC is accomplished directly by the ACPI driver using PORT IO and eSPI Peripheral Bus commands. On ARM platforms there is no PORT IO and these must be substituted with MMIO regions. The ACPI driver needs changes to support MMIO which is being evaluated and support is not yet available. Some Silicon Vendors also do not implement the full eSPI specification and as such the ACPI driver cannot handle all the communication needs. On these platforms using Legacy EC interface is not an option.

Security of eSPI bus

When non-secure world is given access to the eSPI bus it can send commands to device on that bus. Some HW designs have the TPM or SPINOR on the same physical bus as the EC. On these designs allowing non-secure world to directly sends commands to EC can break the security requirements of other devices on the bus. In these cases the eSPI communication must be done in the secure world over FF-A as covered in this document and not use the Legacy EC channel. Since non-secure world has complete access to the EC operation region there is no chance for encryption of data. All data in the operation region is considered non-secure.

Functional limitations of Legacy EC

The peripheral region that is mapped in the Legacy EC in ACPI is limited to 256 bytes and notification events to the ones that are defined and handled in ACPI driver. To create custom solutions, send large packets or support encryption of data the Legacy EC interface has limitations in this area.