1.. _pm-power-domain: 2 3Power Domain 4############ 5 6Introduction 7************ 8 9The Zephyr power domain abstraction is designed to support groupings of devices 10powered by a common source to be notified of power source state changes in a 11generic fashion. Application code that is using device A does not need to know 12that device B is on the same power domain and should also be configured into a 13low power state. 14 15Power domains are optional on Zephyr, to enable this feature the 16option :kconfig:option:`CONFIG_PM_DEVICE_POWER_DOMAIN` has to be set. 17 18When a power domain turns itself on or off, it is the responsibility of the 19power domain to notify all devices using it through their power management 20callback called with 21:c:enumerator:`PM_DEVICE_ACTION_TURN_ON` or 22:c:enumerator:`PM_DEVICE_ACTION_TURN_OFF` respectively. This 23work flow is illustrated in the diagram below. 24 25.. _pm-domain-work-flow: 26 27.. graphviz:: 28 :caption: Power domain work flow 29 30 digraph { 31 rankdir="TB"; 32 33 action [style=invis] 34 { 35 rank = same; 36 rankdir="LR" 37 devA [label="gpio0"] 38 devB [label="gpio1"] 39 } 40 domain [label="gpio_domain"] 41 42 action -> devA [label="pm_device_get()"] 43 devA:se -> domain:n [label="pm_device_get()"] 44 45 domain -> devB [label="action_cb(PM_DEVICE_ACTION_TURN_ON)"] 46 domain:sw -> devA:sw [label="action_cb(PM_DEVICE_ACTION_TURN_ON)"] 47 } 48 49Internal Power Domains 50---------------------- 51 52Most of the devices in an SoC have independent power control that can 53be turned on or off to reduce power consumption. But there is a 54significant amount of static current leakage that can't be controlled 55only using device power management. To solve this problem, SoCs 56normally are divided into several regions grouping devices that 57are generally used together, so that an unused region can be 58completely powered off to eliminate this leakage. These regions are 59called "power domains", can be present in a hierarchy and can be 60nested. 61 62External Power Domains 63---------------------- 64 65Devices external to a SoC can be powered from sources other than the main power 66source of the SoC. These external sources are typically a switch, a regulator, 67or a dedicated power IC. Multiple devices can be powered from the same source, 68and this grouping of devices is typically called a "power domain". 69 70Placing devices on power domains can be done for a variety of reasons, 71including to enable devices with high power consumption in low power mode to be 72completely turned off when not in use. 73 74Implementation guidelines 75************************* 76 77In a first place, a device that acts as a power domain needs to 78declare compatible with ``power-domain``. Taking 79:ref:`pm-domain-work-flow` as example, the following code defines a 80domain called ``gpio_domain``. 81 82.. code-block:: devicetree 83 84 gpio_domain: gpio_domain@4 { 85 compatible = "power-domain"; 86 ... 87 }; 88 89A power domain needs to implement the PM action callback used by the 90PM subsystem to turn devices on and off. 91 92.. code-block:: c 93 94 static int mydomain_pm_action(const struct device *dev, 95 enum pm_device_action *action) 96 { 97 switch (action) { 98 case PM_DEVICE_ACTION_RESUME: 99 /* resume the domain */ 100 ... 101 /* notify children domain is now powered */ 102 pm_device_children_action_run(dev, PM_DEVICE_ACTION_TURN_ON, NULL); 103 break; 104 case PM_DEVICE_ACTION_SUSPEND: 105 /* notify children domain is going down */ 106 pm_device_children_action_run(dev, PM_DEVICE_ACTION_TURN_OFF, NULL); 107 /* suspend the domain */ 108 ... 109 break; 110 case PM_DEVICE_ACTION_TURN_ON: 111 /* turn on the domain (e.g. setup control pins to disabled) */ 112 ... 113 break; 114 case PM_DEVICE_ACTION_TURN_OFF: 115 /* turn off the domain (e.g. reset control pins to default state) */ 116 ... 117 break; 118 default: 119 return -ENOTSUP; 120 } 121 122 return 0; 123 } 124 125Devices belonging to this device can be declared referring it in the 126``power-domain`` node's property. The example below declares devices 127``gpio0`` and ``gpio1`` belonging to domain ``gpio_domain```. 128 129.. code-block:: devicetree 130 131 &gpio0 { 132 compatible = "zephyr,gpio-emul"; 133 gpio-controller; 134 power-domain = <&gpio_domain>; 135 }; 136 137 &gpio1 { 138 compatible = "zephyr,gpio-emul"; 139 gpio-controller; 140 power-domain = <&gpio_domain>; 141 }; 142 143All devices under a domain will be notified when the domain changes 144state. These notifications are sent as actions in the device PM action 145callback and can be used by them to do any additional work required. 146They can safely be ignored though. 147 148.. code-block:: c 149 150 static int mydev_pm_action(const struct device *dev, 151 enum pm_device_action *action) 152 { 153 switch (action) { 154 case PM_DEVICE_ACTION_SUSPEND: 155 /* suspend the device */ 156 ... 157 break; 158 case PM_DEVICE_ACTION_RESUME: 159 /* resume the device */ 160 ... 161 break; 162 case PM_DEVICE_ACTION_TURN_ON: 163 /* configure the device into low power mode */ 164 ... 165 break; 166 case PM_DEVICE_ACTION_TURN_OFF: 167 /* prepare the device for power down */ 168 ... 169 break; 170 default: 171 return -ENOTSUP; 172 } 173 174 return 0; 175 } 176 177.. note:: 178 179 It is responsibility of driver or the application to set the domain as 180 "wakeup" source if a device depending on it is used as "wakeup" source. 181