| # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
| %YAML 1.2 |
| --- |
| $id: http://devicetree.org/schemas/cpu/idle-states.yaml# |
| $schema: http://devicetree.org/meta-schemas/core.yaml# |
| |
| title: Idle states |
| |
| maintainers: |
| - Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> |
| - Anup Patel <anup@brainfault.org> |
| |
| description: |+ |
| ========================================== |
| 1 - Introduction |
| ========================================== |
| |
| ARM and RISC-V systems contain HW capable of managing power consumption |
| dynamically, where cores can be put in different low-power states (ranging |
| from simple wfi to power gating) according to OS PM policies. The CPU states |
| representing the range of dynamic idle states that a processor can enter at |
| run-time, can be specified through device tree bindings representing the |
| parameters required to enter/exit specific idle states on a given processor. |
| |
| ========================================== |
| 2 - ARM idle states |
| ========================================== |
| |
| According to the Server Base System Architecture document (SBSA, [3]), the |
| power states an ARM CPU can be put into are identified by the following list: |
| |
| - Running |
| - Idle_standby |
| - Idle_retention |
| - Sleep |
| - Off |
| |
| The power states described in the SBSA document define the basic CPU states on |
| top of which ARM platforms implement power management schemes that allow an OS |
| PM implementation to put the processor in different idle states (which include |
| states listed above; "off" state is not an idle state since it does not have |
| wake-up capabilities, hence it is not considered in this document). |
| |
| Idle state parameters (e.g. entry latency) are platform specific and need to |
| be characterized with bindings that provide the required information to OS PM |
| code so that it can build the required tables and use them at runtime. |
| |
| The device tree binding definition for ARM idle states is the subject of this |
| document. |
| |
| ========================================== |
| 3 - RISC-V idle states |
| ========================================== |
| |
| On RISC-V systems, the HARTs (or CPUs) [6] can be put in platform specific |
| suspend (or idle) states (ranging from simple WFI, power gating, etc). The |
| RISC-V SBI v0.3 (or higher) [7] hart state management extension provides a |
| standard mechanism for OS to request HART state transitions. |
| |
| The platform specific suspend (or idle) states of a hart can be either |
| retentive or non-rententive in nature. A retentive suspend state will |
| preserve HART registers and CSR values for all privilege modes whereas |
| a non-retentive suspend state will not preserve HART registers and CSR |
| values. |
| |
| =========================================== |
| 4 - idle-states definitions |
| =========================================== |
| |
| Idle states are characterized for a specific system through a set of |
| timing and energy related properties, that underline the HW behaviour |
| triggered upon idle states entry and exit. |
| |
| The following diagram depicts the CPU execution phases and related timing |
| properties required to enter and exit an idle state: |
| |
| ..__[EXEC]__|__[PREP]__|__[ENTRY]__|__[IDLE]__|__[EXIT]__|__[EXEC]__.. |
| | | | | | |
| |
| |<------ entry ------->| |
| | latency | |
| |<- exit ->| |
| | latency | |
| |<-------- min-residency -------->| |
| |<------- wakeup-latency ------->| |
| |
| Diagram 1: CPU idle state execution phases |
| |
| EXEC: Normal CPU execution. |
| |
| PREP: Preparation phase before committing the hardware to idle mode |
| like cache flushing. This is abortable on pending wake-up |
| event conditions. The abort latency is assumed to be negligible |
| (i.e. less than the ENTRY + EXIT duration). If aborted, CPU |
| goes back to EXEC. This phase is optional. If not abortable, |
| this should be included in the ENTRY phase instead. |
| |
| ENTRY: The hardware is committed to idle mode. This period must run |
| to completion up to IDLE before anything else can happen. |
| |
| IDLE: This is the actual energy-saving idle period. This may last |
| between 0 and infinite time, until a wake-up event occurs. |
| |
| EXIT: Period during which the CPU is brought back to operational |
| mode (EXEC). |
| |
| entry-latency: Worst case latency required to enter the idle state. The |
| exit-latency may be guaranteed only after entry-latency has passed. |
| |
| min-residency: Minimum period, including preparation and entry, for a given |
| idle state to be worthwhile energywise. |
| |
| wakeup-latency: Maximum delay between the signaling of a wake-up event and the |
| CPU being able to execute normal code again. If not specified, this is assumed |
| to be entry-latency + exit-latency. |
| |
| These timing parameters can be used by an OS in different circumstances. |
| |
| An idle CPU requires the expected min-residency time to select the most |
| appropriate idle state based on the expected expiry time of the next IRQ |
| (i.e. wake-up) that causes the CPU to return to the EXEC phase. |
| |
| An operating system scheduler may need to compute the shortest wake-up delay |
| for CPUs in the system by detecting how long will it take to get a CPU out |
| of an idle state, e.g.: |
| |
| wakeup-delay = exit-latency + max(entry-latency - (now - entry-timestamp), 0) |
| |
| In other words, the scheduler can make its scheduling decision by selecting |
| (e.g. waking-up) the CPU with the shortest wake-up delay. |
| The wake-up delay must take into account the entry latency if that period |
| has not expired. The abortable nature of the PREP period can be ignored |
| if it cannot be relied upon (e.g. the PREP deadline may occur much sooner than |
| the worst case since it depends on the CPU operating conditions, i.e. caches |
| state). |
| |
| An OS has to reliably probe the wakeup-latency since some devices can enforce |
| latency constraint guarantees to work properly, so the OS has to detect the |
| worst case wake-up latency it can incur if a CPU is allowed to enter an |
| idle state, and possibly to prevent that to guarantee reliable device |
| functioning. |
| |
| The min-residency time parameter deserves further explanation since it is |
| expressed in time units but must factor in energy consumption coefficients. |
| |
| The energy consumption of a cpu when it enters a power state can be roughly |
| characterised by the following graph: |
| |
| | |
| | |
| | |
| e | |
| n | /--- |
| e | /------ |
| r | /------ |
| g | /----- |
| y | /------ |
| | ---- |
| | /| |
| | / | |
| | / | |
| | / | |
| | / | |
| | / | |
| |/ | |
| -----|-------+---------------------------------- |
| 0| 1 time(ms) |
| |
| Graph 1: Energy vs time example |
| |
| The graph is split in two parts delimited by time 1ms on the X-axis. |
| The graph curve with X-axis values = { x | 0 < x < 1ms } has a steep slope |
| and denotes the energy costs incurred while entering and leaving the idle |
| state. |
| The graph curve in the area delimited by X-axis values = {x | x > 1ms } has |
| shallower slope and essentially represents the energy consumption of the idle |
| state. |
| |
| min-residency is defined for a given idle state as the minimum expected |
| residency time for a state (inclusive of preparation and entry) after |
| which choosing that state become the most energy efficient option. A good |
| way to visualise this, is by taking the same graph above and comparing some |
| states energy consumptions plots. |
| |
| For sake of simplicity, let's consider a system with two idle states IDLE1, |
| and IDLE2: |
| |
| | |
| | |
| | |
| | /-- IDLE1 |
| e | /--- |
| n | /---- |
| e | /--- |
| r | /-----/--------- IDLE2 |
| g | /-------/--------- |
| y | ------------ /---| |
| | / /---- | |
| | / /--- | |
| | / /---- | |
| | / /--- | |
| | --- | |
| | / | |
| | / | |
| |/ | time |
| ---/----------------------------+------------------------ |
| |IDLE1-energy < IDLE2-energy | IDLE2-energy < IDLE1-energy |
| | |
| IDLE2-min-residency |
| |
| Graph 2: idle states min-residency example |
| |
| In graph 2 above, that takes into account idle states entry/exit energy |
| costs, it is clear that if the idle state residency time (i.e. time till next |
| wake-up IRQ) is less than IDLE2-min-residency, IDLE1 is the better idle state |
| choice energywise. |
| |
| This is mainly down to the fact that IDLE1 entry/exit energy costs are lower |
| than IDLE2. |
| |
| However, the lower power consumption (i.e. shallower energy curve slope) of |
| idle state IDLE2 implies that after a suitable time, IDLE2 becomes more energy |
| efficient. |
| |
| The time at which IDLE2 becomes more energy efficient than IDLE1 (and other |
| shallower states in a system with multiple idle states) is defined |
| IDLE2-min-residency and corresponds to the time when energy consumption of |
| IDLE1 and IDLE2 states breaks even. |
| |
| The definitions provided in this section underpin the idle states |
| properties specification that is the subject of the following sections. |
| |
| =========================================== |
| 5 - idle-states node |
| =========================================== |
| |
| The processor idle states are defined within the idle-states node, which is |
| a direct child of the cpus node [1] and provides a container where the |
| processor idle states, defined as device tree nodes, are listed. |
| |
| On ARM systems, it is a container of processor idle states nodes. If the |
| system does not provide CPU power management capabilities, or the processor |
| just supports idle_standby, an idle-states node is not required. |
| |
| =========================================== |
| 6 - Qualcomm specific STATES |
| =========================================== |
| |
| Idle states have different enter/exit latency and residency values. |
| The idle states supported by the QCOM SoC are defined as - |
| |
| * Standby |
| * Retention |
| * Standalone Power Collapse (Standalone PC or SPC) |
| * Power Collapse (PC) |
| |
| Standby: Standby does a little more in addition to architectural clock gating. |
| When the WFI instruction is executed the ARM core would gate its internal |
| clocks. In addition to gating the clocks, QCOM cpus use this instruction as a |
| trigger to execute the SPM state machine. The SPM state machine waits for the |
| interrupt to trigger the core back in to active. This triggers the cache |
| hierarchy to enter standby states, when all cpus are idle. An interrupt brings |
| the SPM state machine out of its wait, the next step is to ensure that the |
| cache hierarchy is also out of standby, and then the cpu is allowed to resume |
| execution. This state is defined as a generic ARM WFI state by the ARM cpuidle |
| driver and is not defined in the DT. The SPM state machine should be |
| configured to execute this state by default and after executing every other |
| state below. |
| |
| Retention: Retention is a low power state where the core is clock gated and |
| the memory and the registers associated with the core are retained. The |
| voltage may be reduced to the minimum value needed to keep the processor |
| registers active. The SPM should be configured to execute the retention |
| sequence and would wait for interrupt, before restoring the cpu to execution |
| state. Retention may have a slightly higher latency than Standby. |
| |
| Standalone PC: A cpu can power down and warmboot if there is a sufficient time |
| between the time it enters idle and the next known wake up. SPC mode is used |
| to indicate a core entering a power down state without consulting any other |
| cpu or the system resources. This helps save power only on that core. The SPM |
| sequence for this idle state is programmed to power down the supply to the |
| core, wait for the interrupt, restore power to the core, and ensure the |
| system state including cache hierarchy is ready before allowing core to |
| resume. Applying power and resetting the core causes the core to warmboot |
| back into Elevation Level (EL) which trampolines the control back to the |
| kernel. Entering a power down state for the cpu, needs to be done by trapping |
| into a EL. Failing to do so, would result in a crash enforced by the warm boot |
| code in the EL for the SoC. On SoCs with write-back L1 cache, the cache has to |
| be flushed in s/w, before powering down the core. |
| |
| Power Collapse: This state is similar to the SPC mode, but distinguishes |
| itself in that the cpu acknowledges and permits the SoC to enter deeper sleep |
| modes. In a hierarchical power domain SoC, this means L2 and other caches can |
| be flushed, system bus, clocks - lowered, and SoC main XO clock gated and |
| voltages reduced, provided all cpus enter this state. Since the span of low |
| power modes possible at this state is vast, the exit latency and the residency |
| of this low power mode would be considered high even though at a cpu level, |
| this essentially is cpu power down. The SPM in this state also may handshake |
| with the Resource power manager (RPM) processor in the SoC to indicate a |
| complete application processor subsystem shut down. |
| |
| =========================================== |
| 7 - References |
| =========================================== |
| |
| [1] ARM Linux Kernel documentation - CPUs bindings |
| Documentation/devicetree/bindings/arm/cpus.yaml |
| |
| [2] ARM Linux Kernel documentation - PSCI bindings |
| Documentation/devicetree/bindings/arm/psci.yaml |
| |
| [3] ARM Server Base System Architecture (SBSA) |
| http://infocenter.arm.com/help/index.jsp |
| |
| [4] ARM Architecture Reference Manuals |
| http://infocenter.arm.com/help/index.jsp |
| |
| [5] ARM Linux Kernel documentation - Booting AArch64 Linux |
| Documentation/arch/arm64/booting.rst |
| |
| [6] RISC-V Linux Kernel documentation - CPUs bindings |
| Documentation/devicetree/bindings/riscv/cpus.yaml |
| |
| [7] RISC-V Supervisor Binary Interface (SBI) |
| http://github.com/riscv/riscv-sbi-doc/riscv-sbi.adoc |
| |
| properties: |
| $nodename: |
| const: idle-states |
| |
| entry-method: |
| description: | |
| Usage and definition depend on ARM architecture version. |
| |
| On ARM v8 64-bit this property is required. |
| On ARM 32-bit systems this property is optional |
| |
| This assumes that the "enable-method" property is set to "psci" in the cpu |
| node[5] that is responsible for setting up CPU idle management in the OS |
| implementation. |
| const: psci |
| |
| patternProperties: |
| "^(cpu|cluster)-": |
| type: object |
| description: | |
| Each state node represents an idle state description and must be defined |
| as follows. |
| |
| The idle state entered by executing the wfi instruction (idle_standby |
| SBSA,[3][4]) is considered standard on all ARM and RISC-V platforms and |
| therefore must not be listed. |
| |
| In addition to the properties listed above, a state node may require |
| additional properties specific to the entry-method defined in the |
| idle-states node. Please refer to the entry-method bindings |
| documentation for properties definitions. |
| |
| properties: |
| compatible: |
| oneOf: |
| - items: |
| - enum: |
| - qcom,idle-state-ret |
| - qcom,idle-state-spc |
| - qcom,idle-state-pc |
| - const: arm,idle-state |
| - enum: |
| - arm,idle-state |
| - riscv,idle-state |
| |
| arm,psci-suspend-param: |
| $ref: /schemas/types.yaml#/definitions/uint32 |
| description: | |
| power_state parameter to pass to the ARM PSCI suspend call. |
| |
| Device tree nodes that require usage of PSCI CPU_SUSPEND function |
| (i.e. idle states node with entry-method property is set to "psci") |
| must specify this property. |
| |
| riscv,sbi-suspend-param: |
| $ref: /schemas/types.yaml#/definitions/uint32 |
| description: | |
| suspend_type parameter to pass to the RISC-V SBI HSM suspend call. |
| |
| This property is required in idle state nodes of device tree meant |
| for RISC-V systems. For more details on the suspend_type parameter |
| refer the SBI specification v0.3 (or higher) [7]. |
| |
| local-timer-stop: |
| description: |
| If present the CPU local timer control logic is |
| lost on state entry, otherwise it is retained. |
| type: boolean |
| |
| entry-latency-us: |
| description: |
| Worst case latency in microseconds required to enter the idle state. |
| |
| exit-latency-us: |
| description: |
| Worst case latency in microseconds required to exit the idle state. |
| The exit-latency-us duration may be guaranteed only after |
| entry-latency-us has passed. |
| |
| min-residency-us: |
| description: |
| Minimum residency duration in microseconds, inclusive of preparation |
| and entry, for this idle state to be considered worthwhile energy wise |
| (refer to section 2 of this document for a complete description). |
| |
| wakeup-latency-us: |
| description: | |
| Maximum delay between the signaling of a wake-up event and the CPU |
| being able to execute normal code again. If omitted, this is assumed |
| to be equal to: |
| |
| entry-latency-us + exit-latency-us |
| |
| It is important to supply this value on systems where the duration of |
| PREP phase (see diagram 1, section 2) is non-neglibigle. In such |
| systems entry-latency-us + exit-latency-us will exceed |
| wakeup-latency-us by this duration. |
| |
| idle-state-name: |
| $ref: /schemas/types.yaml#/definitions/string |
| description: |
| A string used as a descriptive name for the idle state. |
| |
| additionalProperties: false |
| |
| required: |
| - compatible |
| - entry-latency-us |
| - exit-latency-us |
| - min-residency-us |
| |
| additionalProperties: false |
| |
| examples: |
| - | |
| |
| cpus { |
| #size-cells = <0>; |
| #address-cells = <2>; |
| |
| cpu@0 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a57"; |
| reg = <0x0 0x0>; |
| enable-method = "psci"; |
| cpu-idle-states = <&CPU_RETENTION_0_0>, <&CPU_SLEEP_0_0>, |
| <&CLUSTER_RETENTION_0>, <&CLUSTER_SLEEP_0>; |
| }; |
| |
| cpu@1 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a57"; |
| reg = <0x0 0x1>; |
| enable-method = "psci"; |
| cpu-idle-states = <&CPU_RETENTION_0_0>, <&CPU_SLEEP_0_0>, |
| <&CLUSTER_RETENTION_0>, <&CLUSTER_SLEEP_0>; |
| }; |
| |
| cpu@100 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a57"; |
| reg = <0x0 0x100>; |
| enable-method = "psci"; |
| cpu-idle-states = <&CPU_RETENTION_0_0>, <&CPU_SLEEP_0_0>, |
| <&CLUSTER_RETENTION_0>, <&CLUSTER_SLEEP_0>; |
| }; |
| |
| cpu@101 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a57"; |
| reg = <0x0 0x101>; |
| enable-method = "psci"; |
| cpu-idle-states = <&CPU_RETENTION_0_0>, <&CPU_SLEEP_0_0>, |
| <&CLUSTER_RETENTION_0>, <&CLUSTER_SLEEP_0>; |
| }; |
| |
| cpu@10000 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a57"; |
| reg = <0x0 0x10000>; |
| enable-method = "psci"; |
| cpu-idle-states = <&CPU_RETENTION_0_0>, <&CPU_SLEEP_0_0>, |
| <&CLUSTER_RETENTION_0>, <&CLUSTER_SLEEP_0>; |
| }; |
| |
| cpu@10001 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a57"; |
| reg = <0x0 0x10001>; |
| enable-method = "psci"; |
| cpu-idle-states = <&CPU_RETENTION_0_0>, <&CPU_SLEEP_0_0>, |
| <&CLUSTER_RETENTION_0>, <&CLUSTER_SLEEP_0>; |
| }; |
| |
| cpu@10100 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a57"; |
| reg = <0x0 0x10100>; |
| enable-method = "psci"; |
| cpu-idle-states = <&CPU_RETENTION_0_0>, <&CPU_SLEEP_0_0>, |
| <&CLUSTER_RETENTION_0>, <&CLUSTER_SLEEP_0>; |
| }; |
| |
| cpu@10101 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a57"; |
| reg = <0x0 0x10101>; |
| enable-method = "psci"; |
| cpu-idle-states = <&CPU_RETENTION_0_0>, <&CPU_SLEEP_0_0>, |
| <&CLUSTER_RETENTION_0>, <&CLUSTER_SLEEP_0>; |
| }; |
| |
| cpu@100000000 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a53"; |
| reg = <0x1 0x0>; |
| enable-method = "psci"; |
| cpu-idle-states = <&CPU_RETENTION_1_0>, <&CPU_SLEEP_1_0>, |
| <&CLUSTER_RETENTION_1>, <&CLUSTER_SLEEP_1>; |
| }; |
| |
| cpu@100000001 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a53"; |
| reg = <0x1 0x1>; |
| enable-method = "psci"; |
| cpu-idle-states = <&CPU_RETENTION_1_0>, <&CPU_SLEEP_1_0>, |
| <&CLUSTER_RETENTION_1>, <&CLUSTER_SLEEP_1>; |
| }; |
| |
| cpu@100000100 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a53"; |
| reg = <0x1 0x100>; |
| enable-method = "psci"; |
| cpu-idle-states = <&CPU_RETENTION_1_0>, <&CPU_SLEEP_1_0>, |
| <&CLUSTER_RETENTION_1>, <&CLUSTER_SLEEP_1>; |
| }; |
| |
| cpu@100000101 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a53"; |
| reg = <0x1 0x101>; |
| enable-method = "psci"; |
| cpu-idle-states = <&CPU_RETENTION_1_0>, <&CPU_SLEEP_1_0>, |
| <&CLUSTER_RETENTION_1>, <&CLUSTER_SLEEP_1>; |
| }; |
| |
| cpu@100010000 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a53"; |
| reg = <0x1 0x10000>; |
| enable-method = "psci"; |
| cpu-idle-states = <&CPU_RETENTION_1_0>, <&CPU_SLEEP_1_0>, |
| <&CLUSTER_RETENTION_1>, <&CLUSTER_SLEEP_1>; |
| }; |
| |
| cpu@100010001 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a53"; |
| reg = <0x1 0x10001>; |
| enable-method = "psci"; |
| cpu-idle-states = <&CPU_RETENTION_1_0>, <&CPU_SLEEP_1_0>, |
| <&CLUSTER_RETENTION_1>, <&CLUSTER_SLEEP_1>; |
| }; |
| |
| cpu@100010100 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a53"; |
| reg = <0x1 0x10100>; |
| enable-method = "psci"; |
| cpu-idle-states = <&CPU_RETENTION_1_0>, <&CPU_SLEEP_1_0>, |
| <&CLUSTER_RETENTION_1>, <&CLUSTER_SLEEP_1>; |
| }; |
| |
| cpu@100010101 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a53"; |
| reg = <0x1 0x10101>; |
| enable-method = "psci"; |
| cpu-idle-states = <&CPU_RETENTION_1_0>, <&CPU_SLEEP_1_0>, |
| <&CLUSTER_RETENTION_1>, <&CLUSTER_SLEEP_1>; |
| }; |
| |
| idle-states { |
| entry-method = "psci"; |
| |
| CPU_RETENTION_0_0: cpu-retention-0-0 { |
| compatible = "arm,idle-state"; |
| arm,psci-suspend-param = <0x0010000>; |
| entry-latency-us = <20>; |
| exit-latency-us = <40>; |
| min-residency-us = <80>; |
| }; |
| |
| CLUSTER_RETENTION_0: cluster-retention-0 { |
| compatible = "arm,idle-state"; |
| local-timer-stop; |
| arm,psci-suspend-param = <0x1010000>; |
| entry-latency-us = <50>; |
| exit-latency-us = <100>; |
| min-residency-us = <250>; |
| wakeup-latency-us = <130>; |
| }; |
| |
| CPU_SLEEP_0_0: cpu-sleep-0-0 { |
| compatible = "arm,idle-state"; |
| local-timer-stop; |
| arm,psci-suspend-param = <0x0010000>; |
| entry-latency-us = <250>; |
| exit-latency-us = <500>; |
| min-residency-us = <950>; |
| }; |
| |
| CLUSTER_SLEEP_0: cluster-sleep-0 { |
| compatible = "arm,idle-state"; |
| local-timer-stop; |
| arm,psci-suspend-param = <0x1010000>; |
| entry-latency-us = <600>; |
| exit-latency-us = <1100>; |
| min-residency-us = <2700>; |
| wakeup-latency-us = <1500>; |
| }; |
| |
| CPU_RETENTION_1_0: cpu-retention-1-0 { |
| compatible = "arm,idle-state"; |
| arm,psci-suspend-param = <0x0010000>; |
| entry-latency-us = <20>; |
| exit-latency-us = <40>; |
| min-residency-us = <90>; |
| }; |
| |
| CLUSTER_RETENTION_1: cluster-retention-1 { |
| compatible = "arm,idle-state"; |
| local-timer-stop; |
| arm,psci-suspend-param = <0x1010000>; |
| entry-latency-us = <50>; |
| exit-latency-us = <100>; |
| min-residency-us = <270>; |
| wakeup-latency-us = <100>; |
| }; |
| |
| CPU_SLEEP_1_0: cpu-sleep-1-0 { |
| compatible = "arm,idle-state"; |
| local-timer-stop; |
| arm,psci-suspend-param = <0x0010000>; |
| entry-latency-us = <70>; |
| exit-latency-us = <100>; |
| min-residency-us = <300>; |
| wakeup-latency-us = <150>; |
| }; |
| |
| CLUSTER_SLEEP_1: cluster-sleep-1 { |
| compatible = "arm,idle-state"; |
| local-timer-stop; |
| arm,psci-suspend-param = <0x1010000>; |
| entry-latency-us = <500>; |
| exit-latency-us = <1200>; |
| min-residency-us = <3500>; |
| wakeup-latency-us = <1300>; |
| }; |
| }; |
| }; |
| |
| - | |
| // Example 2 (ARM 32-bit, 8-cpu system, two clusters): |
| |
| cpus { |
| #size-cells = <0>; |
| #address-cells = <1>; |
| |
| cpu@0 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a15"; |
| reg = <0x0>; |
| cpu-idle-states = <&cpu_sleep_0_0>, <&cluster_sleep_0>; |
| }; |
| |
| cpu@1 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a15"; |
| reg = <0x1>; |
| cpu-idle-states = <&cpu_sleep_0_0>, <&cluster_sleep_0>; |
| }; |
| |
| cpu@2 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a15"; |
| reg = <0x2>; |
| cpu-idle-states = <&cpu_sleep_0_0>, <&cluster_sleep_0>; |
| }; |
| |
| cpu@3 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a15"; |
| reg = <0x3>; |
| cpu-idle-states = <&cpu_sleep_0_0>, <&cluster_sleep_0>; |
| }; |
| |
| cpu@100 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a7"; |
| reg = <0x100>; |
| cpu-idle-states = <&cpu_sleep_1_0>, <&cluster_sleep_1>; |
| }; |
| |
| cpu@101 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a7"; |
| reg = <0x101>; |
| cpu-idle-states = <&cpu_sleep_1_0>, <&cluster_sleep_1>; |
| }; |
| |
| cpu@102 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a7"; |
| reg = <0x102>; |
| cpu-idle-states = <&cpu_sleep_1_0>, <&cluster_sleep_1>; |
| }; |
| |
| cpu@103 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a7"; |
| reg = <0x103>; |
| cpu-idle-states = <&cpu_sleep_1_0>, <&cluster_sleep_1>; |
| }; |
| |
| idle-states { |
| cpu_sleep_0_0: cpu-sleep-0-0 { |
| compatible = "arm,idle-state"; |
| local-timer-stop; |
| entry-latency-us = <200>; |
| exit-latency-us = <100>; |
| min-residency-us = <400>; |
| wakeup-latency-us = <250>; |
| }; |
| |
| cluster_sleep_0: cluster-sleep-0 { |
| compatible = "arm,idle-state"; |
| local-timer-stop; |
| entry-latency-us = <500>; |
| exit-latency-us = <1500>; |
| min-residency-us = <2500>; |
| wakeup-latency-us = <1700>; |
| }; |
| |
| cpu_sleep_1_0: cpu-sleep-1-0 { |
| compatible = "arm,idle-state"; |
| local-timer-stop; |
| entry-latency-us = <300>; |
| exit-latency-us = <500>; |
| min-residency-us = <900>; |
| wakeup-latency-us = <600>; |
| }; |
| |
| cluster_sleep_1: cluster-sleep-1 { |
| compatible = "arm,idle-state"; |
| local-timer-stop; |
| entry-latency-us = <800>; |
| exit-latency-us = <2000>; |
| min-residency-us = <6500>; |
| wakeup-latency-us = <2300>; |
| }; |
| }; |
| }; |
| |
| - | |
| // Example 3 (RISC-V 64-bit, 4-cpu systems, two clusters): |
| |
| cpus { |
| #size-cells = <0>; |
| #address-cells = <1>; |
| |
| cpu@0 { |
| device_type = "cpu"; |
| compatible = "riscv"; |
| reg = <0x0>; |
| riscv,isa = "rv64imafdc"; |
| mmu-type = "riscv,sv48"; |
| cpu-idle-states = <&CPU_RET_0_0>, <&CPU_NONRET_0_0>, |
| <&CLUSTER_RET_0>, <&CLUSTER_NONRET_0>; |
| |
| cpu_intc0: interrupt-controller { |
| #interrupt-cells = <1>; |
| compatible = "riscv,cpu-intc"; |
| interrupt-controller; |
| }; |
| }; |
| |
| cpu@1 { |
| device_type = "cpu"; |
| compatible = "riscv"; |
| reg = <0x1>; |
| riscv,isa = "rv64imafdc"; |
| mmu-type = "riscv,sv48"; |
| cpu-idle-states = <&CPU_RET_0_0>, <&CPU_NONRET_0_0>, |
| <&CLUSTER_RET_0>, <&CLUSTER_NONRET_0>; |
| |
| cpu_intc1: interrupt-controller { |
| #interrupt-cells = <1>; |
| compatible = "riscv,cpu-intc"; |
| interrupt-controller; |
| }; |
| }; |
| |
| cpu@10 { |
| device_type = "cpu"; |
| compatible = "riscv"; |
| reg = <0x10>; |
| riscv,isa = "rv64imafdc"; |
| mmu-type = "riscv,sv48"; |
| cpu-idle-states = <&CPU_RET_1_0>, <&CPU_NONRET_1_0>, |
| <&CLUSTER_RET_1>, <&CLUSTER_NONRET_1>; |
| |
| cpu_intc10: interrupt-controller { |
| #interrupt-cells = <1>; |
| compatible = "riscv,cpu-intc"; |
| interrupt-controller; |
| }; |
| }; |
| |
| cpu@11 { |
| device_type = "cpu"; |
| compatible = "riscv"; |
| reg = <0x11>; |
| riscv,isa = "rv64imafdc"; |
| mmu-type = "riscv,sv48"; |
| cpu-idle-states = <&CPU_RET_1_0>, <&CPU_NONRET_1_0>, |
| <&CLUSTER_RET_1>, <&CLUSTER_NONRET_1>; |
| |
| cpu_intc11: interrupt-controller { |
| #interrupt-cells = <1>; |
| compatible = "riscv,cpu-intc"; |
| interrupt-controller; |
| }; |
| }; |
| |
| idle-states { |
| CPU_RET_0_0: cpu-retentive-0-0 { |
| compatible = "riscv,idle-state"; |
| riscv,sbi-suspend-param = <0x10000000>; |
| entry-latency-us = <20>; |
| exit-latency-us = <40>; |
| min-residency-us = <80>; |
| }; |
| |
| CPU_NONRET_0_0: cpu-nonretentive-0-0 { |
| compatible = "riscv,idle-state"; |
| riscv,sbi-suspend-param = <0x90000000>; |
| entry-latency-us = <250>; |
| exit-latency-us = <500>; |
| min-residency-us = <950>; |
| }; |
| |
| CLUSTER_RET_0: cluster-retentive-0 { |
| compatible = "riscv,idle-state"; |
| riscv,sbi-suspend-param = <0x11000000>; |
| local-timer-stop; |
| entry-latency-us = <50>; |
| exit-latency-us = <100>; |
| min-residency-us = <250>; |
| wakeup-latency-us = <130>; |
| }; |
| |
| CLUSTER_NONRET_0: cluster-nonretentive-0 { |
| compatible = "riscv,idle-state"; |
| riscv,sbi-suspend-param = <0x91000000>; |
| local-timer-stop; |
| entry-latency-us = <600>; |
| exit-latency-us = <1100>; |
| min-residency-us = <2700>; |
| wakeup-latency-us = <1500>; |
| }; |
| |
| CPU_RET_1_0: cpu-retentive-1-0 { |
| compatible = "riscv,idle-state"; |
| riscv,sbi-suspend-param = <0x10000010>; |
| entry-latency-us = <20>; |
| exit-latency-us = <40>; |
| min-residency-us = <80>; |
| }; |
| |
| CPU_NONRET_1_0: cpu-nonretentive-1-0 { |
| compatible = "riscv,idle-state"; |
| riscv,sbi-suspend-param = <0x90000010>; |
| entry-latency-us = <250>; |
| exit-latency-us = <500>; |
| min-residency-us = <950>; |
| }; |
| |
| CLUSTER_RET_1: cluster-retentive-1 { |
| compatible = "riscv,idle-state"; |
| riscv,sbi-suspend-param = <0x11000010>; |
| local-timer-stop; |
| entry-latency-us = <50>; |
| exit-latency-us = <100>; |
| min-residency-us = <250>; |
| wakeup-latency-us = <130>; |
| }; |
| |
| CLUSTER_NONRET_1: cluster-nonretentive-1 { |
| compatible = "riscv,idle-state"; |
| riscv,sbi-suspend-param = <0x91000010>; |
| local-timer-stop; |
| entry-latency-us = <600>; |
| exit-latency-us = <1100>; |
| min-residency-us = <2700>; |
| wakeup-latency-us = <1500>; |
| }; |
| }; |
| }; |
| |
| // Example 4 - Qualcomm SPC |
| idle-states { |
| cpu_spc: cpu-spc { |
| compatible = "qcom,idle-state-spc", "arm,idle-state"; |
| entry-latency-us = <150>; |
| exit-latency-us = <200>; |
| min-residency-us = <2000>; |
| }; |
| }; |
| ... |