![]() |
RT-Thread RTOS
An open source embedded real-time operating system
|
Header: **components/drivers/include/drivers/core/power_domain.h**. Core: **components/drivers/core/power_domain.c**.
A power domain models a switchable SoC power island (GPU block, USB PHY, display cluster, …). Consumers reference domains in DT via **power-domains**; the provider driver registers **struct rt_dm_power_domain** (or a proxy) and implements **power_on / power_off**.
This is not system shutdown (System power off and reboot (core)) and not a regulator rail (Regulator).
In-tree provider example: **components/drivers/pmdomain/pm-domain-scmi.c** (SCMI **genpd**).
On remove/shutdown / failed probe:
**-RT_EEMPTY**: no **power-domains** property — Platform bus treats this as OK.
Consumer:
| Property | Role |
|---|---|
**power-domains** | Phandle(s) to provider; cells per **#power-domain-cells** |
**power-domain-names** | Maps names to index for **rt_dm_power_domain_get_by_name** |
Provider node must expose **#power-domain-cells** and bind **rt_ofw_data** to either:
rt_ofw_data object name | Type |
|---|---|
**PMD** (RT_POWER_DOMAIN_OBJ_NAME) | Direct **struct rt_dm_power_domain** |
**PMP** (RT_POWER_DOMAIN_PROXY_OBJ_NAME) | **struct rt_dm_power_domain_proxy** with **ofw_parse** |
OFW core registers these in **ofw.c** object table.
**rt_dm_power_domain_register**: initializes lists, **ref**, spinlock — does not touch hardware.
When one DT node represents many domains (SCMI, generic genpd):
Reference: **scmi_pm_domain_probe** — registers **num_domains** entries, binds proxy on SCMI device node.
Sets **child->parent_domain**. **power_on(parent)** recursively powers on children listed in **parent->child_nodes** (BSP must link children into that list if hierarchy is used). **unregister_child** removes the child when the parent is idle.
| API | Role |
|---|---|
**rt_dm_power_domain_attach(dev, on)** | Link **dev** to first **power-domains** entry; **on==RT_TRUE** → **power_on** |
**rt_dm_power_domain_detach(dev, off)** | Unlink; **off==RT_TRUE** → **power_off** |
**rt_dm_power_domain_get_by_index(dev, index)** | Resolve domain pointer (no refcount change in **put** today) |
**rt_dm_power_domain_get_by_name(dev, name)** | Uses **power-domain-names** |
**rt_dm_power_domain_put(domain)** | Currently no-op success — hold domain via attach lifecycle |
**rt_dm_power_domain_power_on/off(domain)** | Explicit on/off with **ref** counting |
rt_ref_init**: domain starts at refcount 1 (idle / registered).power_on**: if **ref == 1**, calls hardware **power_on**, then **ref_get**.power_off**: **ref_put**; when **ref returns to 1**, calls hardware **power_off**.Multiple consumers should share one domain through **attach** + refcount, not duplicate **power_on** without coordination.
Usually unnecessary — platform bus already calls **attach(dev, RT_TRUE)**.
Extra domains (index > 0):
**attach only handles index 0** (see comment in **power_domain.c**).
| Callback | Role |
|---|---|
**attach_dev / detach_dev** | Provider notified when a consumer links (clock/regulator coordination) |
**pirv** | Provider private pointer (upstream spelling) |
From **platform_probe**:
Failed driver **probe** → **rt_dm_power_domain_detach(dev, RT_TRUE)**.
RPMsg and PCI PME also call **attach** where DT requires it.
With regulator and reset (Power subsystem overview, Clock framework (CLK)):
Power off for suspend (if implemented): reverse order per SoC manual - often **idle clocks -> reset assert -> power_off**.
| Option | Role |
|---|---|
**RT_PMDOMAIN_SCMI** | SCMI power protocol → **pm-domain-scmi.c** |
**SOC_DM_PMDOMAIN_DIR** | BSP-specific genpd drivers |
Requires **RT_USING_DM** and **RT_USING_OFW** for DT phandle parsing.
| Issue | Mitigation |
|---|---|
No **rt_ofw_data on provider** | **ofw_find_power_domain** fails — bind domain or proxy at provider probe |
**attach only index 0** | Use **get_by_index(1, …)** + **power_on** for more domains |
**-RT_EEMPTY vs error** | Missing property is normal; log real failures only |
**power_on in IRQ** | Callbacks may sleep — use thread context |
**put is stub** | Rely on **detach** / **power_off** for lifecycle |
| Provider not probed before consumer | Ensure provider driver probes first or defer consumer |
Confuse with **rt_dm_power_off_handler** | Domain = IP block; handler = whole system off |
attach** in probe#power-domain-cells**components/drivers/core/power_domain.ccomponents/drivers/pmdomain/pm-domain-scmi.c