11.7. Thermal Zone Examples

11.7.1. Example: The Basic Thermal Zone

The following ASL describes a basic configuration where the entire system is treated as a single thermal zone. Cooling devices for this thermal zone consist of a processor and one single-speed fan. This is an example only.

Notice that this thermal zone object (TZ0) is defined in the \_SB scope. Thermal zone objects should appear in the namespace under the portion of the system that comprises the thermal zone. For example, a thermal zone that is isolated to a docking station should be defined within the scope of the docking station device. Besides providing for a well-organized namespace, this configuration allows OSPM to dynamically adjust its thermal policy as devices are added or removed from the system.

Scope(\_SB) {
    Device(CPU0) {
        Name(_HID, "ACPI0007")
        Name(_UID, 1) // unique number for this processor
    }
<...>
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(_TC1, 4) // bogus example constant
        Name(_TC2, 3) // bogus example constant
        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-
} // end of \\_SB scope

11.7.2. Example: Multiple-Speed Fans

The following ASL describes a thermal zone consisting of a processor and one dual-speed fan. As with the previous example, this thermal zone object (TZ0) is defined in the _SB scope and represents the entire system. This is an example only.

Scope(\_SB) {
    Device(CPU0) {
        Name(_HID, "ACPI0007")
        Name(_UID, 1) // unique number for this processor
    }
<...>
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)
            FAN0, 1, // fan strength high/off
            FAN1, 1, // fan strength low/off
            , 5, // reserved
            TMP, 16, // current temp
            AC0, 16, // active cooling temp (high)
            AC1, 16, // active cooling temp (low)
            PSV, 16, // passive cooling temp
            HOT 18, // 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 mode high/off - engaged at AC0 temp
        PowerResource(FN10, 0, 0) {
            Method(_STA) { Return (\_SB.PCI0.ISA0.EC0.FAN0) } // check power state
            Method(_ON) { Store (One, \\_SB.PCI0.ISA0.EC0.FAN0) } // turn on fan at high
            Method(_OFF) { Store (Zero, \\_SB.PCI0.ISA0.EC0.FAN0) } // turn off fan
        }
        // fan cooling mode low/off - engaged at AC1 temp
        PowerResource(FN11, 0, 0) {
            Method(_STA) { Return (\_SB.PCI0.ISA0.EC0.FAN1) } // check power state
            Method(_ON) { Store (One, \\_SB.PCI0.ISA0.EC0.FAN1) } // turn on fan at low
            Method(_OFF) { Store (Zero, \\_SB.PCI0.ISA0.EC0.FAN1) } // turn off fan
}
    // Following is a single fan with two speeds. This is represented
    // by creating two logical fan devices. When FN2 is turned on then
    // the fan is at a low speed. When FN1 and FN2 are both on then
    // the fan is at high speed.
    //
    // Create FAN device object FN1
    Device (FN1) {
        // Device ID for the FAN
        Name(_HID, EISAID("PNP0C0B"))
        Name(_UID, 0)
        Name(_PR0, Package(){FN10, FN11})
    }
    // Create FAN device object FN2
    Device (FN2) {
        // Device ID for the FAN
        Name(_HID, EISAID("PNP0C0B"))
        Name(_UID, 1)
        Name(_PR0, Package(){FN10})
    }
    // 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
        Method(_AC1) { Return (\_SB.PCI0.ISA0.EC0.AC1) } // fan low temp
        Name(_AL0, Package() {\_SB.PCI0.ISA0.EC0.FN1}) // active cooling (high)
        Name(_AL1, Package() {\_SB.PCI0.ISA0.EC0.FN2}) // active cooling (low)
        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 crit. temp
        Method(_SCP, 1) { Store (Arg1, \\_SB.PCI0.ISA0.EC0.MODE) } // cooling mode
        Name(_TC1, 4) // bogus example constant
        Name(_TC2, 3) // bogus example constant
        Name(_TSP, 150) // passive sampling = 15 sec
        Name(_TZP, 0) // polling not required
        } // end of TZ0
    } // end of ECO
} // end of \\_SB.PCI0.ISA0 scope
} // end of \\_SB scope

11.7.3. Example: Thermal Zone with Multiple Devices

Scope(\_SB) {
    Device(CPU0) {
        Name(_HID, "ACPI0007")
        Name(_UID, 0)
        //
        // Load additional objects if 3.0 Thermal model support is available
        //
        Method(_INI, 0) {
            If (\_OSI("3.0 Thermal Model")) {
            LoadTable("OEM1", "PmRef", "Cpu0", "\\_SB.CPU0") // 3.0 Thermal Model
        }
        }
        // For brevity, most processor objects have been excluded
        // from this example (such as \_PSS, \_CST, \_PCT, \_PPC, etc.)
        // Processor Throttle Control object
        Name(_PTC, ResourceTemplate() {
            Register(SystemIO, 32, 0, 0x120) // Processor Control
            Register(SystemIO, 32, 0, 0x120) // Processor Status
        })
        // Throttling Supported States
        // The values shown are for exemplary purposes only
        Name(_TSS, Package() {
        // Read: freq percentage, power, latency, control, status
            Package() {0x64, 1000, 0x0, 0x7, 0x0}, // Throttle off (100%)
            Package() {0x58, 800, 0x0, 0xF, 0x0}, // 87.5%
            Package() {0x4B, 600, 0x0, 0xE, 0x0}, // 75%
            Package() {0x3F, 400, 0x0, 0xD, 0x0} // 62.5%
        })
        // Throttling Present Capabilities
        // The values shown are for exemplary purposes only
        Method(_TPC) {
            If(\_SB.AC) {
                Return(0) // All throttle states available
            } Else {
                Return(2) // Throttle states >= 2 are available
            }
        }
    } // end of CPU0 scope
    Device(CPU1) {
        Name(_HID, "ACPI0007")
        Name(_UID, 1)
        //
        // Load additional objects if 3.0 Thermal model support is available
        //
        Method(_INI, 0) {
            If (\_OSI("3.0 Thermal Model")) {
                LoadTable("OEM1", "PmRef", "Cpu1", "\\_SB.CPU1") // 3.0 Thermal Model
            }
        }
        // For brevity, most processor objects have been excluded
        // from this example (such as \_PSS, \_CST, \_PCT, \_PPC, \_PTC, etc.)
        // Processor Throttle Control object
        Name(_PTC, ResourceTemplate() {
            Register(SystemIO, 32, 0, 0x120) // Processor Control
            Register(SystemIO, 32, 0, 0x120) // Processor Status
        })
        // Throttling Supported States
        // The values shown are for exemplary purposes only
        Name(_TSS, Package() {
        // Read: freq percentage, power, latency, control, status
            Package() {0x64, 1000, 0x0, 0x7, 0x0}, // Throttle off (100%)
            Package() {0x58, 800, 0x0, 0xF, 0x0}, // 87.5%
            Package() {0x4B, 600, 0x0, 0xE, 0x0}, // 75%
            Package() {0x3F, 400, 0x0, 0xD, 0x0} // 62.5%
        })
        // Throttling Present Capabilities
        // The values shown are for exemplary purposes only
        Method(_TPC) {
            If(\_SB.AC)
                {Return(0) // All throttle states available
            } Else {
                Return(2) // Throttle states >= 2 are available
            }
        }
    } // end of CPU1 scope
Scope(\_SB.PCI0.ISA0) {
    Device(EC0) {
        Name(_HID, EISAID("PNP0C09")) // ID for this EC
        //
        // Load additional objects if 3.0 Thermal model support is available
        //
        Method(_INI, 0) {
            If (\_OSI("3.0 Thermal Model")) {
                LoadTable("OEM1", "PmRef", "Tz3", "\\_SB.PCI0.ISA0.EC0") // 3.0 Tz
            }
        }
        // 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)
            FAN0, 1, // fan strength high/off
            , 6, // reserved
            TMP, 16, // current temp
            AC0, 16, // active cooling temp
            PSV, 16, // passive cooling temp
            HOT, 16, // critical S4 temp
            CRT, 16 // critical temp
        }
        // Following is a method that OSPM will schedule after it
    // fan cooling mode high/off - engaged at AC0 temp
    PowerResource(FN10, 0, 0) {
        Method(_STA) { Return (\_SB.PCI0.ISA0.EC0.FAN0) } // check power state
        Method(_ON) { Store (One, \\_SB.PCI0.ISA0.EC0.FAN0) } // turn on fan at high
        Method(_OFF) { Store (Zero, \\_SB.PCI0.ISA0.EC0.FAN0) } // turn off fan
    }
    // Following is a single fan with one speed.
    // Create FAN device object FN1
    Device (FN1) {
        // Device ID for the FAN
        Name(_HID, EISAID("PNP0C0B"))
        Name(_UID, 0)
        Name(_PR0, Package(){FN10})
    }
        // Receives an SCI and queries the EC to receive value 7
         Method(_Q07) {
            Notify (\_SB.PCI0.ISA0.EC0.TZ0, 0x80)
        } // end of Notify method
    // Create standard specific thermal zone
    ThermalZone (TZ0) {
        Method(_TMP) { Return (\_SB.PCI0.ISA0.EC0.TMP )} // get current temp
        Name(_PSL, Package() {\_SB.CPU0, \\_SB.CPU1}) // passive cooling devices
        Name(_AL0, Package() {\_SB.PCI0.ISA0.EC0.FN1}) // active cooling
        Method(_AC0) { Return (\_SB.PCI0.ISA0.EC0.AC0) } // fan temp (high)
        Method(_AC1) { Return (\_SB.PCI0.ISA0.EC0.AC1) } // fan temp (low)
        Method(_PSV) { Return (\_SB.PCI0.ISA0.EC0.PSV) } // passive cooling temp
        Method(_HOT) { Return (\_SB.PCI0.ISA0.EC0.HOT) } // get critical S4 temp
        Method(_CRT) { Return (\_SB.PCI0.ISA0.EC0.CRT) } // get crit. temp
        Name(_TC1, 4) // bogus example constant
        Name(_TC2, 3) // bogus example constant
        Method(_SCP, 1) { Store (Arg0, \\_SB.PCI0.ISA0.EC0.MODE) } // set cooling mode
        Name(_TSP, 150) // passive sampling = 15 sec
    } // end of TZ0
} // end of ECO
} // end of \\_SB.PCI0.ISA0 scope
} // end of \\_SB scope
//
// ACPI 3.0 Thermal Model SSDT
//
DefinitionBlock (

    "TZASSDT.aml",
    "OEM1",
    0x01,
    "PmRef",
    "Tz3",
    0x3000
    )
{
    External(\_SB.PCI0.ISA0.EC0, DeviceObj)
    External(\_SB.CPU0, DeviceObj)
    External(\_SB.CPU1, DeviceObj)
    Scope(\_SB.PCI0.ISA0.EC0)
    {
    // Create an ACPI 3.0 specific thermal zone
    ThermalZone (TZ0) {
        // This TRT is for exemplary purposes only
        Name(_TRT, Package() {
            // Thermal relationship package data. A package is generated for
            // each permutation of device sets. 2 devices = 4 entries.
            // Read: source, target, thermal influence, sampling period, 4 reserved
            Package () {\_SB.CPU0, \\_SB.CPU0, 20, 1, 0, 0, 0, 0},
            Package () {\_SB.CPU0, \\_SB.CPU1, 10, 15, 0, 0, 0, 0},
            Package () {\_SB.CPU1, \\_SB.CPU0, 10, 15, 0, 0, 0, 0},
            Package () {\_SB.CPU1, \\_SB.CPU1, 20, 1, 0, 0, 0, 0}
        }) // end of TRT
    } // end of TZ0
    } // end of EC0 Scope
} // end of SSDT

//
// CPU0 3.0 Thermal Model SSDT
//
DefinitionBlock (
    "CPU0SSDT.aml",
    "OEM1",
    0x01,
    "PmRef",
    "CPU0",
    0x3000
    )
{
    External(\_SB.CPU0, DeviceObj)
    External(\_SB.PCI0.ISA0.TZ0, ThermalZoneObj)
    Scope(\_SB.CPU0)
    {
        //
        // Add the objects required for 3.0 extended thermal support
        //
        // Create a region and fields for thermal support; the platform
        // fills in the values and traps on writes to enable hysteresis.
        // The Operation Region location is invalid
        OperationRegion(CP00, SystemMemory, 0x00000000, 0xA)
        Field(CP00, ByteAcc, Lock, Preserve) {
            SCP, 1, // thermal policy (passive/active)
            RTV, 1, // absolute or relative temperature
            , 6, // reserved
            AC0, 16, // active cooling temp
            PSV, 16, // passive cooling temp
            CRT, 16, // critical temp
            TPT, 16, // Temp trip point crossed
            TST, 8 // Temp sensor threshold
        }
        Method(_TZM, 0) { Return(\_SB.PCI0.ISA0.TZ0) } // thermal zone member
        // Some thermal zone methods are now located under the
        // thermal device participating in the 3.0 thermal model.
        // These methods provide device specific thermal information
    Method(_SCP, 1) { Store (Arg0, \\_SB.CPU0.SCP) } // set cooling mode
    Method(_RTV) { Return (\_SB.CPU0.RTV) } // absolute or relative temp
    Method(_AC0) { Return (\_SB.CPU0.AC0) } // active cooling (fan) temp
    Method(_PSV) { Return (\_SB.CPU0.PSV) } // passive cooling temp
    Method(_CRT) { Return (\_SB.CPU0.CRT) } // critical temp
    Name(_TC1, 4) // thermal constant 1 (INVALID)
    Name(_TC2, 3) // thermal constant 2 (INVALID)
    Method(_TPT, 1) { Store (Arg0, \\_SB.CPU0.TPT)} // trip point temp
    Method(_TST) { Return (\_SB.CPU0.TST) } // temp sensor threshold
    } // end of CPU0 scope
} // end of SSDT
//
// CPU1 3.0 Thermal Model SSDT
//
DefinitionBlock (
    "CPU1SSDT.aml",
    "OEM1",
    0x01,
    "PmRef",
    "CPU1",
    0x3000
    )
{
    External(\_SB.CPU1, DeviceObj)
    External(\_SB.PCI0.ISA0.TZ0, ThermalZoneObj)
    Scope(\_SB.CPU1)
    {
        //
        // Add the objects required for 3.0 extended thermal support
        //
        // Create a region and fields for thermal support; the platform
        // fills in the values and traps on writes to enable hysteresis.
        // The Operation Region location is invalid
        OperationRegion(CP01, SystemIO, 0x00000008, 0xA)
        Field(CP01, ByteAcc, Lock, Preserve) {
            SCP, 1, // thermal policy (passive/active)
            RTV, 1, // absolute or relative temperature
            , 6, // reserved
            AC0, 16, // active cooling temp
            PSV, 16, // passive cooling temp
            CRT, 16, // critical temp
            TPT, 16, // Temp trip point crossed
            TST, 8 // Temp sensor threshold
        }
        Method(_TZM, 0) { Return(\_SB.PCI0.ISA0.TZ0) } // thermal zone member
        // Some thermal zone methods are now located under the
        // thermal device participating in the 3.0 thermal model.
        // These methods provide device specific thermal information
    Method(_SCP, 1) { Store (Arg0, \\_SB.CPU1.SCP) } // set cooling mode
    Method(_RTV) { Return (\_SB.CPU1.RTV) } // absolute or relative temp
    Method(_AC0) { Return (\_SB.CPU1.AC0) } // active cooling (fan) temp
    Method(_PSV) { Return (\_SB.CPU1.PSV) } // passive cooling temp
    Method(_CRT) { Return (\_SB.CPU1.CRT) } // critical temp
    Name(_TC1, 4) // thermal constant 1 (INVALID)
    Name(_TC2, 3) // thermal constant 2 (INVALID)
    Method(_TPT, 1) { Store (Arg0, \\_SB.CPU1.TPT)} // trip point temp
    Method(_TST) { Return (\_SB.CPU1.TST) } // temp sensor threshold
    } // end of CPU1 scope
} // end of SSDT