Files
rt-thread/documentation/6.components/device-driver/reset/reset.md
T
GuEe-GUI cfda3b3d1a
doc_doxygen / doxygen_doc generate (push) Has been cancelled
doc_doxygen / deploy (push) Has been cancelled
[docs] device-driver: add DM subsystem docs and expand INDEX
Add Doxygen pages for RT-Thread device-model drivers: platform/OFW,
DM core (bus, dm, power), clk/regulator/reset/power-domain, PCI/PIC,
Phye, DMA/hwcache, block/SCSI/ATA/NVMe/UFS/SDIO, SCMI, RPMsg,
mailbox, NVMem, NUMA, syscon, thermal, input/LED/IIO/graphic, and
related power/charger/supply docs.
Expand device-driver INDEX.md with ~90 @subpage entries so all new
pages appear in the driver chapter navigation.
Update existing UART/SPI/RTC/pin/framework/dtc pages: UART docs moved
from serial/ to uart/ (uart + uart_dm + uart_earlycon); SPI and RTC
gain DM companion pages; pin links to pin_dm; framework points at DM
topics.
Focus on registration/probe flow and in-tree APIs; no standalone
VirtIO subsystem page (transport code still incomplete).
Test plan: build Doxygen for documentation/ and verify device-driver
INDEX links resolve without missing @ref/@subpage warnings.

Signed-off-by: GuEe-GUI <2991707448@qq.com>
2026-05-28 16:09:55 +08:00

8.3 KiB
Executable File

@page page_device_reset Reset controller

Reset controller (rt_reset_control)

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 @ref page_device_power_board_reset and @ref page_device_dm_power.

Kconfig: RT_USING_RESET (requires RT_USING_DM + RT_USING_OFW). In-tree: reset-simple, reset-scmi, SOC_DM_RESET_DIR.


End-to-end flow

Controller (provider)

Platform / SCMI driver probe
        |
        v
Fill rt_reset_control_ops (ofw_parse, assert, deassert [, reset, status])
        |
        v
rt_reset_controller_register(rstcer)
        |
        +-- rstcer->ofw_node set
        +-- rt_ofw_data(np) = rstcer   (object name "RSTC")

Consumer (device using a reset line)

Consumer probe (reset controller must be registered first)
        |
        v
rstc = rt_reset_control_get_by_name(dev, "reset")
     or rt_reset_control_get_by_index(dev, 0)
        |
        v
rt_reset_control_deassert(rstc)    /* release IP from reset — typical */
        |
        v
... clocks enabled, iomap, init ...
        |
        v
remove: rt_reset_control_assert(rstc)   /* optional */
        rt_reset_control_put(rstc)

Not automatic: platform_probe does not deassert resets — the driver must get and deassert explicitly.

Typical bring-up order (@ref page_device_power): regulator → power domain → clock → reset deassert → MMIO.


Registering a reset controller (important)

rt_reset_controller_register

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, …)
struct my_rstc {
    struct rt_reset_controller controller;
    void __iomem *base;
};

static rt_err_t my_assert(struct rt_reset_control *rstc)
{
    /* rstc->id from #reset-cells — put line into reset */
    return RT_EOK;
}

static rt_err_t my_deassert(struct rt_reset_control *rstc)
{
    /* take line out of reset */
    return RT_EOK;
}

static const struct rt_reset_control_ops my_rst_ops = {
    .assert = my_assert,
    .deassert = my_deassert,
};

static rt_err_t my_rst_probe(struct rt_platform_device *pdev)
{
    struct rt_device *dev = &pdev->parent;
    struct my_rstc *r = rt_calloc(1, sizeof(*r));

    r->base = rt_dm_dev_iomap(dev, 0);
    r->controller.ofw_node = dev->ofw_node;
    r->controller.ops = &my_rst_ops;
    r->controller.priv = r;

    return rt_reset_controller_register(&r->controller);
}

Reference: reset-simple.c — MMIO bit per line, INIT_SUBSYS_EXPORT + rt_platform_driver_register.

rt_reset_control_ops

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.

Unregister

rt_reset_controller_unregister: -RT_EBUSY if any consumer handle remains on rstc_nodesput all rt_reset_control first.


Device tree

Controller:

rst: reset-controller@1000 {
    compatible = "vendor,reset";
    reg = <0x1000 0x100>;
    #reset-cells = <1>;
};

Consumer:

uart@2000 {
    compatible = "vendor,uart";
    reg = <0x2000 0x100>;
    resets = <&rst 5>;
    reset-names = "uart";
};
Property Role
resets Phandle + cell(s) per #reset-cells
reset-names Maps name → index for get_by_name

Multiple lines:

dma@3000 {
    resets = <&rst 10>, <&rst 11>;
    reset-names = "dma", "dma-ocp";
};

Consumer API

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.

Error pointers

get_* may return rt_err_ptr(-RT_ENOMEM) etc. Always test:

rstc = rt_reset_control_get_by_name(dev, "reset");
if (rt_is_err(rstc))
    return rt_ptr_err(rstc);
if (!rstc)
    return -RT_EEMPTY;   /* no resets property */

NULL handle

assert / deassert / reset on NULL return RT_EOK (no-op). Do not use that to detect “no reset in DT” — check get return.

Reset arrays

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.


Consumer probe / remove pattern

static rt_err_t my_probe(struct rt_platform_device *pdev)
{
    struct rt_device *dev = &pdev->parent;
    struct rt_reset_control *rstc;
    rt_err_t err;

    rstc = rt_reset_control_get_by_name(dev, "reset");
    if (rt_is_err(rstc))
        return rt_ptr_err(rstc);

    if (rstc && (err = rt_reset_control_deassert(rstc)))
        goto err_put;

    /* clk_prepare_enable, rt_dm_dev_iomap, ... */
    pdev->priv = rstc;
    return RT_EOK;

err_put:
    if (rstc)
        rt_reset_control_put(rstc);
    return err;
}

static rt_err_t my_remove(struct rt_platform_device *pdev)
{
    struct rt_reset_control *rstc = pdev->priv;

    if (rstc) {
        rt_reset_control_assert(rstc);
        rt_reset_control_put(rstc);
    }
    return RT_EOK;
}

Example in-tree: dma-pl330.c (dma, dma-ocp), sdio-dw.c, 8250-ofw.c, pinctrl-single.c (aib_rst).


In-tree providers

Driver Binding Registration
reset-simple snps,dw-low-reset, st,stm32-rcc, Allwinner, Aspeed, … Platform probert_reset_controller_register
reset-scmi SCMI protocol reset SCMI probe → register on agent node

Semantics cheat sheet

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).


Pitfalls

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

See also

  • @ref page_device_power — ordering with regulator / domain / clk
  • @ref page_device_power_board_reset — system shutdown GPIO (not this API)
  • @ref page_device_platform — provider driver binding
  • @ref page_device_clk
  • @ref page_device_ofw — phandles, #reset-cells
  • components/drivers/reset/reset.c, reset-simple.c