docs: pm: Add power domain information
Document power domains on Zephyr. Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com> Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
This commit is contained in:
parent
9e9fb319a7
commit
2b9d2f6f6c
4 changed files with 193 additions and 0 deletions
|
@ -75,6 +75,11 @@ Glossary of Terms
|
|||
The set of Zephyr-supplied files that implement the Zephyr kernel,
|
||||
including its core services, device drivers, network stack, and so on.
|
||||
|
||||
power domain
|
||||
A power domain is a collection of devices for which power is
|
||||
applied and removed collectively in a single action. Power
|
||||
domains are represented by :c:struct:`device`.
|
||||
|
||||
power gating
|
||||
Power gating reduces power consumption by shutting off areas of an
|
||||
integrated circuit that are not in use.
|
||||
|
|
|
@ -134,3 +134,12 @@ later calling :c:func:`pm_device_wakeup_enable`.
|
|||
devices that should not be suspended.
|
||||
It is responsability of driver or the application to do any additional
|
||||
configuration required by the device to support it.
|
||||
|
||||
Power Domain
|
||||
************
|
||||
|
||||
Power domain on Zephyr is represented as a regular device. The power management
|
||||
subsystem ensures that a domain is resumed before and suspended after devices
|
||||
using it. When :kconfig:`CONFIG_PM_DEVICE_RUNTIME` is enabled, every time a
|
||||
device is suspended or resumed the same action is done in the domain the
|
||||
device belongs.
|
||||
|
|
|
@ -14,3 +14,4 @@ advantage of the power saving features of SOCs.
|
|||
system
|
||||
device
|
||||
device_runtime
|
||||
power_domain
|
||||
|
|
178
doc/guides/pm/power_domain.rst
Normal file
178
doc/guides/pm/power_domain.rst
Normal file
|
@ -0,0 +1,178 @@
|
|||
Power Domain
|
||||
############
|
||||
|
||||
Introduction
|
||||
************
|
||||
|
||||
The Zephyr power domain abstraction is designed to support groupings of devices
|
||||
powered by a common source to be notified of power source state changes in a
|
||||
generic fashion. Application code that is using device A does not need to know
|
||||
that device B is on the same power domain and should also be configured into a
|
||||
low power state.
|
||||
|
||||
Power domains are optional on Zephyr, to enable this feature the
|
||||
option :kconfig:`PM_DEVICE_POWER_DOMAIN` has to be set.
|
||||
|
||||
When a power domain turns itself on or off, it is the responsibilty of the
|
||||
power domain to notify all devices using it through their power management
|
||||
callback called with
|
||||
:c:enumerator:`PM_DEVICE_ACTION_TURN_ON` or
|
||||
:c:enumerator:`PM_DEVICE_ACTION_TURN_OFF` respectively. This
|
||||
work flow is illustrated in the diagram bellow.
|
||||
|
||||
.. _pm-domain-work-flow:
|
||||
|
||||
.. graphviz::
|
||||
:caption: Power domain work flow
|
||||
|
||||
digraph {
|
||||
rankdir="TB";
|
||||
|
||||
action [style=invis]
|
||||
{
|
||||
rank = same;
|
||||
rankdir="LR"
|
||||
devA [label="gpio0"]
|
||||
devB [label="gpio1"]
|
||||
}
|
||||
domain [label="gpio_domain"]
|
||||
|
||||
action -> devA [label="pm_device_get()"]
|
||||
devA:se -> domain:n [label="pm_device_get()"]
|
||||
|
||||
domain -> devB [label="action_cb(PM_DEVICE_ACTION_TURN_ON)"]
|
||||
domain:sw -> devA:sw [label="action_cb(PM_DEVICE_ACTION_TURN_ON)"]
|
||||
}
|
||||
|
||||
Internal Power Domains
|
||||
----------------------
|
||||
|
||||
Most of the devices in an SoC have independent power control that can
|
||||
be turned on or off to reduce power consumption. But there is a
|
||||
significant amount of static current leakage that can't be controlled
|
||||
only using device power management. To solve this problem, SoCs
|
||||
normally are divided into several regions grouping devices that
|
||||
are generally used together, so that an unused region can be
|
||||
completely powered off to eliminate this leakage. These regions are
|
||||
called "power domains", can be present in a hierarchy and can be
|
||||
nested.
|
||||
|
||||
External Power Domains
|
||||
----------------------
|
||||
|
||||
Devices external to a SoC can be powered from sources other than the main power
|
||||
source of the SoC. These external sources are typically a switch, a regulator,
|
||||
or a dedicated power IC. Multiple devices can be powered from the same source,
|
||||
and this grouping of devices is typically called a "power domain".
|
||||
|
||||
Placing devices on power domains can be done for a variety of reasons,
|
||||
including to enable devices with high power consumption in low power mode to be
|
||||
completely turned off when not in use.
|
||||
|
||||
Implementation guidelines
|
||||
*************************
|
||||
|
||||
In a first place, a device that acts as a power domain needs to
|
||||
declare compatible with ``power-domain``. Taking
|
||||
:ref:`pm-domain-work-flow` as example, the following code defines a
|
||||
domain called ``gpio_domain``.
|
||||
|
||||
.. code-block:: devicetree
|
||||
|
||||
gpio_domain: gpio_domain@4 {
|
||||
compatible = "power-domain";
|
||||
...
|
||||
};
|
||||
|
||||
A power domain needs to implement the PM action callback used by the
|
||||
PM subsystem to turn devices on and off.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
static int mydomain_pm_action(const struct device *dev,
|
||||
enum pm_device_action *action)
|
||||
{
|
||||
switch (action) {
|
||||
case PM_DEVICE_ACTION_RESUME:
|
||||
/* resume the domain */
|
||||
...
|
||||
/* notify children domain is now powered */
|
||||
pm_device_children_action_run(dev, PM_DEVICE_ACTION_TURN_ON, NULL);
|
||||
break;
|
||||
case PM_DEVICE_ACTION_SUSPEND:
|
||||
/* notify children domain is going down */
|
||||
pm_device_children_action_run(dev, PM_DEVICE_ACTION_TURN_OFF, NULL);
|
||||
/* suspend the domain */
|
||||
...
|
||||
break;
|
||||
case PM_DEVICE_ACTION_TURN_ON:
|
||||
/* turn on the domain (e.g. setup control pins to disabled) */
|
||||
...
|
||||
break;
|
||||
case PM_DEVICE_ACTION_TURN_OFF:
|
||||
/* turn off the domain (e.g. reset control pins to default state) */
|
||||
...
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Devices belonging to this device can be declared referring it in the
|
||||
``power-domain`` node's property. The example below declares devices
|
||||
``gpio0`` and ``gpio1`` belonging to domain ``gpio_domain```.
|
||||
|
||||
.. code-block:: devicetree
|
||||
|
||||
&gpio0 {
|
||||
compatible = "zephyr,gpio-emul";
|
||||
gpio-controller;
|
||||
power-domain = <&gpio_domain>;
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
compatible = "zephyr,gpio-emul";
|
||||
gpio-controller;
|
||||
power-domain = <&gpio_domain>;
|
||||
};
|
||||
|
||||
All devices under a domain will be notified when the domain changes
|
||||
state. These notifications are sent as actions in the device PM action
|
||||
callback and can be used by them to do any additional work required.
|
||||
They can safely be ignored though.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
static int mydev_pm_action(const struct device *dev,
|
||||
enum pm_device_action *action)
|
||||
{
|
||||
switch (action) {
|
||||
case PM_DEVICE_ACTION_SUSPEND:
|
||||
/* suspend the device */
|
||||
...
|
||||
break;
|
||||
case PM_DEVICE_ACTION_RESUME:
|
||||
/* resume the device */
|
||||
...
|
||||
break;
|
||||
case PM_DEVICE_ACTION_TURN_ON:
|
||||
/* configure the device into low power mode */
|
||||
...
|
||||
break;
|
||||
case PM_DEVICE_ACTION_TURN_OFF:
|
||||
/* prepare the device for power down */
|
||||
...
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
.. note::
|
||||
|
||||
It is responsibility of driver or the application to set the domain as
|
||||
"wakeup" source if a device depending on it is used as "wakeup" source.
|
Loading…
Add table
Add a link
Reference in a new issue