All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/8] ARM generic idle states
@ 2014-06-25 14:10 ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Lorenzo Pieralisi, Mark Rutland, Sudeep Holla, Catalin Marinas,
	Charles Garcia Tobin, Nicolas Pitre, Rob Herring, Grant Likely,
	Peter De Schrijver, Santosh Shilimkar, Daniel Lezcano,
	Amit Kucheria, Vincent Guittot, Antti Miettinen, Stephen Boyd,
	Kevin Hilman, Sebastian Capella, Tomasz Figa, Mark Brown,
	Paul Walmsley, Chander Kashyap

This patch is v5 of a previous posting:

http://lists.infradead.org/pipermail/linux-arm-kernel/2014-June/263060.html

Changes in v5:

- Added power-rank property to implement state sorting, following a number
  of on/off list review comments
- Added timer retained bool property
- Ported TC2 big.LITTLE and Exynos drivers to DT initialization
- Renamed s/OF/dt/ throughout the patch
- Incorporated review comments and list discussions in the idle states
  bindings documents
- Rebased against 3.16-rc2

Changes in v4:

- States sorting using exit-latency
- Added cosmetic review comments
- Dropped RFC
- Rebased against 3.15

Changes in v3:

- Streamlined the idle states bindings and added them to the series
  http://www.spinics.net/lists/arm-kernel/msg316299.html
- Sorting states through min-residency+exit-latency
- Added debug strings formatting
- Reworded min-residency-us idle state property
- Removed power-domain properties from idle states waiting for code
  examples requiring them to be defined

Changes in v2:

- Moved OF parsing code to drivers/cpuidle
- Improved states detection and sorting through linked list
- Split code in generic and ARM64 specific bits
- Moved idle enter function into ARM64 idle driver
- Refactored PSCI idle states register function
- Renamed suspend operations and moved detection to ARM64 idle driver
- Changed the way CPUIDLE_FLAG_TIMER_STOP is handled
- Simplified idle state nodes parsing since according to the latest
  bindings idle state nodes are a flat list, not hierarchical anymore
- Used min-residency-us to sort the states, to be further discussed

Idle states on most ARM platforms can be characterized by a set of
parameters that are platform agnostic and describe the HW idle states
features. So far, CPU idle drivers for ARM platforms required the definition
of parameters through static tables, duplicating control data for different
platforms. Moreover, the lack of standardization on firmware interfaces
hampered any standardization effort, resulting in CPU idle drivers for ARM
platforms containing duplicated code and platform specific power down routines.

The introduction of the PSCI firmware interface, and more in general, well
defined suspend back-ends, allows the definition of generic idle states and
the respective kernel infrastructure to support them.

Building on top of DT idle states bindings, that standardize idle states
parameters and corresponding suspend back-ends, this patchset provides code
that parses DT idle states nodes and builds at run-time the control data
infrastructure required by the ARM CPU idle drivers.

Idle states define an entry method (eg PSCI), that requires the respective
ARM64 kernel back-end to be invoked to initialize idle states parameters, so
that when the idle driver executes the back-end specific entry method a table
look-up can be carried out to retrieve the corresponding idle state parameter.

On legacy ARM platforms, the OF idle states are just used to initialize
states data.

The idle states bindings can be extended with new back-ends; the ARM64 CPUidle
driver must be updated accordingly so that the corresponding back
end initializer can be invoked at boot time for parameters initialization.

Patchset has been tested on AEM v8 models, on top of bootwrapper PSCI CPU
SUSPEND implementation which provides simulated core power gating.

[1] http://www.spinics.net/lists/arm-kernel/msg316299.html

Lorenzo Pieralisi (8):
  Documentation: arm: define DT idle states bindings
  Documentation: devicetree: psci: define CPU suspend parameter
  drivers: cpuidle: implement DT based idle states infrastructure
  arm64: add PSCI CPU_SUSPEND based cpu_suspend support
  drivers: cpuidle: CPU idle ARM64 driver
  drivers: cpuidle: initialize big.LITTLE driver through DT
  drivers: cpuidle: initialize Exynos driver through DT
  arm64: boot: dts: update rtsm aemv8 dts with PSCI and idle states

 Documentation/devicetree/bindings/arm/cpus.txt     |   8 +
 .../devicetree/bindings/arm/exynos/idle-states.txt |  27 +
 .../devicetree/bindings/arm/idle-states.txt        | 733 +++++++++++++++++++++
 Documentation/devicetree/bindings/arm/psci.txt     |  12 +-
 Documentation/devicetree/bindings/arm/vexpress.txt |  25 +
 arch/arm/boot/dts/exynos3250.dtsi                  |  16 +
 arch/arm/boot/dts/exynos5250.dtsi                  |  15 +
 arch/arm/boot/dts/exynos5410.dtsi                  |  17 +
 arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts         |  25 +
 arch/arm64/boot/dts/rtsm_ve-aemv8a.dts             |  44 +-
 arch/arm64/include/asm/psci.h                      |   4 +
 arch/arm64/kernel/psci.c                           | 103 +++
 drivers/cpuidle/Kconfig                            |  13 +
 drivers/cpuidle/Kconfig.arm                        |   2 +
 drivers/cpuidle/Kconfig.arm64                      |  13 +
 drivers/cpuidle/Makefile                           |   5 +
 drivers/cpuidle/cpuidle-arm64.c                    | 165 +++++
 drivers/cpuidle/cpuidle-big_little.c               |  43 +-
 drivers/cpuidle/cpuidle-exynos.c                   |  29 +-
 drivers/cpuidle/dt_idle_states.c                   | 283 ++++++++
 drivers/cpuidle/dt_idle_states.h                   |   8 +
 21 files changed, 1548 insertions(+), 42 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt
 create mode 100644 Documentation/devicetree/bindings/arm/idle-states.txt
 create mode 100644 drivers/cpuidle/Kconfig.arm64
 create mode 100644 drivers/cpuidle/cpuidle-arm64.c
 create mode 100644 drivers/cpuidle/dt_idle_states.c
 create mode 100644 drivers/cpuidle/dt_idle_states.h

-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 0/8] ARM generic idle states
@ 2014-06-25 14:10 ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel

This patch is v5 of a previous posting:

http://lists.infradead.org/pipermail/linux-arm-kernel/2014-June/263060.html

Changes in v5:

- Added power-rank property to implement state sorting, following a number
  of on/off list review comments
- Added timer retained bool property
- Ported TC2 big.LITTLE and Exynos drivers to DT initialization
- Renamed s/OF/dt/ throughout the patch
- Incorporated review comments and list discussions in the idle states
  bindings documents
- Rebased against 3.16-rc2

Changes in v4:

- States sorting using exit-latency
- Added cosmetic review comments
- Dropped RFC
- Rebased against 3.15

Changes in v3:

- Streamlined the idle states bindings and added them to the series
  http://www.spinics.net/lists/arm-kernel/msg316299.html
- Sorting states through min-residency+exit-latency
- Added debug strings formatting
- Reworded min-residency-us idle state property
- Removed power-domain properties from idle states waiting for code
  examples requiring them to be defined

Changes in v2:

- Moved OF parsing code to drivers/cpuidle
- Improved states detection and sorting through linked list
- Split code in generic and ARM64 specific bits
- Moved idle enter function into ARM64 idle driver
- Refactored PSCI idle states register function
- Renamed suspend operations and moved detection to ARM64 idle driver
- Changed the way CPUIDLE_FLAG_TIMER_STOP is handled
- Simplified idle state nodes parsing since according to the latest
  bindings idle state nodes are a flat list, not hierarchical anymore
- Used min-residency-us to sort the states, to be further discussed

Idle states on most ARM platforms can be characterized by a set of
parameters that are platform agnostic and describe the HW idle states
features. So far, CPU idle drivers for ARM platforms required the definition
of parameters through static tables, duplicating control data for different
platforms. Moreover, the lack of standardization on firmware interfaces
hampered any standardization effort, resulting in CPU idle drivers for ARM
platforms containing duplicated code and platform specific power down routines.

The introduction of the PSCI firmware interface, and more in general, well
defined suspend back-ends, allows the definition of generic idle states and
the respective kernel infrastructure to support them.

Building on top of DT idle states bindings, that standardize idle states
parameters and corresponding suspend back-ends, this patchset provides code
that parses DT idle states nodes and builds at run-time the control data
infrastructure required by the ARM CPU idle drivers.

Idle states define an entry method (eg PSCI), that requires the respective
ARM64 kernel back-end to be invoked to initialize idle states parameters, so
that when the idle driver executes the back-end specific entry method a table
look-up can be carried out to retrieve the corresponding idle state parameter.

On legacy ARM platforms, the OF idle states are just used to initialize
states data.

The idle states bindings can be extended with new back-ends; the ARM64 CPUidle
driver must be updated accordingly so that the corresponding back
end initializer can be invoked at boot time for parameters initialization.

Patchset has been tested on AEM v8 models, on top of bootwrapper PSCI CPU
SUSPEND implementation which provides simulated core power gating.

[1] http://www.spinics.net/lists/arm-kernel/msg316299.html

Lorenzo Pieralisi (8):
  Documentation: arm: define DT idle states bindings
  Documentation: devicetree: psci: define CPU suspend parameter
  drivers: cpuidle: implement DT based idle states infrastructure
  arm64: add PSCI CPU_SUSPEND based cpu_suspend support
  drivers: cpuidle: CPU idle ARM64 driver
  drivers: cpuidle: initialize big.LITTLE driver through DT
  drivers: cpuidle: initialize Exynos driver through DT
  arm64: boot: dts: update rtsm aemv8 dts with PSCI and idle states

 Documentation/devicetree/bindings/arm/cpus.txt     |   8 +
 .../devicetree/bindings/arm/exynos/idle-states.txt |  27 +
 .../devicetree/bindings/arm/idle-states.txt        | 733 +++++++++++++++++++++
 Documentation/devicetree/bindings/arm/psci.txt     |  12 +-
 Documentation/devicetree/bindings/arm/vexpress.txt |  25 +
 arch/arm/boot/dts/exynos3250.dtsi                  |  16 +
 arch/arm/boot/dts/exynos5250.dtsi                  |  15 +
 arch/arm/boot/dts/exynos5410.dtsi                  |  17 +
 arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts         |  25 +
 arch/arm64/boot/dts/rtsm_ve-aemv8a.dts             |  44 +-
 arch/arm64/include/asm/psci.h                      |   4 +
 arch/arm64/kernel/psci.c                           | 103 +++
 drivers/cpuidle/Kconfig                            |  13 +
 drivers/cpuidle/Kconfig.arm                        |   2 +
 drivers/cpuidle/Kconfig.arm64                      |  13 +
 drivers/cpuidle/Makefile                           |   5 +
 drivers/cpuidle/cpuidle-arm64.c                    | 165 +++++
 drivers/cpuidle/cpuidle-big_little.c               |  43 +-
 drivers/cpuidle/cpuidle-exynos.c                   |  29 +-
 drivers/cpuidle/dt_idle_states.c                   | 283 ++++++++
 drivers/cpuidle/dt_idle_states.h                   |   8 +
 21 files changed, 1548 insertions(+), 42 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt
 create mode 100644 Documentation/devicetree/bindings/arm/idle-states.txt
 create mode 100644 drivers/cpuidle/Kconfig.arm64
 create mode 100644 drivers/cpuidle/cpuidle-arm64.c
 create mode 100644 drivers/cpuidle/dt_idle_states.c
 create mode 100644 drivers/cpuidle/dt_idle_states.h

-- 
1.9.1

^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 1/8] Documentation: arm: define DT idle states bindings
  2014-06-25 14:10 ` Lorenzo Pieralisi
@ 2014-06-25 14:10   ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel, linux-pm, devicetree
  Cc: Lorenzo Pieralisi, Mark Rutland, Sudeep Holla, Catalin Marinas,
	Charles Garcia Tobin, Nicolas Pitre, Rob Herring, Grant Likely,
	Peter De Schrijver, Santosh Shilimkar, Daniel Lezcano,
	Amit Kucheria, Vincent Guittot, Antti Miettinen, Stephen Boyd,
	Kevin Hilman, Sebastian Capella, Tomasz Figa, Mark Brown,
	Paul Walmsley, Chander Kashyap

ARM based platforms implement a variety of power management schemes that
allow processors to enter idle states at run-time.
The parameters defining these idle states vary on a per-platform basis forcing
the OS to hardcode the state parameters in platform specific static tables
whose size grows as the number of platforms supported in the kernel increases
and hampers device drivers standardization.

Therefore, this patch aims at standardizing idle state device tree bindings for
ARM platforms. Bindings define idle state parameters inclusive of entry methods
and state latencies, to allow operating systems to retrieve the configuration
entries from the device tree and initialize the related power management
drivers, paving the way for common code in the kernel to deal with idle
states and removing the need for static data in current and previous kernel
versions.

Reviewed-by: Sebastian Capella <sebcape@gmail.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
 Documentation/devicetree/bindings/arm/cpus.txt     |   8 +
 .../devicetree/bindings/arm/idle-states.txt        | 733 +++++++++++++++++++++
 2 files changed, 741 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/idle-states.txt

diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
index 1fe72a0..a44d4fd 100644
--- a/Documentation/devicetree/bindings/arm/cpus.txt
+++ b/Documentation/devicetree/bindings/arm/cpus.txt
@@ -215,6 +215,12 @@ nodes to be present and contain the properties described below.
 		Value type: <phandle>
 		Definition: Specifies the ACC[2] node associated with this CPU.
 
+	- cpu-idle-states
+		Usage: Optional
+		Value type: <prop-encoded-array>
+		Definition:
+			# List of phandles to idle state nodes supported
+			  by this cpu [3].
 
 Example 1 (dual-cluster big.LITTLE system 32-bit):
 
@@ -411,3 +417,5 @@ cpus {
 --
 [1] arm/msm/qcom,saw2.txt
 [2] arm/msm/qcom,kpss-acc.txt
+[3] ARM Linux kernel documentation - idle states bindings
+    Documentation/devicetree/bindings/arm/idle-states.txt
diff --git a/Documentation/devicetree/bindings/arm/idle-states.txt b/Documentation/devicetree/bindings/arm/idle-states.txt
new file mode 100644
index 0000000..5efd198
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/idle-states.txt
@@ -0,0 +1,733 @@
+==========================================
+ARM idle states binding description
+==========================================
+
+==========================================
+1 - Introduction
+==========================================
+
+ARM 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.
+
+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 (eg 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.
+
+===========================================
+2 - 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
+(ie 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, eg:
+
+wakeup-delay = exit-latency + max(entry-latency - (now - entry-timestamp), 0)
+
+In other words, the scheduler can make its scheduling decision by selecting
+(eg waking-up) the CPU with the shortest wake-up latency.
+The wake-up latency 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, ie caches
+state).
+
+An OS has to reliably probe the wakeup-latency since some devices can enforce
+latency constraints 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 whilst 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 (ie 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 (ie 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.
+
+===========================================
+3 - idle-states node
+===========================================
+
+ARM 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.
+
+- idle-states node
+
+	Usage: Optional - 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.
+
+	Description: idle-states node is a container node, where its
+		     subnodes describe the CPU idle states.
+
+	Node name must be "idle-states".
+
+	The idle-states node's parent node must be the cpus node.
+
+	The idle-states node's child nodes can be:
+
+	- one or more state nodes
+
+	Any other configuration is considered invalid.
+
+	An idle-states node defines the following properties:
+
+	- entry-method
+		Usage: Required
+		Value type: <stringlist>
+		Definition: Describes the method by which a CPU enters the
+			    idle states. This property is required and must be
+			    one of:
+
+			    - "arm,psci"
+			      ARM PSCI firmware interface [2].
+
+			    - "[vendor],[method]"
+			      An implementation dependent string with
+			      format "vendor,method", where vendor is a string
+			      denoting the name of the manufacturer and
+			      method is a string specifying the mechanism
+			      used to enter the idle state.
+
+The nodes describing the idle states (state) can only be defined within the
+idle-states node, any other configuration is considered invalid and therefore
+must be ignored.
+
+===========================================
+4 - state node
+===========================================
+
+A state node represents an idle state description and must be defined as
+follows:
+
+- state node
+
+	Description: must be child of the idle-states node
+
+	The state node name shall follow standard device tree naming
+	rules ([5], 2.2.1 "Node names"), in particular state nodes which
+	are siblings within a single common parent must be given a unique name.
+
+	The idle state entered by executing the wfi instruction (idle_standby
+	SBSA,[3][4]) is considered standard on all ARM platforms and therefore
+	must not be listed.
+
+	With the definitions provided above, the following list represents
+	the valid properties for a state node:
+
+	- compatible
+		Usage: Required
+		Value type: <stringlist>
+		Definition: Must be "arm,idle-state".
+
+	- logic-state-retained
+		Usage: See definition
+		Value type: <none>
+		Definition: if present logic is retained on state entry,
+			    otherwise it is lost.
+
+	- cache-state-retained
+		Usage: See definition
+		Value type: <none>
+		Definition: if present cache memory is retained on state entry,
+			    otherwise it is lost.
+
+	- timer-state-retained
+		Usage: See definition
+		Value type: <none>
+		Definition: if present the timer control logic is retained on
+                            state entry, otherwise it is lost.
+
+	- power-rank
+		Usage: Required
+		Value type: <u32>
+		Definition: It represents the idle state power-rank.
+			    An increasing value implies less power
+			    consumption. It must be given a sequential
+			    value = {0, 1, ....}, starting from 0.
+			    Phandles in the cpu nodes [1] cpu-idle-states
+			    array property are not allowed to point at idle
+			    state nodes having the same power-rank value.
+
+	- entry-method-param
+		Usage: See definition.
+		Value type: <u32>
+		Definition: Depends on the idle-states node entry-method
+			    property value. Refer to the entry-method bindings
+			    for this property value definition.
+
+	- entry-latency-us
+		Usage: Required
+		Value type: <prop-encoded-array>
+		Definition: u32 value representing worst case latency in
+			    microseconds required to enter the idle state.
+			    The exit-latency-us duration may be guaranteed
+			    only after entry-latency-us has passed.
+
+	- exit-latency-us
+		Usage: Required
+		Value type: <prop-encoded-array>
+		Definition: u32 value representing worst case latency
+			    in microseconds required to exit the idle state.
+
+	- min-residency-us
+		Usage: Required
+		Value type: <prop-encoded-array>
+		Definition: u32 value representing 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:
+		Usage: Optional
+		Value type: <prop-encoded-array>
+		Definition: u32 value representing 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.
+
+===========================================
+4 - Examples
+===========================================
+
+Example 1 (ARM 64-bit, 16-cpu system):
+
+cpus {
+	#size-cells = <0>;
+	#address-cells = <2>;
+
+	idle-states {
+		entry-method = "arm,psci";
+
+		CPU_RETENTION_0_0: cpu-retention-0-0 {
+			compatible = "arm,idle-state";
+			power-rank = <0>;
+			logic-state-retained;
+			cache-state-retained;
+			entry-method-param = <0x0010000>;
+			entry-latency-us = <20>;
+			exit-latency-us = <40>;
+			min-residency-us = <80>;
+		};
+
+		CLUSTER_RETENTION_0: cluster-retention-0 {
+			compatible = "arm,idle-state";
+			power-rank = <2>;
+			cache-state-retained;
+			entry-method-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";
+			power-rank = <1>;
+			entry-method-param = <0x0010000>;
+			entry-latency-us = <250>;
+			exit-latency-us = <500>;
+			min-residency-us = <950>;
+		};
+
+		CLUSTER_SLEEP_0: cluster-sleep-0 {
+			compatible = "arm,idle-state";
+			power-rank = <3>;
+			entry-method-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";
+			power-rank = <0>;
+			logic-state-retained;
+			cache-state-retained;
+			entry-method-param = <0x0010000>;
+			entry-latency-us = <20>;
+			exit-latency-us = <40>;
+			min-residency-us = <90>;
+		};
+
+		CLUSTER_RETENTION_1: cluster-retention-1 {
+			compatible = "arm,idle-state";
+			power-rank = <2>;
+			cache-state-retained;
+			entry-method-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";
+			power-rank = <1>;
+			entry-method-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";
+			power-rank = <3>;
+			entry-method-param = <0x1010000>;
+			entry-latency-us = <500>;
+			exit-latency-us = <1200>;
+			min-residency-us = <3500>;
+			wakeup-latency-us = <1300>;
+		};
+	};
+
+	CPU0: 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>;
+	};
+
+	CPU1: 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>;
+	};
+
+	CPU2: 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>;
+	};
+
+	CPU3: 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>;
+	};
+
+	CPU4: 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>;
+	};
+
+	CPU5: 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>;
+	};
+
+	CPU6: 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>;
+	};
+
+	CPU7: 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>;
+	};
+
+	CPU8: 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>;
+	};
+
+	CPU9: 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>;
+	};
+
+	CPU10: 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>;
+	};
+
+	CPU11: 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>;
+	};
+
+	CPU12: 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>;
+	};
+
+	CPU13: 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>;
+	};
+
+	CPU14: 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>;
+	};
+
+	CPU15: 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>;
+	};
+};
+
+Example 2 (ARM 32-bit, 8-cpu system, two clusters):
+
+cpus {
+	#size-cells = <0>;
+	#address-cells = <1>;
+
+	idle-states {
+		entry-method = "arm,psci";
+
+		CPU_SLEEP_0_0: cpu-sleep-0-0 {
+			compatible = "arm,idle-state";
+			power-rank = <0>;
+			entry-method-param = <0x0010000>;
+			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";
+			power-rank = <2>;
+			entry-method-param = <0x1010000>;
+			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";
+			power-rank = <1>;
+			entry-method-param = <0x0010000>;
+			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";
+			power-rank = <3>;
+			entry-method-param = <0x1010000>;
+			entry-latency-us = <800>;
+			exit-latency-us = <2000>;
+			min-residency-us = <6500>;
+			wakeup-latency-us = <2300>;
+		};
+	};
+
+	CPU0: cpu@0 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a15";
+		reg = <0x0>;
+		enable-method = "psci";
+		cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>;
+	};
+
+	CPU1: cpu@1 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a15";
+		reg = <0x1>;
+		enable-method = "psci";
+		cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>;
+	};
+
+	CPU2: cpu@2 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a15";
+		reg = <0x2>;
+		enable-method = "psci";
+		cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>;
+	};
+
+	CPU3: cpu@3 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a15";
+		reg = <0x3>;
+		enable-method = "psci";
+		cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>;
+	};
+
+	CPU4: cpu@100 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a7";
+		reg = <0x100>;
+		enable-method = "psci";
+		cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>;
+	};
+
+	CPU5: cpu@101 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a7";
+		reg = <0x101>;
+		enable-method = "psci";
+		cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>;
+	};
+
+	CPU6: cpu@102 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a7";
+		reg = <0x102>;
+		enable-method = "psci";
+		cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>;
+	};
+
+	CPU7: cpu@103 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a7";
+		reg = <0x103>;
+		enable-method = "psci";
+		cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>;
+	};
+};
+
+===========================================
+5 - References
+===========================================
+
+[1] ARM Linux Kernel documentation - CPUs bindings
+    Documentation/devicetree/bindings/arm/cpus.txt
+
+[2] ARM Linux Kernel documentation - PSCI bindings
+    Documentation/devicetree/bindings/arm/psci.txt
+
+[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] ePAPR standard
+    https://www.power.org/documentation/epapr-version-1-1/
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH v5 1/8] Documentation: arm: define DT idle states bindings
@ 2014-06-25 14:10   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel

ARM based platforms implement a variety of power management schemes that
allow processors to enter idle states at run-time.
The parameters defining these idle states vary on a per-platform basis forcing
the OS to hardcode the state parameters in platform specific static tables
whose size grows as the number of platforms supported in the kernel increases
and hampers device drivers standardization.

Therefore, this patch aims at standardizing idle state device tree bindings for
ARM platforms. Bindings define idle state parameters inclusive of entry methods
and state latencies, to allow operating systems to retrieve the configuration
entries from the device tree and initialize the related power management
drivers, paving the way for common code in the kernel to deal with idle
states and removing the need for static data in current and previous kernel
versions.

Reviewed-by: Sebastian Capella <sebcape@gmail.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
 Documentation/devicetree/bindings/arm/cpus.txt     |   8 +
 .../devicetree/bindings/arm/idle-states.txt        | 733 +++++++++++++++++++++
 2 files changed, 741 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/idle-states.txt

diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
index 1fe72a0..a44d4fd 100644
--- a/Documentation/devicetree/bindings/arm/cpus.txt
+++ b/Documentation/devicetree/bindings/arm/cpus.txt
@@ -215,6 +215,12 @@ nodes to be present and contain the properties described below.
 		Value type: <phandle>
 		Definition: Specifies the ACC[2] node associated with this CPU.
 
+	- cpu-idle-states
+		Usage: Optional
+		Value type: <prop-encoded-array>
+		Definition:
+			# List of phandles to idle state nodes supported
+			  by this cpu [3].
 
 Example 1 (dual-cluster big.LITTLE system 32-bit):
 
@@ -411,3 +417,5 @@ cpus {
 --
 [1] arm/msm/qcom,saw2.txt
 [2] arm/msm/qcom,kpss-acc.txt
+[3] ARM Linux kernel documentation - idle states bindings
+    Documentation/devicetree/bindings/arm/idle-states.txt
diff --git a/Documentation/devicetree/bindings/arm/idle-states.txt b/Documentation/devicetree/bindings/arm/idle-states.txt
new file mode 100644
index 0000000..5efd198
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/idle-states.txt
@@ -0,0 +1,733 @@
+==========================================
+ARM idle states binding description
+==========================================
+
+==========================================
+1 - Introduction
+==========================================
+
+ARM 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.
+
+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 (eg 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.
+
+===========================================
+2 - 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
+(ie 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, eg:
+
+wakeup-delay = exit-latency + max(entry-latency - (now - entry-timestamp), 0)
+
+In other words, the scheduler can make its scheduling decision by selecting
+(eg waking-up) the CPU with the shortest wake-up latency.
+The wake-up latency 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, ie caches
+state).
+
+An OS has to reliably probe the wakeup-latency since some devices can enforce
+latency constraints 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 whilst 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 (ie 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 (ie shallower energy curve slope) of idle
+state IDLE2 implies that after a suitable time, IDLE2 becomes more energy
+efficient.
+
+The time@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.
+
+===========================================
+3 - idle-states node
+===========================================
+
+ARM 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.
+
+- idle-states node
+
+	Usage: Optional - 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.
+
+	Description: idle-states node is a container node, where its
+		     subnodes describe the CPU idle states.
+
+	Node name must be "idle-states".
+
+	The idle-states node's parent node must be the cpus node.
+
+	The idle-states node's child nodes can be:
+
+	- one or more state nodes
+
+	Any other configuration is considered invalid.
+
+	An idle-states node defines the following properties:
+
+	- entry-method
+		Usage: Required
+		Value type: <stringlist>
+		Definition: Describes the method by which a CPU enters the
+			    idle states. This property is required and must be
+			    one of:
+
+			    - "arm,psci"
+			      ARM PSCI firmware interface [2].
+
+			    - "[vendor],[method]"
+			      An implementation dependent string with
+			      format "vendor,method", where vendor is a string
+			      denoting the name of the manufacturer and
+			      method is a string specifying the mechanism
+			      used to enter the idle state.
+
+The nodes describing the idle states (state) can only be defined within the
+idle-states node, any other configuration is considered invalid and therefore
+must be ignored.
+
+===========================================
+4 - state node
+===========================================
+
+A state node represents an idle state description and must be defined as
+follows:
+
+- state node
+
+	Description: must be child of the idle-states node
+
+	The state node name shall follow standard device tree naming
+	rules ([5], 2.2.1 "Node names"), in particular state nodes which
+	are siblings within a single common parent must be given a unique name.
+
+	The idle state entered by executing the wfi instruction (idle_standby
+	SBSA,[3][4]) is considered standard on all ARM platforms and therefore
+	must not be listed.
+
+	With the definitions provided above, the following list represents
+	the valid properties for a state node:
+
+	- compatible
+		Usage: Required
+		Value type: <stringlist>
+		Definition: Must be "arm,idle-state".
+
+	- logic-state-retained
+		Usage: See definition
+		Value type: <none>
+		Definition: if present logic is retained on state entry,
+			    otherwise it is lost.
+
+	- cache-state-retained
+		Usage: See definition
+		Value type: <none>
+		Definition: if present cache memory is retained on state entry,
+			    otherwise it is lost.
+
+	- timer-state-retained
+		Usage: See definition
+		Value type: <none>
+		Definition: if present the timer control logic is retained on
+                            state entry, otherwise it is lost.
+
+	- power-rank
+		Usage: Required
+		Value type: <u32>
+		Definition: It represents the idle state power-rank.
+			    An increasing value implies less power
+			    consumption. It must be given a sequential
+			    value = {0, 1, ....}, starting from 0.
+			    Phandles in the cpu nodes [1] cpu-idle-states
+			    array property are not allowed to point at idle
+			    state nodes having the same power-rank value.
+
+	- entry-method-param
+		Usage: See definition.
+		Value type: <u32>
+		Definition: Depends on the idle-states node entry-method
+			    property value. Refer to the entry-method bindings
+			    for this property value definition.
+
+	- entry-latency-us
+		Usage: Required
+		Value type: <prop-encoded-array>
+		Definition: u32 value representing worst case latency in
+			    microseconds required to enter the idle state.
+			    The exit-latency-us duration may be guaranteed
+			    only after entry-latency-us has passed.
+
+	- exit-latency-us
+		Usage: Required
+		Value type: <prop-encoded-array>
+		Definition: u32 value representing worst case latency
+			    in microseconds required to exit the idle state.
+
+	- min-residency-us
+		Usage: Required
+		Value type: <prop-encoded-array>
+		Definition: u32 value representing 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:
+		Usage: Optional
+		Value type: <prop-encoded-array>
+		Definition: u32 value representing 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.
+
+===========================================
+4 - Examples
+===========================================
+
+Example 1 (ARM 64-bit, 16-cpu system):
+
+cpus {
+	#size-cells = <0>;
+	#address-cells = <2>;
+
+	idle-states {
+		entry-method = "arm,psci";
+
+		CPU_RETENTION_0_0: cpu-retention-0-0 {
+			compatible = "arm,idle-state";
+			power-rank = <0>;
+			logic-state-retained;
+			cache-state-retained;
+			entry-method-param = <0x0010000>;
+			entry-latency-us = <20>;
+			exit-latency-us = <40>;
+			min-residency-us = <80>;
+		};
+
+		CLUSTER_RETENTION_0: cluster-retention-0 {
+			compatible = "arm,idle-state";
+			power-rank = <2>;
+			cache-state-retained;
+			entry-method-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";
+			power-rank = <1>;
+			entry-method-param = <0x0010000>;
+			entry-latency-us = <250>;
+			exit-latency-us = <500>;
+			min-residency-us = <950>;
+		};
+
+		CLUSTER_SLEEP_0: cluster-sleep-0 {
+			compatible = "arm,idle-state";
+			power-rank = <3>;
+			entry-method-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";
+			power-rank = <0>;
+			logic-state-retained;
+			cache-state-retained;
+			entry-method-param = <0x0010000>;
+			entry-latency-us = <20>;
+			exit-latency-us = <40>;
+			min-residency-us = <90>;
+		};
+
+		CLUSTER_RETENTION_1: cluster-retention-1 {
+			compatible = "arm,idle-state";
+			power-rank = <2>;
+			cache-state-retained;
+			entry-method-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";
+			power-rank = <1>;
+			entry-method-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";
+			power-rank = <3>;
+			entry-method-param = <0x1010000>;
+			entry-latency-us = <500>;
+			exit-latency-us = <1200>;
+			min-residency-us = <3500>;
+			wakeup-latency-us = <1300>;
+		};
+	};
+
+	CPU0: cpu at 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>;
+	};
+
+	CPU1: cpu at 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>;
+	};
+
+	CPU2: cpu at 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>;
+	};
+
+	CPU3: cpu at 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>;
+	};
+
+	CPU4: cpu at 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>;
+	};
+
+	CPU5: cpu at 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>;
+	};
+
+	CPU6: cpu at 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>;
+	};
+
+	CPU7: cpu at 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>;
+	};
+
+	CPU8: cpu at 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>;
+	};
+
+	CPU9: cpu at 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>;
+	};
+
+	CPU10: cpu at 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>;
+	};
+
+	CPU11: cpu at 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>;
+	};
+
+	CPU12: cpu at 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>;
+	};
+
+	CPU13: cpu at 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>;
+	};
+
+	CPU14: cpu at 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>;
+	};
+
+	CPU15: cpu at 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>;
+	};
+};
+
+Example 2 (ARM 32-bit, 8-cpu system, two clusters):
+
+cpus {
+	#size-cells = <0>;
+	#address-cells = <1>;
+
+	idle-states {
+		entry-method = "arm,psci";
+
+		CPU_SLEEP_0_0: cpu-sleep-0-0 {
+			compatible = "arm,idle-state";
+			power-rank = <0>;
+			entry-method-param = <0x0010000>;
+			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";
+			power-rank = <2>;
+			entry-method-param = <0x1010000>;
+			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";
+			power-rank = <1>;
+			entry-method-param = <0x0010000>;
+			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";
+			power-rank = <3>;
+			entry-method-param = <0x1010000>;
+			entry-latency-us = <800>;
+			exit-latency-us = <2000>;
+			min-residency-us = <6500>;
+			wakeup-latency-us = <2300>;
+		};
+	};
+
+	CPU0: cpu at 0 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a15";
+		reg = <0x0>;
+		enable-method = "psci";
+		cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>;
+	};
+
+	CPU1: cpu at 1 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a15";
+		reg = <0x1>;
+		enable-method = "psci";
+		cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>;
+	};
+
+	CPU2: cpu at 2 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a15";
+		reg = <0x2>;
+		enable-method = "psci";
+		cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>;
+	};
+
+	CPU3: cpu at 3 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a15";
+		reg = <0x3>;
+		enable-method = "psci";
+		cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>;
+	};
+
+	CPU4: cpu at 100 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a7";
+		reg = <0x100>;
+		enable-method = "psci";
+		cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>;
+	};
+
+	CPU5: cpu at 101 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a7";
+		reg = <0x101>;
+		enable-method = "psci";
+		cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>;
+	};
+
+	CPU6: cpu at 102 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a7";
+		reg = <0x102>;
+		enable-method = "psci";
+		cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>;
+	};
+
+	CPU7: cpu at 103 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a7";
+		reg = <0x103>;
+		enable-method = "psci";
+		cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>;
+	};
+};
+
+===========================================
+5 - References
+===========================================
+
+[1] ARM Linux Kernel documentation - CPUs bindings
+    Documentation/devicetree/bindings/arm/cpus.txt
+
+[2] ARM Linux Kernel documentation - PSCI bindings
+    Documentation/devicetree/bindings/arm/psci.txt
+
+[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] ePAPR standard
+    https://www.power.org/documentation/epapr-version-1-1/
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH v5 2/8] Documentation: devicetree: psci: define CPU suspend parameter
  2014-06-25 14:10 ` Lorenzo Pieralisi
@ 2014-06-25 14:10   ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel, linux-pm, devicetree
  Cc: Lorenzo Pieralisi, Mark Rutland, Sudeep Holla, Catalin Marinas,
	Charles Garcia Tobin, Nicolas Pitre, Rob Herring, Grant Likely,
	Peter De Schrijver, Santosh Shilimkar, Daniel Lezcano,
	Amit Kucheria, Vincent Guittot, Antti Miettinen, Stephen Boyd,
	Kevin Hilman, Sebastian Capella, Tomasz Figa, Mark Brown,
	Paul Walmsley, Chander Kashyap

OS layers built on top of PSCI to enter low-power states require the
power_state parameter to be passed to the PSCI CPU suspend method.

This parameter is specific to a power state and platform specific,
therefore must be provided by firmware to the OS in order to enable
proper call sequence.

This patch adds a property in the PSCI bindings that describes how
the CPU suspend power_state parameter should be defined in DT in
all device nodes that rely on PSCI CPU suspend method usage.

Reviewed-by: Sebastian Capella <sebcape@gmail.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
 Documentation/devicetree/bindings/arm/psci.txt | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/arm/psci.txt b/Documentation/devicetree/bindings/arm/psci.txt
index b4a58f3..fae3eed 100644
--- a/Documentation/devicetree/bindings/arm/psci.txt
+++ b/Documentation/devicetree/bindings/arm/psci.txt
@@ -50,6 +50,14 @@ Main node optional properties:
 
  - migrate       : Function ID for MIGRATE operation
 
+Device tree nodes that require usage of PSCI CPU_SUSPEND function (ie idle
+states bindings[1]) must specify the following properties:
+
+- entry-method-param
+		Usage: Required for idle states bindings [1].
+		Value type: <u32>
+		Definition: power_state parameter to pass to the PSCI
+			    suspend call.
 
 Example:
 
@@ -64,7 +72,6 @@ Case 1: PSCI v0.1 only.
 		migrate		= <0x95c10003>;
 	};
 
-
 Case 2: PSCI v0.2 only
 
 	psci {
@@ -88,3 +95,6 @@ Case 3: PSCI v0.2 and PSCI v0.1.
 
 		...
 	};
+
+[1] Kernel documentation - ARM idle states bindings
+    Documentation/devicetree/bindings/arm/idle-states.txt
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH v5 2/8] Documentation: devicetree: psci: define CPU suspend parameter
@ 2014-06-25 14:10   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel

OS layers built on top of PSCI to enter low-power states require the
power_state parameter to be passed to the PSCI CPU suspend method.

This parameter is specific to a power state and platform specific,
therefore must be provided by firmware to the OS in order to enable
proper call sequence.

This patch adds a property in the PSCI bindings that describes how
the CPU suspend power_state parameter should be defined in DT in
all device nodes that rely on PSCI CPU suspend method usage.

Reviewed-by: Sebastian Capella <sebcape@gmail.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
 Documentation/devicetree/bindings/arm/psci.txt | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/arm/psci.txt b/Documentation/devicetree/bindings/arm/psci.txt
index b4a58f3..fae3eed 100644
--- a/Documentation/devicetree/bindings/arm/psci.txt
+++ b/Documentation/devicetree/bindings/arm/psci.txt
@@ -50,6 +50,14 @@ Main node optional properties:
 
  - migrate       : Function ID for MIGRATE operation
 
+Device tree nodes that require usage of PSCI CPU_SUSPEND function (ie idle
+states bindings[1]) must specify the following properties:
+
+- entry-method-param
+		Usage: Required for idle states bindings [1].
+		Value type: <u32>
+		Definition: power_state parameter to pass to the PSCI
+			    suspend call.
 
 Example:
 
@@ -64,7 +72,6 @@ Case 1: PSCI v0.1 only.
 		migrate		= <0x95c10003>;
 	};
 
-
 Case 2: PSCI v0.2 only
 
 	psci {
@@ -88,3 +95,6 @@ Case 3: PSCI v0.2 and PSCI v0.1.
 
 		...
 	};
+
+[1] Kernel documentation - ARM idle states bindings
+    Documentation/devicetree/bindings/arm/idle-states.txt
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH v5 3/8] drivers: cpuidle: implement DT based idle states infrastructure
  2014-06-25 14:10 ` Lorenzo Pieralisi
@ 2014-06-25 14:10   ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel, linux-pm, devicetree
  Cc: Lorenzo Pieralisi, Mark Rutland, Sudeep Holla, Catalin Marinas,
	Charles Garcia Tobin, Nicolas Pitre, Rob Herring, Grant Likely,
	Peter De Schrijver, Santosh Shilimkar, Daniel Lezcano,
	Amit Kucheria, Vincent Guittot, Antti Miettinen, Stephen Boyd,
	Kevin Hilman, Sebastian Capella, Tomasz Figa, Mark Brown,
	Paul Walmsley, Chander Kashyap

On most common ARM systems, the low-power states a CPU can be put into are
not discoverable in HW and require device tree bindings to describe
power down suspend operations and idle states parameters.

In order to enable DT based idle states and configure idle drivers, this
patch implements the bulk infrastructure required to parse the device tree
idle states bindings and initialize the corresponding CPUidle driver states
data.

Code that initializes idle states checks the CPU idle driver cpumask so
that multiple CPU idle drivers can be initialized through it in the
kernel. The CPU idle driver cpumask defines which idle states should be
considered valid for the driver, ie idle states that are valid on a set
of cpus the idle driver manages.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
 drivers/cpuidle/Kconfig          |   8 ++
 drivers/cpuidle/Makefile         |   1 +
 drivers/cpuidle/dt_idle_states.c | 283 +++++++++++++++++++++++++++++++++++++++
 drivers/cpuidle/dt_idle_states.h |   8 ++
 4 files changed, 300 insertions(+)
 create mode 100644 drivers/cpuidle/dt_idle_states.c
 create mode 100644 drivers/cpuidle/dt_idle_states.h

diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
index 1b96fb9..414e7a96 100644
--- a/drivers/cpuidle/Kconfig
+++ b/drivers/cpuidle/Kconfig
@@ -30,6 +30,14 @@ config CPU_IDLE_GOV_MENU
 	bool "Menu governor (for tickless system)"
 	default y
 
+config DT_IDLE_STATES
+        bool "Idle states DT support"
+	depends on ARM || ARM64
+	help
+	 Allows the CPU idle framework to initialize CPU idle drivers
+	 state data by using DT provided nodes compliant with idle states
+	 device tree bindings.
+
 menu "ARM CPU Idle Drivers"
 depends on ARM
 source "drivers/cpuidle/Kconfig.arm"
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index d8bb1ff..b27a062 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -4,6 +4,7 @@
 
 obj-y += cpuidle.o driver.o governor.o sysfs.o governors/
 obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
+obj-$(CONFIG_DT_IDLE_STATES)		  += dt_idle_states.o
 
 ##################################################################################
 # ARM SoC drivers
diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c
new file mode 100644
index 0000000..5c16001c
--- /dev/null
+++ b/drivers/cpuidle/dt_idle_states.c
@@ -0,0 +1,283 @@
+/*
+ * DT idle states parsing code.
+ *
+ * Copyright (C) 2014 ARM Ltd.
+ * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt) "DT idle-states: " fmt
+
+#include <linux/cpuidle.h>
+#include <linux/cpumask.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/list_sort.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#include "dt_idle_states.h"
+
+struct state_elem {
+	struct list_head list;
+	struct device_node *node;
+	u32 val;
+};
+
+static struct list_head head __initdata = LIST_HEAD_INIT(head);
+
+static bool __init state_cpu_valid(struct device_node *state_node,
+				   struct device_node *cpu_node)
+{
+	int i = 0;
+	struct device_node *cpu_state;
+
+	while ((cpu_state = of_parse_phandle(cpu_node,
+					     "cpu-idle-states", i++))) {
+		if (cpu_state && state_node == cpu_state) {
+			of_node_put(cpu_state);
+			return true;
+		}
+		of_node_put(cpu_state);
+	}
+	return false;
+}
+
+static bool __init state_cpus_valid(const cpumask_t *cpus,
+				    struct device_node *state_node)
+{
+	int cpu;
+	struct device_node *cpu_node;
+
+	/*
+	 * Check if state is valid on driver cpumask cpus
+	 */
+	for_each_cpu(cpu, cpus) {
+		cpu_node = of_get_cpu_node(cpu, NULL);
+
+		if (!cpu_node) {
+			pr_err("Missing device node for CPU %d\n", cpu);
+			return false;
+		}
+
+		if (!state_cpu_valid(state_node, cpu_node))
+			return false;
+	}
+
+	return true;
+}
+
+static int __init state_cmp(void *priv, struct list_head *a,
+			    struct list_head *b)
+{
+	struct state_elem *ela, *elb;
+
+	ela = container_of(a, struct state_elem, list);
+	elb = container_of(b, struct state_elem, list);
+
+	return ela->val - elb->val;
+}
+
+static int __init add_state_node(cpumask_t *cpumask,
+				 struct device_node *state_node)
+{
+	struct state_elem *el;
+	u32 val;
+
+	pr_debug(" * %s...\n", state_node->full_name);
+
+	if (!state_cpus_valid(cpumask, state_node))
+		return -EINVAL;
+	/*
+	 * Parse just the property required to sort the states.
+	 */
+	if (of_property_read_u32(state_node, "power-rank",
+				 &val)) {
+		pr_debug(" * %s missing power-rank property\n",
+			     state_node->full_name);
+		return -EINVAL;
+	}
+
+	el = kmalloc(sizeof(*el), GFP_KERNEL);
+	if (!el) {
+		pr_err("%s failed to allocate memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	el->node = state_node;
+	el->val = val;
+	list_add_tail(&el->list, &head);
+
+	return 0;
+}
+
+static void __init init_state_node(struct cpuidle_driver *drv,
+				   struct device_node *state_node,
+				   int *cnt)
+{
+	struct cpuidle_state *idle_state;
+
+	pr_debug(" * %s...\n", state_node->full_name);
+
+	idle_state = &drv->states[*cnt];
+
+	if (of_property_read_u32(state_node, "wakeup-latency-us",
+				 &idle_state->exit_latency)) {
+		u32 entry_latency, exit_latency;
+
+		if (of_property_read_u32(state_node, "entry-latency-us",
+					 &entry_latency)) {
+			pr_debug(" * %s missing entry-latency-us property\n",
+				 state_node->full_name);
+			return;
+		}
+
+		if (of_property_read_u32(state_node, "exit-latency-us",
+					 &exit_latency)) {
+			pr_debug(" * %s missing exit-latency-us property\n",
+				 state_node->full_name);
+			return;
+		}
+		/*
+		 * If wakeup-latency-us is missing, default to entry+exit
+		 * latencies as defined in idle states bindings
+		 */
+		idle_state->exit_latency = entry_latency + exit_latency;
+	}
+
+	if (of_property_read_u32(state_node, "min-residency-us",
+				 &idle_state->target_residency)) {
+		pr_debug(" * %s missing min-residency-us property\n",
+			     state_node->full_name);
+		return;
+	}
+
+	idle_state->flags = CPUIDLE_FLAG_TIME_VALID;
+	if (!of_property_read_bool(state_node, "timer-state-retained"))
+		idle_state->flags |= CPUIDLE_FLAG_TIMER_STOP;
+
+	strncpy(idle_state->name, state_node->name, CPUIDLE_NAME_LEN);
+	strncpy(idle_state->desc, state_node->name, CPUIDLE_NAME_LEN);
+
+	(*cnt)++;
+}
+
+static int __init init_idle_states(struct cpuidle_driver *drv,
+				   struct device_node *state_nodes[],
+				   unsigned int start_idx, bool init_nodes)
+{
+	struct state_elem *el;
+	struct list_head *curr, *tmp;
+	unsigned int cnt = start_idx;
+
+	list_for_each_entry(el, &head, list) {
+		/*
+		 * Check if the init function has to fill the
+		 * state_nodes array on behalf of the CPUidle driver.
+		 */
+		if (init_nodes)
+			state_nodes[cnt] = el->node;
+		/*
+		 * cnt is updated on return if a state was added.
+		 */
+		init_state_node(drv, el->node, &cnt);
+
+		if (cnt == CPUIDLE_STATE_MAX) {
+			pr_warn("State index reached static CPU idle state limit\n");
+			break;
+		}
+	}
+
+	drv->state_count = cnt;
+
+	list_for_each_safe(curr, tmp, &head) {
+		list_del(curr);
+		kfree(container_of(curr, struct state_elem, list));
+	}
+
+	/*
+	 * If no idle states are detected, return an error and let the idle
+	 * driver initialization fail accordingly.
+	 */
+	return (cnt > start_idx) ? 0 : -ENODATA;
+}
+
+static void __init add_idle_states(struct cpuidle_driver *drv,
+				   struct device_node *idle_states)
+{
+	struct device_node *state_node;
+
+	for_each_child_of_node(idle_states, state_node) {
+		if ((!of_device_is_compatible(state_node, "arm,idle-state"))) {
+			pr_warn(" * %s: children of /cpus/idle-states must be \"arm,idle-state\" compatible\n",
+				     state_node->full_name);
+			continue;
+		}
+		/*
+		 * If memory allocation fails, better bail out.
+		 * Initialized nodes are freed at initialization
+		 * completion in of_init_idle_driver().
+		 */
+		if ((add_state_node(drv->cpumask, state_node) == -ENOMEM))
+			break;
+	}
+	/*
+	 * Sort the states list before initializing the CPUidle driver
+	 * states array.
+	 */
+	list_sort(NULL, &head, state_cmp);
+}
+
+/**
+ * dt_init_idle_driver() - Parse the DT idle states and initialize the
+ *			   idle driver states array
+ *
+ * @drv:	  Pointer to CPU idle driver to be initialized
+ * @state_nodes:  Array of struct device_nodes to be initialized if
+ *		  init_nodes == true. Must be sized CPUIDLE_STATE_MAX
+ * @start_idx:    First idle state index to be initialized
+ * @init_nodes:   Boolean to request device nodes initialization
+ *
+ * On success the states array in the cpuidle driver contains
+ * initialized entries in the states array, starting from index start_idx.
+ * If init_nodes == true, on success the state_nodes array is initialized
+ * with idle state DT node pointers, starting from index start_idx,
+ * in a 1:1 relation with the idle driver states array.
+ *
+ * Return:
+ *	0 on success
+ *	<0 on failure
+ */
+int __init dt_init_idle_driver(struct cpuidle_driver *drv,
+			       struct device_node *state_nodes[],
+			       unsigned int start_idx, bool init_nodes)
+{
+	struct device_node *idle_states_node;
+	int ret;
+
+	if (start_idx >= CPUIDLE_STATE_MAX) {
+		pr_warn("State index exceeds static CPU idle driver states array size\n");
+		return -EINVAL;
+	}
+
+	if (WARN(init_nodes && !state_nodes,
+		"Requested nodes stashing in an invalid nodes container\n"))
+		return -EINVAL;
+
+	idle_states_node = of_find_node_by_path("/cpus/idle-states");
+	if (!idle_states_node)
+		return -ENOENT;
+
+	add_idle_states(drv, idle_states_node);
+
+	ret = init_idle_states(drv, state_nodes, start_idx, init_nodes);
+
+	of_node_put(idle_states_node);
+
+	return ret;
+}
diff --git a/drivers/cpuidle/dt_idle_states.h b/drivers/cpuidle/dt_idle_states.h
new file mode 100644
index 0000000..e74f1e8
--- /dev/null
+++ b/drivers/cpuidle/dt_idle_states.h
@@ -0,0 +1,8 @@
+#ifndef __DT_IDLE_STATES
+#define __DT_IDLE_STATES
+
+int __init dt_init_idle_driver(struct cpuidle_driver *drv,
+			       struct device_node *state_nodes[],
+			       unsigned int start_idx,
+			       bool init_nodes);
+#endif
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH v5 3/8] drivers: cpuidle: implement DT based idle states infrastructure
@ 2014-06-25 14:10   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel

On most common ARM systems, the low-power states a CPU can be put into are
not discoverable in HW and require device tree bindings to describe
power down suspend operations and idle states parameters.

In order to enable DT based idle states and configure idle drivers, this
patch implements the bulk infrastructure required to parse the device tree
idle states bindings and initialize the corresponding CPUidle driver states
data.

Code that initializes idle states checks the CPU idle driver cpumask so
that multiple CPU idle drivers can be initialized through it in the
kernel. The CPU idle driver cpumask defines which idle states should be
considered valid for the driver, ie idle states that are valid on a set
of cpus the idle driver manages.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
 drivers/cpuidle/Kconfig          |   8 ++
 drivers/cpuidle/Makefile         |   1 +
 drivers/cpuidle/dt_idle_states.c | 283 +++++++++++++++++++++++++++++++++++++++
 drivers/cpuidle/dt_idle_states.h |   8 ++
 4 files changed, 300 insertions(+)
 create mode 100644 drivers/cpuidle/dt_idle_states.c
 create mode 100644 drivers/cpuidle/dt_idle_states.h

diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
index 1b96fb9..414e7a96 100644
--- a/drivers/cpuidle/Kconfig
+++ b/drivers/cpuidle/Kconfig
@@ -30,6 +30,14 @@ config CPU_IDLE_GOV_MENU
 	bool "Menu governor (for tickless system)"
 	default y
 
+config DT_IDLE_STATES
+        bool "Idle states DT support"
+	depends on ARM || ARM64
+	help
+	 Allows the CPU idle framework to initialize CPU idle drivers
+	 state data by using DT provided nodes compliant with idle states
+	 device tree bindings.
+
 menu "ARM CPU Idle Drivers"
 depends on ARM
 source "drivers/cpuidle/Kconfig.arm"
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index d8bb1ff..b27a062 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -4,6 +4,7 @@
 
 obj-y += cpuidle.o driver.o governor.o sysfs.o governors/
 obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
+obj-$(CONFIG_DT_IDLE_STATES)		  += dt_idle_states.o
 
 ##################################################################################
 # ARM SoC drivers
diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c
new file mode 100644
index 0000000..5c16001c
--- /dev/null
+++ b/drivers/cpuidle/dt_idle_states.c
@@ -0,0 +1,283 @@
+/*
+ * DT idle states parsing code.
+ *
+ * Copyright (C) 2014 ARM Ltd.
+ * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt) "DT idle-states: " fmt
+
+#include <linux/cpuidle.h>
+#include <linux/cpumask.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/list_sort.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#include "dt_idle_states.h"
+
+struct state_elem {
+	struct list_head list;
+	struct device_node *node;
+	u32 val;
+};
+
+static struct list_head head __initdata = LIST_HEAD_INIT(head);
+
+static bool __init state_cpu_valid(struct device_node *state_node,
+				   struct device_node *cpu_node)
+{
+	int i = 0;
+	struct device_node *cpu_state;
+
+	while ((cpu_state = of_parse_phandle(cpu_node,
+					     "cpu-idle-states", i++))) {
+		if (cpu_state && state_node == cpu_state) {
+			of_node_put(cpu_state);
+			return true;
+		}
+		of_node_put(cpu_state);
+	}
+	return false;
+}
+
+static bool __init state_cpus_valid(const cpumask_t *cpus,
+				    struct device_node *state_node)
+{
+	int cpu;
+	struct device_node *cpu_node;
+
+	/*
+	 * Check if state is valid on driver cpumask cpus
+	 */
+	for_each_cpu(cpu, cpus) {
+		cpu_node = of_get_cpu_node(cpu, NULL);
+
+		if (!cpu_node) {
+			pr_err("Missing device node for CPU %d\n", cpu);
+			return false;
+		}
+
+		if (!state_cpu_valid(state_node, cpu_node))
+			return false;
+	}
+
+	return true;
+}
+
+static int __init state_cmp(void *priv, struct list_head *a,
+			    struct list_head *b)
+{
+	struct state_elem *ela, *elb;
+
+	ela = container_of(a, struct state_elem, list);
+	elb = container_of(b, struct state_elem, list);
+
+	return ela->val - elb->val;
+}
+
+static int __init add_state_node(cpumask_t *cpumask,
+				 struct device_node *state_node)
+{
+	struct state_elem *el;
+	u32 val;
+
+	pr_debug(" * %s...\n", state_node->full_name);
+
+	if (!state_cpus_valid(cpumask, state_node))
+		return -EINVAL;
+	/*
+	 * Parse just the property required to sort the states.
+	 */
+	if (of_property_read_u32(state_node, "power-rank",
+				 &val)) {
+		pr_debug(" * %s missing power-rank property\n",
+			     state_node->full_name);
+		return -EINVAL;
+	}
+
+	el = kmalloc(sizeof(*el), GFP_KERNEL);
+	if (!el) {
+		pr_err("%s failed to allocate memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	el->node = state_node;
+	el->val = val;
+	list_add_tail(&el->list, &head);
+
+	return 0;
+}
+
+static void __init init_state_node(struct cpuidle_driver *drv,
+				   struct device_node *state_node,
+				   int *cnt)
+{
+	struct cpuidle_state *idle_state;
+
+	pr_debug(" * %s...\n", state_node->full_name);
+
+	idle_state = &drv->states[*cnt];
+
+	if (of_property_read_u32(state_node, "wakeup-latency-us",
+				 &idle_state->exit_latency)) {
+		u32 entry_latency, exit_latency;
+
+		if (of_property_read_u32(state_node, "entry-latency-us",
+					 &entry_latency)) {
+			pr_debug(" * %s missing entry-latency-us property\n",
+				 state_node->full_name);
+			return;
+		}
+
+		if (of_property_read_u32(state_node, "exit-latency-us",
+					 &exit_latency)) {
+			pr_debug(" * %s missing exit-latency-us property\n",
+				 state_node->full_name);
+			return;
+		}
+		/*
+		 * If wakeup-latency-us is missing, default to entry+exit
+		 * latencies as defined in idle states bindings
+		 */
+		idle_state->exit_latency = entry_latency + exit_latency;
+	}
+
+	if (of_property_read_u32(state_node, "min-residency-us",
+				 &idle_state->target_residency)) {
+		pr_debug(" * %s missing min-residency-us property\n",
+			     state_node->full_name);
+		return;
+	}
+
+	idle_state->flags = CPUIDLE_FLAG_TIME_VALID;
+	if (!of_property_read_bool(state_node, "timer-state-retained"))
+		idle_state->flags |= CPUIDLE_FLAG_TIMER_STOP;
+
+	strncpy(idle_state->name, state_node->name, CPUIDLE_NAME_LEN);
+	strncpy(idle_state->desc, state_node->name, CPUIDLE_NAME_LEN);
+
+	(*cnt)++;
+}
+
+static int __init init_idle_states(struct cpuidle_driver *drv,
+				   struct device_node *state_nodes[],
+				   unsigned int start_idx, bool init_nodes)
+{
+	struct state_elem *el;
+	struct list_head *curr, *tmp;
+	unsigned int cnt = start_idx;
+
+	list_for_each_entry(el, &head, list) {
+		/*
+		 * Check if the init function has to fill the
+		 * state_nodes array on behalf of the CPUidle driver.
+		 */
+		if (init_nodes)
+			state_nodes[cnt] = el->node;
+		/*
+		 * cnt is updated on return if a state was added.
+		 */
+		init_state_node(drv, el->node, &cnt);
+
+		if (cnt == CPUIDLE_STATE_MAX) {
+			pr_warn("State index reached static CPU idle state limit\n");
+			break;
+		}
+	}
+
+	drv->state_count = cnt;
+
+	list_for_each_safe(curr, tmp, &head) {
+		list_del(curr);
+		kfree(container_of(curr, struct state_elem, list));
+	}
+
+	/*
+	 * If no idle states are detected, return an error and let the idle
+	 * driver initialization fail accordingly.
+	 */
+	return (cnt > start_idx) ? 0 : -ENODATA;
+}
+
+static void __init add_idle_states(struct cpuidle_driver *drv,
+				   struct device_node *idle_states)
+{
+	struct device_node *state_node;
+
+	for_each_child_of_node(idle_states, state_node) {
+		if ((!of_device_is_compatible(state_node, "arm,idle-state"))) {
+			pr_warn(" * %s: children of /cpus/idle-states must be \"arm,idle-state\" compatible\n",
+				     state_node->full_name);
+			continue;
+		}
+		/*
+		 * If memory allocation fails, better bail out.
+		 * Initialized nodes are freed at initialization
+		 * completion in of_init_idle_driver().
+		 */
+		if ((add_state_node(drv->cpumask, state_node) == -ENOMEM))
+			break;
+	}
+	/*
+	 * Sort the states list before initializing the CPUidle driver
+	 * states array.
+	 */
+	list_sort(NULL, &head, state_cmp);
+}
+
+/**
+ * dt_init_idle_driver() - Parse the DT idle states and initialize the
+ *			   idle driver states array
+ *
+ * @drv:	  Pointer to CPU idle driver to be initialized
+ * @state_nodes:  Array of struct device_nodes to be initialized if
+ *		  init_nodes == true. Must be sized CPUIDLE_STATE_MAX
+ * @start_idx:    First idle state index to be initialized
+ * @init_nodes:   Boolean to request device nodes initialization
+ *
+ * On success the states array in the cpuidle driver contains
+ * initialized entries in the states array, starting from index start_idx.
+ * If init_nodes == true, on success the state_nodes array is initialized
+ * with idle state DT node pointers, starting from index start_idx,
+ * in a 1:1 relation with the idle driver states array.
+ *
+ * Return:
+ *	0 on success
+ *	<0 on failure
+ */
+int __init dt_init_idle_driver(struct cpuidle_driver *drv,
+			       struct device_node *state_nodes[],
+			       unsigned int start_idx, bool init_nodes)
+{
+	struct device_node *idle_states_node;
+	int ret;
+
+	if (start_idx >= CPUIDLE_STATE_MAX) {
+		pr_warn("State index exceeds static CPU idle driver states array size\n");
+		return -EINVAL;
+	}
+
+	if (WARN(init_nodes && !state_nodes,
+		"Requested nodes stashing in an invalid nodes container\n"))
+		return -EINVAL;
+
+	idle_states_node = of_find_node_by_path("/cpus/idle-states");
+	if (!idle_states_node)
+		return -ENOENT;
+
+	add_idle_states(drv, idle_states_node);
+
+	ret = init_idle_states(drv, state_nodes, start_idx, init_nodes);
+
+	of_node_put(idle_states_node);
+
+	return ret;
+}
diff --git a/drivers/cpuidle/dt_idle_states.h b/drivers/cpuidle/dt_idle_states.h
new file mode 100644
index 0000000..e74f1e8
--- /dev/null
+++ b/drivers/cpuidle/dt_idle_states.h
@@ -0,0 +1,8 @@
+#ifndef __DT_IDLE_STATES
+#define __DT_IDLE_STATES
+
+int __init dt_init_idle_driver(struct cpuidle_driver *drv,
+			       struct device_node *state_nodes[],
+			       unsigned int start_idx,
+			       bool init_nodes);
+#endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH v5 4/8] arm64: add PSCI CPU_SUSPEND based cpu_suspend support
  2014-06-25 14:10 ` Lorenzo Pieralisi
@ 2014-06-25 14:10     ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Lorenzo Pieralisi, Mark Rutland, Sudeep Holla, Catalin Marinas,
	Charles Garcia Tobin, Nicolas Pitre, Rob Herring, Grant Likely,
	Peter De Schrijver, Santosh Shilimkar, Daniel Lezcano,
	Amit Kucheria, Vincent Guittot, Antti Miettinen, Stephen Boyd,
	Kevin Hilman, Sebastian Capella, Tomasz Figa, Mark Brown,
	Paul Walmsley, Chander Kashyap

This patch implements the cpu_suspend cpu operations method through
the PSCI CPU_SUSPEND API. The PSCI implementation translates the idle state
index passed by the cpu_suspend core call into a valid PSCI state according to
the PSCI states initialized at boot by the PSCI suspend backend.

Entry point is set to cpu_resume physical address, that represents the
default kernel execution address following a CPU reset.

Idle state indices missing a DT node description are initialized to power
state standby WFI so that if called by the idle driver they provide the
default behaviour.

Reviewed-by: Sebastian Capella <sebcape-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
---
 arch/arm64/include/asm/psci.h |   4 ++
 arch/arm64/kernel/psci.c      | 103 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 107 insertions(+)

diff --git a/arch/arm64/include/asm/psci.h b/arch/arm64/include/asm/psci.h
index e5312ea..16c1351 100644
--- a/arch/arm64/include/asm/psci.h
+++ b/arch/arm64/include/asm/psci.h
@@ -14,6 +14,10 @@
 #ifndef __ASM_PSCI_H
 #define __ASM_PSCI_H
 
+struct cpuidle_driver;
 int psci_init(void);
 
+int __init psci_dt_register_idle_states(struct cpuidle_driver *,
+					struct device_node *[]);
+
 #endif /* __ASM_PSCI_H */
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index 9e9798f..f708bcc 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -15,12 +15,14 @@
 
 #define pr_fmt(fmt) "psci: " fmt
 
+#include <linux/cpuidle.h>
 #include <linux/init.h>
 #include <linux/of.h>
 #include <linux/smp.h>
 #include <linux/reboot.h>
 #include <linux/pm.h>
 #include <linux/delay.h>
+#include <linux/slab.h>
 #include <uapi/linux/psci.h>
 
 #include <asm/compiler.h>
@@ -28,6 +30,7 @@
 #include <asm/errno.h>
 #include <asm/psci.h>
 #include <asm/smp_plat.h>
+#include <asm/suspend.h>
 #include <asm/system_misc.h>
 
 #define PSCI_POWER_STATE_TYPE_STANDBY		0
@@ -65,6 +68,8 @@ enum psci_function {
 	PSCI_FN_MAX,
 };
 
+static DEFINE_PER_CPU_READ_MOSTLY(struct psci_power_state *, psci_power_state);
+
 static u32 psci_function_id[PSCI_FN_MAX];
 
 static int psci_to_linux_errno(int errno)
@@ -93,6 +98,18 @@ static u32 psci_power_state_pack(struct psci_power_state state)
 		 & PSCI_0_2_POWER_STATE_AFFL_MASK);
 }
 
+static void psci_power_state_unpack(u32 power_state,
+				    struct psci_power_state *state)
+{
+	state->id = (power_state & PSCI_0_2_POWER_STATE_ID_MASK) >>
+			PSCI_0_2_POWER_STATE_ID_SHIFT;
+	state->type = (power_state & PSCI_0_2_POWER_STATE_TYPE_MASK) >>
+			PSCI_0_2_POWER_STATE_TYPE_SHIFT;
+	state->affinity_level =
+			(power_state & PSCI_0_2_POWER_STATE_AFFL_MASK) >>
+			PSCI_0_2_POWER_STATE_AFFL_SHIFT;
+}
+
 /*
  * The following two functions are invoked via the invoke_psci_fn pointer
  * and will not be inlined, allowing us to piggyback on the AAPCS.
@@ -199,6 +216,77 @@ static int psci_migrate_info_type(void)
 	return err;
 }
 
+int __init psci_dt_register_idle_states(struct cpuidle_driver *drv,
+					struct device_node *state_nodes[])
+{
+	int cpu, i;
+	struct psci_power_state *psci_states;
+	const struct cpu_operations *cpu_ops_ptr;
+
+	if (!state_nodes)
+		return -EINVAL;
+	/*
+	 * This is belt-and-braces: make sure that if the idle
+	 * specified protocol is psci, the cpu_ops have been
+	 * initialized to psci operations. Anything else is
+	 * a recipe for mayhem.
+	 */
+	for_each_cpu(cpu, drv->cpumask) {
+		cpu_ops_ptr = cpu_ops[cpu];
+		if (WARN_ON(!cpu_ops_ptr || strcmp(cpu_ops_ptr->name, "psci")))
+			return -EOPNOTSUPP;
+	}
+
+	psci_states = kcalloc(drv->state_count, sizeof(*psci_states),
+			      GFP_KERNEL);
+
+	if (!psci_states) {
+		pr_warn("psci idle state allocation failed\n");
+		return -ENOMEM;
+	}
+
+	for_each_cpu(cpu, drv->cpumask) {
+		if (per_cpu(psci_power_state, cpu)) {
+			pr_warn("idle states already initialized on cpu %u\n",
+				cpu);
+			continue;
+		}
+		per_cpu(psci_power_state, cpu) = psci_states;
+	}
+
+
+	for (i = 0; i < drv->state_count; i++) {
+		u32 psci_power_state;
+
+		if (!state_nodes[i]) {
+			/*
+			 * An index with a missing node pointer falls back to
+			 * simple STANDBYWFI
+			 */
+			psci_states[i].type = PSCI_POWER_STATE_TYPE_STANDBY;
+			continue;
+		}
+
+		if (of_property_read_u32(state_nodes[i], "entry-method-param",
+					 &psci_power_state)) {
+			pr_warn(" * %s missing entry-method-param property\n",
+				state_nodes[i]->full_name);
+			/*
+			 * If entry-method-param property is missing, fall
+			 * back to STANDBYWFI state
+			 */
+			psci_states[i].type = PSCI_POWER_STATE_TYPE_STANDBY;
+			continue;
+		}
+
+		pr_debug("psci-power-state %#x index %u\n", psci_power_state,
+							    i);
+		psci_power_state_unpack(psci_power_state, &psci_states[i]);
+	}
+
+	return 0;
+}
+
 static int get_set_conduit_method(struct device_node *np)
 {
 	const char *method;
@@ -435,6 +523,18 @@ static int cpu_psci_cpu_kill(unsigned int cpu)
 }
 #endif
 
+#ifdef CONFIG_ARM64_CPU_SUSPEND
+static int cpu_psci_cpu_suspend(unsigned long index)
+{
+	struct psci_power_state *state = __get_cpu_var(psci_power_state);
+
+	if (!state)
+		return -EOPNOTSUPP;
+
+	return psci_ops.cpu_suspend(state[index], virt_to_phys(cpu_resume));
+}
+#endif
+
 const struct cpu_operations cpu_psci_ops = {
 	.name		= "psci",
 	.cpu_init	= cpu_psci_cpu_init,
@@ -445,6 +545,9 @@ const struct cpu_operations cpu_psci_ops = {
 	.cpu_die	= cpu_psci_cpu_die,
 	.cpu_kill	= cpu_psci_cpu_kill,
 #endif
+#ifdef CONFIG_ARM64_CPU_SUSPEND
+	.cpu_suspend	= cpu_psci_cpu_suspend,
+#endif
 };
 
 #endif
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH v5 4/8] arm64: add PSCI CPU_SUSPEND based cpu_suspend support
@ 2014-06-25 14:10     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel

This patch implements the cpu_suspend cpu operations method through
the PSCI CPU_SUSPEND API. The PSCI implementation translates the idle state
index passed by the cpu_suspend core call into a valid PSCI state according to
the PSCI states initialized at boot by the PSCI suspend backend.

Entry point is set to cpu_resume physical address, that represents the
default kernel execution address following a CPU reset.

Idle state indices missing a DT node description are initialized to power
state standby WFI so that if called by the idle driver they provide the
default behaviour.

Reviewed-by: Sebastian Capella <sebcape@gmail.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
 arch/arm64/include/asm/psci.h |   4 ++
 arch/arm64/kernel/psci.c      | 103 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 107 insertions(+)

diff --git a/arch/arm64/include/asm/psci.h b/arch/arm64/include/asm/psci.h
index e5312ea..16c1351 100644
--- a/arch/arm64/include/asm/psci.h
+++ b/arch/arm64/include/asm/psci.h
@@ -14,6 +14,10 @@
 #ifndef __ASM_PSCI_H
 #define __ASM_PSCI_H
 
+struct cpuidle_driver;
 int psci_init(void);
 
+int __init psci_dt_register_idle_states(struct cpuidle_driver *,
+					struct device_node *[]);
+
 #endif /* __ASM_PSCI_H */
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index 9e9798f..f708bcc 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -15,12 +15,14 @@
 
 #define pr_fmt(fmt) "psci: " fmt
 
+#include <linux/cpuidle.h>
 #include <linux/init.h>
 #include <linux/of.h>
 #include <linux/smp.h>
 #include <linux/reboot.h>
 #include <linux/pm.h>
 #include <linux/delay.h>
+#include <linux/slab.h>
 #include <uapi/linux/psci.h>
 
 #include <asm/compiler.h>
@@ -28,6 +30,7 @@
 #include <asm/errno.h>
 #include <asm/psci.h>
 #include <asm/smp_plat.h>
+#include <asm/suspend.h>
 #include <asm/system_misc.h>
 
 #define PSCI_POWER_STATE_TYPE_STANDBY		0
@@ -65,6 +68,8 @@ enum psci_function {
 	PSCI_FN_MAX,
 };
 
+static DEFINE_PER_CPU_READ_MOSTLY(struct psci_power_state *, psci_power_state);
+
 static u32 psci_function_id[PSCI_FN_MAX];
 
 static int psci_to_linux_errno(int errno)
@@ -93,6 +98,18 @@ static u32 psci_power_state_pack(struct psci_power_state state)
 		 & PSCI_0_2_POWER_STATE_AFFL_MASK);
 }
 
+static void psci_power_state_unpack(u32 power_state,
+				    struct psci_power_state *state)
+{
+	state->id = (power_state & PSCI_0_2_POWER_STATE_ID_MASK) >>
+			PSCI_0_2_POWER_STATE_ID_SHIFT;
+	state->type = (power_state & PSCI_0_2_POWER_STATE_TYPE_MASK) >>
+			PSCI_0_2_POWER_STATE_TYPE_SHIFT;
+	state->affinity_level =
+			(power_state & PSCI_0_2_POWER_STATE_AFFL_MASK) >>
+			PSCI_0_2_POWER_STATE_AFFL_SHIFT;
+}
+
 /*
  * The following two functions are invoked via the invoke_psci_fn pointer
  * and will not be inlined, allowing us to piggyback on the AAPCS.
@@ -199,6 +216,77 @@ static int psci_migrate_info_type(void)
 	return err;
 }
 
+int __init psci_dt_register_idle_states(struct cpuidle_driver *drv,
+					struct device_node *state_nodes[])
+{
+	int cpu, i;
+	struct psci_power_state *psci_states;
+	const struct cpu_operations *cpu_ops_ptr;
+
+	if (!state_nodes)
+		return -EINVAL;
+	/*
+	 * This is belt-and-braces: make sure that if the idle
+	 * specified protocol is psci, the cpu_ops have been
+	 * initialized to psci operations. Anything else is
+	 * a recipe for mayhem.
+	 */
+	for_each_cpu(cpu, drv->cpumask) {
+		cpu_ops_ptr = cpu_ops[cpu];
+		if (WARN_ON(!cpu_ops_ptr || strcmp(cpu_ops_ptr->name, "psci")))
+			return -EOPNOTSUPP;
+	}
+
+	psci_states = kcalloc(drv->state_count, sizeof(*psci_states),
+			      GFP_KERNEL);
+
+	if (!psci_states) {
+		pr_warn("psci idle state allocation failed\n");
+		return -ENOMEM;
+	}
+
+	for_each_cpu(cpu, drv->cpumask) {
+		if (per_cpu(psci_power_state, cpu)) {
+			pr_warn("idle states already initialized on cpu %u\n",
+				cpu);
+			continue;
+		}
+		per_cpu(psci_power_state, cpu) = psci_states;
+	}
+
+
+	for (i = 0; i < drv->state_count; i++) {
+		u32 psci_power_state;
+
+		if (!state_nodes[i]) {
+			/*
+			 * An index with a missing node pointer falls back to
+			 * simple STANDBYWFI
+			 */
+			psci_states[i].type = PSCI_POWER_STATE_TYPE_STANDBY;
+			continue;
+		}
+
+		if (of_property_read_u32(state_nodes[i], "entry-method-param",
+					 &psci_power_state)) {
+			pr_warn(" * %s missing entry-method-param property\n",
+				state_nodes[i]->full_name);
+			/*
+			 * If entry-method-param property is missing, fall
+			 * back to STANDBYWFI state
+			 */
+			psci_states[i].type = PSCI_POWER_STATE_TYPE_STANDBY;
+			continue;
+		}
+
+		pr_debug("psci-power-state %#x index %u\n", psci_power_state,
+							    i);
+		psci_power_state_unpack(psci_power_state, &psci_states[i]);
+	}
+
+	return 0;
+}
+
 static int get_set_conduit_method(struct device_node *np)
 {
 	const char *method;
@@ -435,6 +523,18 @@ static int cpu_psci_cpu_kill(unsigned int cpu)
 }
 #endif
 
+#ifdef CONFIG_ARM64_CPU_SUSPEND
+static int cpu_psci_cpu_suspend(unsigned long index)
+{
+	struct psci_power_state *state = __get_cpu_var(psci_power_state);
+
+	if (!state)
+		return -EOPNOTSUPP;
+
+	return psci_ops.cpu_suspend(state[index], virt_to_phys(cpu_resume));
+}
+#endif
+
 const struct cpu_operations cpu_psci_ops = {
 	.name		= "psci",
 	.cpu_init	= cpu_psci_cpu_init,
@@ -445,6 +545,9 @@ const struct cpu_operations cpu_psci_ops = {
 	.cpu_die	= cpu_psci_cpu_die,
 	.cpu_kill	= cpu_psci_cpu_kill,
 #endif
+#ifdef CONFIG_ARM64_CPU_SUSPEND
+	.cpu_suspend	= cpu_psci_cpu_suspend,
+#endif
 };
 
 #endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH v5 5/8] drivers: cpuidle: CPU idle ARM64 driver
  2014-06-25 14:10 ` Lorenzo Pieralisi
@ 2014-06-25 14:10   ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel, linux-pm, devicetree
  Cc: Lorenzo Pieralisi, Mark Rutland, Sudeep Holla, Catalin Marinas,
	Charles Garcia Tobin, Nicolas Pitre, Rob Herring, Grant Likely,
	Peter De Schrijver, Santosh Shilimkar, Daniel Lezcano,
	Amit Kucheria, Vincent Guittot, Antti Miettinen, Stephen Boyd,
	Kevin Hilman, Sebastian Capella, Tomasz Figa, Mark Brown,
	Paul Walmsley, Chander Kashyap

This patch implements a generic CPU idle driver for ARM64 machines.

It relies on the DT idle states infrastructure to initialize idle
states count and respective parameters. Current code assumes the driver
is managing idle states on all possible CPUs but can be easily
generalized to support heterogenous systems and build cpumasks at
runtime using MIDRs or DT cpu nodes compatible properties.

Suspend back-ends (eg PSCI) must register a suspend initializer with
the CPU idle driver so that the suspend backend call can be detected,
and the driver code can call the back-end infrastructure to complete the
suspend backend initialization.

Idle state index 0 is always initialized as a simple wfi state, ie always
considered present and functional on all ARM64 platforms.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
 drivers/cpuidle/Kconfig         |   5 ++
 drivers/cpuidle/Kconfig.arm64   |  13 ++++
 drivers/cpuidle/Makefile        |   4 +
 drivers/cpuidle/cpuidle-arm64.c | 165 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 187 insertions(+)
 create mode 100644 drivers/cpuidle/Kconfig.arm64
 create mode 100644 drivers/cpuidle/cpuidle-arm64.c

diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
index 414e7a96..ebf0c2e 100644
--- a/drivers/cpuidle/Kconfig
+++ b/drivers/cpuidle/Kconfig
@@ -43,6 +43,11 @@ depends on ARM
 source "drivers/cpuidle/Kconfig.arm"
 endmenu
 
+menu "ARM64 CPU Idle Drivers"
+depends on ARM64
+source "drivers/cpuidle/Kconfig.arm64"
+endmenu
+
 menu "MIPS CPU Idle Drivers"
 depends on MIPS
 source "drivers/cpuidle/Kconfig.mips"
diff --git a/drivers/cpuidle/Kconfig.arm64 b/drivers/cpuidle/Kconfig.arm64
new file mode 100644
index 0000000..5fc5522
--- /dev/null
+++ b/drivers/cpuidle/Kconfig.arm64
@@ -0,0 +1,13 @@
+#
+# ARM64 CPU Idle drivers
+#
+
+config ARM64_CPUIDLE
+	bool "Generic ARM64 CPU idle Driver"
+	select DT_IDLE_STATES
+	help
+	  Select this to enable generic cpuidle driver for ARM v8.
+	  It provides a generic idle driver whose idle states are configured
+	  at run-time through DT nodes. The CPUidle suspend backend is
+	  initialized by the device tree parsing code on matching the entry
+	  method to the respective CPU operations.
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index b27a062..706cb7f 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -23,6 +23,10 @@ obj-$(CONFIG_ARM_EXYNOS_CPUIDLE)        += cpuidle-exynos.o
 obj-$(CONFIG_MIPS_CPS_CPUIDLE)		+= cpuidle-cps.o
 
 ###############################################################################
+# ARM64 drivers
+obj-$(CONFIG_ARM64_CPUIDLE)		+= cpuidle-arm64.o
+
+###############################################################################
 # POWERPC drivers
 obj-$(CONFIG_PSERIES_CPUIDLE)		+= cpuidle-pseries.o
 obj-$(CONFIG_POWERNV_CPUIDLE)		+= cpuidle-powernv.o
diff --git a/drivers/cpuidle/cpuidle-arm64.c b/drivers/cpuidle/cpuidle-arm64.c
new file mode 100644
index 0000000..e966a40
--- /dev/null
+++ b/drivers/cpuidle/cpuidle-arm64.c
@@ -0,0 +1,165 @@
+/*
+ * ARM64 generic CPU idle driver.
+ *
+ * Copyright (C) 2014 ARM Ltd.
+ * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt) "CPUidle arm64: " fmt
+
+#include <linux/cpuidle.h>
+#include <linux/cpumask.h>
+#include <linux/cpu_pm.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#include <asm/psci.h>
+#include <asm/suspend.h>
+
+#include "dt_idle_states.h"
+
+typedef int (*suspend_init_fn)(struct cpuidle_driver *,
+			       struct device_node *[]);
+
+struct cpu_suspend_ops {
+	const char *id;
+	suspend_init_fn init_fn;
+};
+
+static const struct cpu_suspend_ops suspend_operations[] __initconst = {
+	{"arm,psci", psci_dt_register_idle_states},
+	{}
+};
+
+static __init const struct cpu_suspend_ops *get_suspend_ops(const char *str)
+{
+	int i;
+
+	if (!str)
+		return NULL;
+
+	for (i = 0; suspend_operations[i].id; i++)
+		if (!strcmp(suspend_operations[i].id, str))
+			return &suspend_operations[i];
+
+	return NULL;
+}
+
+/*
+ * arm_enter_idle_state - Programs CPU to enter the specified state
+ *
+ * dev: cpuidle device
+ * drv: cpuidle driver
+ * idx: state index
+ *
+ * Called from the CPUidle framework to program the device to the
+ * specified target state selected by the governor.
+ */
+static int arm_enter_idle_state(struct cpuidle_device *dev,
+				struct cpuidle_driver *drv, int idx)
+{
+	int ret;
+
+	if (!idx) {
+		cpu_do_idle();
+		return idx;
+	}
+
+	ret = cpu_pm_enter();
+	if (!ret) {
+		/*
+		 * Pass idle state index to cpu_suspend which in turn will
+		 * call the CPU ops suspend protocol with idle index as a
+		 * parameter.
+		 */
+		ret = cpu_suspend(idx);
+
+		cpu_pm_exit();
+	}
+
+	return ret ? -1 : idx;
+}
+
+struct cpuidle_driver arm64_idle_driver = {
+	.name = "arm64_idle",
+	.owner = THIS_MODULE,
+};
+
+static struct device_node *state_nodes[CPUIDLE_STATE_MAX] __initdata;
+
+/*
+ * arm64_idle_init
+ *
+ * Registers the arm64 specific cpuidle driver with the cpuidle
+ * framework. It relies on core code to parse the idle states
+ * and initialize them using driver data structures accordingly.
+ */
+static int __init arm64_idle_init(void)
+{
+	int i, ret;
+	const char *entry_method;
+	struct device_node *idle_states_node;
+	const struct cpu_suspend_ops *suspend_init;
+	struct cpuidle_driver *drv = &arm64_idle_driver;
+
+	idle_states_node = of_find_node_by_path("/cpus/idle-states");
+	if (!idle_states_node)
+		return -ENOENT;
+
+	if (of_property_read_string(idle_states_node, "entry-method",
+				    &entry_method)) {
+		pr_warn(" * %s missing entry-method property\n",
+			    idle_states_node->full_name);
+		of_node_put(idle_states_node);
+		ret = -EOPNOTSUPP;
+		goto put_node;
+	}
+
+	suspend_init = get_suspend_ops(entry_method);
+	if (!suspend_init) {
+		pr_warn("Missing suspend initializer\n");
+		ret = -EOPNOTSUPP;
+		goto put_node;
+	}
+
+	/*
+	 * State at index 0 is standby wfi and considered standard
+	 * on all ARM platforms. If in some platforms simple wfi
+	 * can't be used as "state 0", DT bindings must be implemented
+	 * to work around this issue and allow installing a special
+	 * handler for idle state index 0.
+	 */
+	drv->states[0].exit_latency = 1;
+	drv->states[0].target_residency = 1;
+	drv->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+	strncpy(drv->states[0].name, "ARM WFI", CPUIDLE_NAME_LEN);
+	strncpy(drv->states[0].desc, "ARM WFI", CPUIDLE_DESC_LEN);
+
+	drv->cpumask = (struct cpumask *) cpu_possible_mask;
+	/*
+	 * Start at index 1, request idle state nodes to be filled
+	 */
+	ret = dt_init_idle_driver(drv, state_nodes, 1, true);
+	if (ret)
+		goto put_node;
+
+	if (suspend_init->init_fn(drv, state_nodes)) {
+		ret = -EOPNOTSUPP;
+		goto put_node;
+	}
+
+	for (i = 0; i < drv->state_count; i++)
+		drv->states[i].enter = arm_enter_idle_state;
+
+	ret = cpuidle_register(drv, NULL);
+
+put_node:
+	of_node_put(idle_states_node);
+	return ret;
+}
+device_initcall(arm64_idle_init);
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH v5 5/8] drivers: cpuidle: CPU idle ARM64 driver
@ 2014-06-25 14:10   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel

This patch implements a generic CPU idle driver for ARM64 machines.

It relies on the DT idle states infrastructure to initialize idle
states count and respective parameters. Current code assumes the driver
is managing idle states on all possible CPUs but can be easily
generalized to support heterogenous systems and build cpumasks at
runtime using MIDRs or DT cpu nodes compatible properties.

Suspend back-ends (eg PSCI) must register a suspend initializer with
the CPU idle driver so that the suspend backend call can be detected,
and the driver code can call the back-end infrastructure to complete the
suspend backend initialization.

Idle state index 0 is always initialized as a simple wfi state, ie always
considered present and functional on all ARM64 platforms.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
 drivers/cpuidle/Kconfig         |   5 ++
 drivers/cpuidle/Kconfig.arm64   |  13 ++++
 drivers/cpuidle/Makefile        |   4 +
 drivers/cpuidle/cpuidle-arm64.c | 165 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 187 insertions(+)
 create mode 100644 drivers/cpuidle/Kconfig.arm64
 create mode 100644 drivers/cpuidle/cpuidle-arm64.c

diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
index 414e7a96..ebf0c2e 100644
--- a/drivers/cpuidle/Kconfig
+++ b/drivers/cpuidle/Kconfig
@@ -43,6 +43,11 @@ depends on ARM
 source "drivers/cpuidle/Kconfig.arm"
 endmenu
 
+menu "ARM64 CPU Idle Drivers"
+depends on ARM64
+source "drivers/cpuidle/Kconfig.arm64"
+endmenu
+
 menu "MIPS CPU Idle Drivers"
 depends on MIPS
 source "drivers/cpuidle/Kconfig.mips"
diff --git a/drivers/cpuidle/Kconfig.arm64 b/drivers/cpuidle/Kconfig.arm64
new file mode 100644
index 0000000..5fc5522
--- /dev/null
+++ b/drivers/cpuidle/Kconfig.arm64
@@ -0,0 +1,13 @@
+#
+# ARM64 CPU Idle drivers
+#
+
+config ARM64_CPUIDLE
+	bool "Generic ARM64 CPU idle Driver"
+	select DT_IDLE_STATES
+	help
+	  Select this to enable generic cpuidle driver for ARM v8.
+	  It provides a generic idle driver whose idle states are configured
+	  at run-time through DT nodes. The CPUidle suspend backend is
+	  initialized by the device tree parsing code on matching the entry
+	  method to the respective CPU operations.
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index b27a062..706cb7f 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -23,6 +23,10 @@ obj-$(CONFIG_ARM_EXYNOS_CPUIDLE)        += cpuidle-exynos.o
 obj-$(CONFIG_MIPS_CPS_CPUIDLE)		+= cpuidle-cps.o
 
 ###############################################################################
+# ARM64 drivers
+obj-$(CONFIG_ARM64_CPUIDLE)		+= cpuidle-arm64.o
+
+###############################################################################
 # POWERPC drivers
 obj-$(CONFIG_PSERIES_CPUIDLE)		+= cpuidle-pseries.o
 obj-$(CONFIG_POWERNV_CPUIDLE)		+= cpuidle-powernv.o
diff --git a/drivers/cpuidle/cpuidle-arm64.c b/drivers/cpuidle/cpuidle-arm64.c
new file mode 100644
index 0000000..e966a40
--- /dev/null
+++ b/drivers/cpuidle/cpuidle-arm64.c
@@ -0,0 +1,165 @@
+/*
+ * ARM64 generic CPU idle driver.
+ *
+ * Copyright (C) 2014 ARM Ltd.
+ * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt) "CPUidle arm64: " fmt
+
+#include <linux/cpuidle.h>
+#include <linux/cpumask.h>
+#include <linux/cpu_pm.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#include <asm/psci.h>
+#include <asm/suspend.h>
+
+#include "dt_idle_states.h"
+
+typedef int (*suspend_init_fn)(struct cpuidle_driver *,
+			       struct device_node *[]);
+
+struct cpu_suspend_ops {
+	const char *id;
+	suspend_init_fn init_fn;
+};
+
+static const struct cpu_suspend_ops suspend_operations[] __initconst = {
+	{"arm,psci", psci_dt_register_idle_states},
+	{}
+};
+
+static __init const struct cpu_suspend_ops *get_suspend_ops(const char *str)
+{
+	int i;
+
+	if (!str)
+		return NULL;
+
+	for (i = 0; suspend_operations[i].id; i++)
+		if (!strcmp(suspend_operations[i].id, str))
+			return &suspend_operations[i];
+
+	return NULL;
+}
+
+/*
+ * arm_enter_idle_state - Programs CPU to enter the specified state
+ *
+ * dev: cpuidle device
+ * drv: cpuidle driver
+ * idx: state index
+ *
+ * Called from the CPUidle framework to program the device to the
+ * specified target state selected by the governor.
+ */
+static int arm_enter_idle_state(struct cpuidle_device *dev,
+				struct cpuidle_driver *drv, int idx)
+{
+	int ret;
+
+	if (!idx) {
+		cpu_do_idle();
+		return idx;
+	}
+
+	ret = cpu_pm_enter();
+	if (!ret) {
+		/*
+		 * Pass idle state index to cpu_suspend which in turn will
+		 * call the CPU ops suspend protocol with idle index as a
+		 * parameter.
+		 */
+		ret = cpu_suspend(idx);
+
+		cpu_pm_exit();
+	}
+
+	return ret ? -1 : idx;
+}
+
+struct cpuidle_driver arm64_idle_driver = {
+	.name = "arm64_idle",
+	.owner = THIS_MODULE,
+};
+
+static struct device_node *state_nodes[CPUIDLE_STATE_MAX] __initdata;
+
+/*
+ * arm64_idle_init
+ *
+ * Registers the arm64 specific cpuidle driver with the cpuidle
+ * framework. It relies on core code to parse the idle states
+ * and initialize them using driver data structures accordingly.
+ */
+static int __init arm64_idle_init(void)
+{
+	int i, ret;
+	const char *entry_method;
+	struct device_node *idle_states_node;
+	const struct cpu_suspend_ops *suspend_init;
+	struct cpuidle_driver *drv = &arm64_idle_driver;
+
+	idle_states_node = of_find_node_by_path("/cpus/idle-states");
+	if (!idle_states_node)
+		return -ENOENT;
+
+	if (of_property_read_string(idle_states_node, "entry-method",
+				    &entry_method)) {
+		pr_warn(" * %s missing entry-method property\n",
+			    idle_states_node->full_name);
+		of_node_put(idle_states_node);
+		ret = -EOPNOTSUPP;
+		goto put_node;
+	}
+
+	suspend_init = get_suspend_ops(entry_method);
+	if (!suspend_init) {
+		pr_warn("Missing suspend initializer\n");
+		ret = -EOPNOTSUPP;
+		goto put_node;
+	}
+
+	/*
+	 * State at index 0 is standby wfi and considered standard
+	 * on all ARM platforms. If in some platforms simple wfi
+	 * can't be used as "state 0", DT bindings must be implemented
+	 * to work around this issue and allow installing a special
+	 * handler for idle state index 0.
+	 */
+	drv->states[0].exit_latency = 1;
+	drv->states[0].target_residency = 1;
+	drv->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+	strncpy(drv->states[0].name, "ARM WFI", CPUIDLE_NAME_LEN);
+	strncpy(drv->states[0].desc, "ARM WFI", CPUIDLE_DESC_LEN);
+
+	drv->cpumask = (struct cpumask *) cpu_possible_mask;
+	/*
+	 * Start at index 1, request idle state nodes to be filled
+	 */
+	ret = dt_init_idle_driver(drv, state_nodes, 1, true);
+	if (ret)
+		goto put_node;
+
+	if (suspend_init->init_fn(drv, state_nodes)) {
+		ret = -EOPNOTSUPP;
+		goto put_node;
+	}
+
+	for (i = 0; i < drv->state_count; i++)
+		drv->states[i].enter = arm_enter_idle_state;
+
+	ret = cpuidle_register(drv, NULL);
+
+put_node:
+	of_node_put(idle_states_node);
+	return ret;
+}
+device_initcall(arm64_idle_init);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH v5 6/8] drivers: cpuidle: initialize big.LITTLE driver through DT
  2014-06-25 14:10 ` Lorenzo Pieralisi
@ 2014-06-25 14:10   ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel, linux-pm, devicetree
  Cc: Lorenzo Pieralisi, Chander Kashyap, Mark Rutland, Sudeep Holla,
	Catalin Marinas, Charles Garcia Tobin, Nicolas Pitre,
	Rob Herring, Grant Likely, Peter De Schrijver, Santosh Shilimkar,
	Daniel Lezcano, Amit Kucheria, Vincent Guittot, Antti Miettinen,
	Stephen Boyd, Kevin Hilman, Sebastian Capella, Tomasz Figa,
	Mark Brown, Paul Walmsley

With the introduction of DT based idle states, CPUidle drivers for ARM
can now initialize idle states data through properties in the device tree.

This patch adds code to the big.LITTLE CPUidle driver to dynamically
initialize idle states data through the updated device tree source file.

Cc: Chander Kashyap <chander.kashyap@linaro.org>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
 Documentation/devicetree/bindings/arm/vexpress.txt | 25 +++++++++++++
 arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts         | 25 +++++++++++++
 drivers/cpuidle/Kconfig.arm                        |  1 +
 drivers/cpuidle/cpuidle-big_little.c               | 43 +++++++++++-----------
 4 files changed, 73 insertions(+), 21 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/vexpress.txt b/Documentation/devicetree/bindings/arm/vexpress.txt
index 39844cd..7f52ac8 100644
--- a/Documentation/devicetree/bindings/arm/vexpress.txt
+++ b/Documentation/devicetree/bindings/arm/vexpress.txt
@@ -67,6 +67,28 @@ with device_type = "cpu" property for every available core, eg.:
 		};
 	};
 
+idle-states node
+----------------
+
+On Versatile Express platforms with power management capabilities, the device
+tree source file must contain the idle-states node[1]. As defined in [1] the
+idle-states node must contain an entry-method property that for Versatile
+Express platforms can be one of:
+
+	- "arm,vexpress-v2p-ca15_a7"
+
+Versatile Express idle-states nodes example:
+
+	idle-states {
+		entry-method = "arm,vexpress-v2p-ca15_a7";
+
+		cluster-sleep-0 {
+			compatible = "arm,idle-state";
+			entry-latency-us = <1000>;
+			exit-latency-us = <700>;
+			min-residency-us = <3500>;
+		};
+	};
 
 Configuration infrastructure
 ----------------------------
@@ -227,3 +249,6 @@ Example of a VE tile description (simplified)
 	};
 };
 
+
+[1] ARM Linux Kernel documentation - Idle states bindings
+    Documentation/devicetree/bindings/arm/idle-states.txt
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
index a25c262..ad28242 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
@@ -33,11 +33,32 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
+		idle-states {
+			entry-method = "arm,vexpress-v2p-ca15_a7";
+
+			CLUSTER_SLEEP_BIG: cluster-sleep-big {
+				compatible = "arm,idle-state";
+				power-rank = <0>;
+				entry-latency-us = <1000>;
+				exit-latency-us = <700>;
+				min-residency-us = <3500>;
+			};
+
+			CLUSTER_SLEEP_LITTLE: cluster-sleep-little {
+				compatible = "arm,idle-state";
+				power-rank = <0>;
+				entry-latency-us = <1000>;
+				exit-latency-us = <500>;
+				min-residency-us = <3000>;
+			};
+		};
+
 		cpu0: cpu@0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0>;
 			cci-control-port = <&cci_control1>;
+			cpu-idle-states = <&CLUSTER_SLEEP_BIG>;
 		};
 
 		cpu1: cpu@1 {
@@ -45,6 +66,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <1>;
 			cci-control-port = <&cci_control1>;
+			cpu-idle-states = <&CLUSTER_SLEEP_BIG>;
 		};
 
 		cpu2: cpu@2 {
@@ -52,6 +74,7 @@
 			compatible = "arm,cortex-a7";
 			reg = <0x100>;
 			cci-control-port = <&cci_control2>;
+			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
 		};
 
 		cpu3: cpu@3 {
@@ -59,6 +82,7 @@
 			compatible = "arm,cortex-a7";
 			reg = <0x101>;
 			cci-control-port = <&cci_control2>;
+			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
 		};
 
 		cpu4: cpu@4 {
@@ -66,6 +90,7 @@
 			compatible = "arm,cortex-a7";
 			reg = <0x102>;
 			cci-control-port = <&cci_control2>;
+			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
 		};
 	};
 
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
index b6d69e8..a9b089c 100644
--- a/drivers/cpuidle/Kconfig.arm
+++ b/drivers/cpuidle/Kconfig.arm
@@ -12,6 +12,7 @@ config ARM_BIG_LITTLE_CPUIDLE
 	depends on ARCH_VEXPRESS_TC2_PM
 	select ARM_CPU_SUSPEND
 	select CPU_IDLE_MULTIPLE_DRIVERS
+	select DT_IDLE_STATES
 	help
 	  Select this option to enable CPU idle driver for big.LITTLE based
 	  ARM systems. Driver manages CPUs coordination through MCPM and
diff --git a/drivers/cpuidle/cpuidle-big_little.c b/drivers/cpuidle/cpuidle-big_little.c
index b45fc62..6712441 100644
--- a/drivers/cpuidle/cpuidle-big_little.c
+++ b/drivers/cpuidle/cpuidle-big_little.c
@@ -24,6 +24,8 @@
 #include <asm/smp_plat.h>
 #include <asm/suspend.h>
 
+#include "dt_idle_states.h"
+
 static int bl_enter_powerdown(struct cpuidle_device *dev,
 			      struct cpuidle_driver *drv, int idx);
 
@@ -61,32 +63,12 @@ static struct cpuidle_driver bl_idle_little_driver = {
 	.name = "little_idle",
 	.owner = THIS_MODULE,
 	.states[0] = ARM_CPUIDLE_WFI_STATE,
-	.states[1] = {
-		.enter			= bl_enter_powerdown,
-		.exit_latency		= 700,
-		.target_residency	= 2500,
-		.flags			= CPUIDLE_FLAG_TIME_VALID |
-					  CPUIDLE_FLAG_TIMER_STOP,
-		.name			= "C1",
-		.desc			= "ARM little-cluster power down",
-	},
-	.state_count = 2,
 };
 
 static struct cpuidle_driver bl_idle_big_driver = {
 	.name = "big_idle",
 	.owner = THIS_MODULE,
 	.states[0] = ARM_CPUIDLE_WFI_STATE,
-	.states[1] = {
-		.enter			= bl_enter_powerdown,
-		.exit_latency		= 500,
-		.target_residency	= 2000,
-		.flags			= CPUIDLE_FLAG_TIME_VALID |
-					  CPUIDLE_FLAG_TIMER_STOP,
-		.name			= "C1",
-		.desc			= "ARM big-cluster power down",
-	},
-	.state_count = 2,
 };
 
 /*
@@ -165,7 +147,8 @@ static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int cpu_id)
 
 static int __init bl_idle_init(void)
 {
-	int ret;
+	int ret, i;
+	struct cpuidle_driver *drv;
 
 	/*
 	 * Initialize the driver just for a compliant set of machines
@@ -187,6 +170,24 @@ static int __init bl_idle_init(void)
 	if (ret)
 		goto out_uninit_little;
 
+	 /* Start at index 1, index 0 standard WFI */
+	ret = dt_init_idle_driver(&bl_idle_big_driver, NULL, 1, false);
+	if (ret)
+		goto out_uninit_big;
+
+	 /* Start at index 1, index 0 standard WFI */
+	ret = dt_init_idle_driver(&bl_idle_little_driver, NULL, 1, false);
+	if (ret)
+		goto out_uninit_big;
+
+	drv = &bl_idle_big_driver;
+	for (i = 1; i < drv->state_count; i++)
+		drv->states[i].enter = bl_enter_powerdown;
+
+	drv = &bl_idle_little_driver;
+	for (i = 1; i < drv->state_count; i++)
+		drv->states[i].enter = bl_enter_powerdown;
+
 	ret = cpuidle_register(&bl_idle_little_driver, NULL);
 	if (ret)
 		goto out_uninit_big;
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH v5 6/8] drivers: cpuidle: initialize big.LITTLE driver through DT
@ 2014-06-25 14:10   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel

With the introduction of DT based idle states, CPUidle drivers for ARM
can now initialize idle states data through properties in the device tree.

This patch adds code to the big.LITTLE CPUidle driver to dynamically
initialize idle states data through the updated device tree source file.

Cc: Chander Kashyap <chander.kashyap@linaro.org>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
 Documentation/devicetree/bindings/arm/vexpress.txt | 25 +++++++++++++
 arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts         | 25 +++++++++++++
 drivers/cpuidle/Kconfig.arm                        |  1 +
 drivers/cpuidle/cpuidle-big_little.c               | 43 +++++++++++-----------
 4 files changed, 73 insertions(+), 21 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/vexpress.txt b/Documentation/devicetree/bindings/arm/vexpress.txt
index 39844cd..7f52ac8 100644
--- a/Documentation/devicetree/bindings/arm/vexpress.txt
+++ b/Documentation/devicetree/bindings/arm/vexpress.txt
@@ -67,6 +67,28 @@ with device_type = "cpu" property for every available core, eg.:
 		};
 	};
 
+idle-states node
+----------------
+
+On Versatile Express platforms with power management capabilities, the device
+tree source file must contain the idle-states node[1]. As defined in [1] the
+idle-states node must contain an entry-method property that for Versatile
+Express platforms can be one of:
+
+	- "arm,vexpress-v2p-ca15_a7"
+
+Versatile Express idle-states nodes example:
+
+	idle-states {
+		entry-method = "arm,vexpress-v2p-ca15_a7";
+
+		cluster-sleep-0 {
+			compatible = "arm,idle-state";
+			entry-latency-us = <1000>;
+			exit-latency-us = <700>;
+			min-residency-us = <3500>;
+		};
+	};
 
 Configuration infrastructure
 ----------------------------
@@ -227,3 +249,6 @@ Example of a VE tile description (simplified)
 	};
 };
 
+
+[1] ARM Linux Kernel documentation - Idle states bindings
+    Documentation/devicetree/bindings/arm/idle-states.txt
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
index a25c262..ad28242 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
@@ -33,11 +33,32 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
+		idle-states {
+			entry-method = "arm,vexpress-v2p-ca15_a7";
+
+			CLUSTER_SLEEP_BIG: cluster-sleep-big {
+				compatible = "arm,idle-state";
+				power-rank = <0>;
+				entry-latency-us = <1000>;
+				exit-latency-us = <700>;
+				min-residency-us = <3500>;
+			};
+
+			CLUSTER_SLEEP_LITTLE: cluster-sleep-little {
+				compatible = "arm,idle-state";
+				power-rank = <0>;
+				entry-latency-us = <1000>;
+				exit-latency-us = <500>;
+				min-residency-us = <3000>;
+			};
+		};
+
 		cpu0: cpu at 0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0>;
 			cci-control-port = <&cci_control1>;
+			cpu-idle-states = <&CLUSTER_SLEEP_BIG>;
 		};
 
 		cpu1: cpu at 1 {
@@ -45,6 +66,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <1>;
 			cci-control-port = <&cci_control1>;
+			cpu-idle-states = <&CLUSTER_SLEEP_BIG>;
 		};
 
 		cpu2: cpu at 2 {
@@ -52,6 +74,7 @@
 			compatible = "arm,cortex-a7";
 			reg = <0x100>;
 			cci-control-port = <&cci_control2>;
+			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
 		};
 
 		cpu3: cpu at 3 {
@@ -59,6 +82,7 @@
 			compatible = "arm,cortex-a7";
 			reg = <0x101>;
 			cci-control-port = <&cci_control2>;
+			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
 		};
 
 		cpu4: cpu at 4 {
@@ -66,6 +90,7 @@
 			compatible = "arm,cortex-a7";
 			reg = <0x102>;
 			cci-control-port = <&cci_control2>;
+			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
 		};
 	};
 
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
index b6d69e8..a9b089c 100644
--- a/drivers/cpuidle/Kconfig.arm
+++ b/drivers/cpuidle/Kconfig.arm
@@ -12,6 +12,7 @@ config ARM_BIG_LITTLE_CPUIDLE
 	depends on ARCH_VEXPRESS_TC2_PM
 	select ARM_CPU_SUSPEND
 	select CPU_IDLE_MULTIPLE_DRIVERS
+	select DT_IDLE_STATES
 	help
 	  Select this option to enable CPU idle driver for big.LITTLE based
 	  ARM systems. Driver manages CPUs coordination through MCPM and
diff --git a/drivers/cpuidle/cpuidle-big_little.c b/drivers/cpuidle/cpuidle-big_little.c
index b45fc62..6712441 100644
--- a/drivers/cpuidle/cpuidle-big_little.c
+++ b/drivers/cpuidle/cpuidle-big_little.c
@@ -24,6 +24,8 @@
 #include <asm/smp_plat.h>
 #include <asm/suspend.h>
 
+#include "dt_idle_states.h"
+
 static int bl_enter_powerdown(struct cpuidle_device *dev,
 			      struct cpuidle_driver *drv, int idx);
 
@@ -61,32 +63,12 @@ static struct cpuidle_driver bl_idle_little_driver = {
 	.name = "little_idle",
 	.owner = THIS_MODULE,
 	.states[0] = ARM_CPUIDLE_WFI_STATE,
-	.states[1] = {
-		.enter			= bl_enter_powerdown,
-		.exit_latency		= 700,
-		.target_residency	= 2500,
-		.flags			= CPUIDLE_FLAG_TIME_VALID |
-					  CPUIDLE_FLAG_TIMER_STOP,
-		.name			= "C1",
-		.desc			= "ARM little-cluster power down",
-	},
-	.state_count = 2,
 };
 
 static struct cpuidle_driver bl_idle_big_driver = {
 	.name = "big_idle",
 	.owner = THIS_MODULE,
 	.states[0] = ARM_CPUIDLE_WFI_STATE,
-	.states[1] = {
-		.enter			= bl_enter_powerdown,
-		.exit_latency		= 500,
-		.target_residency	= 2000,
-		.flags			= CPUIDLE_FLAG_TIME_VALID |
-					  CPUIDLE_FLAG_TIMER_STOP,
-		.name			= "C1",
-		.desc			= "ARM big-cluster power down",
-	},
-	.state_count = 2,
 };
 
 /*
@@ -165,7 +147,8 @@ static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int cpu_id)
 
 static int __init bl_idle_init(void)
 {
-	int ret;
+	int ret, i;
+	struct cpuidle_driver *drv;
 
 	/*
 	 * Initialize the driver just for a compliant set of machines
@@ -187,6 +170,24 @@ static int __init bl_idle_init(void)
 	if (ret)
 		goto out_uninit_little;
 
+	 /* Start at index 1, index 0 standard WFI */
+	ret = dt_init_idle_driver(&bl_idle_big_driver, NULL, 1, false);
+	if (ret)
+		goto out_uninit_big;
+
+	 /* Start at index 1, index 0 standard WFI */
+	ret = dt_init_idle_driver(&bl_idle_little_driver, NULL, 1, false);
+	if (ret)
+		goto out_uninit_big;
+
+	drv = &bl_idle_big_driver;
+	for (i = 1; i < drv->state_count; i++)
+		drv->states[i].enter = bl_enter_powerdown;
+
+	drv = &bl_idle_little_driver;
+	for (i = 1; i < drv->state_count; i++)
+		drv->states[i].enter = bl_enter_powerdown;
+
 	ret = cpuidle_register(&bl_idle_little_driver, NULL);
 	if (ret)
 		goto out_uninit_big;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH v5 7/8] drivers: cpuidle: initialize Exynos driver through DT
  2014-06-25 14:10 ` Lorenzo Pieralisi
@ 2014-06-25 14:10   ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel, linux-pm, devicetree
  Cc: Lorenzo Pieralisi, Kukjin Kim, Tomasz Figa, Mark Rutland,
	Sudeep Holla, Catalin Marinas, Charles Garcia Tobin,
	Nicolas Pitre, Rob Herring, Grant Likely, Peter De Schrijver,
	Santosh Shilimkar, Daniel Lezcano, Amit Kucheria,
	Vincent Guittot, Antti Miettinen, Stephen Boyd, Kevin Hilman,
	Sebastian Capella, Mark Brown, Paul Walmsley, Chander Kashyap

With the introduction of DT based idle states, CPUidle drivers for
ARM can now initialize idle states data through properties in the device
tree.

This patch adds code to the Exynos CPUidle driver to dynamically
initialize idle states data through the updated device tree source
files.

Cc: Kukjin Kim <kgene.kim@samsung.com>
Cc: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
Compile tested, I am not sure I patched the right dts files, please check.

 .../devicetree/bindings/arm/exynos/idle-states.txt | 27 ++++++++++++++++++++
 arch/arm/boot/dts/exynos3250.dtsi                  | 16 ++++++++++++
 arch/arm/boot/dts/exynos5250.dtsi                  | 15 +++++++++++
 arch/arm/boot/dts/exynos5410.dtsi                  | 17 +++++++++++++
 drivers/cpuidle/Kconfig.arm                        |  1 +
 drivers/cpuidle/cpuidle-exynos.c                   | 29 +++++++++++++---------
 6 files changed, 93 insertions(+), 12 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt

diff --git a/Documentation/devicetree/bindings/arm/exynos/idle-states.txt b/Documentation/devicetree/bindings/arm/exynos/idle-states.txt
new file mode 100644
index 0000000..342ecb4
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/exynos/idle-states.txt
@@ -0,0 +1,27 @@
+idle-states node
+----------------
+
+On Exynos platforms with power management capabilities, the device
+tree source file must contain the idle-states node[1]. As defined in [1] the
+idle-states node must contain an entry-method property that for Exynos
+platforms can be one of:
+
+	- "samsung,exynos"
+
+Exynos idle-states nodes example:
+
+	idle-states {
+		entry-method = "samsung,exynos";
+
+		CLUSTER_SLEEP_0: cluster-sleep-0 {
+			compatible = "arm,idle-state";
+			timer-state-retained;
+			power-rank = <0>;
+			entry-latency-us = <1000>;
+			exit-latency-us = <300>;
+			min-residency-us = <100000>;
+		};
+	};
+
+[1] ARM Linux Kernel documentation - Idle states bindings
+    Documentation/devicetree/bindings/arm/idle-states.txt
diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi
index 3e678fa..b0ccfca 100644
--- a/arch/arm/boot/dts/exynos3250.dtsi
+++ b/arch/arm/boot/dts/exynos3250.dtsi
@@ -45,11 +45,26 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
+		idle-states {
+			entry-method = "samsung,exynos";
+
+			CLUSTER_SLEEP_0: cluster-sleep-0 {
+				compatible = "arm,idle-state";
+				timer-state-retained;
+				power-rank = <0>;
+				entry-latency-us = <1000>;
+				exit-latency-us = <300>;
+				min-residency-us = <100000>;
+			};
+
+		};
+
 		cpu0: cpu@0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a7";
 			reg = <0>;
 			clock-frequency = <1000000000>;
+			cpu-idle-states = <&CLUSTER_SLEEP_0>;
 		};
 
 		cpu1: cpu@1 {
@@ -57,6 +72,7 @@
 			compatible = "arm,cortex-a7";
 			reg = <1>;
 			clock-frequency = <1000000000>;
+			cpu-idle-states = <&CLUSTER_SLEEP_0>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index 834fb5a..b806653 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -58,17 +58,32 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
+		idle-states {
+			entry-method = "samsung,exynos";
+
+			CLUSTER_SLEEP_0: cluster-sleep-0 {
+				compatible = "arm,idle-state";
+				timer-state-retained;
+				power-rank = <0>;
+				entry-latency-us = <1000>;
+				exit-latency-us = <300>;
+				min-residency-us = <100000>;
+			};
+		};
+
 		cpu@0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0>;
 			clock-frequency = <1700000000>;
+			cpu-idle-states = <&CLUSTER_SLEEP_0>;
 		};
 		cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <1>;
 			clock-frequency = <1700000000>;
+			cpu-idle-states = <&CLUSTER_SLEEP_0>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 3839c26..82e4b7b 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -24,28 +24,45 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
+		idle-states {
+			entry-method = "samsung,exynos";
+
+			CLUSTER_SLEEP_0: cluster-sleep-0 {
+				compatible = "arm,idle-state";
+				timer-state-retained;
+				power-rank = <0>;
+				entry-latency-us = <1000>;
+				exit-latency-us = <300>;
+				min-residency-us = <100000>;
+			};
+		};
+
 		CPU0: cpu@0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x0>;
+			cpu-idle-states = <&CLUSTER_SLEEP_0>;
 		};
 
 		CPU1: cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x1>;
+			cpu-idle-states = <&CLUSTER_SLEEP_0>;
 		};
 
 		CPU2: cpu@2 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x2>;
+			cpu-idle-states = <&CLUSTER_SLEEP_0>;
 		};
 
 		CPU3: cpu@3 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x3>;
+			cpu-idle-states = <&CLUSTER_SLEEP_0>;
 		};
 	};
 
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
index a9b089c..d8a9cd2 100644
--- a/drivers/cpuidle/Kconfig.arm
+++ b/drivers/cpuidle/Kconfig.arm
@@ -60,5 +60,6 @@ config ARM_AT91_CPUIDLE
 config ARM_EXYNOS_CPUIDLE
 	bool "Cpu Idle Driver for the Exynos processors"
 	depends on ARCH_EXYNOS
+	select DT_IDLE_STATES
 	help
 	  Select this to enable cpuidle for Exynos processors
diff --git a/drivers/cpuidle/cpuidle-exynos.c b/drivers/cpuidle/cpuidle-exynos.c
index 7c01512..d76af54 100644
--- a/drivers/cpuidle/cpuidle-exynos.c
+++ b/drivers/cpuidle/cpuidle-exynos.c
@@ -18,6 +18,8 @@
 #include <asm/suspend.h>
 #include <asm/cpuidle.h>
 
+#include "dt_idle_states.h"
+
 static void (*exynos_enter_aftr)(void);
 
 static int idle_finisher(unsigned long flags)
@@ -60,26 +62,29 @@ static struct cpuidle_driver exynos_idle_driver = {
 	.owner			= THIS_MODULE,
 	.states = {
 		[0] = ARM_CPUIDLE_WFI_STATE,
-		[1] = {
-			.enter			= exynos_enter_lowpower,
-			.exit_latency		= 300,
-			.target_residency	= 100000,
-			.flags			= CPUIDLE_FLAG_TIME_VALID,
-			.name			= "C1",
-			.desc			= "ARM power down",
-		},
 	},
-	.state_count = 2,
-	.safe_state_index = 0,
 };
 
 static int exynos_cpuidle_probe(struct platform_device *pdev)
 {
-	int ret;
+	int ret, i;
+	struct cpuidle_driver *drv = &exynos_idle_driver;
 
 	exynos_enter_aftr = (void *)(pdev->dev.platform_data);
 
-	ret = cpuidle_register(&exynos_idle_driver, NULL);
+	drv->cpumask = (struct cpumask *) cpu_possible_mask;
+
+	/* Start at index 1, index 0 standard WFI */
+	ret = dt_init_idle_driver(drv, NULL, 1, false);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to initialize idle states\n");
+		return ret;
+	}
+
+	for (i = 1; i < drv->state_count; i++)
+		drv->states[i].enter = exynos_enter_lowpower;
+
+	ret = cpuidle_register(drv, NULL);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register cpuidle driver\n");
 		return ret;
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH v5 7/8] drivers: cpuidle: initialize Exynos driver through DT
@ 2014-06-25 14:10   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel

With the introduction of DT based idle states, CPUidle drivers for
ARM can now initialize idle states data through properties in the device
tree.

This patch adds code to the Exynos CPUidle driver to dynamically
initialize idle states data through the updated device tree source
files.

Cc: Kukjin Kim <kgene.kim@samsung.com>
Cc: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
Compile tested, I am not sure I patched the right dts files, please check.

 .../devicetree/bindings/arm/exynos/idle-states.txt | 27 ++++++++++++++++++++
 arch/arm/boot/dts/exynos3250.dtsi                  | 16 ++++++++++++
 arch/arm/boot/dts/exynos5250.dtsi                  | 15 +++++++++++
 arch/arm/boot/dts/exynos5410.dtsi                  | 17 +++++++++++++
 drivers/cpuidle/Kconfig.arm                        |  1 +
 drivers/cpuidle/cpuidle-exynos.c                   | 29 +++++++++++++---------
 6 files changed, 93 insertions(+), 12 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt

diff --git a/Documentation/devicetree/bindings/arm/exynos/idle-states.txt b/Documentation/devicetree/bindings/arm/exynos/idle-states.txt
new file mode 100644
index 0000000..342ecb4
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/exynos/idle-states.txt
@@ -0,0 +1,27 @@
+idle-states node
+----------------
+
+On Exynos platforms with power management capabilities, the device
+tree source file must contain the idle-states node[1]. As defined in [1] the
+idle-states node must contain an entry-method property that for Exynos
+platforms can be one of:
+
+	- "samsung,exynos"
+
+Exynos idle-states nodes example:
+
+	idle-states {
+		entry-method = "samsung,exynos";
+
+		CLUSTER_SLEEP_0: cluster-sleep-0 {
+			compatible = "arm,idle-state";
+			timer-state-retained;
+			power-rank = <0>;
+			entry-latency-us = <1000>;
+			exit-latency-us = <300>;
+			min-residency-us = <100000>;
+		};
+	};
+
+[1] ARM Linux Kernel documentation - Idle states bindings
+    Documentation/devicetree/bindings/arm/idle-states.txt
diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi
index 3e678fa..b0ccfca 100644
--- a/arch/arm/boot/dts/exynos3250.dtsi
+++ b/arch/arm/boot/dts/exynos3250.dtsi
@@ -45,11 +45,26 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
+		idle-states {
+			entry-method = "samsung,exynos";
+
+			CLUSTER_SLEEP_0: cluster-sleep-0 {
+				compatible = "arm,idle-state";
+				timer-state-retained;
+				power-rank = <0>;
+				entry-latency-us = <1000>;
+				exit-latency-us = <300>;
+				min-residency-us = <100000>;
+			};
+
+		};
+
 		cpu0: cpu at 0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a7";
 			reg = <0>;
 			clock-frequency = <1000000000>;
+			cpu-idle-states = <&CLUSTER_SLEEP_0>;
 		};
 
 		cpu1: cpu at 1 {
@@ -57,6 +72,7 @@
 			compatible = "arm,cortex-a7";
 			reg = <1>;
 			clock-frequency = <1000000000>;
+			cpu-idle-states = <&CLUSTER_SLEEP_0>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index 834fb5a..b806653 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -58,17 +58,32 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
+		idle-states {
+			entry-method = "samsung,exynos";
+
+			CLUSTER_SLEEP_0: cluster-sleep-0 {
+				compatible = "arm,idle-state";
+				timer-state-retained;
+				power-rank = <0>;
+				entry-latency-us = <1000>;
+				exit-latency-us = <300>;
+				min-residency-us = <100000>;
+			};
+		};
+
 		cpu at 0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0>;
 			clock-frequency = <1700000000>;
+			cpu-idle-states = <&CLUSTER_SLEEP_0>;
 		};
 		cpu at 1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <1>;
 			clock-frequency = <1700000000>;
+			cpu-idle-states = <&CLUSTER_SLEEP_0>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 3839c26..82e4b7b 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -24,28 +24,45 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
+		idle-states {
+			entry-method = "samsung,exynos";
+
+			CLUSTER_SLEEP_0: cluster-sleep-0 {
+				compatible = "arm,idle-state";
+				timer-state-retained;
+				power-rank = <0>;
+				entry-latency-us = <1000>;
+				exit-latency-us = <300>;
+				min-residency-us = <100000>;
+			};
+		};
+
 		CPU0: cpu at 0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x0>;
+			cpu-idle-states = <&CLUSTER_SLEEP_0>;
 		};
 
 		CPU1: cpu at 1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x1>;
+			cpu-idle-states = <&CLUSTER_SLEEP_0>;
 		};
 
 		CPU2: cpu at 2 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x2>;
+			cpu-idle-states = <&CLUSTER_SLEEP_0>;
 		};
 
 		CPU3: cpu at 3 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x3>;
+			cpu-idle-states = <&CLUSTER_SLEEP_0>;
 		};
 	};
 
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
index a9b089c..d8a9cd2 100644
--- a/drivers/cpuidle/Kconfig.arm
+++ b/drivers/cpuidle/Kconfig.arm
@@ -60,5 +60,6 @@ config ARM_AT91_CPUIDLE
 config ARM_EXYNOS_CPUIDLE
 	bool "Cpu Idle Driver for the Exynos processors"
 	depends on ARCH_EXYNOS
+	select DT_IDLE_STATES
 	help
 	  Select this to enable cpuidle for Exynos processors
diff --git a/drivers/cpuidle/cpuidle-exynos.c b/drivers/cpuidle/cpuidle-exynos.c
index 7c01512..d76af54 100644
--- a/drivers/cpuidle/cpuidle-exynos.c
+++ b/drivers/cpuidle/cpuidle-exynos.c
@@ -18,6 +18,8 @@
 #include <asm/suspend.h>
 #include <asm/cpuidle.h>
 
+#include "dt_idle_states.h"
+
 static void (*exynos_enter_aftr)(void);
 
 static int idle_finisher(unsigned long flags)
@@ -60,26 +62,29 @@ static struct cpuidle_driver exynos_idle_driver = {
 	.owner			= THIS_MODULE,
 	.states = {
 		[0] = ARM_CPUIDLE_WFI_STATE,
-		[1] = {
-			.enter			= exynos_enter_lowpower,
-			.exit_latency		= 300,
-			.target_residency	= 100000,
-			.flags			= CPUIDLE_FLAG_TIME_VALID,
-			.name			= "C1",
-			.desc			= "ARM power down",
-		},
 	},
-	.state_count = 2,
-	.safe_state_index = 0,
 };
 
 static int exynos_cpuidle_probe(struct platform_device *pdev)
 {
-	int ret;
+	int ret, i;
+	struct cpuidle_driver *drv = &exynos_idle_driver;
 
 	exynos_enter_aftr = (void *)(pdev->dev.platform_data);
 
-	ret = cpuidle_register(&exynos_idle_driver, NULL);
+	drv->cpumask = (struct cpumask *) cpu_possible_mask;
+
+	/* Start at index 1, index 0 standard WFI */
+	ret = dt_init_idle_driver(drv, NULL, 1, false);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to initialize idle states\n");
+		return ret;
+	}
+
+	for (i = 1; i < drv->state_count; i++)
+		drv->states[i].enter = exynos_enter_lowpower;
+
+	ret = cpuidle_register(drv, NULL);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register cpuidle driver\n");
 		return ret;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH v5 8/8] arm64: boot: dts: update rtsm aemv8 dts with PSCI and idle states
  2014-06-25 14:10 ` Lorenzo Pieralisi
@ 2014-06-25 14:10   ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel, linux-pm, devicetree
  Cc: Lorenzo Pieralisi, Mark Rutland, Sudeep Holla, Catalin Marinas,
	Charles Garcia Tobin, Nicolas Pitre, Rob Herring, Grant Likely,
	Peter De Schrijver, Santosh Shilimkar, Daniel Lezcano,
	Amit Kucheria, Vincent Guittot, Antti Miettinen, Stephen Boyd,
	Kevin Hilman, Sebastian Capella, Tomasz Figa, Mark Brown,
	Paul Walmsley, Chander Kashyap

This patch updates the RTSM dts file with PSCI bindings and nodes
describing the AEMv8 model idle states parameters.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
 arch/arm64/boot/dts/rtsm_ve-aemv8a.dts | 44 +++++++++++++++++++++++++++-------
 1 file changed, 36 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
index d79de9c..4051ffb 100644
--- a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
+++ b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
@@ -27,37 +27,65 @@
 		serial3 = &v2m_serial3;
 	};
 
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+		cpu_suspend = <0xc4000001>;
+		cpu_off = <0x84000002>;
+		cpu_on = <0xc4000003>;
+	};
+
 	cpus {
 		#address-cells = <2>;
 		#size-cells = <0>;
 
+		idle-states {
+			entry-method = "arm,psci";
+
+			CPU_SLEEP_0: cpu-sleep-0 {
+				compatible = "arm,idle-state";
+				entry-method-param = <0x0010000>;
+				entry-latency-us = <40>;
+				exit-latency-us = <100>;
+				min-residency-us = <150>;
+			};
+
+			CLUSTER_SLEEP_0: cluster-sleep-0 {
+				compatible = "arm,idle-state";
+				entry-method-param = <0x1010000>;
+				entry-latency-us = <500>;
+				exit-latency-us = <1000>;
+				min-residency-us = <2500>;
+			};
+		};
+
 		cpu@0 {
 			device_type = "cpu";
 			compatible = "arm,armv8";
 			reg = <0x0 0x0>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0x0 0x8000fff8>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
 		cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,armv8";
 			reg = <0x0 0x1>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0x0 0x8000fff8>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
 		cpu@2 {
 			device_type = "cpu";
 			compatible = "arm,armv8";
 			reg = <0x0 0x2>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0x0 0x8000fff8>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
 		cpu@3 {
 			device_type = "cpu";
 			compatible = "arm,armv8";
 			reg = <0x0 0x3>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0x0 0x8000fff8>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
 	};
 
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH v5 8/8] arm64: boot: dts: update rtsm aemv8 dts with PSCI and idle states
@ 2014-06-25 14:10   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 14:10 UTC (permalink / raw)
  To: linux-arm-kernel

This patch updates the RTSM dts file with PSCI bindings and nodes
describing the AEMv8 model idle states parameters.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
 arch/arm64/boot/dts/rtsm_ve-aemv8a.dts | 44 +++++++++++++++++++++++++++-------
 1 file changed, 36 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
index d79de9c..4051ffb 100644
--- a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
+++ b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
@@ -27,37 +27,65 @@
 		serial3 = &v2m_serial3;
 	};
 
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+		cpu_suspend = <0xc4000001>;
+		cpu_off = <0x84000002>;
+		cpu_on = <0xc4000003>;
+	};
+
 	cpus {
 		#address-cells = <2>;
 		#size-cells = <0>;
 
+		idle-states {
+			entry-method = "arm,psci";
+
+			CPU_SLEEP_0: cpu-sleep-0 {
+				compatible = "arm,idle-state";
+				entry-method-param = <0x0010000>;
+				entry-latency-us = <40>;
+				exit-latency-us = <100>;
+				min-residency-us = <150>;
+			};
+
+			CLUSTER_SLEEP_0: cluster-sleep-0 {
+				compatible = "arm,idle-state";
+				entry-method-param = <0x1010000>;
+				entry-latency-us = <500>;
+				exit-latency-us = <1000>;
+				min-residency-us = <2500>;
+			};
+		};
+
 		cpu at 0 {
 			device_type = "cpu";
 			compatible = "arm,armv8";
 			reg = <0x0 0x0>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0x0 0x8000fff8>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
 		cpu at 1 {
 			device_type = "cpu";
 			compatible = "arm,armv8";
 			reg = <0x0 0x1>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0x0 0x8000fff8>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
 		cpu at 2 {
 			device_type = "cpu";
 			compatible = "arm,armv8";
 			reg = <0x0 0x2>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0x0 0x8000fff8>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
 		cpu at 3 {
 			device_type = "cpu";
 			compatible = "arm,armv8";
 			reg = <0x0 0x3>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0x0 0x8000fff8>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
 	};
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 8/8] arm64: boot: dts: update rtsm aemv8 dts with PSCI and idle states
  2014-06-25 14:10   ` Lorenzo Pieralisi
@ 2014-06-25 14:27     ` Mark Rutland
  -1 siblings, 0 replies; 70+ messages in thread
From: Mark Rutland @ 2014-06-25 14:27 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: linux-arm-kernel, linux-pm, devicetree, Sudeep Holla,
	Catalin Marinas, Charles Garcia-Tobin, Nicolas Pitre,
	Rob Herring, grant.likely, Peter De Schrijver, Santosh Shilimkar,
	Daniel Lezcano, Amit Kucheria, Vincent Guittot, Antti Miettinen,
	Stephen Boyd, Kevin Hilman, Sebastian Capella, Tomasz Figa,
	Mark Brown

Hi Lorenzo,

On Wed, Jun 25, 2014 at 03:10:21PM +0100, Lorenzo Pieralisi wrote:
> This patch updates the RTSM dts file with PSCI bindings and nodes
> describing the AEMv8 model idle states parameters.
> 
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> ---
>  arch/arm64/boot/dts/rtsm_ve-aemv8a.dts | 44 +++++++++++++++++++++++++++-------
>  1 file changed, 36 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> index d79de9c..4051ffb 100644
> --- a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> +++ b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> @@ -27,37 +27,65 @@
>  		serial3 = &v2m_serial3;
>  	};
>  
> +	psci {
> +		compatible = "arm,psci-0.2";

Where can I find a PSCI 0.2 implementation for the RTSM VE model? I
couldn't find a link in the cover.

The upstream bootwrapper is not PSCI 0.2 compliant and it does not
implement CPU_SUSPEND.

> +		method = "smc";
> +		cpu_suspend = <0xc4000001>;
> +		cpu_off = <0x84000002>;
> +		cpu_on = <0xc4000003>;

Without "arm,psci" in the compatible list, these three properties are
meaningless.

> +	};
> +
>  	cpus {
>  		#address-cells = <2>;
>  		#size-cells = <0>;
>  
> +		idle-states {
> +			entry-method = "arm,psci";
> +
> +			CPU_SLEEP_0: cpu-sleep-0 {
> +				compatible = "arm,idle-state";
> +				entry-method-param = <0x0010000>;
> +				entry-latency-us = <40>;
> +				exit-latency-us = <100>;
> +				min-residency-us = <150>;
> +			};
> +
> +			CLUSTER_SLEEP_0: cluster-sleep-0 {
> +				compatible = "arm,idle-state";
> +				entry-method-param = <0x1010000>;
> +				entry-latency-us = <500>;
> +				exit-latency-us = <1000>;
> +				min-residency-us = <2500>;
> +			};
> +		};
> +

If this is going to live in the /cpus node, could it please be placed
after the cpu nodes?

>  		cpu@0 {
>  			device_type = "cpu";
>  			compatible = "arm,armv8";
>  			reg = <0x0 0x0>;
> -			enable-method = "spin-table";
> -			cpu-release-addr = <0x0 0x8000fff8>;
> +			enable-method = "psci";

Changing the enable-method will break boot on a model when using a
bootwrapper without PSCI support. Really we should leave it up to the
bootwrapper to inject the enable method...

Mark.

^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 8/8] arm64: boot: dts: update rtsm aemv8 dts with PSCI and idle states
@ 2014-06-25 14:27     ` Mark Rutland
  0 siblings, 0 replies; 70+ messages in thread
From: Mark Rutland @ 2014-06-25 14:27 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lorenzo,

On Wed, Jun 25, 2014 at 03:10:21PM +0100, Lorenzo Pieralisi wrote:
> This patch updates the RTSM dts file with PSCI bindings and nodes
> describing the AEMv8 model idle states parameters.
> 
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> ---
>  arch/arm64/boot/dts/rtsm_ve-aemv8a.dts | 44 +++++++++++++++++++++++++++-------
>  1 file changed, 36 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> index d79de9c..4051ffb 100644
> --- a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> +++ b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> @@ -27,37 +27,65 @@
>  		serial3 = &v2m_serial3;
>  	};
>  
> +	psci {
> +		compatible = "arm,psci-0.2";

Where can I find a PSCI 0.2 implementation for the RTSM VE model? I
couldn't find a link in the cover.

The upstream bootwrapper is not PSCI 0.2 compliant and it does not
implement CPU_SUSPEND.

> +		method = "smc";
> +		cpu_suspend = <0xc4000001>;
> +		cpu_off = <0x84000002>;
> +		cpu_on = <0xc4000003>;

Without "arm,psci" in the compatible list, these three properties are
meaningless.

> +	};
> +
>  	cpus {
>  		#address-cells = <2>;
>  		#size-cells = <0>;
>  
> +		idle-states {
> +			entry-method = "arm,psci";
> +
> +			CPU_SLEEP_0: cpu-sleep-0 {
> +				compatible = "arm,idle-state";
> +				entry-method-param = <0x0010000>;
> +				entry-latency-us = <40>;
> +				exit-latency-us = <100>;
> +				min-residency-us = <150>;
> +			};
> +
> +			CLUSTER_SLEEP_0: cluster-sleep-0 {
> +				compatible = "arm,idle-state";
> +				entry-method-param = <0x1010000>;
> +				entry-latency-us = <500>;
> +				exit-latency-us = <1000>;
> +				min-residency-us = <2500>;
> +			};
> +		};
> +

If this is going to live in the /cpus node, could it please be placed
after the cpu nodes?

>  		cpu at 0 {
>  			device_type = "cpu";
>  			compatible = "arm,armv8";
>  			reg = <0x0 0x0>;
> -			enable-method = "spin-table";
> -			cpu-release-addr = <0x0 0x8000fff8>;
> +			enable-method = "psci";

Changing the enable-method will break boot on a model when using a
bootwrapper without PSCI support. Really we should leave it up to the
bootwrapper to inject the enable method...

Mark.

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 8/8] arm64: boot: dts: update rtsm aemv8 dts with PSCI and idle states
  2014-06-25 14:10   ` Lorenzo Pieralisi
@ 2014-06-25 14:29     ` Sudeep Holla
  -1 siblings, 0 replies; 70+ messages in thread
From: Sudeep Holla @ 2014-06-25 14:29 UTC (permalink / raw)
  To: Lorenzo Pieralisi, linux-arm-kernel, linux-pm, devicetree
  Cc: Sudeep Holla, Mark Rutland, Catalin Marinas,
	Charles Garcia-Tobin, Nicolas Pitre, Rob Herring, grant.likely,
	Peter De Schrijver, Santosh Shilimkar, Daniel Lezcano,
	Amit Kucheria, Vincent Guittot, Antti Miettinen, Stephen Boyd,
	Kevin Hilman, Sebastian Capella, Tomasz Figa, Mark Brown,
	Paul Walmsley, Chander Kashyap



On 25/06/14 15:10, Lorenzo Pieralisi wrote:
> This patch updates the RTSM dts file with PSCI bindings and nodes
> describing the AEMv8 model idle states parameters.
>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> ---
>   arch/arm64/boot/dts/rtsm_ve-aemv8a.dts | 44 +++++++++++++++++++++++++++-------
>   1 file changed, 36 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> index d79de9c..4051ffb 100644
> --- a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> +++ b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> @@ -27,37 +27,65 @@
>   		serial3 = &v2m_serial3;
>   	};
>
> +	psci {
> +		compatible = "arm,psci-0.2";
> +		method = "smc";
> +		cpu_suspend = <0xc4000001>;
> +		cpu_off = <0x84000002>;
> +		cpu_on = <0xc4000003>;

Standard PSCI v0.2 function IDs are used for "arm,psci-0.2", so you can drop
them here.

Regards,
Sudeep


^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 8/8] arm64: boot: dts: update rtsm aemv8 dts with PSCI and idle states
@ 2014-06-25 14:29     ` Sudeep Holla
  0 siblings, 0 replies; 70+ messages in thread
From: Sudeep Holla @ 2014-06-25 14:29 UTC (permalink / raw)
  To: linux-arm-kernel



On 25/06/14 15:10, Lorenzo Pieralisi wrote:
> This patch updates the RTSM dts file with PSCI bindings and nodes
> describing the AEMv8 model idle states parameters.
>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> ---
>   arch/arm64/boot/dts/rtsm_ve-aemv8a.dts | 44 +++++++++++++++++++++++++++-------
>   1 file changed, 36 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> index d79de9c..4051ffb 100644
> --- a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> +++ b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> @@ -27,37 +27,65 @@
>   		serial3 = &v2m_serial3;
>   	};
>
> +	psci {
> +		compatible = "arm,psci-0.2";
> +		method = "smc";
> +		cpu_suspend = <0xc4000001>;
> +		cpu_off = <0x84000002>;
> +		cpu_on = <0xc4000003>;

Standard PSCI v0.2 function IDs are used for "arm,psci-0.2", so you can drop
them here.

Regards,
Sudeep

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 1/8] Documentation: arm: define DT idle states bindings
  2014-06-25 14:10   ` Lorenzo Pieralisi
@ 2014-06-25 14:58     ` Mark Rutland
  -1 siblings, 0 replies; 70+ messages in thread
From: Mark Rutland @ 2014-06-25 14:58 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: linux-arm-kernel, linux-pm, devicetree, Sudeep Holla,
	Catalin Marinas, Charles Garcia-Tobin, Nicolas Pitre,
	Rob Herring, grant.likely, Peter De Schrijver, Santosh Shilimkar,
	Daniel Lezcano, Amit Kucheria, Vincent Guittot, Antti Miettinen,
	Stephen Boyd, Kevin Hilman, Sebastian Capella, Tomasz Figa,
	Mark Brown

Hi Lorenzo,

On Wed, Jun 25, 2014 at 03:10:14PM +0100, Lorenzo Pieralisi wrote:
> ARM based platforms implement a variety of power management schemes that
> allow processors to enter idle states at run-time.
> The parameters defining these idle states vary on a per-platform basis forcing
> the OS to hardcode the state parameters in platform specific static tables
> whose size grows as the number of platforms supported in the kernel increases
> and hampers device drivers standardization.
>
> Therefore, this patch aims at standardizing idle state device tree bindings for
> ARM platforms. Bindings define idle state parameters inclusive of entry methods
> and state latencies, to allow operating systems to retrieve the configuration
> entries from the device tree and initialize the related power management
> drivers, paving the way for common code in the kernel to deal with idle
> states and removing the need for static data in current and previous kernel
> versions.
>
> Reviewed-by: Sebastian Capella <sebcape@gmail.com>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> ---
>  Documentation/devicetree/bindings/arm/cpus.txt     |   8 +
>  .../devicetree/bindings/arm/idle-states.txt        | 733 +++++++++++++++++++++
>  2 files changed, 741 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/idle-states.txt

[...]

> +===========================================
> +3 - idle-states node
> +===========================================
> +
> +ARM 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.
> +
> +- idle-states node
> +
> +       Usage: Optional - 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.
> +
> +       Description: idle-states node is a container node, where its
> +                    subnodes describe the CPU idle states.
> +
> +       Node name must be "idle-states".
> +
> +       The idle-states node's parent node must be the cpus node.
> +
> +       The idle-states node's child nodes can be:
> +
> +       - one or more state nodes
> +
> +       Any other configuration is considered invalid.
> +
> +       An idle-states node defines the following properties:
> +
> +       - entry-method
> +               Usage: Required
> +               Value type: <stringlist>
> +               Definition: Describes the method by which a CPU enters the
> +                           idle states. This property is required and must be
> +                           one of:
> +
> +                           - "arm,psci"
> +                             ARM PSCI firmware interface [2].
> +
> +                           - "[vendor],[method]"
> +                             An implementation dependent string with
> +                             format "vendor,method", where vendor is a string
> +                             denoting the name of the manufacturer and
> +                             method is a string specifying the mechanism
> +                             used to enter the idle state.
> +
> +The nodes describing the idle states (state) can only be defined within the
> +idle-states node, any other configuration is considered invalid and therefore
> +must be ignored.
> +
> +===========================================
> +4 - state node
> +===========================================
> +
> +A state node represents an idle state description and must be defined as
> +follows:
> +
> +- state node
> +
> +       Description: must be child of the idle-states node
> +
> +       The state node name shall follow standard device tree naming
> +       rules ([5], 2.2.1 "Node names"), in particular state nodes which
> +       are siblings within a single common parent must be given a unique name.
> +
> +       The idle state entered by executing the wfi instruction (idle_standby
> +       SBSA,[3][4]) is considered standard on all ARM platforms and therefore
> +       must not be listed.
> +
> +       With the definitions provided above, the following list represents
> +       the valid properties for a state node:
> +
> +       - compatible
> +               Usage: Required
> +               Value type: <stringlist>
> +               Definition: Must be "arm,idle-state".
> +
> +       - logic-state-retained
> +               Usage: See definition
> +               Value type: <none>
> +               Definition: if present logic is retained on state entry,
> +                           otherwise it is lost.

What logic state is retained? All system registers?

> +       - cache-state-retained
> +               Usage: See definition
> +               Value type: <none>
> +               Definition: if present cache memory is retained on state entry,
> +                           otherwise it is lost.

Likewise, how much of the cache hierarchy is affected? Any of it? All of
it?

> +       - timer-state-retained
> +               Usage: See definition
> +               Value type: <none>
> +               Definition: if present the timer control logic is retained on
> +                            state entry, otherwise it is lost.

The architected generic timers? Any CPU-local timers? Or any timers
whatsoever?

> +       - power-rank
> +               Usage: Required
> +               Value type: <u32>
> +               Definition: It represents the idle state power-rank.
> +                           An increasing value implies less power
> +                           consumption. It must be given a sequential
> +                           value = {0, 1, ....}, starting from 0.
> +                           Phandles in the cpu nodes [1] cpu-idle-states
> +                           array property are not allowed to point at idle
> +                           state nodes having the same power-rank value.

Why can't this be implicit in the order of the cpu-idle-states list?
That way it's impossible to violate the ordering requirement.

> +       - entry-method-param
> +               Usage: See definition.
> +               Value type: <u32>
> +               Definition: Depends on the idle-states node entry-method
> +                           property value. Refer to the entry-method bindings
> +                           for this property value definition.

Should this not be left up to the particular mechanism to describe?
e.g. for PSCI we could have a arm,psci-suspend-param property.

Are we sure a single u32 value is going to be sufficient?

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 1/8] Documentation: arm: define DT idle states bindings
@ 2014-06-25 14:58     ` Mark Rutland
  0 siblings, 0 replies; 70+ messages in thread
From: Mark Rutland @ 2014-06-25 14:58 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lorenzo,

On Wed, Jun 25, 2014 at 03:10:14PM +0100, Lorenzo Pieralisi wrote:
> ARM based platforms implement a variety of power management schemes that
> allow processors to enter idle states at run-time.
> The parameters defining these idle states vary on a per-platform basis forcing
> the OS to hardcode the state parameters in platform specific static tables
> whose size grows as the number of platforms supported in the kernel increases
> and hampers device drivers standardization.
>
> Therefore, this patch aims at standardizing idle state device tree bindings for
> ARM platforms. Bindings define idle state parameters inclusive of entry methods
> and state latencies, to allow operating systems to retrieve the configuration
> entries from the device tree and initialize the related power management
> drivers, paving the way for common code in the kernel to deal with idle
> states and removing the need for static data in current and previous kernel
> versions.
>
> Reviewed-by: Sebastian Capella <sebcape@gmail.com>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> ---
>  Documentation/devicetree/bindings/arm/cpus.txt     |   8 +
>  .../devicetree/bindings/arm/idle-states.txt        | 733 +++++++++++++++++++++
>  2 files changed, 741 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/idle-states.txt

[...]

> +===========================================
> +3 - idle-states node
> +===========================================
> +
> +ARM 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.
> +
> +- idle-states node
> +
> +       Usage: Optional - 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.
> +
> +       Description: idle-states node is a container node, where its
> +                    subnodes describe the CPU idle states.
> +
> +       Node name must be "idle-states".
> +
> +       The idle-states node's parent node must be the cpus node.
> +
> +       The idle-states node's child nodes can be:
> +
> +       - one or more state nodes
> +
> +       Any other configuration is considered invalid.
> +
> +       An idle-states node defines the following properties:
> +
> +       - entry-method
> +               Usage: Required
> +               Value type: <stringlist>
> +               Definition: Describes the method by which a CPU enters the
> +                           idle states. This property is required and must be
> +                           one of:
> +
> +                           - "arm,psci"
> +                             ARM PSCI firmware interface [2].
> +
> +                           - "[vendor],[method]"
> +                             An implementation dependent string with
> +                             format "vendor,method", where vendor is a string
> +                             denoting the name of the manufacturer and
> +                             method is a string specifying the mechanism
> +                             used to enter the idle state.
> +
> +The nodes describing the idle states (state) can only be defined within the
> +idle-states node, any other configuration is considered invalid and therefore
> +must be ignored.
> +
> +===========================================
> +4 - state node
> +===========================================
> +
> +A state node represents an idle state description and must be defined as
> +follows:
> +
> +- state node
> +
> +       Description: must be child of the idle-states node
> +
> +       The state node name shall follow standard device tree naming
> +       rules ([5], 2.2.1 "Node names"), in particular state nodes which
> +       are siblings within a single common parent must be given a unique name.
> +
> +       The idle state entered by executing the wfi instruction (idle_standby
> +       SBSA,[3][4]) is considered standard on all ARM platforms and therefore
> +       must not be listed.
> +
> +       With the definitions provided above, the following list represents
> +       the valid properties for a state node:
> +
> +       - compatible
> +               Usage: Required
> +               Value type: <stringlist>
> +               Definition: Must be "arm,idle-state".
> +
> +       - logic-state-retained
> +               Usage: See definition
> +               Value type: <none>
> +               Definition: if present logic is retained on state entry,
> +                           otherwise it is lost.

What logic state is retained? All system registers?

> +       - cache-state-retained
> +               Usage: See definition
> +               Value type: <none>
> +               Definition: if present cache memory is retained on state entry,
> +                           otherwise it is lost.

Likewise, how much of the cache hierarchy is affected? Any of it? All of
it?

> +       - timer-state-retained
> +               Usage: See definition
> +               Value type: <none>
> +               Definition: if present the timer control logic is retained on
> +                            state entry, otherwise it is lost.

The architected generic timers? Any CPU-local timers? Or any timers
whatsoever?

> +       - power-rank
> +               Usage: Required
> +               Value type: <u32>
> +               Definition: It represents the idle state power-rank.
> +                           An increasing value implies less power
> +                           consumption. It must be given a sequential
> +                           value = {0, 1, ....}, starting from 0.
> +                           Phandles in the cpu nodes [1] cpu-idle-states
> +                           array property are not allowed to point at idle
> +                           state nodes having the same power-rank value.

Why can't this be implicit in the order of the cpu-idle-states list?
That way it's impossible to violate the ordering requirement.

> +       - entry-method-param
> +               Usage: See definition.
> +               Value type: <u32>
> +               Definition: Depends on the idle-states node entry-method
> +                           property value. Refer to the entry-method bindings
> +                           for this property value definition.

Should this not be left up to the particular mechanism to describe?
e.g. for PSCI we could have a arm,psci-suspend-param property.

Are we sure a single u32 value is going to be sufficient?

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 6/8] drivers: cpuidle: initialize big.LITTLE driver through DT
  2014-06-25 14:10   ` Lorenzo Pieralisi
@ 2014-06-25 15:06     ` Mark Rutland
  -1 siblings, 0 replies; 70+ messages in thread
From: Mark Rutland @ 2014-06-25 15:06 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: linux-arm-kernel, linux-pm, devicetree, Chander Kashyap,
	Sudeep Holla, Catalin Marinas, Charles Garcia-Tobin,
	Nicolas Pitre, Rob Herring, grant.likely, Peter De Schrijver,
	Santosh Shilimkar, Daniel Lezcano, Amit Kucheria,
	Vincent Guittot, Antti Miettinen, Stephen Boyd, Kevin Hilman,
	Sebastian Capella

On Wed, Jun 25, 2014 at 03:10:19PM +0100, Lorenzo Pieralisi wrote:
> With the introduction of DT based idle states, CPUidle drivers for ARM
> can now initialize idle states data through properties in the device tree.
> 
> This patch adds code to the big.LITTLE CPUidle driver to dynamically
> initialize idle states data through the updated device tree source file.
> 
> Cc: Chander Kashyap <chander.kashyap@linaro.org>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> ---
>  Documentation/devicetree/bindings/arm/vexpress.txt | 25 +++++++++++++
>  arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts         | 25 +++++++++++++
>  drivers/cpuidle/Kconfig.arm                        |  1 +
>  drivers/cpuidle/cpuidle-big_little.c               | 43 +++++++++++-----------
>  4 files changed, 73 insertions(+), 21 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/arm/vexpress.txt b/Documentation/devicetree/bindings/arm/vexpress.txt
> index 39844cd..7f52ac8 100644
> --- a/Documentation/devicetree/bindings/arm/vexpress.txt
> +++ b/Documentation/devicetree/bindings/arm/vexpress.txt
> @@ -67,6 +67,28 @@ with device_type = "cpu" property for every available core, eg.:
>  		};
>  	};
>  
> +idle-states node
> +----------------
> +
> +On Versatile Express platforms with power management capabilities, the device
> +tree source file must contain the idle-states node[1]. As defined in [1] the
> +idle-states node must contain an entry-method property that for Versatile
> +Express platforms can be one of:
> +
> +	- "arm,vexpress-v2p-ca15_a7"

... and what does this mean? It's the name we've assigned the platform
in the Linux DT bindings, but this binding document tells me nothing
about how this method works.

This feels like leaking Linux internals rather than a reusable
interface.

Mark.

> +
> +Versatile Express idle-states nodes example:
> +
> +	idle-states {
> +		entry-method = "arm,vexpress-v2p-ca15_a7";
> +
> +		cluster-sleep-0 {
> +			compatible = "arm,idle-state";
> +			entry-latency-us = <1000>;
> +			exit-latency-us = <700>;
> +			min-residency-us = <3500>;
> +		};
> +	};
>  
>  Configuration infrastructure
>  ----------------------------
> @@ -227,3 +249,6 @@ Example of a VE tile description (simplified)
>  	};
>  };
>  
> +
> +[1] ARM Linux Kernel documentation - Idle states bindings
> +    Documentation/devicetree/bindings/arm/idle-states.txt
> diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
> index a25c262..ad28242 100644
> --- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
> +++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
> @@ -33,11 +33,32 @@
>  		#address-cells = <1>;
>  		#size-cells = <0>;
>  
> +		idle-states {
> +			entry-method = "arm,vexpress-v2p-ca15_a7";
> +
> +			CLUSTER_SLEEP_BIG: cluster-sleep-big {
> +				compatible = "arm,idle-state";
> +				power-rank = <0>;
> +				entry-latency-us = <1000>;
> +				exit-latency-us = <700>;
> +				min-residency-us = <3500>;
> +			};
> +
> +			CLUSTER_SLEEP_LITTLE: cluster-sleep-little {
> +				compatible = "arm,idle-state";
> +				power-rank = <0>;
> +				entry-latency-us = <1000>;
> +				exit-latency-us = <500>;
> +				min-residency-us = <3000>;
> +			};
> +		};
> +
>  		cpu0: cpu@0 {
>  			device_type = "cpu";
>  			compatible = "arm,cortex-a15";
>  			reg = <0>;
>  			cci-control-port = <&cci_control1>;
> +			cpu-idle-states = <&CLUSTER_SLEEP_BIG>;
>  		};
>  
>  		cpu1: cpu@1 {
> @@ -45,6 +66,7 @@
>  			compatible = "arm,cortex-a15";
>  			reg = <1>;
>  			cci-control-port = <&cci_control1>;
> +			cpu-idle-states = <&CLUSTER_SLEEP_BIG>;
>  		};
>  
>  		cpu2: cpu@2 {
> @@ -52,6 +74,7 @@
>  			compatible = "arm,cortex-a7";
>  			reg = <0x100>;
>  			cci-control-port = <&cci_control2>;
> +			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
>  		};
>  
>  		cpu3: cpu@3 {
> @@ -59,6 +82,7 @@
>  			compatible = "arm,cortex-a7";
>  			reg = <0x101>;
>  			cci-control-port = <&cci_control2>;
> +			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
>  		};
>  
>  		cpu4: cpu@4 {
> @@ -66,6 +90,7 @@
>  			compatible = "arm,cortex-a7";
>  			reg = <0x102>;
>  			cci-control-port = <&cci_control2>;
> +			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
>  		};
>  	};
>  
> diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
> index b6d69e8..a9b089c 100644
> --- a/drivers/cpuidle/Kconfig.arm
> +++ b/drivers/cpuidle/Kconfig.arm
> @@ -12,6 +12,7 @@ config ARM_BIG_LITTLE_CPUIDLE
>  	depends on ARCH_VEXPRESS_TC2_PM
>  	select ARM_CPU_SUSPEND
>  	select CPU_IDLE_MULTIPLE_DRIVERS
> +	select DT_IDLE_STATES
>  	help
>  	  Select this option to enable CPU idle driver for big.LITTLE based
>  	  ARM systems. Driver manages CPUs coordination through MCPM and
> diff --git a/drivers/cpuidle/cpuidle-big_little.c b/drivers/cpuidle/cpuidle-big_little.c
> index b45fc62..6712441 100644
> --- a/drivers/cpuidle/cpuidle-big_little.c
> +++ b/drivers/cpuidle/cpuidle-big_little.c
> @@ -24,6 +24,8 @@
>  #include <asm/smp_plat.h>
>  #include <asm/suspend.h>
>  
> +#include "dt_idle_states.h"
> +
>  static int bl_enter_powerdown(struct cpuidle_device *dev,
>  			      struct cpuidle_driver *drv, int idx);
>  
> @@ -61,32 +63,12 @@ static struct cpuidle_driver bl_idle_little_driver = {
>  	.name = "little_idle",
>  	.owner = THIS_MODULE,
>  	.states[0] = ARM_CPUIDLE_WFI_STATE,
> -	.states[1] = {
> -		.enter			= bl_enter_powerdown,
> -		.exit_latency		= 700,
> -		.target_residency	= 2500,
> -		.flags			= CPUIDLE_FLAG_TIME_VALID |
> -					  CPUIDLE_FLAG_TIMER_STOP,
> -		.name			= "C1",
> -		.desc			= "ARM little-cluster power down",
> -	},
> -	.state_count = 2,
>  };
>  
>  static struct cpuidle_driver bl_idle_big_driver = {
>  	.name = "big_idle",
>  	.owner = THIS_MODULE,
>  	.states[0] = ARM_CPUIDLE_WFI_STATE,
> -	.states[1] = {
> -		.enter			= bl_enter_powerdown,
> -		.exit_latency		= 500,
> -		.target_residency	= 2000,
> -		.flags			= CPUIDLE_FLAG_TIME_VALID |
> -					  CPUIDLE_FLAG_TIMER_STOP,
> -		.name			= "C1",
> -		.desc			= "ARM big-cluster power down",
> -	},
> -	.state_count = 2,
>  };
>  
>  /*
> @@ -165,7 +147,8 @@ static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int cpu_id)
>  
>  static int __init bl_idle_init(void)
>  {
> -	int ret;
> +	int ret, i;
> +	struct cpuidle_driver *drv;
>  
>  	/*
>  	 * Initialize the driver just for a compliant set of machines
> @@ -187,6 +170,24 @@ static int __init bl_idle_init(void)
>  	if (ret)
>  		goto out_uninit_little;
>  
> +	 /* Start at index 1, index 0 standard WFI */
> +	ret = dt_init_idle_driver(&bl_idle_big_driver, NULL, 1, false);
> +	if (ret)
> +		goto out_uninit_big;
> +
> +	 /* Start at index 1, index 0 standard WFI */
> +	ret = dt_init_idle_driver(&bl_idle_little_driver, NULL, 1, false);
> +	if (ret)
> +		goto out_uninit_big;
> +
> +	drv = &bl_idle_big_driver;
> +	for (i = 1; i < drv->state_count; i++)
> +		drv->states[i].enter = bl_enter_powerdown;
> +
> +	drv = &bl_idle_little_driver;
> +	for (i = 1; i < drv->state_count; i++)
> +		drv->states[i].enter = bl_enter_powerdown;
> +
>  	ret = cpuidle_register(&bl_idle_little_driver, NULL);
>  	if (ret)
>  		goto out_uninit_big;
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 6/8] drivers: cpuidle: initialize big.LITTLE driver through DT
@ 2014-06-25 15:06     ` Mark Rutland
  0 siblings, 0 replies; 70+ messages in thread
From: Mark Rutland @ 2014-06-25 15:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 25, 2014 at 03:10:19PM +0100, Lorenzo Pieralisi wrote:
> With the introduction of DT based idle states, CPUidle drivers for ARM
> can now initialize idle states data through properties in the device tree.
> 
> This patch adds code to the big.LITTLE CPUidle driver to dynamically
> initialize idle states data through the updated device tree source file.
> 
> Cc: Chander Kashyap <chander.kashyap@linaro.org>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> ---
>  Documentation/devicetree/bindings/arm/vexpress.txt | 25 +++++++++++++
>  arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts         | 25 +++++++++++++
>  drivers/cpuidle/Kconfig.arm                        |  1 +
>  drivers/cpuidle/cpuidle-big_little.c               | 43 +++++++++++-----------
>  4 files changed, 73 insertions(+), 21 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/arm/vexpress.txt b/Documentation/devicetree/bindings/arm/vexpress.txt
> index 39844cd..7f52ac8 100644
> --- a/Documentation/devicetree/bindings/arm/vexpress.txt
> +++ b/Documentation/devicetree/bindings/arm/vexpress.txt
> @@ -67,6 +67,28 @@ with device_type = "cpu" property for every available core, eg.:
>  		};
>  	};
>  
> +idle-states node
> +----------------
> +
> +On Versatile Express platforms with power management capabilities, the device
> +tree source file must contain the idle-states node[1]. As defined in [1] the
> +idle-states node must contain an entry-method property that for Versatile
> +Express platforms can be one of:
> +
> +	- "arm,vexpress-v2p-ca15_a7"

... and what does this mean? It's the name we've assigned the platform
in the Linux DT bindings, but this binding document tells me nothing
about how this method works.

This feels like leaking Linux internals rather than a reusable
interface.

Mark.

> +
> +Versatile Express idle-states nodes example:
> +
> +	idle-states {
> +		entry-method = "arm,vexpress-v2p-ca15_a7";
> +
> +		cluster-sleep-0 {
> +			compatible = "arm,idle-state";
> +			entry-latency-us = <1000>;
> +			exit-latency-us = <700>;
> +			min-residency-us = <3500>;
> +		};
> +	};
>  
>  Configuration infrastructure
>  ----------------------------
> @@ -227,3 +249,6 @@ Example of a VE tile description (simplified)
>  	};
>  };
>  
> +
> +[1] ARM Linux Kernel documentation - Idle states bindings
> +    Documentation/devicetree/bindings/arm/idle-states.txt
> diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
> index a25c262..ad28242 100644
> --- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
> +++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
> @@ -33,11 +33,32 @@
>  		#address-cells = <1>;
>  		#size-cells = <0>;
>  
> +		idle-states {
> +			entry-method = "arm,vexpress-v2p-ca15_a7";
> +
> +			CLUSTER_SLEEP_BIG: cluster-sleep-big {
> +				compatible = "arm,idle-state";
> +				power-rank = <0>;
> +				entry-latency-us = <1000>;
> +				exit-latency-us = <700>;
> +				min-residency-us = <3500>;
> +			};
> +
> +			CLUSTER_SLEEP_LITTLE: cluster-sleep-little {
> +				compatible = "arm,idle-state";
> +				power-rank = <0>;
> +				entry-latency-us = <1000>;
> +				exit-latency-us = <500>;
> +				min-residency-us = <3000>;
> +			};
> +		};
> +
>  		cpu0: cpu at 0 {
>  			device_type = "cpu";
>  			compatible = "arm,cortex-a15";
>  			reg = <0>;
>  			cci-control-port = <&cci_control1>;
> +			cpu-idle-states = <&CLUSTER_SLEEP_BIG>;
>  		};
>  
>  		cpu1: cpu at 1 {
> @@ -45,6 +66,7 @@
>  			compatible = "arm,cortex-a15";
>  			reg = <1>;
>  			cci-control-port = <&cci_control1>;
> +			cpu-idle-states = <&CLUSTER_SLEEP_BIG>;
>  		};
>  
>  		cpu2: cpu at 2 {
> @@ -52,6 +74,7 @@
>  			compatible = "arm,cortex-a7";
>  			reg = <0x100>;
>  			cci-control-port = <&cci_control2>;
> +			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
>  		};
>  
>  		cpu3: cpu at 3 {
> @@ -59,6 +82,7 @@
>  			compatible = "arm,cortex-a7";
>  			reg = <0x101>;
>  			cci-control-port = <&cci_control2>;
> +			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
>  		};
>  
>  		cpu4: cpu at 4 {
> @@ -66,6 +90,7 @@
>  			compatible = "arm,cortex-a7";
>  			reg = <0x102>;
>  			cci-control-port = <&cci_control2>;
> +			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
>  		};
>  	};
>  
> diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
> index b6d69e8..a9b089c 100644
> --- a/drivers/cpuidle/Kconfig.arm
> +++ b/drivers/cpuidle/Kconfig.arm
> @@ -12,6 +12,7 @@ config ARM_BIG_LITTLE_CPUIDLE
>  	depends on ARCH_VEXPRESS_TC2_PM
>  	select ARM_CPU_SUSPEND
>  	select CPU_IDLE_MULTIPLE_DRIVERS
> +	select DT_IDLE_STATES
>  	help
>  	  Select this option to enable CPU idle driver for big.LITTLE based
>  	  ARM systems. Driver manages CPUs coordination through MCPM and
> diff --git a/drivers/cpuidle/cpuidle-big_little.c b/drivers/cpuidle/cpuidle-big_little.c
> index b45fc62..6712441 100644
> --- a/drivers/cpuidle/cpuidle-big_little.c
> +++ b/drivers/cpuidle/cpuidle-big_little.c
> @@ -24,6 +24,8 @@
>  #include <asm/smp_plat.h>
>  #include <asm/suspend.h>
>  
> +#include "dt_idle_states.h"
> +
>  static int bl_enter_powerdown(struct cpuidle_device *dev,
>  			      struct cpuidle_driver *drv, int idx);
>  
> @@ -61,32 +63,12 @@ static struct cpuidle_driver bl_idle_little_driver = {
>  	.name = "little_idle",
>  	.owner = THIS_MODULE,
>  	.states[0] = ARM_CPUIDLE_WFI_STATE,
> -	.states[1] = {
> -		.enter			= bl_enter_powerdown,
> -		.exit_latency		= 700,
> -		.target_residency	= 2500,
> -		.flags			= CPUIDLE_FLAG_TIME_VALID |
> -					  CPUIDLE_FLAG_TIMER_STOP,
> -		.name			= "C1",
> -		.desc			= "ARM little-cluster power down",
> -	},
> -	.state_count = 2,
>  };
>  
>  static struct cpuidle_driver bl_idle_big_driver = {
>  	.name = "big_idle",
>  	.owner = THIS_MODULE,
>  	.states[0] = ARM_CPUIDLE_WFI_STATE,
> -	.states[1] = {
> -		.enter			= bl_enter_powerdown,
> -		.exit_latency		= 500,
> -		.target_residency	= 2000,
> -		.flags			= CPUIDLE_FLAG_TIME_VALID |
> -					  CPUIDLE_FLAG_TIMER_STOP,
> -		.name			= "C1",
> -		.desc			= "ARM big-cluster power down",
> -	},
> -	.state_count = 2,
>  };
>  
>  /*
> @@ -165,7 +147,8 @@ static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int cpu_id)
>  
>  static int __init bl_idle_init(void)
>  {
> -	int ret;
> +	int ret, i;
> +	struct cpuidle_driver *drv;
>  
>  	/*
>  	 * Initialize the driver just for a compliant set of machines
> @@ -187,6 +170,24 @@ static int __init bl_idle_init(void)
>  	if (ret)
>  		goto out_uninit_little;
>  
> +	 /* Start at index 1, index 0 standard WFI */
> +	ret = dt_init_idle_driver(&bl_idle_big_driver, NULL, 1, false);
> +	if (ret)
> +		goto out_uninit_big;
> +
> +	 /* Start at index 1, index 0 standard WFI */
> +	ret = dt_init_idle_driver(&bl_idle_little_driver, NULL, 1, false);
> +	if (ret)
> +		goto out_uninit_big;
> +
> +	drv = &bl_idle_big_driver;
> +	for (i = 1; i < drv->state_count; i++)
> +		drv->states[i].enter = bl_enter_powerdown;
> +
> +	drv = &bl_idle_little_driver;
> +	for (i = 1; i < drv->state_count; i++)
> +		drv->states[i].enter = bl_enter_powerdown;
> +
>  	ret = cpuidle_register(&bl_idle_little_driver, NULL);
>  	if (ret)
>  		goto out_uninit_big;
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 7/8] drivers: cpuidle: initialize Exynos driver through DT
  2014-06-25 14:10   ` Lorenzo Pieralisi
@ 2014-06-25 15:13     ` Mark Rutland
  -1 siblings, 0 replies; 70+ messages in thread
From: Mark Rutland @ 2014-06-25 15:13 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: linux-arm-kernel, linux-pm, devicetree, Kukjin Kim, Tomasz Figa,
	Sudeep Holla, Catalin Marinas, Charles Garcia-Tobin,
	Nicolas Pitre, Rob Herring, grant.likely, Peter De Schrijver,
	Santosh Shilimkar, Daniel Lezcano, Amit Kucheria,
	Vincent Guittot, Antti Miettinen, Stephen Boyd, Kevin Hilman,
	Sebastian Capella

On Wed, Jun 25, 2014 at 03:10:20PM +0100, Lorenzo Pieralisi wrote:
> With the introduction of DT based idle states, CPUidle drivers for
> ARM can now initialize idle states data through properties in the device
> tree.
> 
> This patch adds code to the Exynos CPUidle driver to dynamically
> initialize idle states data through the updated device tree source
> files.
> 
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Cc: Tomasz Figa <t.figa@samsung.com>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> ---
> Compile tested, I am not sure I patched the right dts files, please check.
> 
>  .../devicetree/bindings/arm/exynos/idle-states.txt | 27 ++++++++++++++++++++
>  arch/arm/boot/dts/exynos3250.dtsi                  | 16 ++++++++++++
>  arch/arm/boot/dts/exynos5250.dtsi                  | 15 +++++++++++
>  arch/arm/boot/dts/exynos5410.dtsi                  | 17 +++++++++++++
>  drivers/cpuidle/Kconfig.arm                        |  1 +
>  drivers/cpuidle/cpuidle-exynos.c                   | 29 +++++++++++++---------
>  6 files changed, 93 insertions(+), 12 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/exynos/idle-states.txt b/Documentation/devicetree/bindings/arm/exynos/idle-states.txt
> new file mode 100644
> index 0000000..342ecb4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/exynos/idle-states.txt
> @@ -0,0 +1,27 @@
> +idle-states node
> +----------------
> +
> +On Exynos platforms with power management capabilities, the device
> +tree source file must contain the idle-states node[1]. As defined in [1] the
> +idle-states node must contain an entry-method property that for Exynos
> +platforms can be one of:
> +
> +	- "samsung,exynos"

Similarly to the TC2 binding, what does this mean?

What is a kernel expected to do when it sees this entry-method?

Using "samsung,exynos" as the entry-method feels like something that's
going to bite us; it sounds far too wide-reaching.

>  static int exynos_cpuidle_probe(struct platform_device *pdev)
>  {
> -	int ret;
> +	int ret, i;
> +	struct cpuidle_driver *drv = &exynos_idle_driver;
>  
>  	exynos_enter_aftr = (void *)(pdev->dev.platform_data);
>  
> -	ret = cpuidle_register(&exynos_idle_driver, NULL);
> +	drv->cpumask = (struct cpumask *) cpu_possible_mask;

This assignment looks scary to me. Why do we need to do this, and why
are we throwing away the constness of cpu_possible_mask?

Mark.

^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 7/8] drivers: cpuidle: initialize Exynos driver through DT
@ 2014-06-25 15:13     ` Mark Rutland
  0 siblings, 0 replies; 70+ messages in thread
From: Mark Rutland @ 2014-06-25 15:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 25, 2014 at 03:10:20PM +0100, Lorenzo Pieralisi wrote:
> With the introduction of DT based idle states, CPUidle drivers for
> ARM can now initialize idle states data through properties in the device
> tree.
> 
> This patch adds code to the Exynos CPUidle driver to dynamically
> initialize idle states data through the updated device tree source
> files.
> 
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Cc: Tomasz Figa <t.figa@samsung.com>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> ---
> Compile tested, I am not sure I patched the right dts files, please check.
> 
>  .../devicetree/bindings/arm/exynos/idle-states.txt | 27 ++++++++++++++++++++
>  arch/arm/boot/dts/exynos3250.dtsi                  | 16 ++++++++++++
>  arch/arm/boot/dts/exynos5250.dtsi                  | 15 +++++++++++
>  arch/arm/boot/dts/exynos5410.dtsi                  | 17 +++++++++++++
>  drivers/cpuidle/Kconfig.arm                        |  1 +
>  drivers/cpuidle/cpuidle-exynos.c                   | 29 +++++++++++++---------
>  6 files changed, 93 insertions(+), 12 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/exynos/idle-states.txt b/Documentation/devicetree/bindings/arm/exynos/idle-states.txt
> new file mode 100644
> index 0000000..342ecb4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/exynos/idle-states.txt
> @@ -0,0 +1,27 @@
> +idle-states node
> +----------------
> +
> +On Exynos platforms with power management capabilities, the device
> +tree source file must contain the idle-states node[1]. As defined in [1] the
> +idle-states node must contain an entry-method property that for Exynos
> +platforms can be one of:
> +
> +	- "samsung,exynos"

Similarly to the TC2 binding, what does this mean?

What is a kernel expected to do when it sees this entry-method?

Using "samsung,exynos" as the entry-method feels like something that's
going to bite us; it sounds far too wide-reaching.

>  static int exynos_cpuidle_probe(struct platform_device *pdev)
>  {
> -	int ret;
> +	int ret, i;
> +	struct cpuidle_driver *drv = &exynos_idle_driver;
>  
>  	exynos_enter_aftr = (void *)(pdev->dev.platform_data);
>  
> -	ret = cpuidle_register(&exynos_idle_driver, NULL);
> +	drv->cpumask = (struct cpumask *) cpu_possible_mask;

This assignment looks scary to me. Why do we need to do this, and why
are we throwing away the constness of cpu_possible_mask?

Mark.

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 7/8] drivers: cpuidle: initialize Exynos driver through DT
  2014-06-25 14:10   ` Lorenzo Pieralisi
@ 2014-06-25 15:23     ` Bartlomiej Zolnierkiewicz
  -1 siblings, 0 replies; 70+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2014-06-25 15:23 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: linux-arm-kernel, linux-pm, devicetree, Kukjin Kim, Tomasz Figa,
	Mark Rutland, Sudeep Holla, Catalin Marinas,
	Charles Garcia Tobin, Nicolas Pitre, Rob Herring, Grant Likely,
	Peter De Schrijver, Santosh Shilimkar, Daniel Lezcano,
	Amit Kucheria, Vincent Guittot, Antti Miettinen, Stephen Boyd,
	Kevin Hilman, Sebastian Capella, Mark Brown, Paul Walmsley


Hi,

On Wednesday, June 25, 2014 03:10:20 PM Lorenzo Pieralisi wrote:
> With the introduction of DT based idle states, CPUidle drivers for
> ARM can now initialize idle states data through properties in the device
> tree.
> 
> This patch adds code to the Exynos CPUidle driver to dynamically
> initialize idle states data through the updated device tree source
> files.
> 
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Cc: Tomasz Figa <t.figa@samsung.com>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> ---
> Compile tested, I am not sure I patched the right dts files, please check.

cpuidle-exynos driver is currently working properly in deeper cpuidle
mode (AFTR) on Exynos4210 and Exynos5250 (please also see the following
patch from Tomasz Figa: [1]).  There is ongoing work to AFTR mode work
also on Exynos4x12 and Exynos3250 but it is not complete yet.  Exynos5410
OTOH should probably use the generic big little cpuidle driver (this SoC
is similar to Exynos5420 one for which Chander Kashyap has developed
cpuidle-big_little support [2]).

Making long story short, I think that your patch should depend on patch
[1] and update only exynos4210.dtsi and exynos5250.dtsi.  Also for your
patch #6 there needs to be some coordination with merging of Chander's
patchset ([2]).

[1] http://www.spinics.net/lists/arm-kernel/msg341023.html
[2] https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg664470.html

>  .../devicetree/bindings/arm/exynos/idle-states.txt | 27 ++++++++++++++++++++
>  arch/arm/boot/dts/exynos3250.dtsi                  | 16 ++++++++++++
>  arch/arm/boot/dts/exynos5250.dtsi                  | 15 +++++++++++
>  arch/arm/boot/dts/exynos5410.dtsi                  | 17 +++++++++++++
>  drivers/cpuidle/Kconfig.arm                        |  1 +
>  drivers/cpuidle/cpuidle-exynos.c                   | 29 +++++++++++++---------
>  6 files changed, 93 insertions(+), 12 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics


^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 7/8] drivers: cpuidle: initialize Exynos driver through DT
@ 2014-06-25 15:23     ` Bartlomiej Zolnierkiewicz
  0 siblings, 0 replies; 70+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2014-06-25 15:23 UTC (permalink / raw)
  To: linux-arm-kernel


Hi,

On Wednesday, June 25, 2014 03:10:20 PM Lorenzo Pieralisi wrote:
> With the introduction of DT based idle states, CPUidle drivers for
> ARM can now initialize idle states data through properties in the device
> tree.
> 
> This patch adds code to the Exynos CPUidle driver to dynamically
> initialize idle states data through the updated device tree source
> files.
> 
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Cc: Tomasz Figa <t.figa@samsung.com>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> ---
> Compile tested, I am not sure I patched the right dts files, please check.

cpuidle-exynos driver is currently working properly in deeper cpuidle
mode (AFTR) on Exynos4210 and Exynos5250 (please also see the following
patch from Tomasz Figa: [1]).  There is ongoing work to AFTR mode work
also on Exynos4x12 and Exynos3250 but it is not complete yet.  Exynos5410
OTOH should probably use the generic big little cpuidle driver (this SoC
is similar to Exynos5420 one for which Chander Kashyap has developed
cpuidle-big_little support [2]).

Making long story short, I think that your patch should depend on patch
[1] and update only exynos4210.dtsi and exynos5250.dtsi.  Also for your
patch #6 there needs to be some coordination with merging of Chander's
patchset ([2]).

[1] http://www.spinics.net/lists/arm-kernel/msg341023.html
[2] https://www.mail-archive.com/linux-kernel at vger.kernel.org/msg664470.html

>  .../devicetree/bindings/arm/exynos/idle-states.txt | 27 ++++++++++++++++++++
>  arch/arm/boot/dts/exynos3250.dtsi                  | 16 ++++++++++++
>  arch/arm/boot/dts/exynos5250.dtsi                  | 15 +++++++++++
>  arch/arm/boot/dts/exynos5410.dtsi                  | 17 +++++++++++++
>  drivers/cpuidle/Kconfig.arm                        |  1 +
>  drivers/cpuidle/cpuidle-exynos.c                   | 29 +++++++++++++---------
>  6 files changed, 93 insertions(+), 12 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 1/8] Documentation: arm: define DT idle states bindings
  2014-06-25 14:10   ` Lorenzo Pieralisi
@ 2014-06-25 15:56     ` Nicolas Pitre
  -1 siblings, 0 replies; 70+ messages in thread
From: Nicolas Pitre @ 2014-06-25 15:56 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: linux-arm-kernel, linux-pm, devicetree, Mark Rutland,
	Sudeep Holla, Catalin Marinas, Charles Garcia Tobin, Rob Herring,
	Grant Likely, Peter De Schrijver, Santosh Shilimkar,
	Daniel Lezcano, Amit Kucheria, Vincent Guittot, Antti Miettinen,
	Stephen Boyd, Kevin Hilman, Sebastian Capella, Tomasz Figa,
	Mark Brown, Paul Walmsley, Chander Kashyap

On Wed, 25 Jun 2014, Lorenzo Pieralisi wrote:

> ARM based platforms implement a variety of power management schemes that
> allow processors to enter idle states at run-time.
> The parameters defining these idle states vary on a per-platform basis forcing
> the OS to hardcode the state parameters in platform specific static tables
> whose size grows as the number of platforms supported in the kernel increases
> and hampers device drivers standardization.
> 
> Therefore, this patch aims at standardizing idle state device tree bindings for
> ARM platforms. Bindings define idle state parameters inclusive of entry methods
> and state latencies, to allow operating systems to retrieve the configuration
> entries from the device tree and initialize the related power management
> drivers, paving the way for common code in the kernel to deal with idle
> states and removing the need for static data in current and previous kernel
> versions.
> 
> Reviewed-by: Sebastian Capella <sebcape@gmail.com>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>

Excellent.

Reviewed-by: Nicolas Pitre <nico@linaro.org>

> ---
>  Documentation/devicetree/bindings/arm/cpus.txt     |   8 +
>  .../devicetree/bindings/arm/idle-states.txt        | 733 +++++++++++++++++++++
>  2 files changed, 741 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/idle-states.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
> index 1fe72a0..a44d4fd 100644
> --- a/Documentation/devicetree/bindings/arm/cpus.txt
> +++ b/Documentation/devicetree/bindings/arm/cpus.txt
> @@ -215,6 +215,12 @@ nodes to be present and contain the properties described below.
>  		Value type: <phandle>
>  		Definition: Specifies the ACC[2] node associated with this CPU.
>  
> +	- cpu-idle-states
> +		Usage: Optional
> +		Value type: <prop-encoded-array>
> +		Definition:
> +			# List of phandles to idle state nodes supported
> +			  by this cpu [3].
>  
>  Example 1 (dual-cluster big.LITTLE system 32-bit):
>  
> @@ -411,3 +417,5 @@ cpus {
>  --
>  [1] arm/msm/qcom,saw2.txt
>  [2] arm/msm/qcom,kpss-acc.txt
> +[3] ARM Linux kernel documentation - idle states bindings
> +    Documentation/devicetree/bindings/arm/idle-states.txt
> diff --git a/Documentation/devicetree/bindings/arm/idle-states.txt b/Documentation/devicetree/bindings/arm/idle-states.txt
> new file mode 100644
> index 0000000..5efd198
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/idle-states.txt
> @@ -0,0 +1,733 @@
> +==========================================
> +ARM idle states binding description
> +==========================================
> +
> +==========================================
> +1 - Introduction
> +==========================================
> +
> +ARM 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.
> +
> +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 (eg 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.
> +
> +===========================================
> +2 - 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
> +(ie 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, eg:
> +
> +wakeup-delay = exit-latency + max(entry-latency - (now - entry-timestamp), 0)
> +
> +In other words, the scheduler can make its scheduling decision by selecting
> +(eg waking-up) the CPU with the shortest wake-up latency.
> +The wake-up latency 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, ie caches
> +state).
> +
> +An OS has to reliably probe the wakeup-latency since some devices can enforce
> +latency constraints 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 whilst 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 (ie 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 (ie 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.
> +
> +===========================================
> +3 - idle-states node
> +===========================================
> +
> +ARM 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.
> +
> +- idle-states node
> +
> +	Usage: Optional - 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.
> +
> +	Description: idle-states node is a container node, where its
> +		     subnodes describe the CPU idle states.
> +
> +	Node name must be "idle-states".
> +
> +	The idle-states node's parent node must be the cpus node.
> +
> +	The idle-states node's child nodes can be:
> +
> +	- one or more state nodes
> +
> +	Any other configuration is considered invalid.
> +
> +	An idle-states node defines the following properties:
> +
> +	- entry-method
> +		Usage: Required
> +		Value type: <stringlist>
> +		Definition: Describes the method by which a CPU enters the
> +			    idle states. This property is required and must be
> +			    one of:
> +
> +			    - "arm,psci"
> +			      ARM PSCI firmware interface [2].
> +
> +			    - "[vendor],[method]"
> +			      An implementation dependent string with
> +			      format "vendor,method", where vendor is a string
> +			      denoting the name of the manufacturer and
> +			      method is a string specifying the mechanism
> +			      used to enter the idle state.
> +
> +The nodes describing the idle states (state) can only be defined within the
> +idle-states node, any other configuration is considered invalid and therefore
> +must be ignored.
> +
> +===========================================
> +4 - state node
> +===========================================
> +
> +A state node represents an idle state description and must be defined as
> +follows:
> +
> +- state node
> +
> +	Description: must be child of the idle-states node
> +
> +	The state node name shall follow standard device tree naming
> +	rules ([5], 2.2.1 "Node names"), in particular state nodes which
> +	are siblings within a single common parent must be given a unique name.
> +
> +	The idle state entered by executing the wfi instruction (idle_standby
> +	SBSA,[3][4]) is considered standard on all ARM platforms and therefore
> +	must not be listed.
> +
> +	With the definitions provided above, the following list represents
> +	the valid properties for a state node:
> +
> +	- compatible
> +		Usage: Required
> +		Value type: <stringlist>
> +		Definition: Must be "arm,idle-state".
> +
> +	- logic-state-retained
> +		Usage: See definition
> +		Value type: <none>
> +		Definition: if present logic is retained on state entry,
> +			    otherwise it is lost.
> +
> +	- cache-state-retained
> +		Usage: See definition
> +		Value type: <none>
> +		Definition: if present cache memory is retained on state entry,
> +			    otherwise it is lost.
> +
> +	- timer-state-retained
> +		Usage: See definition
> +		Value type: <none>
> +		Definition: if present the timer control logic is retained on
> +                            state entry, otherwise it is lost.
> +
> +	- power-rank
> +		Usage: Required
> +		Value type: <u32>
> +		Definition: It represents the idle state power-rank.
> +			    An increasing value implies less power
> +			    consumption. It must be given a sequential
> +			    value = {0, 1, ....}, starting from 0.
> +			    Phandles in the cpu nodes [1] cpu-idle-states
> +			    array property are not allowed to point at idle
> +			    state nodes having the same power-rank value.
> +
> +	- entry-method-param
> +		Usage: See definition.
> +		Value type: <u32>
> +		Definition: Depends on the idle-states node entry-method
> +			    property value. Refer to the entry-method bindings
> +			    for this property value definition.
> +
> +	- entry-latency-us
> +		Usage: Required
> +		Value type: <prop-encoded-array>
> +		Definition: u32 value representing worst case latency in
> +			    microseconds required to enter the idle state.
> +			    The exit-latency-us duration may be guaranteed
> +			    only after entry-latency-us has passed.
> +
> +	- exit-latency-us
> +		Usage: Required
> +		Value type: <prop-encoded-array>
> +		Definition: u32 value representing worst case latency
> +			    in microseconds required to exit the idle state.
> +
> +	- min-residency-us
> +		Usage: Required
> +		Value type: <prop-encoded-array>
> +		Definition: u32 value representing 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:
> +		Usage: Optional
> +		Value type: <prop-encoded-array>
> +		Definition: u32 value representing 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.
> +
> +===========================================
> +4 - Examples
> +===========================================
> +
> +Example 1 (ARM 64-bit, 16-cpu system):
> +
> +cpus {
> +	#size-cells = <0>;
> +	#address-cells = <2>;
> +
> +	idle-states {
> +		entry-method = "arm,psci";
> +
> +		CPU_RETENTION_0_0: cpu-retention-0-0 {
> +			compatible = "arm,idle-state";
> +			power-rank = <0>;
> +			logic-state-retained;
> +			cache-state-retained;
> +			entry-method-param = <0x0010000>;
> +			entry-latency-us = <20>;
> +			exit-latency-us = <40>;
> +			min-residency-us = <80>;
> +		};
> +
> +		CLUSTER_RETENTION_0: cluster-retention-0 {
> +			compatible = "arm,idle-state";
> +			power-rank = <2>;
> +			cache-state-retained;
> +			entry-method-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";
> +			power-rank = <1>;
> +			entry-method-param = <0x0010000>;
> +			entry-latency-us = <250>;
> +			exit-latency-us = <500>;
> +			min-residency-us = <950>;
> +		};
> +
> +		CLUSTER_SLEEP_0: cluster-sleep-0 {
> +			compatible = "arm,idle-state";
> +			power-rank = <3>;
> +			entry-method-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";
> +			power-rank = <0>;
> +			logic-state-retained;
> +			cache-state-retained;
> +			entry-method-param = <0x0010000>;
> +			entry-latency-us = <20>;
> +			exit-latency-us = <40>;
> +			min-residency-us = <90>;
> +		};
> +
> +		CLUSTER_RETENTION_1: cluster-retention-1 {
> +			compatible = "arm,idle-state";
> +			power-rank = <2>;
> +			cache-state-retained;
> +			entry-method-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";
> +			power-rank = <1>;
> +			entry-method-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";
> +			power-rank = <3>;
> +			entry-method-param = <0x1010000>;
> +			entry-latency-us = <500>;
> +			exit-latency-us = <1200>;
> +			min-residency-us = <3500>;
> +			wakeup-latency-us = <1300>;
> +		};
> +	};
> +
> +	CPU0: 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>;
> +	};
> +
> +	CPU1: 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>;
> +	};
> +
> +	CPU2: 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>;
> +	};
> +
> +	CPU3: 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>;
> +	};
> +
> +	CPU4: 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>;
> +	};
> +
> +	CPU5: 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>;
> +	};
> +
> +	CPU6: 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>;
> +	};
> +
> +	CPU7: 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>;
> +	};
> +
> +	CPU8: 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>;
> +	};
> +
> +	CPU9: 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>;
> +	};
> +
> +	CPU10: 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>;
> +	};
> +
> +	CPU11: 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>;
> +	};
> +
> +	CPU12: 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>;
> +	};
> +
> +	CPU13: 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>;
> +	};
> +
> +	CPU14: 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>;
> +	};
> +
> +	CPU15: 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>;
> +	};
> +};
> +
> +Example 2 (ARM 32-bit, 8-cpu system, two clusters):
> +
> +cpus {
> +	#size-cells = <0>;
> +	#address-cells = <1>;
> +
> +	idle-states {
> +		entry-method = "arm,psci";
> +
> +		CPU_SLEEP_0_0: cpu-sleep-0-0 {
> +			compatible = "arm,idle-state";
> +			power-rank = <0>;
> +			entry-method-param = <0x0010000>;
> +			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";
> +			power-rank = <2>;
> +			entry-method-param = <0x1010000>;
> +			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";
> +			power-rank = <1>;
> +			entry-method-param = <0x0010000>;
> +			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";
> +			power-rank = <3>;
> +			entry-method-param = <0x1010000>;
> +			entry-latency-us = <800>;
> +			exit-latency-us = <2000>;
> +			min-residency-us = <6500>;
> +			wakeup-latency-us = <2300>;
> +		};
> +	};
> +
> +	CPU0: cpu@0 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a15";
> +		reg = <0x0>;
> +		enable-method = "psci";
> +		cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>;
> +	};
> +
> +	CPU1: cpu@1 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a15";
> +		reg = <0x1>;
> +		enable-method = "psci";
> +		cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>;
> +	};
> +
> +	CPU2: cpu@2 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a15";
> +		reg = <0x2>;
> +		enable-method = "psci";
> +		cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>;
> +	};
> +
> +	CPU3: cpu@3 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a15";
> +		reg = <0x3>;
> +		enable-method = "psci";
> +		cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>;
> +	};
> +
> +	CPU4: cpu@100 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a7";
> +		reg = <0x100>;
> +		enable-method = "psci";
> +		cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>;
> +	};
> +
> +	CPU5: cpu@101 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a7";
> +		reg = <0x101>;
> +		enable-method = "psci";
> +		cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>;
> +	};
> +
> +	CPU6: cpu@102 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a7";
> +		reg = <0x102>;
> +		enable-method = "psci";
> +		cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>;
> +	};
> +
> +	CPU7: cpu@103 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a7";
> +		reg = <0x103>;
> +		enable-method = "psci";
> +		cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>;
> +	};
> +};
> +
> +===========================================
> +5 - References
> +===========================================
> +
> +[1] ARM Linux Kernel documentation - CPUs bindings
> +    Documentation/devicetree/bindings/arm/cpus.txt
> +
> +[2] ARM Linux Kernel documentation - PSCI bindings
> +    Documentation/devicetree/bindings/arm/psci.txt
> +
> +[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] ePAPR standard
> +    https://www.power.org/documentation/epapr-version-1-1/
> -- 
> 1.9.1
> 
> 

^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 1/8] Documentation: arm: define DT idle states bindings
@ 2014-06-25 15:56     ` Nicolas Pitre
  0 siblings, 0 replies; 70+ messages in thread
From: Nicolas Pitre @ 2014-06-25 15:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 25 Jun 2014, Lorenzo Pieralisi wrote:

> ARM based platforms implement a variety of power management schemes that
> allow processors to enter idle states at run-time.
> The parameters defining these idle states vary on a per-platform basis forcing
> the OS to hardcode the state parameters in platform specific static tables
> whose size grows as the number of platforms supported in the kernel increases
> and hampers device drivers standardization.
> 
> Therefore, this patch aims at standardizing idle state device tree bindings for
> ARM platforms. Bindings define idle state parameters inclusive of entry methods
> and state latencies, to allow operating systems to retrieve the configuration
> entries from the device tree and initialize the related power management
> drivers, paving the way for common code in the kernel to deal with idle
> states and removing the need for static data in current and previous kernel
> versions.
> 
> Reviewed-by: Sebastian Capella <sebcape@gmail.com>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>

Excellent.

Reviewed-by: Nicolas Pitre <nico@linaro.org>

> ---
>  Documentation/devicetree/bindings/arm/cpus.txt     |   8 +
>  .../devicetree/bindings/arm/idle-states.txt        | 733 +++++++++++++++++++++
>  2 files changed, 741 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/idle-states.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
> index 1fe72a0..a44d4fd 100644
> --- a/Documentation/devicetree/bindings/arm/cpus.txt
> +++ b/Documentation/devicetree/bindings/arm/cpus.txt
> @@ -215,6 +215,12 @@ nodes to be present and contain the properties described below.
>  		Value type: <phandle>
>  		Definition: Specifies the ACC[2] node associated with this CPU.
>  
> +	- cpu-idle-states
> +		Usage: Optional
> +		Value type: <prop-encoded-array>
> +		Definition:
> +			# List of phandles to idle state nodes supported
> +			  by this cpu [3].
>  
>  Example 1 (dual-cluster big.LITTLE system 32-bit):
>  
> @@ -411,3 +417,5 @@ cpus {
>  --
>  [1] arm/msm/qcom,saw2.txt
>  [2] arm/msm/qcom,kpss-acc.txt
> +[3] ARM Linux kernel documentation - idle states bindings
> +    Documentation/devicetree/bindings/arm/idle-states.txt
> diff --git a/Documentation/devicetree/bindings/arm/idle-states.txt b/Documentation/devicetree/bindings/arm/idle-states.txt
> new file mode 100644
> index 0000000..5efd198
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/idle-states.txt
> @@ -0,0 +1,733 @@
> +==========================================
> +ARM idle states binding description
> +==========================================
> +
> +==========================================
> +1 - Introduction
> +==========================================
> +
> +ARM 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.
> +
> +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 (eg 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.
> +
> +===========================================
> +2 - 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
> +(ie 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, eg:
> +
> +wakeup-delay = exit-latency + max(entry-latency - (now - entry-timestamp), 0)
> +
> +In other words, the scheduler can make its scheduling decision by selecting
> +(eg waking-up) the CPU with the shortest wake-up latency.
> +The wake-up latency 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, ie caches
> +state).
> +
> +An OS has to reliably probe the wakeup-latency since some devices can enforce
> +latency constraints 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 whilst 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 (ie 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 (ie 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.
> +
> +===========================================
> +3 - idle-states node
> +===========================================
> +
> +ARM 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.
> +
> +- idle-states node
> +
> +	Usage: Optional - 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.
> +
> +	Description: idle-states node is a container node, where its
> +		     subnodes describe the CPU idle states.
> +
> +	Node name must be "idle-states".
> +
> +	The idle-states node's parent node must be the cpus node.
> +
> +	The idle-states node's child nodes can be:
> +
> +	- one or more state nodes
> +
> +	Any other configuration is considered invalid.
> +
> +	An idle-states node defines the following properties:
> +
> +	- entry-method
> +		Usage: Required
> +		Value type: <stringlist>
> +		Definition: Describes the method by which a CPU enters the
> +			    idle states. This property is required and must be
> +			    one of:
> +
> +			    - "arm,psci"
> +			      ARM PSCI firmware interface [2].
> +
> +			    - "[vendor],[method]"
> +			      An implementation dependent string with
> +			      format "vendor,method", where vendor is a string
> +			      denoting the name of the manufacturer and
> +			      method is a string specifying the mechanism
> +			      used to enter the idle state.
> +
> +The nodes describing the idle states (state) can only be defined within the
> +idle-states node, any other configuration is considered invalid and therefore
> +must be ignored.
> +
> +===========================================
> +4 - state node
> +===========================================
> +
> +A state node represents an idle state description and must be defined as
> +follows:
> +
> +- state node
> +
> +	Description: must be child of the idle-states node
> +
> +	The state node name shall follow standard device tree naming
> +	rules ([5], 2.2.1 "Node names"), in particular state nodes which
> +	are siblings within a single common parent must be given a unique name.
> +
> +	The idle state entered by executing the wfi instruction (idle_standby
> +	SBSA,[3][4]) is considered standard on all ARM platforms and therefore
> +	must not be listed.
> +
> +	With the definitions provided above, the following list represents
> +	the valid properties for a state node:
> +
> +	- compatible
> +		Usage: Required
> +		Value type: <stringlist>
> +		Definition: Must be "arm,idle-state".
> +
> +	- logic-state-retained
> +		Usage: See definition
> +		Value type: <none>
> +		Definition: if present logic is retained on state entry,
> +			    otherwise it is lost.
> +
> +	- cache-state-retained
> +		Usage: See definition
> +		Value type: <none>
> +		Definition: if present cache memory is retained on state entry,
> +			    otherwise it is lost.
> +
> +	- timer-state-retained
> +		Usage: See definition
> +		Value type: <none>
> +		Definition: if present the timer control logic is retained on
> +                            state entry, otherwise it is lost.
> +
> +	- power-rank
> +		Usage: Required
> +		Value type: <u32>
> +		Definition: It represents the idle state power-rank.
> +			    An increasing value implies less power
> +			    consumption. It must be given a sequential
> +			    value = {0, 1, ....}, starting from 0.
> +			    Phandles in the cpu nodes [1] cpu-idle-states
> +			    array property are not allowed to point at idle
> +			    state nodes having the same power-rank value.
> +
> +	- entry-method-param
> +		Usage: See definition.
> +		Value type: <u32>
> +		Definition: Depends on the idle-states node entry-method
> +			    property value. Refer to the entry-method bindings
> +			    for this property value definition.
> +
> +	- entry-latency-us
> +		Usage: Required
> +		Value type: <prop-encoded-array>
> +		Definition: u32 value representing worst case latency in
> +			    microseconds required to enter the idle state.
> +			    The exit-latency-us duration may be guaranteed
> +			    only after entry-latency-us has passed.
> +
> +	- exit-latency-us
> +		Usage: Required
> +		Value type: <prop-encoded-array>
> +		Definition: u32 value representing worst case latency
> +			    in microseconds required to exit the idle state.
> +
> +	- min-residency-us
> +		Usage: Required
> +		Value type: <prop-encoded-array>
> +		Definition: u32 value representing 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:
> +		Usage: Optional
> +		Value type: <prop-encoded-array>
> +		Definition: u32 value representing 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.
> +
> +===========================================
> +4 - Examples
> +===========================================
> +
> +Example 1 (ARM 64-bit, 16-cpu system):
> +
> +cpus {
> +	#size-cells = <0>;
> +	#address-cells = <2>;
> +
> +	idle-states {
> +		entry-method = "arm,psci";
> +
> +		CPU_RETENTION_0_0: cpu-retention-0-0 {
> +			compatible = "arm,idle-state";
> +			power-rank = <0>;
> +			logic-state-retained;
> +			cache-state-retained;
> +			entry-method-param = <0x0010000>;
> +			entry-latency-us = <20>;
> +			exit-latency-us = <40>;
> +			min-residency-us = <80>;
> +		};
> +
> +		CLUSTER_RETENTION_0: cluster-retention-0 {
> +			compatible = "arm,idle-state";
> +			power-rank = <2>;
> +			cache-state-retained;
> +			entry-method-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";
> +			power-rank = <1>;
> +			entry-method-param = <0x0010000>;
> +			entry-latency-us = <250>;
> +			exit-latency-us = <500>;
> +			min-residency-us = <950>;
> +		};
> +
> +		CLUSTER_SLEEP_0: cluster-sleep-0 {
> +			compatible = "arm,idle-state";
> +			power-rank = <3>;
> +			entry-method-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";
> +			power-rank = <0>;
> +			logic-state-retained;
> +			cache-state-retained;
> +			entry-method-param = <0x0010000>;
> +			entry-latency-us = <20>;
> +			exit-latency-us = <40>;
> +			min-residency-us = <90>;
> +		};
> +
> +		CLUSTER_RETENTION_1: cluster-retention-1 {
> +			compatible = "arm,idle-state";
> +			power-rank = <2>;
> +			cache-state-retained;
> +			entry-method-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";
> +			power-rank = <1>;
> +			entry-method-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";
> +			power-rank = <3>;
> +			entry-method-param = <0x1010000>;
> +			entry-latency-us = <500>;
> +			exit-latency-us = <1200>;
> +			min-residency-us = <3500>;
> +			wakeup-latency-us = <1300>;
> +		};
> +	};
> +
> +	CPU0: cpu at 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>;
> +	};
> +
> +	CPU1: cpu at 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>;
> +	};
> +
> +	CPU2: cpu at 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>;
> +	};
> +
> +	CPU3: cpu at 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>;
> +	};
> +
> +	CPU4: cpu at 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>;
> +	};
> +
> +	CPU5: cpu at 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>;
> +	};
> +
> +	CPU6: cpu at 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>;
> +	};
> +
> +	CPU7: cpu at 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>;
> +	};
> +
> +	CPU8: cpu at 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>;
> +	};
> +
> +	CPU9: cpu at 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>;
> +	};
> +
> +	CPU10: cpu at 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>;
> +	};
> +
> +	CPU11: cpu at 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>;
> +	};
> +
> +	CPU12: cpu at 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>;
> +	};
> +
> +	CPU13: cpu at 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>;
> +	};
> +
> +	CPU14: cpu at 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>;
> +	};
> +
> +	CPU15: cpu at 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>;
> +	};
> +};
> +
> +Example 2 (ARM 32-bit, 8-cpu system, two clusters):
> +
> +cpus {
> +	#size-cells = <0>;
> +	#address-cells = <1>;
> +
> +	idle-states {
> +		entry-method = "arm,psci";
> +
> +		CPU_SLEEP_0_0: cpu-sleep-0-0 {
> +			compatible = "arm,idle-state";
> +			power-rank = <0>;
> +			entry-method-param = <0x0010000>;
> +			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";
> +			power-rank = <2>;
> +			entry-method-param = <0x1010000>;
> +			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";
> +			power-rank = <1>;
> +			entry-method-param = <0x0010000>;
> +			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";
> +			power-rank = <3>;
> +			entry-method-param = <0x1010000>;
> +			entry-latency-us = <800>;
> +			exit-latency-us = <2000>;
> +			min-residency-us = <6500>;
> +			wakeup-latency-us = <2300>;
> +		};
> +	};
> +
> +	CPU0: cpu at 0 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a15";
> +		reg = <0x0>;
> +		enable-method = "psci";
> +		cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>;
> +	};
> +
> +	CPU1: cpu at 1 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a15";
> +		reg = <0x1>;
> +		enable-method = "psci";
> +		cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>;
> +	};
> +
> +	CPU2: cpu at 2 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a15";
> +		reg = <0x2>;
> +		enable-method = "psci";
> +		cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>;
> +	};
> +
> +	CPU3: cpu at 3 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a15";
> +		reg = <0x3>;
> +		enable-method = "psci";
> +		cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>;
> +	};
> +
> +	CPU4: cpu at 100 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a7";
> +		reg = <0x100>;
> +		enable-method = "psci";
> +		cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>;
> +	};
> +
> +	CPU5: cpu at 101 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a7";
> +		reg = <0x101>;
> +		enable-method = "psci";
> +		cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>;
> +	};
> +
> +	CPU6: cpu at 102 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a7";
> +		reg = <0x102>;
> +		enable-method = "psci";
> +		cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>;
> +	};
> +
> +	CPU7: cpu at 103 {
> +		device_type = "cpu";
> +		compatible = "arm,cortex-a7";
> +		reg = <0x103>;
> +		enable-method = "psci";
> +		cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>;
> +	};
> +};
> +
> +===========================================
> +5 - References
> +===========================================
> +
> +[1] ARM Linux Kernel documentation - CPUs bindings
> +    Documentation/devicetree/bindings/arm/cpus.txt
> +
> +[2] ARM Linux Kernel documentation - PSCI bindings
> +    Documentation/devicetree/bindings/arm/psci.txt
> +
> +[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] ePAPR standard
> +    https://www.power.org/documentation/epapr-version-1-1/
> -- 
> 1.9.1
> 
> 

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 3/8] drivers: cpuidle: implement DT based idle states infrastructure
  2014-06-25 14:10   ` Lorenzo Pieralisi
@ 2014-06-25 15:59     ` Mark Rutland
  -1 siblings, 0 replies; 70+ messages in thread
From: Mark Rutland @ 2014-06-25 15:59 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: linux-arm-kernel, linux-pm, devicetree, Sudeep Holla,
	Catalin Marinas, Charles Garcia-Tobin, Nicolas Pitre,
	Rob Herring, grant.likely, Peter De Schrijver, Santosh Shilimkar,
	Daniel Lezcano, Amit Kucheria, Vincent Guittot, Antti Miettinen,
	Stephen Boyd, Kevin Hilman, Sebastian Capella, Tomasz Figa,
	Mark Brown

On Wed, Jun 25, 2014 at 03:10:16PM +0100, Lorenzo Pieralisi wrote:
> On most common ARM systems, the low-power states a CPU can be put into are
> not discoverable in HW and require device tree bindings to describe
> power down suspend operations and idle states parameters.
> 
> In order to enable DT based idle states and configure idle drivers, this
> patch implements the bulk infrastructure required to parse the device tree
> idle states bindings and initialize the corresponding CPUidle driver states
> data.
> 
> Code that initializes idle states checks the CPU idle driver cpumask so
> that multiple CPU idle drivers can be initialized through it in the
> kernel. The CPU idle driver cpumask defines which idle states should be
> considered valid for the driver, ie idle states that are valid on a set
> of cpus the idle driver manages.
> 
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> ---
>  drivers/cpuidle/Kconfig          |   8 ++
>  drivers/cpuidle/Makefile         |   1 +
>  drivers/cpuidle/dt_idle_states.c | 283 +++++++++++++++++++++++++++++++++++++++
>  drivers/cpuidle/dt_idle_states.h |   8 ++
>  4 files changed, 300 insertions(+)
>  create mode 100644 drivers/cpuidle/dt_idle_states.c
>  create mode 100644 drivers/cpuidle/dt_idle_states.h
> 
> diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
> index 1b96fb9..414e7a96 100644
> --- a/drivers/cpuidle/Kconfig
> +++ b/drivers/cpuidle/Kconfig
> @@ -30,6 +30,14 @@ config CPU_IDLE_GOV_MENU
>  	bool "Menu governor (for tickless system)"
>  	default y
>  
> +config DT_IDLE_STATES
> +        bool "Idle states DT support"
> +	depends on ARM || ARM64
> +	help
> +	 Allows the CPU idle framework to initialize CPU idle drivers
> +	 state data by using DT provided nodes compliant with idle states
> +	 device tree bindings.
> +
>  menu "ARM CPU Idle Drivers"
>  depends on ARM
>  source "drivers/cpuidle/Kconfig.arm"
> diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
> index d8bb1ff..b27a062 100644
> --- a/drivers/cpuidle/Makefile
> +++ b/drivers/cpuidle/Makefile
> @@ -4,6 +4,7 @@
>  
>  obj-y += cpuidle.o driver.o governor.o sysfs.o governors/
>  obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
> +obj-$(CONFIG_DT_IDLE_STATES)		  += dt_idle_states.o
>  
>  ##################################################################################
>  # ARM SoC drivers
> diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c
> new file mode 100644
> index 0000000..5c16001c
> --- /dev/null
> +++ b/drivers/cpuidle/dt_idle_states.c
> @@ -0,0 +1,283 @@
> +/*
> + * DT idle states parsing code.
> + *
> + * Copyright (C) 2014 ARM Ltd.
> + * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#define pr_fmt(fmt) "DT idle-states: " fmt
> +
> +#include <linux/cpuidle.h>
> +#include <linux/cpumask.h>
> +#include <linux/errno.h>
> +#include <linux/kernel.h>
> +#include <linux/list.h>
> +#include <linux/list_sort.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/slab.h>
> +
> +#include "dt_idle_states.h"
> +
> +struct state_elem {
> +	struct list_head list;
> +	struct device_node *node;
> +	u32 val;
> +};

Ah. So the fixed-size entry parameter requirement is because this code
is in charge of allocating and freeing these structs?

> +
> +static struct list_head head __initdata = LIST_HEAD_INIT(head);
> +
> +static bool __init state_cpu_valid(struct device_node *state_node,
> +				   struct device_node *cpu_node)
> +{
> +	int i = 0;
> +	struct device_node *cpu_state;
> +
> +	while ((cpu_state = of_parse_phandle(cpu_node,
> +					     "cpu-idle-states", i++))) {
> +		if (cpu_state && state_node == cpu_state) {

You can drop the cpu_state NULL check, it's implicit in the while loop.

> +			of_node_put(cpu_state);
> +			return true;
> +		}
> +		of_node_put(cpu_state);
> +	}
> +	return false;
> +}

Is it possible to use a bool ret variable to avoid the two of_node_put
cases? Or does that end up making this larger?

> +static bool __init state_cpus_valid(const cpumask_t *cpus,
> +				    struct device_node *state_node)
> +{
> +	int cpu;
> +	struct device_node *cpu_node;
> +
> +	/*
> +	 * Check if state is valid on driver cpumask cpus
> +	 */
> +	for_each_cpu(cpu, cpus) {
> +		cpu_node = of_get_cpu_node(cpu, NULL);
> +
> +		if (!cpu_node) {
> +			pr_err("Missing device node for CPU %d\n", cpu);
> +			return false;
> +		}
> +
> +		if (!state_cpu_valid(state_node, cpu_node))
> +			return false;
> +	}
> +
> +	return true;
> +}

Doesn't this leave all the cpu node refcounts incremented? (it's painful
to get device node refcounting right, I know).

I think you can use the similarly named of_cpu_device_node_get to find
the CPU node. It uses the pointer stored in cpu->dev.of_node, so it
doesn't have to walk the tree to find the CPU node. It also doesn't
increment the refcount.

Unless this is too early for that?

> +static void __init init_state_node(struct cpuidle_driver *drv,
> +				   struct device_node *state_node,
> +				   int *cnt)
> +{
> +	struct cpuidle_state *idle_state;
> +
> +	pr_debug(" * %s...\n", state_node->full_name);
> +
> +	idle_state = &drv->states[*cnt];
> +
> +	if (of_property_read_u32(state_node, "wakeup-latency-us",
> +				 &idle_state->exit_latency)) {

I'm not a fan of this construction, as the obvious reading is that we
take the branch if we succeeded (which obviously isn't true as
of_property_read_* return error codes). 

Could we change it to something like:

	err = of_property_read_u32(state_node, "wakeup-latency-us",
				   &idle_state->exit_latency);
	if (err) {

> +		u32 entry_latency, exit_latency;
> +
> +		if (of_property_read_u32(state_node, "entry-latency-us",
> +					 &entry_latency)) {
> +			pr_debug(" * %s missing entry-latency-us property\n",
> +				 state_node->full_name);
> +			return;
> +		}

Returning without error code? Do the fields have sane default values?

Or is this safe because we didn't increment cnt?

> +
> +		if (of_property_read_u32(state_node, "exit-latency-us",
> +					 &exit_latency)) {
> +			pr_debug(" * %s missing exit-latency-us property\n",
> +				 state_node->full_name);
> +			return;
> +		}
> +		/*
> +		 * If wakeup-latency-us is missing, default to entry+exit
> +		 * latencies as defined in idle states bindings
> +		 */
> +		idle_state->exit_latency = entry_latency + exit_latency;
> +	}
> +
> +	if (of_property_read_u32(state_node, "min-residency-us",
> +				 &idle_state->target_residency)) {
> +		pr_debug(" * %s missing min-residency-us property\n",
> +			     state_node->full_name);
> +		return;
> +	}
> +
> +	idle_state->flags = CPUIDLE_FLAG_TIME_VALID;
> +	if (!of_property_read_bool(state_node, "timer-state-retained"))
> +		idle_state->flags |= CPUIDLE_FLAG_TIMER_STOP;
> + 	strncpy(idle_state->name, state_node->name, CPUIDLE_NAME_LEN);
> +	strncpy(idle_state->desc, state_node->name, CPUIDLE_NAME_LEN);

Does the name make sense as a desc? Is a desc necessary?

CPUIDLE_DESC_LEN seems to exist, and is double CPUIDLE_NAME_LEN.

> +static void __init add_idle_states(struct cpuidle_driver *drv,
> +				   struct device_node *idle_states)
> +{
> +	struct device_node *state_node;
> +
> +	for_each_child_of_node(idle_states, state_node) {
> +		if ((!of_device_is_compatible(state_node, "arm,idle-state"))) {

Holy brackets batman! I think we can drop the outer ones given there's
no assignment we want to supress warnings for.

> +			pr_warn(" * %s: children of /cpus/idle-states must be \"arm,idle-state\" compatible\n",
> +				     state_node->full_name);

Presumably the entire reason for having the compatible string is for
future extensibility.

It would probably be better to have something like:

	pr_warn("Node %s has unrecognised/missing compatible string\n",
		state_node->full_name);

> +			continue;
> +		}
> +		/*
> +		 * If memory allocation fails, better bail out.
> +		 * Initialized nodes are freed at initialization
> +		 * completion in of_init_idle_driver().
> +		 */
> +		if ((add_state_node(drv->cpumask, state_node) == -ENOMEM))
> +			break;

Can we not return? Or is the list sort important in the error case too?

> +	}
> +	/*
> +	 * Sort the states list before initializing the CPUidle driver
> +	 * states array.
> +	 */
> +	list_sort(NULL, &head, state_cmp);
> +}
> +
> +/**
> + * dt_init_idle_driver() - Parse the DT idle states and initialize the
> + *			   idle driver states array
> + *
> + * @drv:	  Pointer to CPU idle driver to be initialized
> + * @state_nodes:  Array of struct device_nodes to be initialized if
> + *		  init_nodes == true. Must be sized CPUIDLE_STATE_MAX
> + * @start_idx:    First idle state index to be initialized
> + * @init_nodes:   Boolean to request device nodes initialization
> + *
> + * On success the states array in the cpuidle driver contains
> + * initialized entries in the states array, starting from index start_idx.
> + * If init_nodes == true, on success the state_nodes array is initialized
> + * with idle state DT node pointers, starting from index start_idx,
> + * in a 1:1 relation with the idle driver states array.
> + *
> + * Return:
> + *	0 on success
> + *	<0 on failure
> + */
> +int __init dt_init_idle_driver(struct cpuidle_driver *drv,
> +			       struct device_node *state_nodes[],
> +			       unsigned int start_idx, bool init_nodes)
> +{
> +	struct device_node *idle_states_node;
> +	int ret;
> +
> +	if (start_idx >= CPUIDLE_STATE_MAX) {
> +		pr_warn("State index exceeds static CPU idle driver states array size\n");
> +		return -EINVAL;
> +	}
> +
> +	if (WARN(init_nodes && !state_nodes,
> +		"Requested nodes stashing in an invalid nodes container\n"))
> +		return -EINVAL;

That warning message is somewhat confusing, and I'm not sure I
follow the logic.

Thanks,
Mark

^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 3/8] drivers: cpuidle: implement DT based idle states infrastructure
@ 2014-06-25 15:59     ` Mark Rutland
  0 siblings, 0 replies; 70+ messages in thread
From: Mark Rutland @ 2014-06-25 15:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 25, 2014 at 03:10:16PM +0100, Lorenzo Pieralisi wrote:
> On most common ARM systems, the low-power states a CPU can be put into are
> not discoverable in HW and require device tree bindings to describe
> power down suspend operations and idle states parameters.
> 
> In order to enable DT based idle states and configure idle drivers, this
> patch implements the bulk infrastructure required to parse the device tree
> idle states bindings and initialize the corresponding CPUidle driver states
> data.
> 
> Code that initializes idle states checks the CPU idle driver cpumask so
> that multiple CPU idle drivers can be initialized through it in the
> kernel. The CPU idle driver cpumask defines which idle states should be
> considered valid for the driver, ie idle states that are valid on a set
> of cpus the idle driver manages.
> 
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> ---
>  drivers/cpuidle/Kconfig          |   8 ++
>  drivers/cpuidle/Makefile         |   1 +
>  drivers/cpuidle/dt_idle_states.c | 283 +++++++++++++++++++++++++++++++++++++++
>  drivers/cpuidle/dt_idle_states.h |   8 ++
>  4 files changed, 300 insertions(+)
>  create mode 100644 drivers/cpuidle/dt_idle_states.c
>  create mode 100644 drivers/cpuidle/dt_idle_states.h
> 
> diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
> index 1b96fb9..414e7a96 100644
> --- a/drivers/cpuidle/Kconfig
> +++ b/drivers/cpuidle/Kconfig
> @@ -30,6 +30,14 @@ config CPU_IDLE_GOV_MENU
>  	bool "Menu governor (for tickless system)"
>  	default y
>  
> +config DT_IDLE_STATES
> +        bool "Idle states DT support"
> +	depends on ARM || ARM64
> +	help
> +	 Allows the CPU idle framework to initialize CPU idle drivers
> +	 state data by using DT provided nodes compliant with idle states
> +	 device tree bindings.
> +
>  menu "ARM CPU Idle Drivers"
>  depends on ARM
>  source "drivers/cpuidle/Kconfig.arm"
> diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
> index d8bb1ff..b27a062 100644
> --- a/drivers/cpuidle/Makefile
> +++ b/drivers/cpuidle/Makefile
> @@ -4,6 +4,7 @@
>  
>  obj-y += cpuidle.o driver.o governor.o sysfs.o governors/
>  obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
> +obj-$(CONFIG_DT_IDLE_STATES)		  += dt_idle_states.o
>  
>  ##################################################################################
>  # ARM SoC drivers
> diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c
> new file mode 100644
> index 0000000..5c16001c
> --- /dev/null
> +++ b/drivers/cpuidle/dt_idle_states.c
> @@ -0,0 +1,283 @@
> +/*
> + * DT idle states parsing code.
> + *
> + * Copyright (C) 2014 ARM Ltd.
> + * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#define pr_fmt(fmt) "DT idle-states: " fmt
> +
> +#include <linux/cpuidle.h>
> +#include <linux/cpumask.h>
> +#include <linux/errno.h>
> +#include <linux/kernel.h>
> +#include <linux/list.h>
> +#include <linux/list_sort.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/slab.h>
> +
> +#include "dt_idle_states.h"
> +
> +struct state_elem {
> +	struct list_head list;
> +	struct device_node *node;
> +	u32 val;
> +};

Ah. So the fixed-size entry parameter requirement is because this code
is in charge of allocating and freeing these structs?

> +
> +static struct list_head head __initdata = LIST_HEAD_INIT(head);
> +
> +static bool __init state_cpu_valid(struct device_node *state_node,
> +				   struct device_node *cpu_node)
> +{
> +	int i = 0;
> +	struct device_node *cpu_state;
> +
> +	while ((cpu_state = of_parse_phandle(cpu_node,
> +					     "cpu-idle-states", i++))) {
> +		if (cpu_state && state_node == cpu_state) {

You can drop the cpu_state NULL check, it's implicit in the while loop.

> +			of_node_put(cpu_state);
> +			return true;
> +		}
> +		of_node_put(cpu_state);
> +	}
> +	return false;
> +}

Is it possible to use a bool ret variable to avoid the two of_node_put
cases? Or does that end up making this larger?

> +static bool __init state_cpus_valid(const cpumask_t *cpus,
> +				    struct device_node *state_node)
> +{
> +	int cpu;
> +	struct device_node *cpu_node;
> +
> +	/*
> +	 * Check if state is valid on driver cpumask cpus
> +	 */
> +	for_each_cpu(cpu, cpus) {
> +		cpu_node = of_get_cpu_node(cpu, NULL);
> +
> +		if (!cpu_node) {
> +			pr_err("Missing device node for CPU %d\n", cpu);
> +			return false;
> +		}
> +
> +		if (!state_cpu_valid(state_node, cpu_node))
> +			return false;
> +	}
> +
> +	return true;
> +}

Doesn't this leave all the cpu node refcounts incremented? (it's painful
to get device node refcounting right, I know).

I think you can use the similarly named of_cpu_device_node_get to find
the CPU node. It uses the pointer stored in cpu->dev.of_node, so it
doesn't have to walk the tree to find the CPU node. It also doesn't
increment the refcount.

Unless this is too early for that?

> +static void __init init_state_node(struct cpuidle_driver *drv,
> +				   struct device_node *state_node,
> +				   int *cnt)
> +{
> +	struct cpuidle_state *idle_state;
> +
> +	pr_debug(" * %s...\n", state_node->full_name);
> +
> +	idle_state = &drv->states[*cnt];
> +
> +	if (of_property_read_u32(state_node, "wakeup-latency-us",
> +				 &idle_state->exit_latency)) {

I'm not a fan of this construction, as the obvious reading is that we
take the branch if we succeeded (which obviously isn't true as
of_property_read_* return error codes). 

Could we change it to something like:

	err = of_property_read_u32(state_node, "wakeup-latency-us",
				   &idle_state->exit_latency);
	if (err) {

> +		u32 entry_latency, exit_latency;
> +
> +		if (of_property_read_u32(state_node, "entry-latency-us",
> +					 &entry_latency)) {
> +			pr_debug(" * %s missing entry-latency-us property\n",
> +				 state_node->full_name);
> +			return;
> +		}

Returning without error code? Do the fields have sane default values?

Or is this safe because we didn't increment cnt?

> +
> +		if (of_property_read_u32(state_node, "exit-latency-us",
> +					 &exit_latency)) {
> +			pr_debug(" * %s missing exit-latency-us property\n",
> +				 state_node->full_name);
> +			return;
> +		}
> +		/*
> +		 * If wakeup-latency-us is missing, default to entry+exit
> +		 * latencies as defined in idle states bindings
> +		 */
> +		idle_state->exit_latency = entry_latency + exit_latency;
> +	}
> +
> +	if (of_property_read_u32(state_node, "min-residency-us",
> +				 &idle_state->target_residency)) {
> +		pr_debug(" * %s missing min-residency-us property\n",
> +			     state_node->full_name);
> +		return;
> +	}
> +
> +	idle_state->flags = CPUIDLE_FLAG_TIME_VALID;
> +	if (!of_property_read_bool(state_node, "timer-state-retained"))
> +		idle_state->flags |= CPUIDLE_FLAG_TIMER_STOP;
> + 	strncpy(idle_state->name, state_node->name, CPUIDLE_NAME_LEN);
> +	strncpy(idle_state->desc, state_node->name, CPUIDLE_NAME_LEN);

Does the name make sense as a desc? Is a desc necessary?

CPUIDLE_DESC_LEN seems to exist, and is double CPUIDLE_NAME_LEN.

> +static void __init add_idle_states(struct cpuidle_driver *drv,
> +				   struct device_node *idle_states)
> +{
> +	struct device_node *state_node;
> +
> +	for_each_child_of_node(idle_states, state_node) {
> +		if ((!of_device_is_compatible(state_node, "arm,idle-state"))) {

Holy brackets batman! I think we can drop the outer ones given there's
no assignment we want to supress warnings for.

> +			pr_warn(" * %s: children of /cpus/idle-states must be \"arm,idle-state\" compatible\n",
> +				     state_node->full_name);

Presumably the entire reason for having the compatible string is for
future extensibility.

It would probably be better to have something like:

	pr_warn("Node %s has unrecognised/missing compatible string\n",
		state_node->full_name);

> +			continue;
> +		}
> +		/*
> +		 * If memory allocation fails, better bail out.
> +		 * Initialized nodes are freed at initialization
> +		 * completion in of_init_idle_driver().
> +		 */
> +		if ((add_state_node(drv->cpumask, state_node) == -ENOMEM))
> +			break;

Can we not return? Or is the list sort important in the error case too?

> +	}
> +	/*
> +	 * Sort the states list before initializing the CPUidle driver
> +	 * states array.
> +	 */
> +	list_sort(NULL, &head, state_cmp);
> +}
> +
> +/**
> + * dt_init_idle_driver() - Parse the DT idle states and initialize the
> + *			   idle driver states array
> + *
> + * @drv:	  Pointer to CPU idle driver to be initialized
> + * @state_nodes:  Array of struct device_nodes to be initialized if
> + *		  init_nodes == true. Must be sized CPUIDLE_STATE_MAX
> + * @start_idx:    First idle state index to be initialized
> + * @init_nodes:   Boolean to request device nodes initialization
> + *
> + * On success the states array in the cpuidle driver contains
> + * initialized entries in the states array, starting from index start_idx.
> + * If init_nodes == true, on success the state_nodes array is initialized
> + * with idle state DT node pointers, starting from index start_idx,
> + * in a 1:1 relation with the idle driver states array.
> + *
> + * Return:
> + *	0 on success
> + *	<0 on failure
> + */
> +int __init dt_init_idle_driver(struct cpuidle_driver *drv,
> +			       struct device_node *state_nodes[],
> +			       unsigned int start_idx, bool init_nodes)
> +{
> +	struct device_node *idle_states_node;
> +	int ret;
> +
> +	if (start_idx >= CPUIDLE_STATE_MAX) {
> +		pr_warn("State index exceeds static CPU idle driver states array size\n");
> +		return -EINVAL;
> +	}
> +
> +	if (WARN(init_nodes && !state_nodes,
> +		"Requested nodes stashing in an invalid nodes container\n"))
> +		return -EINVAL;

That warning message is somewhat confusing, and I'm not sure I
follow the logic.

Thanks,
Mark

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 4/8] arm64: add PSCI CPU_SUSPEND based cpu_suspend support
  2014-06-25 14:10     ` Lorenzo Pieralisi
@ 2014-06-25 16:09       ` Mark Rutland
  -1 siblings, 0 replies; 70+ messages in thread
From: Mark Rutland @ 2014-06-25 16:09 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: linux-arm-kernel, linux-pm, devicetree, Sudeep Holla,
	Catalin Marinas, Charles Garcia-Tobin, Nicolas Pitre,
	Rob Herring, grant.likely, Peter De Schrijver, Santosh Shilimkar,
	Daniel Lezcano, Amit Kucheria, Vincent Guittot, Antti Miettinen,
	Stephen Boyd, Kevin Hilman, Sebastian Capella, Tomasz Figa,
	Mark Brown

On Wed, Jun 25, 2014 at 03:10:17PM +0100, Lorenzo Pieralisi wrote:
> This patch implements the cpu_suspend cpu operations method through
> the PSCI CPU_SUSPEND API. The PSCI implementation translates the idle state
> index passed by the cpu_suspend core call into a valid PSCI state according to
> the PSCI states initialized at boot by the PSCI suspend backend.
> 
> Entry point is set to cpu_resume physical address, that represents the
> default kernel execution address following a CPU reset.
> 
> Idle state indices missing a DT node description are initialized to power
> state standby WFI so that if called by the idle driver they provide the
> default behaviour.
> 
> Reviewed-by: Sebastian Capella <sebcape@gmail.com>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> ---
>  arch/arm64/include/asm/psci.h |   4 ++
>  arch/arm64/kernel/psci.c      | 103 ++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 107 insertions(+)

[...]

> +static void psci_power_state_unpack(u32 power_state,
> +				    struct psci_power_state *state)
> +{
> +	state->id = (power_state & PSCI_0_2_POWER_STATE_ID_MASK) >>
> +			PSCI_0_2_POWER_STATE_ID_SHIFT;
> +	state->type = (power_state & PSCI_0_2_POWER_STATE_TYPE_MASK) >>
> +			PSCI_0_2_POWER_STATE_TYPE_SHIFT;
> +	state->affinity_level =
> +			(power_state & PSCI_0_2_POWER_STATE_AFFL_MASK) >>
> +			PSCI_0_2_POWER_STATE_AFFL_SHIFT;
> +}

Is this valid for PSCI versions prior to 0.2?

>  /*
>   * The following two functions are invoked via the invoke_psci_fn pointer
>   * and will not be inlined, allowing us to piggyback on the AAPCS.
> @@ -199,6 +216,77 @@ static int psci_migrate_info_type(void)
>  	return err;
>  }
>  
> +int __init psci_dt_register_idle_states(struct cpuidle_driver *drv,
> +					struct device_node *state_nodes[])
> +{
> +	int cpu, i;

Perhaps unsigned int? You print i with %u below.

> +	for (i = 0; i < drv->state_count; i++) {
> +		u32 psci_power_state;
> +
> +		if (!state_nodes[i]) {
> +			/*
> +			 * An index with a missing node pointer falls back to
> +			 * simple STANDBYWFI
> +			 */
> +			psci_states[i].type = PSCI_POWER_STATE_TYPE_STANDBY;
> +			continue;
> +		}

Does this make sense? Are there any limitations on which state nodes
could be missing?

> +
> +		if (of_property_read_u32(state_nodes[i], "entry-method-param",
> +					 &psci_power_state)) {
> +			pr_warn(" * %s missing entry-method-param property\n",
> +				state_nodes[i]->full_name);
> +			/*
> +			 * If entry-method-param property is missing, fall
> +			 * back to STANDBYWFI state
> +			 */
> +			psci_states[i].type = PSCI_POWER_STATE_TYPE_STANDBY;
> +			continue;

Surely we want to throw away these states instead?

Otherwise we can get into a mess like:

psci_states[0] => low power state
psci_states[1] => lower power state
psci_states[2] => WFI / not low power
psci_states[3] => lowest power state

Where power usage and latency would jump around rather than follow
monotonic patterns.

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 4/8] arm64: add PSCI CPU_SUSPEND based cpu_suspend support
@ 2014-06-25 16:09       ` Mark Rutland
  0 siblings, 0 replies; 70+ messages in thread
From: Mark Rutland @ 2014-06-25 16:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 25, 2014 at 03:10:17PM +0100, Lorenzo Pieralisi wrote:
> This patch implements the cpu_suspend cpu operations method through
> the PSCI CPU_SUSPEND API. The PSCI implementation translates the idle state
> index passed by the cpu_suspend core call into a valid PSCI state according to
> the PSCI states initialized at boot by the PSCI suspend backend.
> 
> Entry point is set to cpu_resume physical address, that represents the
> default kernel execution address following a CPU reset.
> 
> Idle state indices missing a DT node description are initialized to power
> state standby WFI so that if called by the idle driver they provide the
> default behaviour.
> 
> Reviewed-by: Sebastian Capella <sebcape@gmail.com>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> ---
>  arch/arm64/include/asm/psci.h |   4 ++
>  arch/arm64/kernel/psci.c      | 103 ++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 107 insertions(+)

[...]

> +static void psci_power_state_unpack(u32 power_state,
> +				    struct psci_power_state *state)
> +{
> +	state->id = (power_state & PSCI_0_2_POWER_STATE_ID_MASK) >>
> +			PSCI_0_2_POWER_STATE_ID_SHIFT;
> +	state->type = (power_state & PSCI_0_2_POWER_STATE_TYPE_MASK) >>
> +			PSCI_0_2_POWER_STATE_TYPE_SHIFT;
> +	state->affinity_level =
> +			(power_state & PSCI_0_2_POWER_STATE_AFFL_MASK) >>
> +			PSCI_0_2_POWER_STATE_AFFL_SHIFT;
> +}

Is this valid for PSCI versions prior to 0.2?

>  /*
>   * The following two functions are invoked via the invoke_psci_fn pointer
>   * and will not be inlined, allowing us to piggyback on the AAPCS.
> @@ -199,6 +216,77 @@ static int psci_migrate_info_type(void)
>  	return err;
>  }
>  
> +int __init psci_dt_register_idle_states(struct cpuidle_driver *drv,
> +					struct device_node *state_nodes[])
> +{
> +	int cpu, i;

Perhaps unsigned int? You print i with %u below.

> +	for (i = 0; i < drv->state_count; i++) {
> +		u32 psci_power_state;
> +
> +		if (!state_nodes[i]) {
> +			/*
> +			 * An index with a missing node pointer falls back to
> +			 * simple STANDBYWFI
> +			 */
> +			psci_states[i].type = PSCI_POWER_STATE_TYPE_STANDBY;
> +			continue;
> +		}

Does this make sense? Are there any limitations on which state nodes
could be missing?

> +
> +		if (of_property_read_u32(state_nodes[i], "entry-method-param",
> +					 &psci_power_state)) {
> +			pr_warn(" * %s missing entry-method-param property\n",
> +				state_nodes[i]->full_name);
> +			/*
> +			 * If entry-method-param property is missing, fall
> +			 * back to STANDBYWFI state
> +			 */
> +			psci_states[i].type = PSCI_POWER_STATE_TYPE_STANDBY;
> +			continue;

Surely we want to throw away these states instead?

Otherwise we can get into a mess like:

psci_states[0] => low power state
psci_states[1] => lower power state
psci_states[2] => WFI / not low power
psci_states[3] => lowest power state

Where power usage and latency would jump around rather than follow
monotonic patterns.

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 6/8] drivers: cpuidle: initialize big.LITTLE driver through DT
  2014-06-25 15:06     ` Mark Rutland
@ 2014-06-25 16:44       ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 16:44 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Chander Kashyap, Sudeep Holla,
	Catalin Marinas, Charles Garcia-Tobin, Nicolas Pitre,
	Rob Herring, grant.likely-QSEj5FYQhm4dnm+yROfE0A,
	Peter De Schrijver, Santosh Shilimkar, Daniel Lezcano,
	Amit Kucheria, Vincent Guittot, Antti Miettinen, Stephen Boyd,
	Kevin Hilman, Sebastian Capella

On Wed, Jun 25, 2014 at 04:06:23PM +0100, Mark Rutland wrote:
> On Wed, Jun 25, 2014 at 03:10:19PM +0100, Lorenzo Pieralisi wrote:
> > With the introduction of DT based idle states, CPUidle drivers for ARM
> > can now initialize idle states data through properties in the device tree.
> > 
> > This patch adds code to the big.LITTLE CPUidle driver to dynamically
> > initialize idle states data through the updated device tree source file.
> > 
> > Cc: Chander Kashyap <chander.kashyap-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
> > ---
> >  Documentation/devicetree/bindings/arm/vexpress.txt | 25 +++++++++++++
> >  arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts         | 25 +++++++++++++
> >  drivers/cpuidle/Kconfig.arm                        |  1 +
> >  drivers/cpuidle/cpuidle-big_little.c               | 43 +++++++++++-----------
> >  4 files changed, 73 insertions(+), 21 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/arm/vexpress.txt b/Documentation/devicetree/bindings/arm/vexpress.txt
> > index 39844cd..7f52ac8 100644
> > --- a/Documentation/devicetree/bindings/arm/vexpress.txt
> > +++ b/Documentation/devicetree/bindings/arm/vexpress.txt
> > @@ -67,6 +67,28 @@ with device_type = "cpu" property for every available core, eg.:
> >  		};
> >  	};
> >  
> > +idle-states node
> > +----------------
> > +
> > +On Versatile Express platforms with power management capabilities, the device
> > +tree source file must contain the idle-states node[1]. As defined in [1] the
> > +idle-states node must contain an entry-method property that for Versatile
> > +Express platforms can be one of:
> > +
> > +	- "arm,vexpress-v2p-ca15_a7"
> 
> ... and what does this mean? It's the name we've assigned the platform
> in the Linux DT bindings, but this binding document tells me nothing
> about how this method works.

Ok, I should have omitted it, I added it to make it compliant with
current DT bindings where entry-method for idle-states is required and I
have just added TC2 compatible string to get code out for review.

I should have made the entry-method optional for arm32 and get rid of
this useless binding and entry-method string.

Thanks,
Lorenzo

> This feels like leaking Linux internals rather than a reusable
> interface.
> 
> Mark.
> 
> > +
> > +Versatile Express idle-states nodes example:
> > +
> > +	idle-states {
> > +		entry-method = "arm,vexpress-v2p-ca15_a7";
> > +
> > +		cluster-sleep-0 {
> > +			compatible = "arm,idle-state";
> > +			entry-latency-us = <1000>;
> > +			exit-latency-us = <700>;
> > +			min-residency-us = <3500>;
> > +		};
> > +	};
> >  
> >  Configuration infrastructure
> >  ----------------------------
> > @@ -227,3 +249,6 @@ Example of a VE tile description (simplified)
> >  	};
> >  };
> >  
> > +
> > +[1] ARM Linux Kernel documentation - Idle states bindings
> > +    Documentation/devicetree/bindings/arm/idle-states.txt
> > diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
> > index a25c262..ad28242 100644
> > --- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
> > +++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
> > @@ -33,11 +33,32 @@
> >  		#address-cells = <1>;
> >  		#size-cells = <0>;
> >  
> > +		idle-states {
> > +			entry-method = "arm,vexpress-v2p-ca15_a7";
> > +
> > +			CLUSTER_SLEEP_BIG: cluster-sleep-big {
> > +				compatible = "arm,idle-state";
> > +				power-rank = <0>;
> > +				entry-latency-us = <1000>;
> > +				exit-latency-us = <700>;
> > +				min-residency-us = <3500>;
> > +			};
> > +
> > +			CLUSTER_SLEEP_LITTLE: cluster-sleep-little {
> > +				compatible = "arm,idle-state";
> > +				power-rank = <0>;
> > +				entry-latency-us = <1000>;
> > +				exit-latency-us = <500>;
> > +				min-residency-us = <3000>;
> > +			};
> > +		};
> > +
> >  		cpu0: cpu@0 {
> >  			device_type = "cpu";
> >  			compatible = "arm,cortex-a15";
> >  			reg = <0>;
> >  			cci-control-port = <&cci_control1>;
> > +			cpu-idle-states = <&CLUSTER_SLEEP_BIG>;
> >  		};
> >  
> >  		cpu1: cpu@1 {
> > @@ -45,6 +66,7 @@
> >  			compatible = "arm,cortex-a15";
> >  			reg = <1>;
> >  			cci-control-port = <&cci_control1>;
> > +			cpu-idle-states = <&CLUSTER_SLEEP_BIG>;
> >  		};
> >  
> >  		cpu2: cpu@2 {
> > @@ -52,6 +74,7 @@
> >  			compatible = "arm,cortex-a7";
> >  			reg = <0x100>;
> >  			cci-control-port = <&cci_control2>;
> > +			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
> >  		};
> >  
> >  		cpu3: cpu@3 {
> > @@ -59,6 +82,7 @@
> >  			compatible = "arm,cortex-a7";
> >  			reg = <0x101>;
> >  			cci-control-port = <&cci_control2>;
> > +			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
> >  		};
> >  
> >  		cpu4: cpu@4 {
> > @@ -66,6 +90,7 @@
> >  			compatible = "arm,cortex-a7";
> >  			reg = <0x102>;
> >  			cci-control-port = <&cci_control2>;
> > +			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
> >  		};
> >  	};
> >  
> > diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
> > index b6d69e8..a9b089c 100644
> > --- a/drivers/cpuidle/Kconfig.arm
> > +++ b/drivers/cpuidle/Kconfig.arm
> > @@ -12,6 +12,7 @@ config ARM_BIG_LITTLE_CPUIDLE
> >  	depends on ARCH_VEXPRESS_TC2_PM
> >  	select ARM_CPU_SUSPEND
> >  	select CPU_IDLE_MULTIPLE_DRIVERS
> > +	select DT_IDLE_STATES
> >  	help
> >  	  Select this option to enable CPU idle driver for big.LITTLE based
> >  	  ARM systems. Driver manages CPUs coordination through MCPM and
> > diff --git a/drivers/cpuidle/cpuidle-big_little.c b/drivers/cpuidle/cpuidle-big_little.c
> > index b45fc62..6712441 100644
> > --- a/drivers/cpuidle/cpuidle-big_little.c
> > +++ b/drivers/cpuidle/cpuidle-big_little.c
> > @@ -24,6 +24,8 @@
> >  #include <asm/smp_plat.h>
> >  #include <asm/suspend.h>
> >  
> > +#include "dt_idle_states.h"
> > +
> >  static int bl_enter_powerdown(struct cpuidle_device *dev,
> >  			      struct cpuidle_driver *drv, int idx);
> >  
> > @@ -61,32 +63,12 @@ static struct cpuidle_driver bl_idle_little_driver = {
> >  	.name = "little_idle",
> >  	.owner = THIS_MODULE,
> >  	.states[0] = ARM_CPUIDLE_WFI_STATE,
> > -	.states[1] = {
> > -		.enter			= bl_enter_powerdown,
> > -		.exit_latency		= 700,
> > -		.target_residency	= 2500,
> > -		.flags			= CPUIDLE_FLAG_TIME_VALID |
> > -					  CPUIDLE_FLAG_TIMER_STOP,
> > -		.name			= "C1",
> > -		.desc			= "ARM little-cluster power down",
> > -	},
> > -	.state_count = 2,
> >  };
> >  
> >  static struct cpuidle_driver bl_idle_big_driver = {
> >  	.name = "big_idle",
> >  	.owner = THIS_MODULE,
> >  	.states[0] = ARM_CPUIDLE_WFI_STATE,
> > -	.states[1] = {
> > -		.enter			= bl_enter_powerdown,
> > -		.exit_latency		= 500,
> > -		.target_residency	= 2000,
> > -		.flags			= CPUIDLE_FLAG_TIME_VALID |
> > -					  CPUIDLE_FLAG_TIMER_STOP,
> > -		.name			= "C1",
> > -		.desc			= "ARM big-cluster power down",
> > -	},
> > -	.state_count = 2,
> >  };
> >  
> >  /*
> > @@ -165,7 +147,8 @@ static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int cpu_id)
> >  
> >  static int __init bl_idle_init(void)
> >  {
> > -	int ret;
> > +	int ret, i;
> > +	struct cpuidle_driver *drv;
> >  
> >  	/*
> >  	 * Initialize the driver just for a compliant set of machines
> > @@ -187,6 +170,24 @@ static int __init bl_idle_init(void)
> >  	if (ret)
> >  		goto out_uninit_little;
> >  
> > +	 /* Start at index 1, index 0 standard WFI */
> > +	ret = dt_init_idle_driver(&bl_idle_big_driver, NULL, 1, false);
> > +	if (ret)
> > +		goto out_uninit_big;
> > +
> > +	 /* Start at index 1, index 0 standard WFI */
> > +	ret = dt_init_idle_driver(&bl_idle_little_driver, NULL, 1, false);
> > +	if (ret)
> > +		goto out_uninit_big;
> > +
> > +	drv = &bl_idle_big_driver;
> > +	for (i = 1; i < drv->state_count; i++)
> > +		drv->states[i].enter = bl_enter_powerdown;
> > +
> > +	drv = &bl_idle_little_driver;
> > +	for (i = 1; i < drv->state_count; i++)
> > +		drv->states[i].enter = bl_enter_powerdown;
> > +
> >  	ret = cpuidle_register(&bl_idle_little_driver, NULL);
> >  	if (ret)
> >  		goto out_uninit_big;
> > -- 
> > 1.9.1
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 6/8] drivers: cpuidle: initialize big.LITTLE driver through DT
@ 2014-06-25 16:44       ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 16:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 25, 2014 at 04:06:23PM +0100, Mark Rutland wrote:
> On Wed, Jun 25, 2014 at 03:10:19PM +0100, Lorenzo Pieralisi wrote:
> > With the introduction of DT based idle states, CPUidle drivers for ARM
> > can now initialize idle states data through properties in the device tree.
> > 
> > This patch adds code to the big.LITTLE CPUidle driver to dynamically
> > initialize idle states data through the updated device tree source file.
> > 
> > Cc: Chander Kashyap <chander.kashyap@linaro.org>
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > ---
> >  Documentation/devicetree/bindings/arm/vexpress.txt | 25 +++++++++++++
> >  arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts         | 25 +++++++++++++
> >  drivers/cpuidle/Kconfig.arm                        |  1 +
> >  drivers/cpuidle/cpuidle-big_little.c               | 43 +++++++++++-----------
> >  4 files changed, 73 insertions(+), 21 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/arm/vexpress.txt b/Documentation/devicetree/bindings/arm/vexpress.txt
> > index 39844cd..7f52ac8 100644
> > --- a/Documentation/devicetree/bindings/arm/vexpress.txt
> > +++ b/Documentation/devicetree/bindings/arm/vexpress.txt
> > @@ -67,6 +67,28 @@ with device_type = "cpu" property for every available core, eg.:
> >  		};
> >  	};
> >  
> > +idle-states node
> > +----------------
> > +
> > +On Versatile Express platforms with power management capabilities, the device
> > +tree source file must contain the idle-states node[1]. As defined in [1] the
> > +idle-states node must contain an entry-method property that for Versatile
> > +Express platforms can be one of:
> > +
> > +	- "arm,vexpress-v2p-ca15_a7"
> 
> ... and what does this mean? It's the name we've assigned the platform
> in the Linux DT bindings, but this binding document tells me nothing
> about how this method works.

Ok, I should have omitted it, I added it to make it compliant with
current DT bindings where entry-method for idle-states is required and I
have just added TC2 compatible string to get code out for review.

I should have made the entry-method optional for arm32 and get rid of
this useless binding and entry-method string.

Thanks,
Lorenzo

> This feels like leaking Linux internals rather than a reusable
> interface.
> 
> Mark.
> 
> > +
> > +Versatile Express idle-states nodes example:
> > +
> > +	idle-states {
> > +		entry-method = "arm,vexpress-v2p-ca15_a7";
> > +
> > +		cluster-sleep-0 {
> > +			compatible = "arm,idle-state";
> > +			entry-latency-us = <1000>;
> > +			exit-latency-us = <700>;
> > +			min-residency-us = <3500>;
> > +		};
> > +	};
> >  
> >  Configuration infrastructure
> >  ----------------------------
> > @@ -227,3 +249,6 @@ Example of a VE tile description (simplified)
> >  	};
> >  };
> >  
> > +
> > +[1] ARM Linux Kernel documentation - Idle states bindings
> > +    Documentation/devicetree/bindings/arm/idle-states.txt
> > diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
> > index a25c262..ad28242 100644
> > --- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
> > +++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
> > @@ -33,11 +33,32 @@
> >  		#address-cells = <1>;
> >  		#size-cells = <0>;
> >  
> > +		idle-states {
> > +			entry-method = "arm,vexpress-v2p-ca15_a7";
> > +
> > +			CLUSTER_SLEEP_BIG: cluster-sleep-big {
> > +				compatible = "arm,idle-state";
> > +				power-rank = <0>;
> > +				entry-latency-us = <1000>;
> > +				exit-latency-us = <700>;
> > +				min-residency-us = <3500>;
> > +			};
> > +
> > +			CLUSTER_SLEEP_LITTLE: cluster-sleep-little {
> > +				compatible = "arm,idle-state";
> > +				power-rank = <0>;
> > +				entry-latency-us = <1000>;
> > +				exit-latency-us = <500>;
> > +				min-residency-us = <3000>;
> > +			};
> > +		};
> > +
> >  		cpu0: cpu at 0 {
> >  			device_type = "cpu";
> >  			compatible = "arm,cortex-a15";
> >  			reg = <0>;
> >  			cci-control-port = <&cci_control1>;
> > +			cpu-idle-states = <&CLUSTER_SLEEP_BIG>;
> >  		};
> >  
> >  		cpu1: cpu at 1 {
> > @@ -45,6 +66,7 @@
> >  			compatible = "arm,cortex-a15";
> >  			reg = <1>;
> >  			cci-control-port = <&cci_control1>;
> > +			cpu-idle-states = <&CLUSTER_SLEEP_BIG>;
> >  		};
> >  
> >  		cpu2: cpu at 2 {
> > @@ -52,6 +74,7 @@
> >  			compatible = "arm,cortex-a7";
> >  			reg = <0x100>;
> >  			cci-control-port = <&cci_control2>;
> > +			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
> >  		};
> >  
> >  		cpu3: cpu at 3 {
> > @@ -59,6 +82,7 @@
> >  			compatible = "arm,cortex-a7";
> >  			reg = <0x101>;
> >  			cci-control-port = <&cci_control2>;
> > +			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
> >  		};
> >  
> >  		cpu4: cpu at 4 {
> > @@ -66,6 +90,7 @@
> >  			compatible = "arm,cortex-a7";
> >  			reg = <0x102>;
> >  			cci-control-port = <&cci_control2>;
> > +			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
> >  		};
> >  	};
> >  
> > diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
> > index b6d69e8..a9b089c 100644
> > --- a/drivers/cpuidle/Kconfig.arm
> > +++ b/drivers/cpuidle/Kconfig.arm
> > @@ -12,6 +12,7 @@ config ARM_BIG_LITTLE_CPUIDLE
> >  	depends on ARCH_VEXPRESS_TC2_PM
> >  	select ARM_CPU_SUSPEND
> >  	select CPU_IDLE_MULTIPLE_DRIVERS
> > +	select DT_IDLE_STATES
> >  	help
> >  	  Select this option to enable CPU idle driver for big.LITTLE based
> >  	  ARM systems. Driver manages CPUs coordination through MCPM and
> > diff --git a/drivers/cpuidle/cpuidle-big_little.c b/drivers/cpuidle/cpuidle-big_little.c
> > index b45fc62..6712441 100644
> > --- a/drivers/cpuidle/cpuidle-big_little.c
> > +++ b/drivers/cpuidle/cpuidle-big_little.c
> > @@ -24,6 +24,8 @@
> >  #include <asm/smp_plat.h>
> >  #include <asm/suspend.h>
> >  
> > +#include "dt_idle_states.h"
> > +
> >  static int bl_enter_powerdown(struct cpuidle_device *dev,
> >  			      struct cpuidle_driver *drv, int idx);
> >  
> > @@ -61,32 +63,12 @@ static struct cpuidle_driver bl_idle_little_driver = {
> >  	.name = "little_idle",
> >  	.owner = THIS_MODULE,
> >  	.states[0] = ARM_CPUIDLE_WFI_STATE,
> > -	.states[1] = {
> > -		.enter			= bl_enter_powerdown,
> > -		.exit_latency		= 700,
> > -		.target_residency	= 2500,
> > -		.flags			= CPUIDLE_FLAG_TIME_VALID |
> > -					  CPUIDLE_FLAG_TIMER_STOP,
> > -		.name			= "C1",
> > -		.desc			= "ARM little-cluster power down",
> > -	},
> > -	.state_count = 2,
> >  };
> >  
> >  static struct cpuidle_driver bl_idle_big_driver = {
> >  	.name = "big_idle",
> >  	.owner = THIS_MODULE,
> >  	.states[0] = ARM_CPUIDLE_WFI_STATE,
> > -	.states[1] = {
> > -		.enter			= bl_enter_powerdown,
> > -		.exit_latency		= 500,
> > -		.target_residency	= 2000,
> > -		.flags			= CPUIDLE_FLAG_TIME_VALID |
> > -					  CPUIDLE_FLAG_TIMER_STOP,
> > -		.name			= "C1",
> > -		.desc			= "ARM big-cluster power down",
> > -	},
> > -	.state_count = 2,
> >  };
> >  
> >  /*
> > @@ -165,7 +147,8 @@ static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int cpu_id)
> >  
> >  static int __init bl_idle_init(void)
> >  {
> > -	int ret;
> > +	int ret, i;
> > +	struct cpuidle_driver *drv;
> >  
> >  	/*
> >  	 * Initialize the driver just for a compliant set of machines
> > @@ -187,6 +170,24 @@ static int __init bl_idle_init(void)
> >  	if (ret)
> >  		goto out_uninit_little;
> >  
> > +	 /* Start at index 1, index 0 standard WFI */
> > +	ret = dt_init_idle_driver(&bl_idle_big_driver, NULL, 1, false);
> > +	if (ret)
> > +		goto out_uninit_big;
> > +
> > +	 /* Start at index 1, index 0 standard WFI */
> > +	ret = dt_init_idle_driver(&bl_idle_little_driver, NULL, 1, false);
> > +	if (ret)
> > +		goto out_uninit_big;
> > +
> > +	drv = &bl_idle_big_driver;
> > +	for (i = 1; i < drv->state_count; i++)
> > +		drv->states[i].enter = bl_enter_powerdown;
> > +
> > +	drv = &bl_idle_little_driver;
> > +	for (i = 1; i < drv->state_count; i++)
> > +		drv->states[i].enter = bl_enter_powerdown;
> > +
> >  	ret = cpuidle_register(&bl_idle_little_driver, NULL);
> >  	if (ret)
> >  		goto out_uninit_big;
> > -- 
> > 1.9.1
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 7/8] drivers: cpuidle: initialize Exynos driver through DT
  2014-06-25 15:13     ` Mark Rutland
@ 2014-06-25 16:58       ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 16:58 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, linux-pm, devicetree, Kukjin Kim, Tomasz Figa,
	Sudeep Holla, Catalin Marinas, Charles Garcia-Tobin,
	Nicolas Pitre, Rob Herring, grant.likely, Peter De Schrijver,
	Santosh Shilimkar, Daniel Lezcano, Amit Kucheria,
	Vincent Guittot, Antti Miettinen, Stephen Boyd, Kevin Hilman,
	Sebastian Capella

On Wed, Jun 25, 2014 at 04:13:33PM +0100, Mark Rutland wrote:
> On Wed, Jun 25, 2014 at 03:10:20PM +0100, Lorenzo Pieralisi wrote:
> > With the introduction of DT based idle states, CPUidle drivers for
> > ARM can now initialize idle states data through properties in the device
> > tree.
> > 
> > This patch adds code to the Exynos CPUidle driver to dynamically
> > initialize idle states data through the updated device tree source
> > files.
> > 
> > Cc: Kukjin Kim <kgene.kim@samsung.com>
> > Cc: Tomasz Figa <t.figa@samsung.com>
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > ---
> > Compile tested, I am not sure I patched the right dts files, please check.
> > 
> >  .../devicetree/bindings/arm/exynos/idle-states.txt | 27 ++++++++++++++++++++
> >  arch/arm/boot/dts/exynos3250.dtsi                  | 16 ++++++++++++
> >  arch/arm/boot/dts/exynos5250.dtsi                  | 15 +++++++++++
> >  arch/arm/boot/dts/exynos5410.dtsi                  | 17 +++++++++++++
> >  drivers/cpuidle/Kconfig.arm                        |  1 +
> >  drivers/cpuidle/cpuidle-exynos.c                   | 29 +++++++++++++---------
> >  6 files changed, 93 insertions(+), 12 deletions(-)
> >  create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/arm/exynos/idle-states.txt b/Documentation/devicetree/bindings/arm/exynos/idle-states.txt
> > new file mode 100644
> > index 0000000..342ecb4
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/arm/exynos/idle-states.txt
> > @@ -0,0 +1,27 @@
> > +idle-states node
> > +----------------
> > +
> > +On Exynos platforms with power management capabilities, the device
> > +tree source file must contain the idle-states node[1]. As defined in [1] the
> > +idle-states node must contain an entry-method property that for Exynos
> > +platforms can be one of:
> > +
> > +	- "samsung,exynos"
> 
> Similarly to the TC2 binding, what does this mean?
> 
> What is a kernel expected to do when it sees this entry-method?
> 
> Using "samsung,exynos" as the entry-method feels like something that's
> going to bite us; it sounds far too wide-reaching.

Same story as TC2, it adds nothing to the patch, it is just there for
compliance with current DT bindings, but useless and will disappear.

> >  static int exynos_cpuidle_probe(struct platform_device *pdev)
> >  {
> > -	int ret;
> > +	int ret, i;
> > +	struct cpuidle_driver *drv = &exynos_idle_driver;
> >  
> >  	exynos_enter_aftr = (void *)(pdev->dev.platform_data);
> >  
> > -	ret = cpuidle_register(&exynos_idle_driver, NULL);
> > +	drv->cpumask = (struct cpumask *) cpu_possible_mask;
> 
> This assignment looks scary to me. Why do we need to do this, and why
> are we throwing away the constness of cpu_possible_mask?

Yes, that's how it is done in CPUidle core if the idle driver does not
initialize cpumask pointer, I guess it is to save some bytes, but I agree
with you, I do not like that either, I will allocate the mask and copy.

Thanks,
Lorenzo


^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 7/8] drivers: cpuidle: initialize Exynos driver through DT
@ 2014-06-25 16:58       ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 16:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 25, 2014 at 04:13:33PM +0100, Mark Rutland wrote:
> On Wed, Jun 25, 2014 at 03:10:20PM +0100, Lorenzo Pieralisi wrote:
> > With the introduction of DT based idle states, CPUidle drivers for
> > ARM can now initialize idle states data through properties in the device
> > tree.
> > 
> > This patch adds code to the Exynos CPUidle driver to dynamically
> > initialize idle states data through the updated device tree source
> > files.
> > 
> > Cc: Kukjin Kim <kgene.kim@samsung.com>
> > Cc: Tomasz Figa <t.figa@samsung.com>
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > ---
> > Compile tested, I am not sure I patched the right dts files, please check.
> > 
> >  .../devicetree/bindings/arm/exynos/idle-states.txt | 27 ++++++++++++++++++++
> >  arch/arm/boot/dts/exynos3250.dtsi                  | 16 ++++++++++++
> >  arch/arm/boot/dts/exynos5250.dtsi                  | 15 +++++++++++
> >  arch/arm/boot/dts/exynos5410.dtsi                  | 17 +++++++++++++
> >  drivers/cpuidle/Kconfig.arm                        |  1 +
> >  drivers/cpuidle/cpuidle-exynos.c                   | 29 +++++++++++++---------
> >  6 files changed, 93 insertions(+), 12 deletions(-)
> >  create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/arm/exynos/idle-states.txt b/Documentation/devicetree/bindings/arm/exynos/idle-states.txt
> > new file mode 100644
> > index 0000000..342ecb4
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/arm/exynos/idle-states.txt
> > @@ -0,0 +1,27 @@
> > +idle-states node
> > +----------------
> > +
> > +On Exynos platforms with power management capabilities, the device
> > +tree source file must contain the idle-states node[1]. As defined in [1] the
> > +idle-states node must contain an entry-method property that for Exynos
> > +platforms can be one of:
> > +
> > +	- "samsung,exynos"
> 
> Similarly to the TC2 binding, what does this mean?
> 
> What is a kernel expected to do when it sees this entry-method?
> 
> Using "samsung,exynos" as the entry-method feels like something that's
> going to bite us; it sounds far too wide-reaching.

Same story as TC2, it adds nothing to the patch, it is just there for
compliance with current DT bindings, but useless and will disappear.

> >  static int exynos_cpuidle_probe(struct platform_device *pdev)
> >  {
> > -	int ret;
> > +	int ret, i;
> > +	struct cpuidle_driver *drv = &exynos_idle_driver;
> >  
> >  	exynos_enter_aftr = (void *)(pdev->dev.platform_data);
> >  
> > -	ret = cpuidle_register(&exynos_idle_driver, NULL);
> > +	drv->cpumask = (struct cpumask *) cpu_possible_mask;
> 
> This assignment looks scary to me. Why do we need to do this, and why
> are we throwing away the constness of cpu_possible_mask?

Yes, that's how it is done in CPUidle core if the idle driver does not
initialize cpumask pointer, I guess it is to save some bytes, but I agree
with you, I do not like that either, I will allocate the mask and copy.

Thanks,
Lorenzo

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 1/8] Documentation: arm: define DT idle states bindings
  2014-06-25 14:58     ` Mark Rutland
@ 2014-06-25 17:37       ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 17:37 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, linux-pm, devicetree, Sudeep Holla,
	Catalin Marinas, Charles Garcia-Tobin, Nicolas Pitre,
	Rob Herring, grant.likely, Peter De Schrijver, Santosh Shilimkar,
	Daniel Lezcano, Amit Kucheria, Vincent Guittot, Antti Miettinen,
	Stephen Boyd, Kevin Hilman, Sebastian Capella, Tomasz Figa,
	Mark Brown

On Wed, Jun 25, 2014 at 03:58:49PM +0100, Mark Rutland wrote:
> Hi Lorenzo,
> 
> On Wed, Jun 25, 2014 at 03:10:14PM +0100, Lorenzo Pieralisi wrote:
> > ARM based platforms implement a variety of power management schemes that
> > allow processors to enter idle states at run-time.
> > The parameters defining these idle states vary on a per-platform basis forcing
> > the OS to hardcode the state parameters in platform specific static tables
> > whose size grows as the number of platforms supported in the kernel increases
> > and hampers device drivers standardization.
> >
> > Therefore, this patch aims at standardizing idle state device tree bindings for
> > ARM platforms. Bindings define idle state parameters inclusive of entry methods
> > and state latencies, to allow operating systems to retrieve the configuration
> > entries from the device tree and initialize the related power management
> > drivers, paving the way for common code in the kernel to deal with idle
> > states and removing the need for static data in current and previous kernel
> > versions.
> >
> > Reviewed-by: Sebastian Capella <sebcape@gmail.com>
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > ---
> >  Documentation/devicetree/bindings/arm/cpus.txt     |   8 +
> >  .../devicetree/bindings/arm/idle-states.txt        | 733 +++++++++++++++++++++
> >  2 files changed, 741 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/arm/idle-states.txt
> 
> [...]
> 
> > +===========================================
> > +3 - idle-states node
> > +===========================================
> > +
> > +ARM 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.
> > +
> > +- idle-states node
> > +
> > +       Usage: Optional - 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.
> > +
> > +       Description: idle-states node is a container node, where its
> > +                    subnodes describe the CPU idle states.
> > +
> > +       Node name must be "idle-states".
> > +
> > +       The idle-states node's parent node must be the cpus node.
> > +
> > +       The idle-states node's child nodes can be:
> > +
> > +       - one or more state nodes
> > +
> > +       Any other configuration is considered invalid.
> > +
> > +       An idle-states node defines the following properties:
> > +
> > +       - entry-method
> > +               Usage: Required
> > +               Value type: <stringlist>
> > +               Definition: Describes the method by which a CPU enters the
> > +                           idle states. This property is required and must be
> > +                           one of:
> > +
> > +                           - "arm,psci"
> > +                             ARM PSCI firmware interface [2].
> > +
> > +                           - "[vendor],[method]"
> > +                             An implementation dependent string with
> > +                             format "vendor,method", where vendor is a string
> > +                             denoting the name of the manufacturer and
> > +                             method is a string specifying the mechanism
> > +                             used to enter the idle state.
> > +
> > +The nodes describing the idle states (state) can only be defined within the
> > +idle-states node, any other configuration is considered invalid and therefore
> > +must be ignored.
> > +
> > +===========================================
> > +4 - state node
> > +===========================================
> > +
> > +A state node represents an idle state description and must be defined as
> > +follows:
> > +
> > +- state node
> > +
> > +       Description: must be child of the idle-states node
> > +
> > +       The state node name shall follow standard device tree naming
> > +       rules ([5], 2.2.1 "Node names"), in particular state nodes which
> > +       are siblings within a single common parent must be given a unique name.
> > +
> > +       The idle state entered by executing the wfi instruction (idle_standby
> > +       SBSA,[3][4]) is considered standard on all ARM platforms and therefore
> > +       must not be listed.
> > +
> > +       With the definitions provided above, the following list represents
> > +       the valid properties for a state node:
> > +
> > +       - compatible
> > +               Usage: Required
> > +               Value type: <stringlist>
> > +               Definition: Must be "arm,idle-state".
> > +
> > +       - logic-state-retained
> > +               Usage: See definition
> > +               Value type: <none>
> > +               Definition: if present logic is retained on state entry,
> > +                           otherwise it is lost.
> 
> What logic state is retained? All system registers?
> 
> > +       - cache-state-retained
> > +               Usage: See definition
> > +               Value type: <none>
> > +               Definition: if present cache memory is retained on state entry,
> > +                           otherwise it is lost.
> 
> Likewise, how much of the cache hierarchy is affected? Any of it? All of
> it?

Well, to be honest these properties are shortcuts. If we wanted to do
things properly, I should have added power domains into the picture
(actually I did in the earlier versions of the bindings and later
streamlined them) so that every device inclusive of CPUs and caches
can be linked to a power domain, and from that linkage we could detect
what's lost when an idle state is entered.

PSCI does not need the two properties above (but that's no valid reason
to remove them, or to avoid adding power domains).

In case power domains are added, we need to know if the caches are lost
or retained and this flag specifies that. I can add these properties
when they are needed ie not in the current bindings.

> > +       - timer-state-retained
> > +               Usage: See definition
> > +               Value type: <none>
> > +               Definition: if present the timer control logic is retained on
> > +                            state entry, otherwise it is lost.
> 
> The architected generic timers? Any CPU-local timers? Or any timers
> whatsoever?

See above. Without power domains (and even with power domains attaching
a tick device to a power domain is far from being a simple job) it is
impossible to know if the tick device (what timer lies behind it is
unknown to the idle driver) is lost on idle state entry.

PowerPC guys got around that by adding a flag to DT which is a Linux specific
thing, this property is also a Linux specific property, but I think it
is a problem present in other OS too (and that ACPI solves the same way I
did).

On x86, the idle state index defines what states lose the local timer so
this stuff is not needed at all.

My question is, and that's a very important one: is it worth going the
whole nine yards, implementing bindings with power domains and parse
all this stuff in the kernel to set a flag for some CPUidle states ?

Complexity behind this is significant, but using the power domains is the
proper way to do it.

The only alternative lies in always setting the CPUIDLE_FLAG_TIMER_STOP
on all idle states (which turns out as a nop if the tick device does not have
C3STOP in its features).

Or maybe we can get away with adding the compatible string of the timer that
is lost on idle state entry if any ? That's horrible but that's another
possibility.

I know I am talking DT with kernel code in mind, but in this specific
case it is pretty hard to do otherwise.

Comments very welcome and encouraged because that's a blocking point.

> > +       - power-rank
> > +               Usage: Required
> > +               Value type: <u32>
> > +               Definition: It represents the idle state power-rank.
> > +                           An increasing value implies less power
> > +                           consumption. It must be given a sequential
> > +                           value = {0, 1, ....}, starting from 0.
> > +                           Phandles in the cpu nodes [1] cpu-idle-states
> > +                           array property are not allowed to point at idle
> > +                           state nodes having the same power-rank value.
> 
> Why can't this be implicit in the order of the cpu-idle-states list?
> That way it's impossible to violate the ordering requirement.

You mean the phandles list in the cpu nodes ? Maybe, but this would
require the list to be the same order for all cpu nodes on which the
idle states are valid, or just take one and use that.

It can be viable, as long as everyone agrees, every time I post this
code someone comes up with a new idea on how to sort the states and
honestly I would like to be done with that.

> 
> > +       - entry-method-param
> > +               Usage: See definition.
> > +               Value type: <u32>
> > +               Definition: Depends on the idle-states node entry-method
> > +                           property value. Refer to the entry-method bindings
> > +                           for this property value definition.
> 
> Should this not be left up to the particular mechanism to describe?
> e.g. for PSCI we could have a arm,psci-suspend-param property.

It was like that in early postings, and probably was better than the
current definition. I need to think about that but I am almost convinced
you are right.

> Are we sure a single u32 value is going to be sufficient?

Well, it is for PSCI, so see above, adding generality when it is not
present is a risky business, hoping that a u32 parameter will work
for other entry methods is an unsafe bet, you are right.

Thanks,
Lorenzo


^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 1/8] Documentation: arm: define DT idle states bindings
@ 2014-06-25 17:37       ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 17:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 25, 2014 at 03:58:49PM +0100, Mark Rutland wrote:
> Hi Lorenzo,
> 
> On Wed, Jun 25, 2014 at 03:10:14PM +0100, Lorenzo Pieralisi wrote:
> > ARM based platforms implement a variety of power management schemes that
> > allow processors to enter idle states at run-time.
> > The parameters defining these idle states vary on a per-platform basis forcing
> > the OS to hardcode the state parameters in platform specific static tables
> > whose size grows as the number of platforms supported in the kernel increases
> > and hampers device drivers standardization.
> >
> > Therefore, this patch aims at standardizing idle state device tree bindings for
> > ARM platforms. Bindings define idle state parameters inclusive of entry methods
> > and state latencies, to allow operating systems to retrieve the configuration
> > entries from the device tree and initialize the related power management
> > drivers, paving the way for common code in the kernel to deal with idle
> > states and removing the need for static data in current and previous kernel
> > versions.
> >
> > Reviewed-by: Sebastian Capella <sebcape@gmail.com>
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > ---
> >  Documentation/devicetree/bindings/arm/cpus.txt     |   8 +
> >  .../devicetree/bindings/arm/idle-states.txt        | 733 +++++++++++++++++++++
> >  2 files changed, 741 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/arm/idle-states.txt
> 
> [...]
> 
> > +===========================================
> > +3 - idle-states node
> > +===========================================
> > +
> > +ARM 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.
> > +
> > +- idle-states node
> > +
> > +       Usage: Optional - 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.
> > +
> > +       Description: idle-states node is a container node, where its
> > +                    subnodes describe the CPU idle states.
> > +
> > +       Node name must be "idle-states".
> > +
> > +       The idle-states node's parent node must be the cpus node.
> > +
> > +       The idle-states node's child nodes can be:
> > +
> > +       - one or more state nodes
> > +
> > +       Any other configuration is considered invalid.
> > +
> > +       An idle-states node defines the following properties:
> > +
> > +       - entry-method
> > +               Usage: Required
> > +               Value type: <stringlist>
> > +               Definition: Describes the method by which a CPU enters the
> > +                           idle states. This property is required and must be
> > +                           one of:
> > +
> > +                           - "arm,psci"
> > +                             ARM PSCI firmware interface [2].
> > +
> > +                           - "[vendor],[method]"
> > +                             An implementation dependent string with
> > +                             format "vendor,method", where vendor is a string
> > +                             denoting the name of the manufacturer and
> > +                             method is a string specifying the mechanism
> > +                             used to enter the idle state.
> > +
> > +The nodes describing the idle states (state) can only be defined within the
> > +idle-states node, any other configuration is considered invalid and therefore
> > +must be ignored.
> > +
> > +===========================================
> > +4 - state node
> > +===========================================
> > +
> > +A state node represents an idle state description and must be defined as
> > +follows:
> > +
> > +- state node
> > +
> > +       Description: must be child of the idle-states node
> > +
> > +       The state node name shall follow standard device tree naming
> > +       rules ([5], 2.2.1 "Node names"), in particular state nodes which
> > +       are siblings within a single common parent must be given a unique name.
> > +
> > +       The idle state entered by executing the wfi instruction (idle_standby
> > +       SBSA,[3][4]) is considered standard on all ARM platforms and therefore
> > +       must not be listed.
> > +
> > +       With the definitions provided above, the following list represents
> > +       the valid properties for a state node:
> > +
> > +       - compatible
> > +               Usage: Required
> > +               Value type: <stringlist>
> > +               Definition: Must be "arm,idle-state".
> > +
> > +       - logic-state-retained
> > +               Usage: See definition
> > +               Value type: <none>
> > +               Definition: if present logic is retained on state entry,
> > +                           otherwise it is lost.
> 
> What logic state is retained? All system registers?
> 
> > +       - cache-state-retained
> > +               Usage: See definition
> > +               Value type: <none>
> > +               Definition: if present cache memory is retained on state entry,
> > +                           otherwise it is lost.
> 
> Likewise, how much of the cache hierarchy is affected? Any of it? All of
> it?

Well, to be honest these properties are shortcuts. If we wanted to do
things properly, I should have added power domains into the picture
(actually I did in the earlier versions of the bindings and later
streamlined them) so that every device inclusive of CPUs and caches
can be linked to a power domain, and from that linkage we could detect
what's lost when an idle state is entered.

PSCI does not need the two properties above (but that's no valid reason
to remove them, or to avoid adding power domains).

In case power domains are added, we need to know if the caches are lost
or retained and this flag specifies that. I can add these properties
when they are needed ie not in the current bindings.

> > +       - timer-state-retained
> > +               Usage: See definition
> > +               Value type: <none>
> > +               Definition: if present the timer control logic is retained on
> > +                            state entry, otherwise it is lost.
> 
> The architected generic timers? Any CPU-local timers? Or any timers
> whatsoever?

See above. Without power domains (and even with power domains attaching
a tick device to a power domain is far from being a simple job) it is
impossible to know if the tick device (what timer lies behind it is
unknown to the idle driver) is lost on idle state entry.

PowerPC guys got around that by adding a flag to DT which is a Linux specific
thing, this property is also a Linux specific property, but I think it
is a problem present in other OS too (and that ACPI solves the same way I
did).

On x86, the idle state index defines what states lose the local timer so
this stuff is not needed at all.

My question is, and that's a very important one: is it worth going the
whole nine yards, implementing bindings with power domains and parse
all this stuff in the kernel to set a flag for some CPUidle states ?

Complexity behind this is significant, but using the power domains is the
proper way to do it.

The only alternative lies in always setting the CPUIDLE_FLAG_TIMER_STOP
on all idle states (which turns out as a nop if the tick device does not have
C3STOP in its features).

Or maybe we can get away with adding the compatible string of the timer that
is lost on idle state entry if any ? That's horrible but that's another
possibility.

I know I am talking DT with kernel code in mind, but in this specific
case it is pretty hard to do otherwise.

Comments very welcome and encouraged because that's a blocking point.

> > +       - power-rank
> > +               Usage: Required
> > +               Value type: <u32>
> > +               Definition: It represents the idle state power-rank.
> > +                           An increasing value implies less power
> > +                           consumption. It must be given a sequential
> > +                           value = {0, 1, ....}, starting from 0.
> > +                           Phandles in the cpu nodes [1] cpu-idle-states
> > +                           array property are not allowed to point at idle
> > +                           state nodes having the same power-rank value.
> 
> Why can't this be implicit in the order of the cpu-idle-states list?
> That way it's impossible to violate the ordering requirement.

You mean the phandles list in the cpu nodes ? Maybe, but this would
require the list to be the same order for all cpu nodes on which the
idle states are valid, or just take one and use that.

It can be viable, as long as everyone agrees, every time I post this
code someone comes up with a new idea on how to sort the states and
honestly I would like to be done with that.

> 
> > +       - entry-method-param
> > +               Usage: See definition.
> > +               Value type: <u32>
> > +               Definition: Depends on the idle-states node entry-method
> > +                           property value. Refer to the entry-method bindings
> > +                           for this property value definition.
> 
> Should this not be left up to the particular mechanism to describe?
> e.g. for PSCI we could have a arm,psci-suspend-param property.

It was like that in early postings, and probably was better than the
current definition. I need to think about that but I am almost convinced
you are right.

> Are we sure a single u32 value is going to be sufficient?

Well, it is for PSCI, so see above, adding generality when it is not
present is a risky business, hoping that a u32 parameter will work
for other entry methods is an unsafe bet, you are right.

Thanks,
Lorenzo

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 8/8] arm64: boot: dts: update rtsm aemv8 dts with PSCI and idle states
  2014-06-25 14:27     ` Mark Rutland
@ 2014-06-25 17:47       ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 17:47 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, linux-pm, devicetree, Sudeep Holla,
	Catalin Marinas, Charles Garcia-Tobin, Nicolas Pitre,
	Rob Herring, grant.likely, Peter De Schrijver, Santosh Shilimkar,
	Daniel Lezcano, Amit Kucheria, Vincent Guittot, Antti Miettinen,
	Stephen Boyd, Kevin Hilman, Sebastian Capella, Tomasz Figa,
	Mark Brown

On Wed, Jun 25, 2014 at 03:27:14PM +0100, Mark Rutland wrote:
> Hi Lorenzo,
> 
> On Wed, Jun 25, 2014 at 03:10:21PM +0100, Lorenzo Pieralisi wrote:
> > This patch updates the RTSM dts file with PSCI bindings and nodes
> > describing the AEMv8 model idle states parameters.
> > 
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > ---
> >  arch/arm64/boot/dts/rtsm_ve-aemv8a.dts | 44 +++++++++++++++++++++++++++-------
> >  1 file changed, 36 insertions(+), 8 deletions(-)
> > 
> > diff --git a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> > index d79de9c..4051ffb 100644
> > --- a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> > +++ b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> > @@ -27,37 +27,65 @@
> >  		serial3 = &v2m_serial3;
> >  	};
> >  
> > +	psci {
> > +		compatible = "arm,psci-0.2";
> 
> Where can I find a PSCI 0.2 implementation for the RTSM VE model? I
> couldn't find a link in the cover.
> 
> The upstream bootwrapper is not PSCI 0.2 compliant and it does not
> implement CPU_SUSPEND.

This patch was not meant to be merged, it was for DT bindings demonstration
purposes, you are definitely right. I will patch the FVP model dts and
add a link to trusted firmware that supports the FVP models power
controller.

> > +		method = "smc";
> > +		cpu_suspend = <0xc4000001>;
> > +		cpu_off = <0x84000002>;
> > +		cpu_on = <0xc4000003>;
> 
> Without "arm,psci" in the compatible list, these three properties are
> meaningless.

Right, my bad.

> > +	};
> > +
> >  	cpus {
> >  		#address-cells = <2>;
> >  		#size-cells = <0>;
> >  
> > +		idle-states {
> > +			entry-method = "arm,psci";
> > +
> > +			CPU_SLEEP_0: cpu-sleep-0 {
> > +				compatible = "arm,idle-state";
> > +				entry-method-param = <0x0010000>;
> > +				entry-latency-us = <40>;
> > +				exit-latency-us = <100>;
> > +				min-residency-us = <150>;
> > +			};
> > +
> > +			CLUSTER_SLEEP_0: cluster-sleep-0 {
> > +				compatible = "arm,idle-state";
> > +				entry-method-param = <0x1010000>;
> > +				entry-latency-us = <500>;
> > +				exit-latency-us = <1000>;
> > +				min-residency-us = <2500>;
> > +			};
> > +		};
> > +
> 
> If this is going to live in the /cpus node, could it please be placed
> after the cpu nodes?

Ok.

> >  		cpu@0 {
> >  			device_type = "cpu";
> >  			compatible = "arm,armv8";
> >  			reg = <0x0 0x0>;
> > -			enable-method = "spin-table";
> > -			cpu-release-addr = <0x0 0x8000fff8>;
> > +			enable-method = "psci";
> 
> Changing the enable-method will break boot on a model when using a
> bootwrapper without PSCI support. Really we should leave it up to the
> bootwrapper to inject the enable method...

See above, you are right, I should have made it clear that this patch
was not meant for merging or testing and it was to provide a sample dts, will
fix it for v6.

Thanks,
Lorenzo


^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 8/8] arm64: boot: dts: update rtsm aemv8 dts with PSCI and idle states
@ 2014-06-25 17:47       ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-25 17:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 25, 2014 at 03:27:14PM +0100, Mark Rutland wrote:
> Hi Lorenzo,
> 
> On Wed, Jun 25, 2014 at 03:10:21PM +0100, Lorenzo Pieralisi wrote:
> > This patch updates the RTSM dts file with PSCI bindings and nodes
> > describing the AEMv8 model idle states parameters.
> > 
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > ---
> >  arch/arm64/boot/dts/rtsm_ve-aemv8a.dts | 44 +++++++++++++++++++++++++++-------
> >  1 file changed, 36 insertions(+), 8 deletions(-)
> > 
> > diff --git a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> > index d79de9c..4051ffb 100644
> > --- a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> > +++ b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
> > @@ -27,37 +27,65 @@
> >  		serial3 = &v2m_serial3;
> >  	};
> >  
> > +	psci {
> > +		compatible = "arm,psci-0.2";
> 
> Where can I find a PSCI 0.2 implementation for the RTSM VE model? I
> couldn't find a link in the cover.
> 
> The upstream bootwrapper is not PSCI 0.2 compliant and it does not
> implement CPU_SUSPEND.

This patch was not meant to be merged, it was for DT bindings demonstration
purposes, you are definitely right. I will patch the FVP model dts and
add a link to trusted firmware that supports the FVP models power
controller.

> > +		method = "smc";
> > +		cpu_suspend = <0xc4000001>;
> > +		cpu_off = <0x84000002>;
> > +		cpu_on = <0xc4000003>;
> 
> Without "arm,psci" in the compatible list, these three properties are
> meaningless.

Right, my bad.

> > +	};
> > +
> >  	cpus {
> >  		#address-cells = <2>;
> >  		#size-cells = <0>;
> >  
> > +		idle-states {
> > +			entry-method = "arm,psci";
> > +
> > +			CPU_SLEEP_0: cpu-sleep-0 {
> > +				compatible = "arm,idle-state";
> > +				entry-method-param = <0x0010000>;
> > +				entry-latency-us = <40>;
> > +				exit-latency-us = <100>;
> > +				min-residency-us = <150>;
> > +			};
> > +
> > +			CLUSTER_SLEEP_0: cluster-sleep-0 {
> > +				compatible = "arm,idle-state";
> > +				entry-method-param = <0x1010000>;
> > +				entry-latency-us = <500>;
> > +				exit-latency-us = <1000>;
> > +				min-residency-us = <2500>;
> > +			};
> > +		};
> > +
> 
> If this is going to live in the /cpus node, could it please be placed
> after the cpu nodes?

Ok.

> >  		cpu at 0 {
> >  			device_type = "cpu";
> >  			compatible = "arm,armv8";
> >  			reg = <0x0 0x0>;
> > -			enable-method = "spin-table";
> > -			cpu-release-addr = <0x0 0x8000fff8>;
> > +			enable-method = "psci";
> 
> Changing the enable-method will break boot on a model when using a
> bootwrapper without PSCI support. Really we should leave it up to the
> bootwrapper to inject the enable method...

See above, you are right, I should have made it clear that this patch
was not meant for merging or testing and it was to provide a sample dts, will
fix it for v6.

Thanks,
Lorenzo

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 5/8] drivers: cpuidle: CPU idle ARM64 driver
  2014-06-25 14:10   ` Lorenzo Pieralisi
@ 2014-06-25 20:34     ` Geoff Levand
  -1 siblings, 0 replies; 70+ messages in thread
From: Geoff Levand @ 2014-06-25 20:34 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: linux-arm-kernel, linux-pm, devicetree, Mark Rutland,
	Paul Walmsley, Vincent Guittot, Kevin Hilman, Nicolas Pitre,
	Catalin Marinas, Peter De Schrijver, Daniel Lezcano,
	Stephen Boyd, Amit Kucheria, Chander Kashyap, Sebastian Capella,
	Rob Herring, Santosh Shilimkar, Mark Brown, Sudeep Holla,
	Grant Likely, Tomasz Figa, Antti Miettinen, Charles Garcia Tobin

Hi Lorenzo,

On Wed, 2014-06-25 at 15:10 +0100, Lorenzo Pieralisi wrote:
> This patch implements a generic CPU idle driver for ARM64 machines.

...

> +typedef int (*suspend_init_fn)(struct cpuidle_driver *,
> +			       struct device_node *[]);
> +
> +struct cpu_suspend_ops {
> +	const char *id;
> +	suspend_init_fn init_fn;
> +};
> +
> +static const struct cpu_suspend_ops suspend_operations[] __initconst = {
> +	{"arm,psci", psci_dt_register_idle_states},
> +	{}

With this we'll have two completely independent mechanisms for
interacting with the cpu ops, this struct cpu_suspend_ops, and the
struct cpu_operations.  This doesn't seem good.

I feel we need to fix the cpu ops to include some way to operate on the
operation method to do initialization, shutdown, etc.  At present,
cpu_operations only has a mechanism to operate on the individual cpus.

-Geoff


^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 5/8] drivers: cpuidle: CPU idle ARM64 driver
@ 2014-06-25 20:34     ` Geoff Levand
  0 siblings, 0 replies; 70+ messages in thread
From: Geoff Levand @ 2014-06-25 20:34 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lorenzo,

On Wed, 2014-06-25 at 15:10 +0100, Lorenzo Pieralisi wrote:
> This patch implements a generic CPU idle driver for ARM64 machines.

...

> +typedef int (*suspend_init_fn)(struct cpuidle_driver *,
> +			       struct device_node *[]);
> +
> +struct cpu_suspend_ops {
> +	const char *id;
> +	suspend_init_fn init_fn;
> +};
> +
> +static const struct cpu_suspend_ops suspend_operations[] __initconst = {
> +	{"arm,psci", psci_dt_register_idle_states},
> +	{}

With this we'll have two completely independent mechanisms for
interacting with the cpu ops, this struct cpu_suspend_ops, and the
struct cpu_operations.  This doesn't seem good.

I feel we need to fix the cpu ops to include some way to operate on the
operation method to do initialization, shutdown, etc.  At present,
cpu_operations only has a mechanism to operate on the individual cpus.

-Geoff

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 4/8] arm64: add PSCI CPU_SUSPEND based cpu_suspend support
  2014-06-25 14:10     ` Lorenzo Pieralisi
@ 2014-06-25 20:52       ` Geoff Levand
  -1 siblings, 0 replies; 70+ messages in thread
From: Geoff Levand @ 2014-06-25 20:52 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: linux-arm-kernel, linux-pm, devicetree, Mark Rutland,
	Paul Walmsley, Vincent Guittot, Kevin Hilman, Nicolas Pitre,
	Catalin Marinas, Peter De Schrijver, Daniel Lezcano,
	Stephen Boyd, Amit Kucheria, Chander Kashyap, Sebastian Capella,
	Rob Herring, Santosh Shilimkar, Mark Brown, Sudeep Holla,
	Grant Likely, Tomasz Figa, Antti Miettinen, Charles Garcia Tobin

Hi Lorenzo,

On Wed, 2014-06-25 at 15:10 +0100, Lorenzo Pieralisi wrote:
> diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c

> +	/*
> +	 * This is belt-and-braces: make sure that if the idle
> +	 * specified protocol is psci, the cpu_ops have been
> +	 * initialized to psci operations. Anything else is
> +	 * a recipe for mayhem.
> +	 */
> +	for_each_cpu(cpu, drv->cpumask) {
> +		cpu_ops_ptr = cpu_ops[cpu];
> +		if (WARN_ON(!cpu_ops_ptr || strcmp(cpu_ops_ptr->name, "psci")))
> +			return -EOPNOTSUPP;
> +	}

I'm not sure how drv->cpumask is setup, but if a system has mixed enable
methods, say some cpus 'spin-table' and some 'psci', will this give a
false error?

If drv->cpumask should only include 'psci' cpus, then should this be a
BUG()?

> +
> +	psci_states = kcalloc(drv->state_count, sizeof(*psci_states),
> +			      GFP_KERNEL);
> +
> +	if (!psci_states) {
> +		pr_warn("psci idle state allocation failed\n");
> +		return -ENOMEM;
> +	}
> +
> +	for_each_cpu(cpu, drv->cpumask) {
> +		if (per_cpu(psci_power_state, cpu)) {
> +			pr_warn("idle states already initialized on cpu %u\n",
> +				cpu);

This seems like an implementation problem, if so, shouldn't this be
pr_debug()?


>  #endif
>  
> +#ifdef CONFIG_ARM64_CPU_SUSPEND
> +static int cpu_psci_cpu_suspend(unsigned long index)
> +{
> +	struct psci_power_state *state = __get_cpu_var(psci_power_state);
> +
> +	if (!state)
> +		return -EOPNOTSUPP;
> +
> +	return psci_ops.cpu_suspend(state[index], virt_to_phys(cpu_resume));
> +}
> +#endif

Why not put a __maybe_unused attribute on cpu_psci_cpu_suspend() and
remove the preprocessor conditional.  That way this code will always be
compiled, and with therefor always get a build test.  The linker should
strip out the unused code when CONFIG_ARM64_CPU_SUSPEND=n and the code
below is not compiled. 

> +#ifdef CONFIG_ARM64_CPU_SUSPEND
> +	.cpu_suspend	= cpu_psci_cpu_suspend,
> +#endif
>  };

-Geoff


^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 4/8] arm64: add PSCI CPU_SUSPEND based cpu_suspend support
@ 2014-06-25 20:52       ` Geoff Levand
  0 siblings, 0 replies; 70+ messages in thread
From: Geoff Levand @ 2014-06-25 20:52 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lorenzo,

On Wed, 2014-06-25 at 15:10 +0100, Lorenzo Pieralisi wrote:
> diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c

> +	/*
> +	 * This is belt-and-braces: make sure that if the idle
> +	 * specified protocol is psci, the cpu_ops have been
> +	 * initialized to psci operations. Anything else is
> +	 * a recipe for mayhem.
> +	 */
> +	for_each_cpu(cpu, drv->cpumask) {
> +		cpu_ops_ptr = cpu_ops[cpu];
> +		if (WARN_ON(!cpu_ops_ptr || strcmp(cpu_ops_ptr->name, "psci")))
> +			return -EOPNOTSUPP;
> +	}

I'm not sure how drv->cpumask is setup, but if a system has mixed enable
methods, say some cpus 'spin-table' and some 'psci', will this give a
false error?

If drv->cpumask should only include 'psci' cpus, then should this be a
BUG()?

> +
> +	psci_states = kcalloc(drv->state_count, sizeof(*psci_states),
> +			      GFP_KERNEL);
> +
> +	if (!psci_states) {
> +		pr_warn("psci idle state allocation failed\n");
> +		return -ENOMEM;
> +	}
> +
> +	for_each_cpu(cpu, drv->cpumask) {
> +		if (per_cpu(psci_power_state, cpu)) {
> +			pr_warn("idle states already initialized on cpu %u\n",
> +				cpu);

This seems like an implementation problem, if so, shouldn't this be
pr_debug()?


>  #endif
>  
> +#ifdef CONFIG_ARM64_CPU_SUSPEND
> +static int cpu_psci_cpu_suspend(unsigned long index)
> +{
> +	struct psci_power_state *state = __get_cpu_var(psci_power_state);
> +
> +	if (!state)
> +		return -EOPNOTSUPP;
> +
> +	return psci_ops.cpu_suspend(state[index], virt_to_phys(cpu_resume));
> +}
> +#endif

Why not put a __maybe_unused attribute on cpu_psci_cpu_suspend() and
remove the preprocessor conditional.  That way this code will always be
compiled, and with therefor always get a build test.  The linker should
strip out the unused code when CONFIG_ARM64_CPU_SUSPEND=n and the code
below is not compiled. 

> +#ifdef CONFIG_ARM64_CPU_SUSPEND
> +	.cpu_suspend	= cpu_psci_cpu_suspend,
> +#endif
>  };

-Geoff

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 1/8] Documentation: arm: define DT idle states bindings
  2014-06-25 15:56     ` Nicolas Pitre
@ 2014-06-26 10:17       ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-26 10:17 UTC (permalink / raw)
  To: Nicolas Pitre
  Cc: linux-arm-kernel, linux-pm, devicetree, Mark Rutland,
	Sudeep Holla, Catalin Marinas, Charles Garcia-Tobin, Rob Herring,
	grant.likely, Peter De Schrijver, Santosh Shilimkar,
	Daniel Lezcano, Amit Kucheria, Vincent Guittot, Antti Miettinen,
	Stephen Boyd, Kevin Hilman, Sebastian Capella, Tomasz Figa,
	Mark Brown

On Wed, Jun 25, 2014 at 04:56:02PM +0100, Nicolas Pitre wrote:
> On Wed, 25 Jun 2014, Lorenzo Pieralisi wrote:
> 
> > ARM based platforms implement a variety of power management schemes that
> > allow processors to enter idle states at run-time.
> > The parameters defining these idle states vary on a per-platform basis forcing
> > the OS to hardcode the state parameters in platform specific static tables
> > whose size grows as the number of platforms supported in the kernel increases
> > and hampers device drivers standardization.
> >
> > Therefore, this patch aims at standardizing idle state device tree bindings for
> > ARM platforms. Bindings define idle state parameters inclusive of entry methods
> > and state latencies, to allow operating systems to retrieve the configuration
> > entries from the device tree and initialize the related power management
> > drivers, paving the way for common code in the kernel to deal with idle
> > states and removing the need for static data in current and previous kernel
> > versions.
> >
> > Reviewed-by: Sebastian Capella <sebcape@gmail.com>
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> 
> Excellent.
> 
> Reviewed-by: Nicolas Pitre <nico@linaro.org>

Thanks Nico, there are still a couple of niggles to sort out (ie local
timer state), but the bulk of the document should be complete I hope.

I will postpone adding your (and Seb's) Reviewed-by until we have a
final agreement if it is ok with you.

Thanks !
Lorenzo


^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 1/8] Documentation: arm: define DT idle states bindings
@ 2014-06-26 10:17       ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-26 10:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 25, 2014 at 04:56:02PM +0100, Nicolas Pitre wrote:
> On Wed, 25 Jun 2014, Lorenzo Pieralisi wrote:
> 
> > ARM based platforms implement a variety of power management schemes that
> > allow processors to enter idle states at run-time.
> > The parameters defining these idle states vary on a per-platform basis forcing
> > the OS to hardcode the state parameters in platform specific static tables
> > whose size grows as the number of platforms supported in the kernel increases
> > and hampers device drivers standardization.
> >
> > Therefore, this patch aims at standardizing idle state device tree bindings for
> > ARM platforms. Bindings define idle state parameters inclusive of entry methods
> > and state latencies, to allow operating systems to retrieve the configuration
> > entries from the device tree and initialize the related power management
> > drivers, paving the way for common code in the kernel to deal with idle
> > states and removing the need for static data in current and previous kernel
> > versions.
> >
> > Reviewed-by: Sebastian Capella <sebcape@gmail.com>
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> 
> Excellent.
> 
> Reviewed-by: Nicolas Pitre <nico@linaro.org>

Thanks Nico, there are still a couple of niggles to sort out (ie local
timer state), but the bulk of the document should be complete I hope.

I will postpone adding your (and Seb's) Reviewed-by until we have a
final agreement if it is ok with you.

Thanks !
Lorenzo

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 4/8] arm64: add PSCI CPU_SUSPEND based cpu_suspend support
  2014-06-25 16:09       ` Mark Rutland
@ 2014-06-26 11:23         ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-26 11:23 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, linux-pm, devicetree, Sudeep Holla,
	Catalin Marinas, Charles Garcia-Tobin, Nicolas Pitre,
	Rob Herring, grant.likely, Peter De Schrijver, Santosh Shilimkar,
	Daniel Lezcano, Amit Kucheria, Vincent Guittot, Antti Miettinen,
	Stephen Boyd, Kevin Hilman, Sebastian Capella, Tomasz Figa,
	Mark Brown

On Wed, Jun 25, 2014 at 05:09:11PM +0100, Mark Rutland wrote:
> On Wed, Jun 25, 2014 at 03:10:17PM +0100, Lorenzo Pieralisi wrote:
> > This patch implements the cpu_suspend cpu operations method through
> > the PSCI CPU_SUSPEND API. The PSCI implementation translates the idle state
> > index passed by the cpu_suspend core call into a valid PSCI state according to
> > the PSCI states initialized at boot by the PSCI suspend backend.
> > 
> > Entry point is set to cpu_resume physical address, that represents the
> > default kernel execution address following a CPU reset.
> > 
> > Idle state indices missing a DT node description are initialized to power
> > state standby WFI so that if called by the idle driver they provide the
> > default behaviour.
> > 
> > Reviewed-by: Sebastian Capella <sebcape@gmail.com>
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > ---
> >  arch/arm64/include/asm/psci.h |   4 ++
> >  arch/arm64/kernel/psci.c      | 103 ++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 107 insertions(+)
> 
> [...]
> 
> > +static void psci_power_state_unpack(u32 power_state,
> > +				    struct psci_power_state *state)
> > +{
> > +	state->id = (power_state & PSCI_0_2_POWER_STATE_ID_MASK) >>
> > +			PSCI_0_2_POWER_STATE_ID_SHIFT;
> > +	state->type = (power_state & PSCI_0_2_POWER_STATE_TYPE_MASK) >>
> > +			PSCI_0_2_POWER_STATE_TYPE_SHIFT;
> > +	state->affinity_level =
> > +			(power_state & PSCI_0_2_POWER_STATE_AFFL_MASK) >>
> > +			PSCI_0_2_POWER_STATE_AFFL_SHIFT;
> > +}
> 
> Is this valid for PSCI versions prior to 0.2?

Yes, it should, as for the packing function.

> >  /*
> >   * The following two functions are invoked via the invoke_psci_fn pointer
> >   * and will not be inlined, allowing us to piggyback on the AAPCS.
> > @@ -199,6 +216,77 @@ static int psci_migrate_info_type(void)
> >  	return err;
> >  }
> >  
> > +int __init psci_dt_register_idle_states(struct cpuidle_driver *drv,
> > +					struct device_node *state_nodes[])
> > +{
> > +	int cpu, i;
> 
> Perhaps unsigned int? You print i with %u below.

Yes.

> > +	for (i = 0; i < drv->state_count; i++) {
> > +		u32 psci_power_state;
> > +
> > +		if (!state_nodes[i]) {
> > +			/*
> > +			 * An index with a missing node pointer falls back to
> > +			 * simple STANDBYWFI
> > +			 */
> > +			psci_states[i].type = PSCI_POWER_STATE_TYPE_STANDBY;
> > +			continue;
> > +		}
> 
> Does this make sense? Are there any limitations on which state nodes
> could be missing?

I think the check is overkill, you are right.

> > +
> > +		if (of_property_read_u32(state_nodes[i], "entry-method-param",
> > +					 &psci_power_state)) {
> > +			pr_warn(" * %s missing entry-method-param property\n",
> > +				state_nodes[i]->full_name);
> > +			/*
> > +			 * If entry-method-param property is missing, fall
> > +			 * back to STANDBYWFI state
> > +			 */
> > +			psci_states[i].type = PSCI_POWER_STATE_TYPE_STANDBY;
> > +			continue;
> 
> Surely we want to throw away these states instead?
> 
> Otherwise we can get into a mess like:
> 
> psci_states[0] => low power state
> psci_states[1] => lower power state
> psci_states[2] => WFI / not low power
> psci_states[3] => lowest power state
> 
> Where power usage and latency would jump around rather than follow
> monotonic patterns.

I do not think that's a problem by itself, but honestly I think you have
a point. It is better to barf, throw away the states and avoid initializing
CPUidle to force a firmware update than keep going with a state that is
actually not doing what it probably was designed for, I just tried to be too
accommodating on this.

Thanks,
Lorenzo


^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 4/8] arm64: add PSCI CPU_SUSPEND based cpu_suspend support
@ 2014-06-26 11:23         ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-26 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 25, 2014 at 05:09:11PM +0100, Mark Rutland wrote:
> On Wed, Jun 25, 2014 at 03:10:17PM +0100, Lorenzo Pieralisi wrote:
> > This patch implements the cpu_suspend cpu operations method through
> > the PSCI CPU_SUSPEND API. The PSCI implementation translates the idle state
> > index passed by the cpu_suspend core call into a valid PSCI state according to
> > the PSCI states initialized at boot by the PSCI suspend backend.
> > 
> > Entry point is set to cpu_resume physical address, that represents the
> > default kernel execution address following a CPU reset.
> > 
> > Idle state indices missing a DT node description are initialized to power
> > state standby WFI so that if called by the idle driver they provide the
> > default behaviour.
> > 
> > Reviewed-by: Sebastian Capella <sebcape@gmail.com>
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > ---
> >  arch/arm64/include/asm/psci.h |   4 ++
> >  arch/arm64/kernel/psci.c      | 103 ++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 107 insertions(+)
> 
> [...]
> 
> > +static void psci_power_state_unpack(u32 power_state,
> > +				    struct psci_power_state *state)
> > +{
> > +	state->id = (power_state & PSCI_0_2_POWER_STATE_ID_MASK) >>
> > +			PSCI_0_2_POWER_STATE_ID_SHIFT;
> > +	state->type = (power_state & PSCI_0_2_POWER_STATE_TYPE_MASK) >>
> > +			PSCI_0_2_POWER_STATE_TYPE_SHIFT;
> > +	state->affinity_level =
> > +			(power_state & PSCI_0_2_POWER_STATE_AFFL_MASK) >>
> > +			PSCI_0_2_POWER_STATE_AFFL_SHIFT;
> > +}
> 
> Is this valid for PSCI versions prior to 0.2?

Yes, it should, as for the packing function.

> >  /*
> >   * The following two functions are invoked via the invoke_psci_fn pointer
> >   * and will not be inlined, allowing us to piggyback on the AAPCS.
> > @@ -199,6 +216,77 @@ static int psci_migrate_info_type(void)
> >  	return err;
> >  }
> >  
> > +int __init psci_dt_register_idle_states(struct cpuidle_driver *drv,
> > +					struct device_node *state_nodes[])
> > +{
> > +	int cpu, i;
> 
> Perhaps unsigned int? You print i with %u below.

Yes.

> > +	for (i = 0; i < drv->state_count; i++) {
> > +		u32 psci_power_state;
> > +
> > +		if (!state_nodes[i]) {
> > +			/*
> > +			 * An index with a missing node pointer falls back to
> > +			 * simple STANDBYWFI
> > +			 */
> > +			psci_states[i].type = PSCI_POWER_STATE_TYPE_STANDBY;
> > +			continue;
> > +		}
> 
> Does this make sense? Are there any limitations on which state nodes
> could be missing?

I think the check is overkill, you are right.

> > +
> > +		if (of_property_read_u32(state_nodes[i], "entry-method-param",
> > +					 &psci_power_state)) {
> > +			pr_warn(" * %s missing entry-method-param property\n",
> > +				state_nodes[i]->full_name);
> > +			/*
> > +			 * If entry-method-param property is missing, fall
> > +			 * back to STANDBYWFI state
> > +			 */
> > +			psci_states[i].type = PSCI_POWER_STATE_TYPE_STANDBY;
> > +			continue;
> 
> Surely we want to throw away these states instead?
> 
> Otherwise we can get into a mess like:
> 
> psci_states[0] => low power state
> psci_states[1] => lower power state
> psci_states[2] => WFI / not low power
> psci_states[3] => lowest power state
> 
> Where power usage and latency would jump around rather than follow
> monotonic patterns.

I do not think that's a problem by itself, but honestly I think you have
a point. It is better to barf, throw away the states and avoid initializing
CPUidle to force a firmware update than keep going with a state that is
actually not doing what it probably was designed for, I just tried to be too
accommodating on this.

Thanks,
Lorenzo

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 7/8] drivers: cpuidle: initialize Exynos driver through DT
  2014-06-25 15:23     ` Bartlomiej Zolnierkiewicz
@ 2014-06-26 15:16       ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-26 15:16 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz
  Cc: Mark Rutland, Catalin Marinas, Tomasz Figa, Chander Kashyap,
	Kukjin Kim, Vincent Guittot, Nicolas Pitre, Daniel Lezcano,
	linux-arm-kernel, grant.likely, Charles Garcia-Tobin, devicetree,
	Kevin Hilman, linux-pm, Sebastian Capella, Mark Brown,
	Antti Miettinen, Paul Walmsley, Peter De Schrijver, Stephen Boyd,
	Amit

On Wed, Jun 25, 2014 at 04:23:38PM +0100, Bartlomiej Zolnierkiewicz wrote:
> 
> Hi,
> 
> On Wednesday, June 25, 2014 03:10:20 PM Lorenzo Pieralisi wrote:
> > With the introduction of DT based idle states, CPUidle drivers for
> > ARM can now initialize idle states data through properties in the device
> > tree.
> > 
> > This patch adds code to the Exynos CPUidle driver to dynamically
> > initialize idle states data through the updated device tree source
> > files.
> > 
> > Cc: Kukjin Kim <kgene.kim@samsung.com>
> > Cc: Tomasz Figa <t.figa@samsung.com>
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > ---
> > Compile tested, I am not sure I patched the right dts files, please check.
> 
> cpuidle-exynos driver is currently working properly in deeper cpuidle
> mode (AFTR) on Exynos4210 and Exynos5250 (please also see the following
> patch from Tomasz Figa: [1]).  There is ongoing work to AFTR mode work
> also on Exynos4x12 and Exynos3250 but it is not complete yet.  Exynos5410
> OTOH should probably use the generic big little cpuidle driver (this SoC
> is similar to Exynos5420 one for which Chander Kashyap has developed
> cpuidle-big_little support [2]).
> 
> Making long story short, I think that your patch should depend on patch
> [1] and update only exynos4210.dtsi and exynos5250.dtsi.  Also for your
> patch #6 there needs to be some coordination with merging of Chander's
> patchset ([2]).

Ok, thank you for the info, I will coordinate with Tomasz and Chander
then.

Lorenzo

> [1] http://www.spinics.net/lists/arm-kernel/msg341023.html
> [2] https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg664470.html
> 
> >  .../devicetree/bindings/arm/exynos/idle-states.txt | 27 ++++++++++++++++++++
> >  arch/arm/boot/dts/exynos3250.dtsi                  | 16 ++++++++++++
> >  arch/arm/boot/dts/exynos5250.dtsi                  | 15 +++++++++++
> >  arch/arm/boot/dts/exynos5410.dtsi                  | 17 +++++++++++++
> >  drivers/cpuidle/Kconfig.arm                        |  1 +
> >  drivers/cpuidle/cpuidle-exynos.c                   | 29 +++++++++++++---------
> >  6 files changed, 93 insertions(+), 12 deletions(-)
> >  create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt
> 
> Best regards,
> --
> Bartlomiej Zolnierkiewicz
> Samsung R&D Institute Poland
> Samsung Electronics
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 

^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 7/8] drivers: cpuidle: initialize Exynos driver through DT
@ 2014-06-26 15:16       ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-26 15:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 25, 2014 at 04:23:38PM +0100, Bartlomiej Zolnierkiewicz wrote:
> 
> Hi,
> 
> On Wednesday, June 25, 2014 03:10:20 PM Lorenzo Pieralisi wrote:
> > With the introduction of DT based idle states, CPUidle drivers for
> > ARM can now initialize idle states data through properties in the device
> > tree.
> > 
> > This patch adds code to the Exynos CPUidle driver to dynamically
> > initialize idle states data through the updated device tree source
> > files.
> > 
> > Cc: Kukjin Kim <kgene.kim@samsung.com>
> > Cc: Tomasz Figa <t.figa@samsung.com>
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > ---
> > Compile tested, I am not sure I patched the right dts files, please check.
> 
> cpuidle-exynos driver is currently working properly in deeper cpuidle
> mode (AFTR) on Exynos4210 and Exynos5250 (please also see the following
> patch from Tomasz Figa: [1]).  There is ongoing work to AFTR mode work
> also on Exynos4x12 and Exynos3250 but it is not complete yet.  Exynos5410
> OTOH should probably use the generic big little cpuidle driver (this SoC
> is similar to Exynos5420 one for which Chander Kashyap has developed
> cpuidle-big_little support [2]).
> 
> Making long story short, I think that your patch should depend on patch
> [1] and update only exynos4210.dtsi and exynos5250.dtsi.  Also for your
> patch #6 there needs to be some coordination with merging of Chander's
> patchset ([2]).

Ok, thank you for the info, I will coordinate with Tomasz and Chander
then.

Lorenzo

> [1] http://www.spinics.net/lists/arm-kernel/msg341023.html
> [2] https://www.mail-archive.com/linux-kernel at vger.kernel.org/msg664470.html
> 
> >  .../devicetree/bindings/arm/exynos/idle-states.txt | 27 ++++++++++++++++++++
> >  arch/arm/boot/dts/exynos3250.dtsi                  | 16 ++++++++++++
> >  arch/arm/boot/dts/exynos5250.dtsi                  | 15 +++++++++++
> >  arch/arm/boot/dts/exynos5410.dtsi                  | 17 +++++++++++++
> >  drivers/cpuidle/Kconfig.arm                        |  1 +
> >  drivers/cpuidle/cpuidle-exynos.c                   | 29 +++++++++++++---------
> >  6 files changed, 93 insertions(+), 12 deletions(-)
> >  create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt
> 
> Best regards,
> --
> Bartlomiej Zolnierkiewicz
> Samsung R&D Institute Poland
> Samsung Electronics
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 3/8] drivers: cpuidle: implement DT based idle states infrastructure
  2014-06-25 15:59     ` Mark Rutland
@ 2014-06-26 16:01       ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-26 16:01 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, linux-pm, devicetree, Sudeep Holla,
	Catalin Marinas, Charles Garcia-Tobin, Nicolas Pitre,
	Rob Herring, grant.likely, Peter De Schrijver, Santosh Shilimkar,
	Daniel Lezcano, Amit Kucheria, Vincent Guittot, Antti Miettinen,
	Stephen Boyd, Kevin Hilman, Sebastian Capella, Tomasz Figa,
	Mark Brown

On Wed, Jun 25, 2014 at 04:59:49PM +0100, Mark Rutland wrote:
> On Wed, Jun 25, 2014 at 03:10:16PM +0100, Lorenzo Pieralisi wrote:

[...]

> > diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c
> > new file mode 100644
> > index 0000000..5c16001c
> > --- /dev/null
> > +++ b/drivers/cpuidle/dt_idle_states.c
> > @@ -0,0 +1,283 @@
> > +/*
> > + * DT idle states parsing code.
> > + *
> > + * Copyright (C) 2014 ARM Ltd.
> > + * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#define pr_fmt(fmt) "DT idle-states: " fmt
> > +
> > +#include <linux/cpuidle.h>
> > +#include <linux/cpumask.h>
> > +#include <linux/errno.h>
> > +#include <linux/kernel.h>
> > +#include <linux/list.h>
> > +#include <linux/list_sort.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/slab.h>
> > +
> > +#include "dt_idle_states.h"
> > +
> > +struct state_elem {
> > +	struct list_head list;
> > +	struct device_node *node;
> > +	u32 val;
> > +};
> 
> Ah. So the fixed-size entry parameter requirement is because this code
> is in charge of allocating and freeing these structs?

Nope, I use this struct to sort the states and val is the value that
determines the order (ie power-rank) in this patch. If I used the
phandle lists for ordering nodes, this struct would disappear completely,
I have to check if that's feasible.

> > +
> > +static struct list_head head __initdata = LIST_HEAD_INIT(head);
> > +
> > +static bool __init state_cpu_valid(struct device_node *state_node,
> > +				   struct device_node *cpu_node)
> > +{
> > +	int i = 0;
> > +	struct device_node *cpu_state;
> > +
> > +	while ((cpu_state = of_parse_phandle(cpu_node,
> > +					     "cpu-idle-states", i++))) {
> > +		if (cpu_state && state_node == cpu_state) {
> 
> You can drop the cpu_state NULL check, it's implicit in the while loop.

Yep.

> > +			of_node_put(cpu_state);
> > +			return true;
> > +		}
> > +		of_node_put(cpu_state);
> > +	}
> > +	return false;
> > +}
> 
> Is it possible to use a bool ret variable to avoid the two of_node_put
> cases? Or does that end up making this larger?

No, I think you are right.

> > +static bool __init state_cpus_valid(const cpumask_t *cpus,
> > +				    struct device_node *state_node)
> > +{
> > +	int cpu;
> > +	struct device_node *cpu_node;
> > +
> > +	/*
> > +	 * Check if state is valid on driver cpumask cpus
> > +	 */
> > +	for_each_cpu(cpu, cpus) {
> > +		cpu_node = of_get_cpu_node(cpu, NULL);
> > +
> > +		if (!cpu_node) {
> > +			pr_err("Missing device node for CPU %d\n", cpu);
> > +			return false;
> > +		}
> > +
> > +		if (!state_cpu_valid(state_node, cpu_node))
> > +			return false;
> > +	}
> > +
> > +	return true;
> > +}
> 
> Doesn't this leave all the cpu node refcounts incremented? (it's painful
> to get device node refcounting right, I know).
> 
> I think you can use the similarly named of_cpu_device_node_get to find
> the CPU node. It uses the pointer stored in cpu->dev.of_node, so it
> doesn't have to walk the tree to find the CPU node. It also doesn't
> increment the refcount.
> 
> Unless this is too early for that?

I think I can use of_cpu_device_node_get(...), but I should still manage
refcount properly on that, which I am not doing here, good catch.

> > +static void __init init_state_node(struct cpuidle_driver *drv,
> > +				   struct device_node *state_node,
> > +				   int *cnt)
> > +{
> > +	struct cpuidle_state *idle_state;
> > +
> > +	pr_debug(" * %s...\n", state_node->full_name);
> > +
> > +	idle_state = &drv->states[*cnt];
> > +
> > +	if (of_property_read_u32(state_node, "wakeup-latency-us",
> > +				 &idle_state->exit_latency)) {
> 
> I'm not a fan of this construction, as the obvious reading is that we
> take the branch if we succeeded (which obviously isn't true as
> of_property_read_* return error codes). 
> 
> Could we change it to something like:
> 
> 	err = of_property_read_u32(state_node, "wakeup-latency-us",
> 				   &idle_state->exit_latency);
> 	if (err) {

You are right, I will update it.

> > +		u32 entry_latency, exit_latency;
> > +
> > +		if (of_property_read_u32(state_node, "entry-latency-us",
> > +					 &entry_latency)) {
> > +			pr_debug(" * %s missing entry-latency-us property\n",
> > +				 state_node->full_name);
> > +			return;
> > +		}
> 
> Returning without error code? Do the fields have sane default values?
> 
> Or is this safe because we didn't increment cnt?

The latter, but it isn't nice, agreed, it is just an internal interface
though. I will make it less opaque and easier to understand.

> > +
> > +		if (of_property_read_u32(state_node, "exit-latency-us",
> > +					 &exit_latency)) {
> > +			pr_debug(" * %s missing exit-latency-us property\n",
> > +				 state_node->full_name);
> > +			return;
> > +		}
> > +		/*
> > +		 * If wakeup-latency-us is missing, default to entry+exit
> > +		 * latencies as defined in idle states bindings
> > +		 */
> > +		idle_state->exit_latency = entry_latency + exit_latency;
> > +	}
> > +
> > +	if (of_property_read_u32(state_node, "min-residency-us",
> > +				 &idle_state->target_residency)) {
> > +		pr_debug(" * %s missing min-residency-us property\n",
> > +			     state_node->full_name);
> > +		return;
> > +	}
> > +
> > +	idle_state->flags = CPUIDLE_FLAG_TIME_VALID;
> > +	if (!of_property_read_bool(state_node, "timer-state-retained"))
> > +		idle_state->flags |= CPUIDLE_FLAG_TIMER_STOP;
> > + 	strncpy(idle_state->name, state_node->name, CPUIDLE_NAME_LEN);
> > +	strncpy(idle_state->desc, state_node->name, CPUIDLE_NAME_LEN);
> 
> Does the name make sense as a desc? Is a desc necessary?
> 
> CPUIDLE_DESC_LEN seems to exist, and is double CPUIDLE_NAME_LEN.

Yes, that's a copy and paste typo that I missed. BTW this code is likely
to disappear, since the way CPUidle driver manages these strings is changing.

As to is desc really needed, I need to check all existing drivers to
provide a complete answer.

> > +static void __init add_idle_states(struct cpuidle_driver *drv,
> > +				   struct device_node *idle_states)
> > +{
> > +	struct device_node *state_node;
> > +
> > +	for_each_child_of_node(idle_states, state_node) {
> > +		if ((!of_device_is_compatible(state_node, "arm,idle-state"))) {
> 
> Holy brackets batman! I think we can drop the outer ones given there's
> no assignment we want to supress warnings for.

Eheh sorry, should be a leftover, fixed.

> > +			pr_warn(" * %s: children of /cpus/idle-states must be \"arm,idle-state\" compatible\n",
> > +				     state_node->full_name);
> 
> Presumably the entire reason for having the compatible string is for
> future extensibility.
> 
> It would probably be better to have something like:
> 
> 	pr_warn("Node %s has unrecognised/missing compatible string\n",
> 		state_node->full_name);
> 

It makes sense, so I will change the pr_warn.

> > +			continue;
> > +		}
> > +		/*
> > +		 * If memory allocation fails, better bail out.
> > +		 * Initialized nodes are freed at initialization
> > +		 * completion in of_init_idle_driver().
> > +		 */
> > +		if ((add_state_node(drv->cpumask, state_node) == -ENOMEM))
> > +			break;
> 
> Can we not return? Or is the list sort important in the error case too?

Well, we might have a valid list of states that have to be sorted and I
think that's correct to break and not just return in that case.

Let's see if I can avoid the sorting altogether.

> > +	}
> > +	/*
> > +	 * Sort the states list before initializing the CPUidle driver
> > +	 * states array.
> > +	 */
> > +	list_sort(NULL, &head, state_cmp);
> > +}
> > +
> > +/**
> > + * dt_init_idle_driver() - Parse the DT idle states and initialize the
> > + *			   idle driver states array
> > + *
> > + * @drv:	  Pointer to CPU idle driver to be initialized
> > + * @state_nodes:  Array of struct device_nodes to be initialized if
> > + *		  init_nodes == true. Must be sized CPUIDLE_STATE_MAX
> > + * @start_idx:    First idle state index to be initialized
> > + * @init_nodes:   Boolean to request device nodes initialization
> > + *
> > + * On success the states array in the cpuidle driver contains
> > + * initialized entries in the states array, starting from index start_idx.
> > + * If init_nodes == true, on success the state_nodes array is initialized
> > + * with idle state DT node pointers, starting from index start_idx,
> > + * in a 1:1 relation with the idle driver states array.
> > + *
> > + * Return:
> > + *	0 on success
> > + *	<0 on failure
> > + */
> > +int __init dt_init_idle_driver(struct cpuidle_driver *drv,
> > +			       struct device_node *state_nodes[],
> > +			       unsigned int start_idx, bool init_nodes)
> > +{
> > +	struct device_node *idle_states_node;
> > +	int ret;
> > +
> > +	if (start_idx >= CPUIDLE_STATE_MAX) {
> > +		pr_warn("State index exceeds static CPU idle driver states array size\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (WARN(init_nodes && !state_nodes,
> > +		"Requested nodes stashing in an invalid nodes container\n"))
> > +		return -EINVAL;
> 
> That warning message is somewhat confusing, and I'm not sure I
> follow the logic.

It is a belt and braces check to make sure that, if the dt init code is
requested to fill in the state_nodes array (init_nodes == true), at least
the array base was passed and it is not a NULL pointer. I think I'd better
remove it and let the kernel oops if the interface is used wrongly, that would
be a kernel bug and there is not much to WARN about.

Thanks,
Lorenzo


^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 3/8] drivers: cpuidle: implement DT based idle states infrastructure
@ 2014-06-26 16:01       ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-26 16:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 25, 2014 at 04:59:49PM +0100, Mark Rutland wrote:
> On Wed, Jun 25, 2014 at 03:10:16PM +0100, Lorenzo Pieralisi wrote:

[...]

> > diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c
> > new file mode 100644
> > index 0000000..5c16001c
> > --- /dev/null
> > +++ b/drivers/cpuidle/dt_idle_states.c
> > @@ -0,0 +1,283 @@
> > +/*
> > + * DT idle states parsing code.
> > + *
> > + * Copyright (C) 2014 ARM Ltd.
> > + * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#define pr_fmt(fmt) "DT idle-states: " fmt
> > +
> > +#include <linux/cpuidle.h>
> > +#include <linux/cpumask.h>
> > +#include <linux/errno.h>
> > +#include <linux/kernel.h>
> > +#include <linux/list.h>
> > +#include <linux/list_sort.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/slab.h>
> > +
> > +#include "dt_idle_states.h"
> > +
> > +struct state_elem {
> > +	struct list_head list;
> > +	struct device_node *node;
> > +	u32 val;
> > +};
> 
> Ah. So the fixed-size entry parameter requirement is because this code
> is in charge of allocating and freeing these structs?

Nope, I use this struct to sort the states and val is the value that
determines the order (ie power-rank) in this patch. If I used the
phandle lists for ordering nodes, this struct would disappear completely,
I have to check if that's feasible.

> > +
> > +static struct list_head head __initdata = LIST_HEAD_INIT(head);
> > +
> > +static bool __init state_cpu_valid(struct device_node *state_node,
> > +				   struct device_node *cpu_node)
> > +{
> > +	int i = 0;
> > +	struct device_node *cpu_state;
> > +
> > +	while ((cpu_state = of_parse_phandle(cpu_node,
> > +					     "cpu-idle-states", i++))) {
> > +		if (cpu_state && state_node == cpu_state) {
> 
> You can drop the cpu_state NULL check, it's implicit in the while loop.

Yep.

> > +			of_node_put(cpu_state);
> > +			return true;
> > +		}
> > +		of_node_put(cpu_state);
> > +	}
> > +	return false;
> > +}
> 
> Is it possible to use a bool ret variable to avoid the two of_node_put
> cases? Or does that end up making this larger?

No, I think you are right.

> > +static bool __init state_cpus_valid(const cpumask_t *cpus,
> > +				    struct device_node *state_node)
> > +{
> > +	int cpu;
> > +	struct device_node *cpu_node;
> > +
> > +	/*
> > +	 * Check if state is valid on driver cpumask cpus
> > +	 */
> > +	for_each_cpu(cpu, cpus) {
> > +		cpu_node = of_get_cpu_node(cpu, NULL);
> > +
> > +		if (!cpu_node) {
> > +			pr_err("Missing device node for CPU %d\n", cpu);
> > +			return false;
> > +		}
> > +
> > +		if (!state_cpu_valid(state_node, cpu_node))
> > +			return false;
> > +	}
> > +
> > +	return true;
> > +}
> 
> Doesn't this leave all the cpu node refcounts incremented? (it's painful
> to get device node refcounting right, I know).
> 
> I think you can use the similarly named of_cpu_device_node_get to find
> the CPU node. It uses the pointer stored in cpu->dev.of_node, so it
> doesn't have to walk the tree to find the CPU node. It also doesn't
> increment the refcount.
> 
> Unless this is too early for that?

I think I can use of_cpu_device_node_get(...), but I should still manage
refcount properly on that, which I am not doing here, good catch.

> > +static void __init init_state_node(struct cpuidle_driver *drv,
> > +				   struct device_node *state_node,
> > +				   int *cnt)
> > +{
> > +	struct cpuidle_state *idle_state;
> > +
> > +	pr_debug(" * %s...\n", state_node->full_name);
> > +
> > +	idle_state = &drv->states[*cnt];
> > +
> > +	if (of_property_read_u32(state_node, "wakeup-latency-us",
> > +				 &idle_state->exit_latency)) {
> 
> I'm not a fan of this construction, as the obvious reading is that we
> take the branch if we succeeded (which obviously isn't true as
> of_property_read_* return error codes). 
> 
> Could we change it to something like:
> 
> 	err = of_property_read_u32(state_node, "wakeup-latency-us",
> 				   &idle_state->exit_latency);
> 	if (err) {

You are right, I will update it.

> > +		u32 entry_latency, exit_latency;
> > +
> > +		if (of_property_read_u32(state_node, "entry-latency-us",
> > +					 &entry_latency)) {
> > +			pr_debug(" * %s missing entry-latency-us property\n",
> > +				 state_node->full_name);
> > +			return;
> > +		}
> 
> Returning without error code? Do the fields have sane default values?
> 
> Or is this safe because we didn't increment cnt?

The latter, but it isn't nice, agreed, it is just an internal interface
though. I will make it less opaque and easier to understand.

> > +
> > +		if (of_property_read_u32(state_node, "exit-latency-us",
> > +					 &exit_latency)) {
> > +			pr_debug(" * %s missing exit-latency-us property\n",
> > +				 state_node->full_name);
> > +			return;
> > +		}
> > +		/*
> > +		 * If wakeup-latency-us is missing, default to entry+exit
> > +		 * latencies as defined in idle states bindings
> > +		 */
> > +		idle_state->exit_latency = entry_latency + exit_latency;
> > +	}
> > +
> > +	if (of_property_read_u32(state_node, "min-residency-us",
> > +				 &idle_state->target_residency)) {
> > +		pr_debug(" * %s missing min-residency-us property\n",
> > +			     state_node->full_name);
> > +		return;
> > +	}
> > +
> > +	idle_state->flags = CPUIDLE_FLAG_TIME_VALID;
> > +	if (!of_property_read_bool(state_node, "timer-state-retained"))
> > +		idle_state->flags |= CPUIDLE_FLAG_TIMER_STOP;
> > + 	strncpy(idle_state->name, state_node->name, CPUIDLE_NAME_LEN);
> > +	strncpy(idle_state->desc, state_node->name, CPUIDLE_NAME_LEN);
> 
> Does the name make sense as a desc? Is a desc necessary?
> 
> CPUIDLE_DESC_LEN seems to exist, and is double CPUIDLE_NAME_LEN.

Yes, that's a copy and paste typo that I missed. BTW this code is likely
to disappear, since the way CPUidle driver manages these strings is changing.

As to is desc really needed, I need to check all existing drivers to
provide a complete answer.

> > +static void __init add_idle_states(struct cpuidle_driver *drv,
> > +				   struct device_node *idle_states)
> > +{
> > +	struct device_node *state_node;
> > +
> > +	for_each_child_of_node(idle_states, state_node) {
> > +		if ((!of_device_is_compatible(state_node, "arm,idle-state"))) {
> 
> Holy brackets batman! I think we can drop the outer ones given there's
> no assignment we want to supress warnings for.

Eheh sorry, should be a leftover, fixed.

> > +			pr_warn(" * %s: children of /cpus/idle-states must be \"arm,idle-state\" compatible\n",
> > +				     state_node->full_name);
> 
> Presumably the entire reason for having the compatible string is for
> future extensibility.
> 
> It would probably be better to have something like:
> 
> 	pr_warn("Node %s has unrecognised/missing compatible string\n",
> 		state_node->full_name);
> 

It makes sense, so I will change the pr_warn.

> > +			continue;
> > +		}
> > +		/*
> > +		 * If memory allocation fails, better bail out.
> > +		 * Initialized nodes are freed at initialization
> > +		 * completion in of_init_idle_driver().
> > +		 */
> > +		if ((add_state_node(drv->cpumask, state_node) == -ENOMEM))
> > +			break;
> 
> Can we not return? Or is the list sort important in the error case too?

Well, we might have a valid list of states that have to be sorted and I
think that's correct to break and not just return in that case.

Let's see if I can avoid the sorting altogether.

> > +	}
> > +	/*
> > +	 * Sort the states list before initializing the CPUidle driver
> > +	 * states array.
> > +	 */
> > +	list_sort(NULL, &head, state_cmp);
> > +}
> > +
> > +/**
> > + * dt_init_idle_driver() - Parse the DT idle states and initialize the
> > + *			   idle driver states array
> > + *
> > + * @drv:	  Pointer to CPU idle driver to be initialized
> > + * @state_nodes:  Array of struct device_nodes to be initialized if
> > + *		  init_nodes == true. Must be sized CPUIDLE_STATE_MAX
> > + * @start_idx:    First idle state index to be initialized
> > + * @init_nodes:   Boolean to request device nodes initialization
> > + *
> > + * On success the states array in the cpuidle driver contains
> > + * initialized entries in the states array, starting from index start_idx.
> > + * If init_nodes == true, on success the state_nodes array is initialized
> > + * with idle state DT node pointers, starting from index start_idx,
> > + * in a 1:1 relation with the idle driver states array.
> > + *
> > + * Return:
> > + *	0 on success
> > + *	<0 on failure
> > + */
> > +int __init dt_init_idle_driver(struct cpuidle_driver *drv,
> > +			       struct device_node *state_nodes[],
> > +			       unsigned int start_idx, bool init_nodes)
> > +{
> > +	struct device_node *idle_states_node;
> > +	int ret;
> > +
> > +	if (start_idx >= CPUIDLE_STATE_MAX) {
> > +		pr_warn("State index exceeds static CPU idle driver states array size\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (WARN(init_nodes && !state_nodes,
> > +		"Requested nodes stashing in an invalid nodes container\n"))
> > +		return -EINVAL;
> 
> That warning message is somewhat confusing, and I'm not sure I
> follow the logic.

It is a belt and braces check to make sure that, if the dt init code is
requested to fill in the state_nodes array (init_nodes == true), at least
the array base was passed and it is not a NULL pointer. I think I'd better
remove it and let the kernel oops if the interface is used wrongly, that would
be a kernel bug and there is not much to WARN about.

Thanks,
Lorenzo

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 4/8] arm64: add PSCI CPU_SUSPEND based cpu_suspend support
  2014-06-25 20:52       ` Geoff Levand
@ 2014-06-26 16:55         ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-26 16:55 UTC (permalink / raw)
  To: Geoff Levand
  Cc: linux-arm-kernel, linux-pm, devicetree, Mark Rutland,
	Paul Walmsley, Vincent Guittot, Kevin Hilman, Nicolas Pitre,
	Catalin Marinas, Peter De Schrijver, Daniel Lezcano,
	Stephen Boyd, Amit Kucheria, Chander Kashyap, Sebastian Capella,
	Rob Herring, Santosh Shilimkar, Mark Brown, Sudeep Holla,
	grant.likely

Hi Geoff,

On Wed, Jun 25, 2014 at 09:52:00PM +0100, Geoff Levand wrote:
> Hi Lorenzo,
> 
> On Wed, 2014-06-25 at 15:10 +0100, Lorenzo Pieralisi wrote:
> > diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
> 
> > +	/*
> > +	 * This is belt-and-braces: make sure that if the idle
> > +	 * specified protocol is psci, the cpu_ops have been
> > +	 * initialized to psci operations. Anything else is
> > +	 * a recipe for mayhem.
> > +	 */
> > +	for_each_cpu(cpu, drv->cpumask) {
> > +		cpu_ops_ptr = cpu_ops[cpu];
> > +		if (WARN_ON(!cpu_ops_ptr || strcmp(cpu_ops_ptr->name, "psci")))
> > +			return -EOPNOTSUPP;
> > +	}
> 
> I'm not sure how drv->cpumask is setup, but if a system has mixed enable
> methods, say some cpus 'spin-table' and some 'psci', will this give a
> false error?

I do not think that's a false error. If the idle states specify an
entry-method == psci, and cpu_ops for some cpus are not set to PSCI,
obviously because the enable-method specified that, that's a firmware bug.

> If drv->cpumask should only include 'psci' cpus, then should this be a
> BUG()?

Ok, if we got here, it is because the idle-states entry-method was set
to PSCI. Now, if any of the CPUs in the driver mask has a cpu_ops
pointer != PSCI, we have a problem and we should warn on that. I do
not think that justifies a BUG_ON, but that's one of those things, it is
debatable.

Question is whether the check should also be carried out at cpu_ops
initialization (ie to check for mixed cpu_ops), for certain if the
idle states entry-method is PSCI and cpu_ops != PSCI we should
WARN/BUG on that. Or embed this idle state parameters initialization at
cpu_ops init (see other thread you started) so that we can kill two
birds with one stone.

> > +
> > +	psci_states = kcalloc(drv->state_count, sizeof(*psci_states),
> > +			      GFP_KERNEL);
> > +
> > +	if (!psci_states) {
> > +		pr_warn("psci idle state allocation failed\n");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	for_each_cpu(cpu, drv->cpumask) {
> > +		if (per_cpu(psci_power_state, cpu)) {
> > +			pr_warn("idle states already initialized on cpu %u\n",
> > +				cpu);
> 
> This seems like an implementation problem, if so, shouldn't this be
> pr_debug()?

Maybe, I will give it some thought.

> >  #endif
> >  
> > +#ifdef CONFIG_ARM64_CPU_SUSPEND
> > +static int cpu_psci_cpu_suspend(unsigned long index)
> > +{
> > +	struct psci_power_state *state = __get_cpu_var(psci_power_state);
> > +
> > +	if (!state)
> > +		return -EOPNOTSUPP;
> > +
> > +	return psci_ops.cpu_suspend(state[index], virt_to_phys(cpu_resume));
> > +}
> > +#endif
> 
> Why not put a __maybe_unused attribute on cpu_psci_cpu_suspend() and
> remove the preprocessor conditional.  That way this code will always be
> compiled, and with therefor always get a build test.  The linker should
> strip out the unused code when CONFIG_ARM64_CPU_SUSPEND=n and the code
> below is not compiled. 

It can make sense, yes.

Thanks,
Lorenzo


^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 4/8] arm64: add PSCI CPU_SUSPEND based cpu_suspend support
@ 2014-06-26 16:55         ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-26 16:55 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Geoff,

On Wed, Jun 25, 2014 at 09:52:00PM +0100, Geoff Levand wrote:
> Hi Lorenzo,
> 
> On Wed, 2014-06-25 at 15:10 +0100, Lorenzo Pieralisi wrote:
> > diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
> 
> > +	/*
> > +	 * This is belt-and-braces: make sure that if the idle
> > +	 * specified protocol is psci, the cpu_ops have been
> > +	 * initialized to psci operations. Anything else is
> > +	 * a recipe for mayhem.
> > +	 */
> > +	for_each_cpu(cpu, drv->cpumask) {
> > +		cpu_ops_ptr = cpu_ops[cpu];
> > +		if (WARN_ON(!cpu_ops_ptr || strcmp(cpu_ops_ptr->name, "psci")))
> > +			return -EOPNOTSUPP;
> > +	}
> 
> I'm not sure how drv->cpumask is setup, but if a system has mixed enable
> methods, say some cpus 'spin-table' and some 'psci', will this give a
> false error?

I do not think that's a false error. If the idle states specify an
entry-method == psci, and cpu_ops for some cpus are not set to PSCI,
obviously because the enable-method specified that, that's a firmware bug.

> If drv->cpumask should only include 'psci' cpus, then should this be a
> BUG()?

Ok, if we got here, it is because the idle-states entry-method was set
to PSCI. Now, if any of the CPUs in the driver mask has a cpu_ops
pointer != PSCI, we have a problem and we should warn on that. I do
not think that justifies a BUG_ON, but that's one of those things, it is
debatable.

Question is whether the check should also be carried out at cpu_ops
initialization (ie to check for mixed cpu_ops), for certain if the
idle states entry-method is PSCI and cpu_ops != PSCI we should
WARN/BUG on that. Or embed this idle state parameters initialization at
cpu_ops init (see other thread you started) so that we can kill two
birds with one stone.

> > +
> > +	psci_states = kcalloc(drv->state_count, sizeof(*psci_states),
> > +			      GFP_KERNEL);
> > +
> > +	if (!psci_states) {
> > +		pr_warn("psci idle state allocation failed\n");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	for_each_cpu(cpu, drv->cpumask) {
> > +		if (per_cpu(psci_power_state, cpu)) {
> > +			pr_warn("idle states already initialized on cpu %u\n",
> > +				cpu);
> 
> This seems like an implementation problem, if so, shouldn't this be
> pr_debug()?

Maybe, I will give it some thought.

> >  #endif
> >  
> > +#ifdef CONFIG_ARM64_CPU_SUSPEND
> > +static int cpu_psci_cpu_suspend(unsigned long index)
> > +{
> > +	struct psci_power_state *state = __get_cpu_var(psci_power_state);
> > +
> > +	if (!state)
> > +		return -EOPNOTSUPP;
> > +
> > +	return psci_ops.cpu_suspend(state[index], virt_to_phys(cpu_resume));
> > +}
> > +#endif
> 
> Why not put a __maybe_unused attribute on cpu_psci_cpu_suspend() and
> remove the preprocessor conditional.  That way this code will always be
> compiled, and with therefor always get a build test.  The linker should
> strip out the unused code when CONFIG_ARM64_CPU_SUSPEND=n and the code
> below is not compiled. 

It can make sense, yes.

Thanks,
Lorenzo

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 1/8] Documentation: arm: define DT idle states bindings
  2014-06-25 17:37       ` Lorenzo Pieralisi
@ 2014-06-26 18:32         ` Rob Herring
  -1 siblings, 0 replies; 70+ messages in thread
From: Rob Herring @ 2014-06-26 18:32 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Mark Rutland, linux-arm-kernel, linux-pm, devicetree,
	Sudeep Holla, Catalin Marinas, Charles Garcia-Tobin,
	Nicolas Pitre, Rob Herring, grant.likely, Peter De Schrijver,
	Santosh Shilimkar, Daniel Lezcano, Amit Kucheria,
	Vincent Guittot, Antti Miettinen, Stephen Boyd, Kevin Hilman,
	Sebastian Capella, Tomasz Figa

On Wed, Jun 25, 2014 at 12:37 PM, Lorenzo Pieralisi
<lorenzo.pieralisi@arm.com> wrote:
> On Wed, Jun 25, 2014 at 03:58:49PM +0100, Mark Rutland wrote:
>> Hi Lorenzo,
>>
>> On Wed, Jun 25, 2014 at 03:10:14PM +0100, Lorenzo Pieralisi wrote:
>> > ARM based platforms implement a variety of power management schemes that
>> > allow processors to enter idle states at run-time.
>> > The parameters defining these idle states vary on a per-platform basis forcing
>> > the OS to hardcode the state parameters in platform specific static tables
>> > whose size grows as the number of platforms supported in the kernel increases
>> > and hampers device drivers standardization.
>> >
>> > Therefore, this patch aims at standardizing idle state device tree bindings for
>> > ARM platforms. Bindings define idle state parameters inclusive of entry methods
>> > and state latencies, to allow operating systems to retrieve the configuration
>> > entries from the device tree and initialize the related power management
>> > drivers, paving the way for common code in the kernel to deal with idle
>> > states and removing the need for static data in current and previous kernel
>> > versions.
>> >
>> > Reviewed-by: Sebastian Capella <sebcape@gmail.com>
>> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> > ---
>> >  Documentation/devicetree/bindings/arm/cpus.txt     |   8 +
>> >  .../devicetree/bindings/arm/idle-states.txt        | 733 +++++++++++++++++++++
>> >  2 files changed, 741 insertions(+)
>> >  create mode 100644 Documentation/devicetree/bindings/arm/idle-states.txt
>>
>> [...]


>> > +       - power-rank
>> > +               Usage: Required
>> > +               Value type: <u32>
>> > +               Definition: It represents the idle state power-rank.
>> > +                           An increasing value implies less power
>> > +                           consumption. It must be given a sequential
>> > +                           value = {0, 1, ....}, starting from 0.
>> > +                           Phandles in the cpu nodes [1] cpu-idle-states
>> > +                           array property are not allowed to point at idle
>> > +                           state nodes having the same power-rank value.
>>
>> Why can't this be implicit in the order of the cpu-idle-states list?
>> That way it's impossible to violate the ordering requirement.
>
> You mean the phandles list in the cpu nodes ? Maybe, but this would
> require the list to be the same order for all cpu nodes on which the
> idle states are valid, or just take one and use that.
>
> It can be viable, as long as everyone agrees, every time I post this
> code someone comes up with a new idea on how to sort the states and
> honestly I would like to be done with that.

power-rank feels like an index in disguise. I agree with the phandle
list defining the order.

>> > +       - entry-method-param
>> > +               Usage: See definition.
>> > +               Value type: <u32>
>> > +               Definition: Depends on the idle-states node entry-method
>> > +                           property value. Refer to the entry-method bindings
>> > +                           for this property value definition.
>>
>> Should this not be left up to the particular mechanism to describe?
>> e.g. for PSCI we could have a arm,psci-suspend-param property.
>
> It was like that in early postings, and probably was better than the
> current definition. I need to think about that but I am almost convinced
> you are right.

I think arm,psci-suspend-param is the right way to go.

Rob

^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 1/8] Documentation: arm: define DT idle states bindings
@ 2014-06-26 18:32         ` Rob Herring
  0 siblings, 0 replies; 70+ messages in thread
From: Rob Herring @ 2014-06-26 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 25, 2014 at 12:37 PM, Lorenzo Pieralisi
<lorenzo.pieralisi@arm.com> wrote:
> On Wed, Jun 25, 2014 at 03:58:49PM +0100, Mark Rutland wrote:
>> Hi Lorenzo,
>>
>> On Wed, Jun 25, 2014 at 03:10:14PM +0100, Lorenzo Pieralisi wrote:
>> > ARM based platforms implement a variety of power management schemes that
>> > allow processors to enter idle states at run-time.
>> > The parameters defining these idle states vary on a per-platform basis forcing
>> > the OS to hardcode the state parameters in platform specific static tables
>> > whose size grows as the number of platforms supported in the kernel increases
>> > and hampers device drivers standardization.
>> >
>> > Therefore, this patch aims at standardizing idle state device tree bindings for
>> > ARM platforms. Bindings define idle state parameters inclusive of entry methods
>> > and state latencies, to allow operating systems to retrieve the configuration
>> > entries from the device tree and initialize the related power management
>> > drivers, paving the way for common code in the kernel to deal with idle
>> > states and removing the need for static data in current and previous kernel
>> > versions.
>> >
>> > Reviewed-by: Sebastian Capella <sebcape@gmail.com>
>> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> > ---
>> >  Documentation/devicetree/bindings/arm/cpus.txt     |   8 +
>> >  .../devicetree/bindings/arm/idle-states.txt        | 733 +++++++++++++++++++++
>> >  2 files changed, 741 insertions(+)
>> >  create mode 100644 Documentation/devicetree/bindings/arm/idle-states.txt
>>
>> [...]


>> > +       - power-rank
>> > +               Usage: Required
>> > +               Value type: <u32>
>> > +               Definition: It represents the idle state power-rank.
>> > +                           An increasing value implies less power
>> > +                           consumption. It must be given a sequential
>> > +                           value = {0, 1, ....}, starting from 0.
>> > +                           Phandles in the cpu nodes [1] cpu-idle-states
>> > +                           array property are not allowed to point at idle
>> > +                           state nodes having the same power-rank value.
>>
>> Why can't this be implicit in the order of the cpu-idle-states list?
>> That way it's impossible to violate the ordering requirement.
>
> You mean the phandles list in the cpu nodes ? Maybe, but this would
> require the list to be the same order for all cpu nodes on which the
> idle states are valid, or just take one and use that.
>
> It can be viable, as long as everyone agrees, every time I post this
> code someone comes up with a new idea on how to sort the states and
> honestly I would like to be done with that.

power-rank feels like an index in disguise. I agree with the phandle
list defining the order.

>> > +       - entry-method-param
>> > +               Usage: See definition.
>> > +               Value type: <u32>
>> > +               Definition: Depends on the idle-states node entry-method
>> > +                           property value. Refer to the entry-method bindings
>> > +                           for this property value definition.
>>
>> Should this not be left up to the particular mechanism to describe?
>> e.g. for PSCI we could have a arm,psci-suspend-param property.
>
> It was like that in early postings, and probably was better than the
> current definition. I need to think about that but I am almost convinced
> you are right.

I think arm,psci-suspend-param is the right way to go.

Rob

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 1/8] Documentation: arm: define DT idle states bindings
  2014-06-26 10:17       ` Lorenzo Pieralisi
@ 2014-06-26 19:30         ` Nicolas Pitre
  -1 siblings, 0 replies; 70+ messages in thread
From: Nicolas Pitre @ 2014-06-26 19:30 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: linux-arm-kernel, linux-pm, devicetree, Mark Rutland,
	Sudeep Holla, Catalin Marinas, Charles Garcia-Tobin, Rob Herring,
	grant.likely, Peter De Schrijver, Santosh Shilimkar,
	Daniel Lezcano, Amit Kucheria, Vincent Guittot, Antti Miettinen,
	Stephen Boyd, Kevin Hilman, Sebastian Capella, Tomasz Figa,
	Mark Brown

On Thu, 26 Jun 2014, Lorenzo Pieralisi wrote:

> On Wed, Jun 25, 2014 at 04:56:02PM +0100, Nicolas Pitre wrote:
> > On Wed, 25 Jun 2014, Lorenzo Pieralisi wrote:
> > 
> > > ARM based platforms implement a variety of power management schemes that
> > > allow processors to enter idle states at run-time.
> > > The parameters defining these idle states vary on a per-platform basis forcing
> > > the OS to hardcode the state parameters in platform specific static tables
> > > whose size grows as the number of platforms supported in the kernel increases
> > > and hampers device drivers standardization.
> > >
> > > Therefore, this patch aims at standardizing idle state device tree bindings for
> > > ARM platforms. Bindings define idle state parameters inclusive of entry methods
> > > and state latencies, to allow operating systems to retrieve the configuration
> > > entries from the device tree and initialize the related power management
> > > drivers, paving the way for common code in the kernel to deal with idle
> > > states and removing the need for static data in current and previous kernel
> > > versions.
> > >
> > > Reviewed-by: Sebastian Capella <sebcape@gmail.com>
> > > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > 
> > Excellent.
> > 
> > Reviewed-by: Nicolas Pitre <nico@linaro.org>
> 
> Thanks Nico, there are still a couple of niggles to sort out (ie local
> timer state), but the bulk of the document should be complete I hope.
> 
> I will postpone adding your (and Seb's) Reviewed-by until we have a
> final agreement if it is ok with you.

As you wish.  The parts I care about are now well covered.  I don't 
think I know enough about timers to comment further.

Nicolas

^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 1/8] Documentation: arm: define DT idle states bindings
@ 2014-06-26 19:30         ` Nicolas Pitre
  0 siblings, 0 replies; 70+ messages in thread
From: Nicolas Pitre @ 2014-06-26 19:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 26 Jun 2014, Lorenzo Pieralisi wrote:

> On Wed, Jun 25, 2014 at 04:56:02PM +0100, Nicolas Pitre wrote:
> > On Wed, 25 Jun 2014, Lorenzo Pieralisi wrote:
> > 
> > > ARM based platforms implement a variety of power management schemes that
> > > allow processors to enter idle states at run-time.
> > > The parameters defining these idle states vary on a per-platform basis forcing
> > > the OS to hardcode the state parameters in platform specific static tables
> > > whose size grows as the number of platforms supported in the kernel increases
> > > and hampers device drivers standardization.
> > >
> > > Therefore, this patch aims at standardizing idle state device tree bindings for
> > > ARM platforms. Bindings define idle state parameters inclusive of entry methods
> > > and state latencies, to allow operating systems to retrieve the configuration
> > > entries from the device tree and initialize the related power management
> > > drivers, paving the way for common code in the kernel to deal with idle
> > > states and removing the need for static data in current and previous kernel
> > > versions.
> > >
> > > Reviewed-by: Sebastian Capella <sebcape@gmail.com>
> > > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > 
> > Excellent.
> > 
> > Reviewed-by: Nicolas Pitre <nico@linaro.org>
> 
> Thanks Nico, there are still a couple of niggles to sort out (ie local
> timer state), but the bulk of the document should be complete I hope.
> 
> I will postpone adding your (and Seb's) Reviewed-by until we have a
> final agreement if it is ok with you.

As you wish.  The parts I care about are now well covered.  I don't 
think I know enough about timers to comment further.

Nicolas

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 1/8] Documentation: arm: define DT idle states bindings
  2014-06-25 14:58     ` Mark Rutland
@ 2014-06-27 10:53       ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-27 10:53 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, linux-pm, devicetree, Sudeep Holla,
	Catalin Marinas, Charles Garcia-Tobin, Nicolas Pitre,
	Rob Herring, grant.likely, Peter De Schrijver, Santosh Shilimkar,
	Daniel Lezcano, Amit Kucheria, Vincent Guittot, Antti Miettinen,
	Stephen Boyd, Kevin Hilman, Sebastian Capella, Tomasz Figa,
	Mark Brown

On Wed, Jun 25, 2014 at 03:58:49PM +0100, Mark Rutland wrote:

[...]

> > +===========================================
> > +4 - state node
> > +===========================================
> > +
> > +A state node represents an idle state description and must be defined as
> > +follows:
> > +
> > +- state node
> > +
> > +       Description: must be child of the idle-states node
> > +
> > +       The state node name shall follow standard device tree naming
> > +       rules ([5], 2.2.1 "Node names"), in particular state nodes which
> > +       are siblings within a single common parent must be given a unique name.
> > +
> > +       The idle state entered by executing the wfi instruction (idle_standby
> > +       SBSA,[3][4]) is considered standard on all ARM platforms and therefore
> > +       must not be listed.
> > +
> > +       With the definitions provided above, the following list represents
> > +       the valid properties for a state node:
> > +
> > +       - compatible
> > +               Usage: Required
> > +               Value type: <stringlist>
> > +               Definition: Must be "arm,idle-state".
> > +
> > +       - logic-state-retained
> > +               Usage: See definition
> > +               Value type: <none>
> > +               Definition: if present logic is retained on state entry,
> > +                           otherwise it is lost.
> 
> What logic state is retained? All system registers?
> 
> > +       - cache-state-retained
> > +               Usage: See definition
> > +               Value type: <none>
> > +               Definition: if present cache memory is retained on state entry,
> > +                           otherwise it is lost.
> 
> Likewise, how much of the cache hierarchy is affected? Any of it? All of
> it?
> 
> > +       - timer-state-retained
> > +               Usage: See definition
> > +               Value type: <none>
> > +               Definition: if present the timer control logic is retained on
> > +                            state entry, otherwise it is lost.
> 
> The architected generic timers? Any CPU-local timers? Or any timers
> whatsoever?

Ok, as I mentioned this timer property is a blocking point for the
entire set. I gave it more thought, and it is a very hard nut to crack,
even if we resort to power domains (tick devices do not even contain
struct device or device node pointers, even if I added a list of
phandles to timers that are lost on idle state entry I would not be able
to figure out if the tick device is lost on idle state entry).

I am reasoning in kernel terms, I know it is bad but I can't help it
in this case.

Would a boolean property like the following one be deemed acceptable, eg:

- local-timer-stop

I want to be 100% honest here, this might turn out a Linux specific
thing, or might be not, but I still think it is representative of how HW
works.

Comments welcome and would be very appreciated on this specific detail.

Thanks,
Lorenzo


^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 1/8] Documentation: arm: define DT idle states bindings
@ 2014-06-27 10:53       ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-06-27 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 25, 2014 at 03:58:49PM +0100, Mark Rutland wrote:

[...]

> > +===========================================
> > +4 - state node
> > +===========================================
> > +
> > +A state node represents an idle state description and must be defined as
> > +follows:
> > +
> > +- state node
> > +
> > +       Description: must be child of the idle-states node
> > +
> > +       The state node name shall follow standard device tree naming
> > +       rules ([5], 2.2.1 "Node names"), in particular state nodes which
> > +       are siblings within a single common parent must be given a unique name.
> > +
> > +       The idle state entered by executing the wfi instruction (idle_standby
> > +       SBSA,[3][4]) is considered standard on all ARM platforms and therefore
> > +       must not be listed.
> > +
> > +       With the definitions provided above, the following list represents
> > +       the valid properties for a state node:
> > +
> > +       - compatible
> > +               Usage: Required
> > +               Value type: <stringlist>
> > +               Definition: Must be "arm,idle-state".
> > +
> > +       - logic-state-retained
> > +               Usage: See definition
> > +               Value type: <none>
> > +               Definition: if present logic is retained on state entry,
> > +                           otherwise it is lost.
> 
> What logic state is retained? All system registers?
> 
> > +       - cache-state-retained
> > +               Usage: See definition
> > +               Value type: <none>
> > +               Definition: if present cache memory is retained on state entry,
> > +                           otherwise it is lost.
> 
> Likewise, how much of the cache hierarchy is affected? Any of it? All of
> it?
> 
> > +       - timer-state-retained
> > +               Usage: See definition
> > +               Value type: <none>
> > +               Definition: if present the timer control logic is retained on
> > +                            state entry, otherwise it is lost.
> 
> The architected generic timers? Any CPU-local timers? Or any timers
> whatsoever?

Ok, as I mentioned this timer property is a blocking point for the
entire set. I gave it more thought, and it is a very hard nut to crack,
even if we resort to power domains (tick devices do not even contain
struct device or device node pointers, even if I added a list of
phandles to timers that are lost on idle state entry I would not be able
to figure out if the tick device is lost on idle state entry).

I am reasoning in kernel terms, I know it is bad but I can't help it
in this case.

Would a boolean property like the following one be deemed acceptable, eg:

- local-timer-stop

I want to be 100% honest here, this might turn out a Linux specific
thing, or might be not, but I still think it is representative of how HW
works.

Comments welcome and would be very appreciated on this specific detail.

Thanks,
Lorenzo

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 7/8] drivers: cpuidle: initialize Exynos driver through DT
  2014-06-25 15:23     ` Bartlomiej Zolnierkiewicz
@ 2014-07-17 14:20       ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-07-17 14:20 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz
  Cc: Mark Rutland, Catalin Marinas, Tomasz Figa, Chander Kashyap,
	Kukjin Kim, Vincent Guittot, Nicolas Pitre, Daniel Lezcano,
	linux-arm-kernel, grant.likely, Charles Garcia-Tobin, devicetree,
	Kevin Hilman, linux-pm, Sebastian Capella, Mark Brown,
	Antti Miettinen, Paul Walmsley, Peter De Schrijver, Stephen Boyd,
	Amit

On Wed, Jun 25, 2014 at 04:23:38PM +0100, Bartlomiej Zolnierkiewicz wrote:
> 
> Hi,
> 
> On Wednesday, June 25, 2014 03:10:20 PM Lorenzo Pieralisi wrote:
> > With the introduction of DT based idle states, CPUidle drivers for
> > ARM can now initialize idle states data through properties in the device
> > tree.
> > 
> > This patch adds code to the Exynos CPUidle driver to dynamically
> > initialize idle states data through the updated device tree source
> > files.
> > 
> > Cc: Kukjin Kim <kgene.kim@samsung.com>
> > Cc: Tomasz Figa <t.figa@samsung.com>
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > ---
> > Compile tested, I am not sure I patched the right dts files, please check.
> 
> cpuidle-exynos driver is currently working properly in deeper cpuidle
> mode (AFTR) on Exynos4210 and Exynos5250 (please also see the following
> patch from Tomasz Figa: [1]).  There is ongoing work to AFTR mode work
> also on Exynos4x12 and Exynos3250 but it is not complete yet.  Exynos5410
> OTOH should probably use the generic big little cpuidle driver (this SoC
> is similar to Exynos5420 one for which Chander Kashyap has developed
> cpuidle-big_little support [2]).
> 
> Making long story short, I think that your patch should depend on patch
> [1] and update only exynos4210.dtsi and exynos5250.dtsi.  Also for your
> patch #6 there needs to be some coordination with merging of Chander's
> patchset ([2]).
> 
> [1] http://www.spinics.net/lists/arm-kernel/msg341023.html
> [2] https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg664470.html


exynos4210.dtsi does not even have cpu nodes in it. Should I add them or
this might trigger regression (ie cpu_logical_map()) ?

I will post a new version soon, should I just patch 5250 for now ?

I would need help to test this patch thanks.

Lorenzo

> >  .../devicetree/bindings/arm/exynos/idle-states.txt | 27 ++++++++++++++++++++
> >  arch/arm/boot/dts/exynos3250.dtsi                  | 16 ++++++++++++
> >  arch/arm/boot/dts/exynos5250.dtsi                  | 15 +++++++++++
> >  arch/arm/boot/dts/exynos5410.dtsi                  | 17 +++++++++++++
> >  drivers/cpuidle/Kconfig.arm                        |  1 +
> >  drivers/cpuidle/cpuidle-exynos.c                   | 29 +++++++++++++---------
> >  6 files changed, 93 insertions(+), 12 deletions(-)
> >  create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt
> 
> Best regards,
> --
> Bartlomiej Zolnierkiewicz
> Samsung R&D Institute Poland
> Samsung Electronics
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 

^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 7/8] drivers: cpuidle: initialize Exynos driver through DT
@ 2014-07-17 14:20       ` Lorenzo Pieralisi
  0 siblings, 0 replies; 70+ messages in thread
From: Lorenzo Pieralisi @ 2014-07-17 14:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 25, 2014 at 04:23:38PM +0100, Bartlomiej Zolnierkiewicz wrote:
> 
> Hi,
> 
> On Wednesday, June 25, 2014 03:10:20 PM Lorenzo Pieralisi wrote:
> > With the introduction of DT based idle states, CPUidle drivers for
> > ARM can now initialize idle states data through properties in the device
> > tree.
> > 
> > This patch adds code to the Exynos CPUidle driver to dynamically
> > initialize idle states data through the updated device tree source
> > files.
> > 
> > Cc: Kukjin Kim <kgene.kim@samsung.com>
> > Cc: Tomasz Figa <t.figa@samsung.com>
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > ---
> > Compile tested, I am not sure I patched the right dts files, please check.
> 
> cpuidle-exynos driver is currently working properly in deeper cpuidle
> mode (AFTR) on Exynos4210 and Exynos5250 (please also see the following
> patch from Tomasz Figa: [1]).  There is ongoing work to AFTR mode work
> also on Exynos4x12 and Exynos3250 but it is not complete yet.  Exynos5410
> OTOH should probably use the generic big little cpuidle driver (this SoC
> is similar to Exynos5420 one for which Chander Kashyap has developed
> cpuidle-big_little support [2]).
> 
> Making long story short, I think that your patch should depend on patch
> [1] and update only exynos4210.dtsi and exynos5250.dtsi.  Also for your
> patch #6 there needs to be some coordination with merging of Chander's
> patchset ([2]).
> 
> [1] http://www.spinics.net/lists/arm-kernel/msg341023.html
> [2] https://www.mail-archive.com/linux-kernel at vger.kernel.org/msg664470.html


exynos4210.dtsi does not even have cpu nodes in it. Should I add them or
this might trigger regression (ie cpu_logical_map()) ?

I will post a new version soon, should I just patch 5250 for now ?

I would need help to test this patch thanks.

Lorenzo

> >  .../devicetree/bindings/arm/exynos/idle-states.txt | 27 ++++++++++++++++++++
> >  arch/arm/boot/dts/exynos3250.dtsi                  | 16 ++++++++++++
> >  arch/arm/boot/dts/exynos5250.dtsi                  | 15 +++++++++++
> >  arch/arm/boot/dts/exynos5410.dtsi                  | 17 +++++++++++++
> >  drivers/cpuidle/Kconfig.arm                        |  1 +
> >  drivers/cpuidle/cpuidle-exynos.c                   | 29 +++++++++++++---------
> >  6 files changed, 93 insertions(+), 12 deletions(-)
> >  create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt
> 
> Best regards,
> --
> Bartlomiej Zolnierkiewicz
> Samsung R&D Institute Poland
> Samsung Electronics
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 7/8] drivers: cpuidle: initialize Exynos driver through DT
  2014-07-17 14:20       ` Lorenzo Pieralisi
@ 2014-07-18  8:45         ` Chander Kashyap
  -1 siblings, 0 replies; 70+ messages in thread
From: Chander Kashyap @ 2014-07-18  8:45 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Mark Rutland, Catalin Marinas, Tomasz Figa, Kukjin Kim,
	Vincent Guittot, Nicolas Pitre, Daniel Lezcano, linux-arm-kernel,
	grant.likely, Charles Garcia-Tobin, devicetree, Kevin Hilman,
	linux-pm, Sebastian Capella, Rob Herring, Antti Miettinen,
	Paul Walmsley, Peter De Schrijver, Stephen Boyd, Amit Kucheria,
	Bartlomiej

Hi Lorenzo,


On 17 July 2014 19:50, Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> wrote:
> On Wed, Jun 25, 2014 at 04:23:38PM +0100, Bartlomiej Zolnierkiewicz wrote:
>>
>> Hi,
>>
>> On Wednesday, June 25, 2014 03:10:20 PM Lorenzo Pieralisi wrote:
>> > With the introduction of DT based idle states, CPUidle drivers for
>> > ARM can now initialize idle states data through properties in the device
>> > tree.
>> >
>> > This patch adds code to the Exynos CPUidle driver to dynamically
>> > initialize idle states data through the updated device tree source
>> > files.
>> >
>> > Cc: Kukjin Kim <kgene.kim@samsung.com>
>> > Cc: Tomasz Figa <t.figa@samsung.com>
>> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> > ---
>> > Compile tested, I am not sure I patched the right dts files, please check.
>>
>> cpuidle-exynos driver is currently working properly in deeper cpuidle
>> mode (AFTR) on Exynos4210 and Exynos5250 (please also see the following
>> patch from Tomasz Figa: [1]).  There is ongoing work to AFTR mode work
>> also on Exynos4x12 and Exynos3250 but it is not complete yet.  Exynos5410
>> OTOH should probably use the generic big little cpuidle driver (this SoC
>> is similar to Exynos5420 one for which Chander Kashyap has developed
>> cpuidle-big_little support [2]).
>>
>> Making long story short, I think that your patch should depend on patch
>> [1] and update only exynos4210.dtsi and exynos5250.dtsi.  Also for your
>> patch #6 there needs to be some coordination with merging of Chander's
>> patchset ([2]).
>>
>> [1] http://www.spinics.net/lists/arm-kernel/msg341023.html
>> [2] https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg664470.html
>
>
> exynos4210.dtsi does not even have cpu nodes in it. Should I add them or
> this might trigger regression (ie cpu_logical_map()) ?

Yes that can cause regression.

>
> I will post a new version soon, should I just patch 5250 for now ?
>
> I would need help to test this patch thanks.

I can test the patch for 5250.

>
> Lorenzo
>
>> >  .../devicetree/bindings/arm/exynos/idle-states.txt | 27 ++++++++++++++++++++
>> >  arch/arm/boot/dts/exynos3250.dtsi                  | 16 ++++++++++++
>> >  arch/arm/boot/dts/exynos5250.dtsi                  | 15 +++++++++++
>> >  arch/arm/boot/dts/exynos5410.dtsi                  | 17 +++++++++++++
>> >  drivers/cpuidle/Kconfig.arm                        |  1 +
>> >  drivers/cpuidle/cpuidle-exynos.c                   | 29 +++++++++++++---------
>> >  6 files changed, 93 insertions(+), 12 deletions(-)
>> >  create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt
>>
>> Best regards,
>> --
>> Bartlomiej Zolnierkiewicz
>> Samsung R&D Institute Poland
>> Samsung Electronics
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-pm" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>>
>



-- 
with warm regards,
Chander Kashyap

^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 7/8] drivers: cpuidle: initialize Exynos driver through DT
@ 2014-07-18  8:45         ` Chander Kashyap
  0 siblings, 0 replies; 70+ messages in thread
From: Chander Kashyap @ 2014-07-18  8:45 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lorenzo,


On 17 July 2014 19:50, Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> wrote:
> On Wed, Jun 25, 2014 at 04:23:38PM +0100, Bartlomiej Zolnierkiewicz wrote:
>>
>> Hi,
>>
>> On Wednesday, June 25, 2014 03:10:20 PM Lorenzo Pieralisi wrote:
>> > With the introduction of DT based idle states, CPUidle drivers for
>> > ARM can now initialize idle states data through properties in the device
>> > tree.
>> >
>> > This patch adds code to the Exynos CPUidle driver to dynamically
>> > initialize idle states data through the updated device tree source
>> > files.
>> >
>> > Cc: Kukjin Kim <kgene.kim@samsung.com>
>> > Cc: Tomasz Figa <t.figa@samsung.com>
>> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> > ---
>> > Compile tested, I am not sure I patched the right dts files, please check.
>>
>> cpuidle-exynos driver is currently working properly in deeper cpuidle
>> mode (AFTR) on Exynos4210 and Exynos5250 (please also see the following
>> patch from Tomasz Figa: [1]).  There is ongoing work to AFTR mode work
>> also on Exynos4x12 and Exynos3250 but it is not complete yet.  Exynos5410
>> OTOH should probably use the generic big little cpuidle driver (this SoC
>> is similar to Exynos5420 one for which Chander Kashyap has developed
>> cpuidle-big_little support [2]).
>>
>> Making long story short, I think that your patch should depend on patch
>> [1] and update only exynos4210.dtsi and exynos5250.dtsi.  Also for your
>> patch #6 there needs to be some coordination with merging of Chander's
>> patchset ([2]).
>>
>> [1] http://www.spinics.net/lists/arm-kernel/msg341023.html
>> [2] https://www.mail-archive.com/linux-kernel at vger.kernel.org/msg664470.html
>
>
> exynos4210.dtsi does not even have cpu nodes in it. Should I add them or
> this might trigger regression (ie cpu_logical_map()) ?

Yes that can cause regression.

>
> I will post a new version soon, should I just patch 5250 for now ?
>
> I would need help to test this patch thanks.

I can test the patch for 5250.

>
> Lorenzo
>
>> >  .../devicetree/bindings/arm/exynos/idle-states.txt | 27 ++++++++++++++++++++
>> >  arch/arm/boot/dts/exynos3250.dtsi                  | 16 ++++++++++++
>> >  arch/arm/boot/dts/exynos5250.dtsi                  | 15 +++++++++++
>> >  arch/arm/boot/dts/exynos5410.dtsi                  | 17 +++++++++++++
>> >  drivers/cpuidle/Kconfig.arm                        |  1 +
>> >  drivers/cpuidle/cpuidle-exynos.c                   | 29 +++++++++++++---------
>> >  6 files changed, 93 insertions(+), 12 deletions(-)
>> >  create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt
>>
>> Best regards,
>> --
>> Bartlomiej Zolnierkiewicz
>> Samsung R&D Institute Poland
>> Samsung Electronics
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-pm" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>>
>



-- 
with warm regards,
Chander Kashyap

^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v5 7/8] drivers: cpuidle: initialize Exynos driver through DT
  2014-07-18  8:45         ` Chander Kashyap
@ 2014-07-18 16:10           ` Bartlomiej Zolnierkiewicz
  -1 siblings, 0 replies; 70+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2014-07-18 16:10 UTC (permalink / raw)
  To: Chander Kashyap
  Cc: Mark Rutland, Catalin Marinas, Tomasz Figa, Kukjin Kim,
	Lorenzo Pieralisi, Vincent Guittot, Nicolas Pitre,
	Daniel Lezcano, linux-arm-kernel, grant.likely,
	Charles Garcia-Tobin, devicetree, Kevin Hilman, linux-pm,
	Sebastian Capella, Rob Herring, Antti Miettinen, Paul Walmsley,
	Peter De Schrijver, Stephen Boyd, Amit


Hi,

On Friday, July 18, 2014 02:15:01 PM Chander Kashyap wrote:
> Hi Lorenzo,
> 
> 
> On 17 July 2014 19:50, Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> wrote:
> > On Wed, Jun 25, 2014 at 04:23:38PM +0100, Bartlomiej Zolnierkiewicz wrote:
> >>
> >> Hi,
> >>
> >> On Wednesday, June 25, 2014 03:10:20 PM Lorenzo Pieralisi wrote:
> >> > With the introduction of DT based idle states, CPUidle drivers for
> >> > ARM can now initialize idle states data through properties in the device
> >> > tree.
> >> >
> >> > This patch adds code to the Exynos CPUidle driver to dynamically
> >> > initialize idle states data through the updated device tree source
> >> > files.
> >> >
> >> > Cc: Kukjin Kim <kgene.kim@samsung.com>
> >> > Cc: Tomasz Figa <t.figa@samsung.com>
> >> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> >> > ---
> >> > Compile tested, I am not sure I patched the right dts files, please check.
> >>
> >> cpuidle-exynos driver is currently working properly in deeper cpuidle
> >> mode (AFTR) on Exynos4210 and Exynos5250 (please also see the following
> >> patch from Tomasz Figa: [1]).  There is ongoing work to AFTR mode work
> >> also on Exynos4x12 and Exynos3250 but it is not complete yet.  Exynos5410
> >> OTOH should probably use the generic big little cpuidle driver (this SoC
> >> is similar to Exynos5420 one for which Chander Kashyap has developed
> >> cpuidle-big_little support [2]).
> >>
> >> Making long story short, I think that your patch should depend on patch
> >> [1] and update only exynos4210.dtsi and exynos5250.dtsi.  Also for your
> >> patch #6 there needs to be some coordination with merging of Chander's
> >> patchset ([2]).
> >>
> >> [1] http://www.spinics.net/lists/arm-kernel/msg341023.html
> >> [2] https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg664470.html
> >
> >
> > exynos4210.dtsi does not even have cpu nodes in it. Should I add them or
> > this might trigger regression (ie cpu_logical_map()) ?
> 
> Yes that can cause regression.

Yes, two patches from Tomasz Figa are needed to fix it:

- [PATCH 2/6] ARM: EXYNOS: Fix core ID used by platsmp and hotplug code
  http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg32811.html

- [PATCH] irqchip: gic: Fix core ID calculation when topology is read from DT
  http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg34277.html

> > I will post a new version soon, should I just patch 5250 for now ?

I posted patch adding CPU nodes for Exynos4 SoCs to DT:

- [PATCH] ARM: dts: add CPU nodes for Exynos4 SoCs
  http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg34378.html

Please make your series depend on it and add Exynos4210 support.

> > I would need help to test this patch thanks.
> 
> I can test the patch for 5250.

I can do testing on Exynos4210 if needed.

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

> >
> > Lorenzo
> >
> >> >  .../devicetree/bindings/arm/exynos/idle-states.txt | 27 ++++++++++++++++++++
> >> >  arch/arm/boot/dts/exynos3250.dtsi                  | 16 ++++++++++++
> >> >  arch/arm/boot/dts/exynos5250.dtsi                  | 15 +++++++++++
> >> >  arch/arm/boot/dts/exynos5410.dtsi                  | 17 +++++++++++++
> >> >  drivers/cpuidle/Kconfig.arm                        |  1 +
> >> >  drivers/cpuidle/cpuidle-exynos.c                   | 29 +++++++++++++---------
> >> >  6 files changed, 93 insertions(+), 12 deletions(-)
> >> >  create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt

^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH v5 7/8] drivers: cpuidle: initialize Exynos driver through DT
@ 2014-07-18 16:10           ` Bartlomiej Zolnierkiewicz
  0 siblings, 0 replies; 70+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2014-07-18 16:10 UTC (permalink / raw)
  To: linux-arm-kernel


Hi,

On Friday, July 18, 2014 02:15:01 PM Chander Kashyap wrote:
> Hi Lorenzo,
> 
> 
> On 17 July 2014 19:50, Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> wrote:
> > On Wed, Jun 25, 2014 at 04:23:38PM +0100, Bartlomiej Zolnierkiewicz wrote:
> >>
> >> Hi,
> >>
> >> On Wednesday, June 25, 2014 03:10:20 PM Lorenzo Pieralisi wrote:
> >> > With the introduction of DT based idle states, CPUidle drivers for
> >> > ARM can now initialize idle states data through properties in the device
> >> > tree.
> >> >
> >> > This patch adds code to the Exynos CPUidle driver to dynamically
> >> > initialize idle states data through the updated device tree source
> >> > files.
> >> >
> >> > Cc: Kukjin Kim <kgene.kim@samsung.com>
> >> > Cc: Tomasz Figa <t.figa@samsung.com>
> >> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> >> > ---
> >> > Compile tested, I am not sure I patched the right dts files, please check.
> >>
> >> cpuidle-exynos driver is currently working properly in deeper cpuidle
> >> mode (AFTR) on Exynos4210 and Exynos5250 (please also see the following
> >> patch from Tomasz Figa: [1]).  There is ongoing work to AFTR mode work
> >> also on Exynos4x12 and Exynos3250 but it is not complete yet.  Exynos5410
> >> OTOH should probably use the generic big little cpuidle driver (this SoC
> >> is similar to Exynos5420 one for which Chander Kashyap has developed
> >> cpuidle-big_little support [2]).
> >>
> >> Making long story short, I think that your patch should depend on patch
> >> [1] and update only exynos4210.dtsi and exynos5250.dtsi.  Also for your
> >> patch #6 there needs to be some coordination with merging of Chander's
> >> patchset ([2]).
> >>
> >> [1] http://www.spinics.net/lists/arm-kernel/msg341023.html
> >> [2] https://www.mail-archive.com/linux-kernel at vger.kernel.org/msg664470.html
> >
> >
> > exynos4210.dtsi does not even have cpu nodes in it. Should I add them or
> > this might trigger regression (ie cpu_logical_map()) ?
> 
> Yes that can cause regression.

Yes, two patches from Tomasz Figa are needed to fix it:

- [PATCH 2/6] ARM: EXYNOS: Fix core ID used by platsmp and hotplug code
  http://www.mail-archive.com/linux-samsung-soc at vger.kernel.org/msg32811.html

- [PATCH] irqchip: gic: Fix core ID calculation when topology is read from DT
  http://www.mail-archive.com/linux-samsung-soc at vger.kernel.org/msg34277.html

> > I will post a new version soon, should I just patch 5250 for now ?

I posted patch adding CPU nodes for Exynos4 SoCs to DT:

- [PATCH] ARM: dts: add CPU nodes for Exynos4 SoCs
  http://www.mail-archive.com/linux-samsung-soc at vger.kernel.org/msg34378.html

Please make your series depend on it and add Exynos4210 support.

> > I would need help to test this patch thanks.
> 
> I can test the patch for 5250.

I can do testing on Exynos4210 if needed.

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

> >
> > Lorenzo
> >
> >> >  .../devicetree/bindings/arm/exynos/idle-states.txt | 27 ++++++++++++++++++++
> >> >  arch/arm/boot/dts/exynos3250.dtsi                  | 16 ++++++++++++
> >> >  arch/arm/boot/dts/exynos5250.dtsi                  | 15 +++++++++++
> >> >  arch/arm/boot/dts/exynos5410.dtsi                  | 17 +++++++++++++
> >> >  drivers/cpuidle/Kconfig.arm                        |  1 +
> >> >  drivers/cpuidle/cpuidle-exynos.c                   | 29 +++++++++++++---------
> >> >  6 files changed, 93 insertions(+), 12 deletions(-)
> >> >  create mode 100644 Documentation/devicetree/bindings/arm/exynos/idle-states.txt

^ permalink raw reply	[flat|nested] 70+ messages in thread

end of thread, other threads:[~2014-07-18 16:10 UTC | newest]

Thread overview: 70+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-25 14:10 [PATCH v5 0/8] ARM generic idle states Lorenzo Pieralisi
2014-06-25 14:10 ` Lorenzo Pieralisi
2014-06-25 14:10 ` [PATCH v5 1/8] Documentation: arm: define DT idle states bindings Lorenzo Pieralisi
2014-06-25 14:10   ` Lorenzo Pieralisi
2014-06-25 14:58   ` Mark Rutland
2014-06-25 14:58     ` Mark Rutland
2014-06-25 17:37     ` Lorenzo Pieralisi
2014-06-25 17:37       ` Lorenzo Pieralisi
2014-06-26 18:32       ` Rob Herring
2014-06-26 18:32         ` Rob Herring
2014-06-27 10:53     ` Lorenzo Pieralisi
2014-06-27 10:53       ` Lorenzo Pieralisi
2014-06-25 15:56   ` Nicolas Pitre
2014-06-25 15:56     ` Nicolas Pitre
2014-06-26 10:17     ` Lorenzo Pieralisi
2014-06-26 10:17       ` Lorenzo Pieralisi
2014-06-26 19:30       ` Nicolas Pitre
2014-06-26 19:30         ` Nicolas Pitre
2014-06-25 14:10 ` [PATCH v5 2/8] Documentation: devicetree: psci: define CPU suspend parameter Lorenzo Pieralisi
2014-06-25 14:10   ` Lorenzo Pieralisi
2014-06-25 14:10 ` [PATCH v5 3/8] drivers: cpuidle: implement DT based idle states infrastructure Lorenzo Pieralisi
2014-06-25 14:10   ` Lorenzo Pieralisi
2014-06-25 15:59   ` Mark Rutland
2014-06-25 15:59     ` Mark Rutland
2014-06-26 16:01     ` Lorenzo Pieralisi
2014-06-26 16:01       ` Lorenzo Pieralisi
     [not found] ` <1403705421-17597-1-git-send-email-lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
2014-06-25 14:10   ` [PATCH v5 4/8] arm64: add PSCI CPU_SUSPEND based cpu_suspend support Lorenzo Pieralisi
2014-06-25 14:10     ` Lorenzo Pieralisi
2014-06-25 16:09     ` Mark Rutland
2014-06-25 16:09       ` Mark Rutland
2014-06-26 11:23       ` Lorenzo Pieralisi
2014-06-26 11:23         ` Lorenzo Pieralisi
2014-06-25 20:52     ` Geoff Levand
2014-06-25 20:52       ` Geoff Levand
2014-06-26 16:55       ` Lorenzo Pieralisi
2014-06-26 16:55         ` Lorenzo Pieralisi
2014-06-25 14:10 ` [PATCH v5 5/8] drivers: cpuidle: CPU idle ARM64 driver Lorenzo Pieralisi
2014-06-25 14:10   ` Lorenzo Pieralisi
2014-06-25 20:34   ` Geoff Levand
2014-06-25 20:34     ` Geoff Levand
2014-06-25 14:10 ` [PATCH v5 6/8] drivers: cpuidle: initialize big.LITTLE driver through DT Lorenzo Pieralisi
2014-06-25 14:10   ` Lorenzo Pieralisi
2014-06-25 15:06   ` Mark Rutland
2014-06-25 15:06     ` Mark Rutland
2014-06-25 16:44     ` Lorenzo Pieralisi
2014-06-25 16:44       ` Lorenzo Pieralisi
2014-06-25 14:10 ` [PATCH v5 7/8] drivers: cpuidle: initialize Exynos " Lorenzo Pieralisi
2014-06-25 14:10   ` Lorenzo Pieralisi
2014-06-25 15:13   ` Mark Rutland
2014-06-25 15:13     ` Mark Rutland
2014-06-25 16:58     ` Lorenzo Pieralisi
2014-06-25 16:58       ` Lorenzo Pieralisi
2014-06-25 15:23   ` Bartlomiej Zolnierkiewicz
2014-06-25 15:23     ` Bartlomiej Zolnierkiewicz
2014-06-26 15:16     ` Lorenzo Pieralisi
2014-06-26 15:16       ` Lorenzo Pieralisi
2014-07-17 14:20     ` Lorenzo Pieralisi
2014-07-17 14:20       ` Lorenzo Pieralisi
2014-07-18  8:45       ` Chander Kashyap
2014-07-18  8:45         ` Chander Kashyap
2014-07-18 16:10         ` Bartlomiej Zolnierkiewicz
2014-07-18 16:10           ` Bartlomiej Zolnierkiewicz
2014-06-25 14:10 ` [PATCH v5 8/8] arm64: boot: dts: update rtsm aemv8 dts with PSCI and idle states Lorenzo Pieralisi
2014-06-25 14:10   ` Lorenzo Pieralisi
2014-06-25 14:27   ` Mark Rutland
2014-06-25 14:27     ` Mark Rutland
2014-06-25 17:47     ` Lorenzo Pieralisi
2014-06-25 17:47       ` Lorenzo Pieralisi
2014-06-25 14:29   ` Sudeep Holla
2014-06-25 14:29     ` Sudeep Holla

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.