![]() |
RT-Thread RTOS
An open source embedded real-time operating system
|
Header: **components/drivers/include/drivers/reset.h**. Core: **components/drivers/reset/reset.c**.
Resolves device-tree **resets** / **#reset-cells** / **reset-names** into **struct rt_reset_control** handles, then drives **assert / deassert / reset** on the owning **struct rt_reset_controller**.
This is per-IP reset lines (SoC reset manager), not whole-system power off — see Board poweroff and restart and System power off and reboot (core).
Kconfig: **RT_USING_RESET** (requires **RT_USING_DM** + **RT_USING_OFW**). In-tree: **reset-simple**, **reset-scmi**, **SOC_DM_RESET_DIR**.
Not automatic: **platform_probe** does not deassert resets — the driver must **get** and **deassert** explicitly.
Typical bring-up order (Power subsystem overview): regulator → power domain → clock → reset deassert → MMIO.
| Field | Role |
|---|---|
**rstcer->ofw_node** | Controller DT node — **rt_ofw_data** stored here |
**rstcer->ops** | **struct rt_reset_control_ops** |
**rstcer->priv** | Driver private state (MMIO base, SCMI device, …) |
Reference: **reset-simple.c** — MMIO bit per line, **INIT_SUBSYS_EXPORT** + **rt_platform_driver_register**.
| Callback | Role |
|---|---|
**ofw_parse(rstc, args)** | Optional: validate cells, store extra data in **rstc->priv** |
**assert** | Active in reset (hold block) |
**deassert** | Active out of reset (run block) |
**reset** | Optional pulse: assert → delay → deassert |
**status** | Optional: report whether line is asserted |
Default after parse: **rstc->id = reset_args.args[0]** (first **#reset-cells** argument).
Polarity (active-low vs high) is inside your **assert/deassert** — read the SoC TRM, not just DT naming.
**rt_reset_controller_unregister**: **-RT_EBUSY** if any consumer handle remains on **rstc_nodes** — **put** all **rt_reset_control** first.
Controller:
Consumer:
| Property | Role |
|---|---|
**resets** | Phandle + cell(s) per **#reset-cells** |
**reset-names** | Maps name → index for **get_by_name** |
Multiple lines:
| API | Role |
|---|---|
**rt_reset_control_get_by_index(dev, index)** | Parse **resets** entry index |
**rt_reset_control_get_by_name(dev, name)** | Match **reset-names** |
**rt_reset_control_get_array(dev)** | Synthetic array control (see below) |
**rt_reset_control_put(rstc)** | Remove from controller list, **rt_free** |
**rt_reset_control_deassert(rstc)** | Release from reset (usual probe step) |
**rt_reset_control_assert(rstc)** | Hold in reset (remove / suspend) |
**rt_reset_control_reset(rstc)** | Pulse if **ops->reset** exists |
**rt_reset_control_status(rstc)** | **-RT_ENOSYS** if no **status** op |
OFW variants on raw node: **rt_ofw_get_reset_control_by_index**, **_by_name**, **_array**.
**get_*** may return **rt_err_ptr(-RT_ENOMEM)** etc. Always test:
**assert / deassert / reset** on **NULL** return **RT_EOK** (no-op). Do not use that to detect “no reset in DT” — check **get** return.
**rt_reset_control_get_array**: builds a captain **rstc** with **is_array**; **assert/deassert/reset** recurse into child controls with rollback on partial failure. Use when one logical block needs several **resets** entries applied together.
Example in-tree: **dma-pl330.c** (**dma**, **dma-ocp**), **sdio-dw.c**, **8250-ofw.c**, **pinctrl-single.c** (**aib_rst**).
| Driver | Binding | Registration |
|---|---|---|
| reset-simple | **snps,dw-low-reset**, **st,stm32-rcc**, Allwinner, Aspeed, … | Platform **probe** → **rt_reset_controller_register** |
| reset-scmi | SCMI protocol **reset** | SCMI **probe** → register on agent node |
| Term in API | Typical meaning |
|---|---|
| assert | Line active → block held in reset |
| deassert | Line inactive → block can run |
| reset | Short assert then deassert (pulse) |
Exact bit polarity is driver-specific (**reset-simple** uses **active_low** in platform data).
| Issue | Mitigation |
|---|---|
| Controller not probed | **get** fails — **rt_platform_ofw_request** on provider or fix init order |
| Clock vs reset order | Enable clock only after deassert (or follow TRM) |
Skip put | **unregister** busy; memory leak |
| Shared reset line | One driver assert while another runs → crash |
Wrong id cell | Match **#reset-cells** layout in BSP doc |
| Confuse with gpio-poweroff | System off ≠ IP **resets** |
| Array partial failure | Core rolls back earlier entries — ops must be reversible |
#reset-cells**components/drivers/reset/reset.c, reset-simple.c