![]() |
RT-Thread RTOS
An open source embedded real-time operating system
|
RT-Thread IIO support is intentionally small: it does not implement a full Linux IIO subsystem (no iio_device bus, no buffer/trigger framework in-tree). With **RT_USING_DM**, **components/drivers/iio/iio.c** parses device-tree **io-channels** / **io-channel-names** (Linux-compatible binding names) and returns an opaque provider handle plus a channel index.
Data path (read raw ADC counts, scale to mV, trigger buffers, etc.) remains entirely in the provider driver (ADC, thermal, PMIC ADC, …).
Overview of the IIO concept: Industrial I/O (IIO). This page documents DM phandle resolution and provider obligations.
Sources: **components/drivers/iio/iio.c**, **components/drivers/include/drivers/iio.h**.
| Requirement | Role |
|---|---|
**RT_USING_DM** | **iio/SConscript** builds **iio.c** only when DM is on |
**RT_USING_OFW** | **ofw_iio_channel_get_by_index** parses phandles; without OFW, **get_* returns NULL** |
| Provider driver | Separate Kconfig (e.g. **RT_USING_ADC**, SoC SARADC in BSP) — not part of **iio.c** |
**drivers/iio.h** is included from **rtdevice.h**; link **iio.c** by enabling **RT_USING_DM**.
There is no separate **RT_USING_IIO** menu entry — IIO glue is a DM companion module.
**Unlike I2C device model (DM)**, IIO has no rt_bus and no automatic client probe. Only phandle lookup is centralized.
| API | Behavior |
|---|---|
**get_by_index** | Parse Nth entry in consumer’s **io-channels** list |
**get_by_name** | Resolve index via **io-channel-names**, then same as **get_by_index** |
| Return value | **void *** = **rt_ofw_data(provider_np)** after optional **rt_platform_ofw_request** |
**out_channel** | First cell of provider **#io-channel-cells** specifier (logical channel number) |
| Input check | Result |
|---|---|
**dev == NULL**, **index < 0**, **name == NULL** | **NULL** |
Consumer has no dev->ofw_node | **NULL** |
Missing **io-channels** / parse error | **NULL** |
| Provider not probed | **rt_platform_ofw_request** then retry **rt_ofw_data** |
There is no rt_iio_channel_put in the header — lifetime follows the provider rt_device / platform driver **remove**. Do not use the cookie after the provider unregisters.
| Property | Role |
|---|---|
**#io-channel-cells = <1>** | One integer per phandle in consumer **io-channels** |
**io-channel-ranges** | Optional (Linux); presence documents channel map semantics for porters |
| Channel index | 0 … N-1 — meaning defined by provider driver (SARADC channel id, TSADC sensor input, …) |
| Property | Role |
|---|---|
**io-channels** | Phandle + one cell per channel (provider + index) |
**io-channel-names** | Optional strings aligned with **io-channels** order |
**get_by_name(dev, "bat-voltage", &ch)** → cookie = saradc private struct, **ch == 4**.
The provider must expose **rt_ofw_data(provider_np)** before consumers resolve channels.
Typical pattern (from **adc-rockchip_saradc.c**):
| Obligation | Detail |
|---|---|
**rt_dm_dev_bind_fwdata(dev, NULL, priv)** | Sets **rt_ofw_data(dev->ofw_node) = priv** (Device model helpers (dm.h)) |
**#io-channel-cells** in DTS | Must match **args_count == 1** in **iio.c** (otherwise lookup fails) |
| Probe before consumer | Or rely on **rt_platform_ofw_request** during **get_*** |
| Document channel map | What index 0, 1, 2… mean (pin / internal mux / TSADC sensor) |
Returned cookie is usually the provider’s private struct (struct rockchip_saradc *, etc.) — not a portable struct iio_channel. Consumers in the same BSP cast to the known type.
| Step | Notes |
|---|---|
Call **get_* in probe** | After consumer **ofw_node** is set; provider may be deferred-probed by **rt_platform_ofw_request** |
Store cookie + out_channel | Cookie = provider priv; **ch** selects logical input |
| No standard read API | Pair with **rt_adc_***, **rt_sensor_***, or vendor functions |
**remove** | Drop pointers; do not call **get_*** again |
| Framework | Role vs IIO |
|---|---|
| ADC Device | **rt_adc_device** is often the provider registered by SARADC; IIO only discovers which channel another driver needs |
| Sensor framework | Separate path (rt_sensor_*); may coexist — do not confuse sensor bus with IIO phandles |
IIO is glue for DT io-channels, not a replacement for **rt_device_find("adc0")**.
| Linux | RT-Thread DM IIO |
|---|---|
struct iio_channel + iio_channel_get() | Opaque **void *** + **out_channel int |
iio_read_channel_raw() etc. | Not in-tree — provider-specific |
| IIO core + buffers/triggers | Not implemented |
Porting focus: reproduce DT property names and channel indices; reimplement read path against local ADC driver.
#io-channel-cells = <1>**; document channel index meanings.rt_dm_dev_bind_fwdata** with stable **priv** pointer.io-channels** + optional **io-channel-names**.rt_iio_channel_get_by_***, check **NULL**, store cookie + index.rt_adc_enable / mutex** rules of that driver.remove** first or ensure no use-after-free when provider exits.struct iio_channel.args_count != 1** — **iio.c returns failure**; multi-cell specifiers are unsupported today.bind_fwdata — **get_* returns NULL** even if ADC device registered.ofw_node — always **NULL** (no manual fallback in **iio.c**).remove** while consumer still holds pointer → UAF.iio.c**.rt_dm_dev_bind_fwdata**, property helpersrt_ofw_parse_phandle_cells**probe**rt_hw_adc_register**)components/drivers/iio/iio.ccomponents/drivers/include/drivers/iio.h