![]() |
RT-Thread RTOS
An open source embedded real-time operating system
|
Headers: **components/drivers/include/drivers/regulator.h**, **components/drivers/regulator/regulator_dm.h**. Core: **components/drivers/regulator/regulator.c**, DT parse: **regulator_dm.c**.
Models LDO/DCDC/load switches as **struct rt_regulator_node** (provider) and opaque **struct rt_regulator** (consumer handle). Misuse can damage hardware — use only the public API.
Kconfig: **RT_USING_REGULATOR** (requires **RT_USING_DM**). In-tree: **regulator-fixed**, **regulator-gpio**, **regulator-pwm**, **regulator-fan53555**, **regulator-scmi**, plus **SOC_DM_REGULATOR_DIR**.
Not automatic: unlike power domains, **platform_probe does not enable regulators** — the consumer driver must **get / enable** in **probe** and **disable / put** in **remove**.
Recommended order with other power (Power subsystem overview): regulator → power domain → clock/reset → iomap.
| Field | Required |
|---|---|
**reg_np->dev** | Owning **rt_device** (usually **&pdev->parent** of provider) |
**reg_np->param** | **struct rt_regulator_param** (name, voltage/current limits, delays, flags) |
**reg_np->ops** | At least **enable/disable** (and **set_voltage/get_voltage** if adjustable) |
**reg_np->supply_name** | Rail name (often **param->name** from **regulator-name**) |
On success with **RT_USING_OFW**: **rt_ofw_data(dev->ofw_node) = reg_np** so consumers can resolve phandles.
**boot_on / always_on** in **param**: **register** calls **regulator_enable** immediately.
**regulator-fixed** pattern:
Provider must probe before consumers that call **rt_regulator_get** (or **get** will **rt_platform_ofw_request** the regulator node).
Regulator node (provider):
Consumer:
| Consumer property | Lookup |
|---|---|
**vcc-supply** | **rt_regulator_get(dev, "vcc")** |
**vqmmc-supply** | **rt_regulator_get(dev, "vqmmc")** |
Parent rail: regulator node may have **vin-supply**; **rt_regulator_get** links **parent** via **regulator_check_parent** for enable/disable/voltage propagation up the tree.
| API | Role |
|---|---|
**rt_regulator_get(dev, id)** | Resolve **{id}-supply** phandle → allocate **struct rt_regulator**, **ref_get** on node |
**rt_regulator_put(reg)** | **ref_put**; may **unregister** node when last reference |
**rt_regulator_enable(reg)** | Enable rail (parent first); applies **enable_delay** |
**rt_regulator_disable(reg)** | Consumer refcount then hardware off when last user |
**rt_regulator_set_voltage(reg, min, max)** | Notifiers + **set_voltage**; parent voltage updated too |
**rt_regulator_get_voltage(reg)** | Read back µV |
**rt_regulator_is_supported_voltage(reg, min, max)** | Check against **param** range |
**rt_regulator_set_mode / get_mode** | Optional PMIC modes |
Multiple consumers on one rail:
enable**: runs hardware **ops->enable**, bumps internal **enabled_count**.enable**: if already on, returns **RT_EOK** immediately.disable**: decrements consumer **enabled_count** until zero, then hardware **disable**.Each consumer should still call **enable/disable/put** symmetrically.
Keep callbacks short — they may run under regulator lock.
| DT property | param field |
|---|---|
**regulator-name** | **name** |
**regulator-min/max-microvolt** | **min_uvolt / max_uvolt** |
**regulator-min/max-microamp** | **min_uamp / max_uamp** |
**regulator-boot-on** | **boot_on** |
**regulator-always-on** | **always_on** |
**enable-active-high** | **enable_active_high** |
**regulator-ramp-delay** | **ramp_delay** (or **ramp_disable**) |
**regulator-enable-ramp-delay** | **enable_delay** |
| Driver | Compatible / binding | Registration |
|---|---|---|
| fixed | **regulator-fixed** | GPIO enable, **regulator_ofw_parse**, **rt_regulator_register** |
| gpio | GPIO-controlled rail | Same pattern |
| pwm | PWM duty → voltage | **RT_REGULATOR_PWM** |
| fan53555 | I2C PMIC | **RT_REGULATOR_FAN53555** |
| scmi | SCMI voltage protocol | **RT_REGULATOR_SCMI** |
| Issue | Mitigation |
|---|---|
| Provider not registered | **get** fails — ensure regulator **probe** runs first or defer consumer |
| Wrong property name | **id** must match **{id}-supply** in DT |
| Enable before voltage | Many PMICs need **set_voltage** then **enable** |
Skip put | Leaks **struct rt_regulator** and node **ref** |
**set_voltage in IRQ** | May sleep (I2C PMIC) |
| Shared rail | One consumer lowering voltage affects all — coordinate in DT |
| Bypass framework | Do not write PMIC registers from random drivers |
**always_on rail** | **disable** may no-op in ops — still call **put** |
RT_PLATFORM_DRIVER_EXPORT**components/drivers/regulator/regulator.ccomponents/drivers/regulator/regulator-fixed.c