![]() |
RT-Thread RTOS
An open source embedded real-time operating system
|
**RT_USING_PIN** with **RT_USING_DM** adds a global GPIO namespace: each platform GPIO controller registers a contiguous virtual pin number range. Application code still uses **rt_pin_mode / rt_pin_write / rt_pin_read** (PIN Device); drivers use **rt_pin_get_named_pin** and optional GPIO IRQ domains.
Sources:
| File | Role |
|---|---|
**dev_pin_dm.c** | Global pin table, **pin_api_init**, **pin_pic_init**, DM **rt_pin_ops** shim |
**dev_pin_ofw.c** | **rt_ofw_get_named_pin** — gpios / gpio properties |
**dev_pin.c** | Legacy single **gpio** device when no DM controllers |
**pin-pl061.c** | Reference platform driver (arm,pl061) |
| Option | Role |
|---|---|
**RT_USING_PIN** | GPIO framework (default y) |
**RT_USING_DM** | Required for DM path described here |
**RT_PIN_PL061** | In-tree PL061 driver |
**SOC_DM_PIN_DIR** | BSP adds SoC GPIO drivers via **osource** |
| Concept | Meaning |
|---|---|
| Local pin | Index 0 … pin_nr-1 passed to **rt_pin_ops** |
| Virtual pin | **pin_start + local** — value for **rt_pin_*** and **rt_pin_get_named_pin** |
**pin_device_find** | Maps virtual pin → owning **struct rt_device_pin** |
Controllers are linked on **pin_nodes**; **pin_total_nr** only grows (ranges are not recycled).
struct rt_device_pin** (or embed as first member of private struct).struct rt_pin_ops**: at minimum **pin_mode**, **pin_write**, **pin_read**.probe**: iomap, clock, **rt_dm_dev_bind_fwdata(dev, NULL, &gpio->parent)**.pin_api_init(&gpio->parent, gpio_count)** — assigns **pin_start**.irq = rt_dm_dev_get_irq(dev, 0)**pin_pic_init(&gpio->parent, irq)**pin_pic_handle_isr(&gpio->parent, local_pin)**rt_hw_interrupt_install(irq, …)** + **umask**pin_parse** for non-default **#gpio-cells** (flags from **dt-bindings/pin/pin.h**).Reference: **pin-pl061.c** (pl061_probe).
| Callback | Role |
|---|---|
**pin_mode** | Input / output / pull / open-drain |
**pin_write / pin_read** | Level |
**pin_attach_irq** | Direct per-pin ISR (optional) |
**pin_detach_irq** | Remove handler |
**pin_irq_enable** | Enable/disable line interrupt |
**pin_irq_mode** | Edge/level when using legacy IRQ path |
**pin_parse** | Decode **#gpio-cells** → local pin + **flags** |
**pin_get** | Name → virtual pin (optional) |
**pin_debounce** | Debounce time |
If **pin_attach_irq** is NULL, **dev_pin_dm.c** stores handlers in **legacy_isr[]** and relies on **pin_irq_mode** + **pin_pic_handle_isr**.
**rt_ofw_get_named_pin(np, propname, index, out_mode, out_value)** tries:
{propname}-gpios**, then **{propname}-gpio**propname** is **NULL**, tries **gpios** / **gpio**Flow:
rt_ofw_parse_phandle_cells(..., "#gpio-cells", …)**rt_platform_ofw_request** on GPIO provider if neededpin_parse** or default: **args[0]** = local pinflags** → **PIN_MODE_***, active levellocal + pin_dev->pin_start** (virtual pin)Wrapper on device:
Typical **probe**:
Examples in-tree: **phye-generic-usb.c** (reset), **gpio-restart.c**, **led-gpio.c** (child node), **backlight-gpio.c**.
**struct rt_pin_irqchip** is embedded in **struct rt_device_pin** (after **parent**).
| API | Role |
|---|---|
**pin_pic_init(gpio, irq)** | **rt_pic_linear_irq**, **legacy_isr** array, **pin_dm_ops** |
**pin_pic_handle_isr(gpio, local_pin)** | Dispatch PIC path and/or legacy_isr callback |
Per-line DT interrupt (2 cells: pin + flags) uses **pin_dm_ops.irq_parse** / **irq_map**:
rt_pic_cascade(pirq, gpio->irqchip.irq)** — GPIO block IRQ cascades to controller's **rt_dm_dev_get_irq**For **rt_pin_attach_irq(virtual_pin, …)** without DT interrupt on that line, legacy path + **pin_irq_enable** on hardware still applies.
DM systems should prefer:
Legacy **GET_PIN** / **drv_gpio.c** pin tables apply to non-DM BSP GPIO only.
| Issue | Mitigation |
|---|---|
Skip **pin_api_init** | **rt_ofw_get_named_pin** adds wrong **pin_start** |
**pin_parse missing** | Only **args[0]** used; wrong if #gpio-cells > 1 with flags |
IRQ without **pin_pic_init** | Shared IRQ controllers need **pin_pic_handle_isr** |
**pin_attach_irq vs legacy** | If **pin_attach_irq NULL**, must enable via **pin_irq_enable** after attach |
| Provider not probed | Ensure **rt_platform_ofw_request** or platform driver registered |
rt_pin_*** application APIcomponents/drivers/include/drivers/dev_pin.hcomponents/drivers/pin/dev_pin_dm.c, dev_pin_ofw.c