Linux IIO Framework Basics
Free Linux Kernel Development Course • Free Linux Device Drivers Course • Free Embedded Linux Course
free linux kernel development course
free linux device drivers course
free embedded systems course
iio device channel model
devm_iio_device_register
If you are searching for a free linux kernel development course that actually teaches how sensor drivers work in modern Linux, this lecture on the linux iio framework is exactly where you need to start. The Industrial I/O (IIO) subsystem is the standard kernel framework for every analog-to-digital and digital-to-analog device: accelerometers, gyroscopes, ADCs, DACs, pressure sensors, light sensors, and current/voltage monitors all register through it. This lecture is part of our free linux device drivers course and free embedded systems course series, and it builds directly on the platform, device tree, I2C, SPI, and regmap chapters you have already completed.
What You Will Learn
- Why the IIO framework exists and which devices belong to it
- The device and channel model that IIO is built around
- How user space talks to an IIO driver through sysfs and a character device
- Which header files an IIO driver needs and why
- How to write, build, and load a minimal modern IIO driver
- How to read the driver’s output from user space and verify it works
Prerequisites
- Completed the Platform Device Drivers and Device Tree chapters of this free linux device drivers course
- Comfortable with kernel modules,
probe()/remove(), anddevm_*managed resources - A Linux kernel 6.x build environment (headers installed, cross or native toolchain ready)
What Is the Linux IIO Framework?
Industrial I/O (IIO) is a Linux kernel subsystem dedicated to Analog-to-Digital Converters (ADC) and Digital-to-Analog Converters (DAC). Before IIO existed, every vendor wrote its own sensor driver with its own private sysfs layout, its own ioctl numbers, and its own buffering code. That duplication made it hard for user space applications to support more than one chip. The IIO framework, started by Jonathan Cameron and maintained by the Linux-IIO community, solves this by giving every measurement device a common, generic interface, regardless of what physical quantity it measures.
Any chip that converts a physical signal into a digital value, or a digital value into a physical signal, is a candidate for IIO: accelerometers, gyroscopes, magnetometers, current and voltage monitors, light and proximity sensors, pressure and humidity sensors, and precision DACs used for signal generation.
The IIO Device and Channel Model
IIO organizes every driver around two core concepts:
- Device — represents the physical chip itself. It sits at the top of the hierarchy and is what you register with the IIO core.
- Channel — represents a single acquisition line belonging to that device. A device can expose one or many channels. A 3-axis accelerometer, for example, is one IIO device with three channels: X, Y, and Z.
How User Space Talks to an IIO Driver
Every IIO chip is exposed to user space in two complementary ways, and understanding both is essential before writing any driver code:
| Interface | Path | Purpose |
|---|---|---|
| Sysfs directory | /sys/bus/iio/devices/iio:deviceX/ |
One plain-text file per channel attribute (raw value, scale, offset). Good for occasional one-shot reads. |
| Character device | /dev/iio:deviceX |
Exposes the device’s event queue and, when triggered buffering is configured, a continuous binary sample stream. |
Header Files Used by an IIO Driver
IIO functionality is spread across a small set of headers. On kernel 6.x you will typically include:
#include <linux/iio/iio.h> /* mandatory: core IIO API */
#include <linux/iio/sysfs.h> /* mandatory: sysfs attribute helpers */
#include <linux/iio/events.h> /* optional: IIO event/threshold support */
#include <linux/iio/buffer.h> /* needed only for triggered buffer capture */
#include <linux/iio/trigger.h> /* needed only if your driver defines a trigger */
For a simple one-shot sysfs-only driver — the kind we build in this lecture — only the first two headers are required. The buffer and trigger headers matter once you move to continuous capture, which is covered later in this chapter.
Hands-On: A Minimal Modern IIO Voltage Driver
Let’s write an original, from-scratch IIO driver named ep_iio_volt_demo. It simulates a single-channel voltage sensor and exposes its raw reading through sysfs, using the modern, devm-managed registration API found in current kernel trees.
// ep_iio_volt_demo.c
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
struct ep_iio_priv {
int last_raw;
};
static int ep_iio_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct ep_iio_priv *priv = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
/* In a real driver this would talk to hardware (I2C/SPI/regmap). */
priv->last_raw = 512;
*val = priv->last_raw;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
/* Example: 1 LSB = 3.22 mV -> scale = 3.22 */
*val = 3;
*val2 = 220000;
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
}
static const struct iio_info ep_iio_info = {
.read_raw = ep_iio_read_raw,
};
static const struct iio_chan_spec ep_iio_channels[] = {
{
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
},
};
static int ep_iio_probe(struct platform_device *pdev)
{
struct iio_dev *indio_dev;
struct ep_iio_priv *priv;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
if (!indio_dev)
return -ENOMEM;
priv = iio_priv(indio_dev);
priv->last_raw = 0;
indio_dev->name = "ep_iio_volt_demo";
indio_dev->info = &ep_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = ep_iio_channels;
indio_dev->num_channels = ARRAY_SIZE(ep_iio_channels);
platform_set_drvdata(pdev, indio_dev);
return devm_iio_device_register(&pdev->dev, indio_dev);
}
static struct platform_driver ep_iio_driver = {
.driver = {
.name = "ep_iio_volt_demo",
},
.probe = ep_iio_probe,
};
static struct platform_device *ep_iio_pdev;
static int __init ep_iio_init(void)
{
ep_iio_pdev = platform_device_register_simple("ep_iio_volt_demo", -1, NULL, 0);
if (IS_ERR(ep_iio_pdev))
return PTR_ERR(ep_iio_pdev);
return platform_driver_register(&ep_iio_driver);
}
static void __exit ep_iio_exit(void)
{
platform_driver_unregister(&ep_iio_driver);
platform_device_unregister(ep_iio_pdev);
}
module_init(ep_iio_init);
module_exit(ep_iio_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("EmbeddedPathashala");
MODULE_DESCRIPTION("Minimal modern IIO voltage sensor demo driver");
Why these calls matter:
| Function | Role |
|---|---|
devm_iio_device_alloc() |
Allocates the iio_dev plus private driver storage, freed automatically on driver detach — the modern replacement for the old manual iio_device_alloc()/iio_device_free() pair. |
iio_priv() |
Returns a pointer to your private data area embedded right after the iio_dev structure. |
devm_iio_device_register() |
Registers the device with the IIO core and automatically unregisters it on removal — no manual iio_device_unregister() needed in remove(). |
read_raw() |
Callback invoked whenever user space reads a channel’s raw or scale sysfs file. |
Build and Load
# Makefile
obj-m += ep_iio_volt_demo.o
# Build against your running kernel headers
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
# Load it
sudo insmod ep_iio_volt_demo.ko
# Confirm registration
dmesg | tail
Expected Output
$ ls /sys/bus/iio/devices/
iio:device0
$ cat /sys/bus/iio/devices/iio:device0/name
ep_iio_volt_demo
$ cat /sys/bus/iio/devices/iio:device0/in_voltage0_raw
512
$ cat /sys/bus/iio/devices/iio:device0/in_voltage0_scale
3.220000
The in_voltage0_raw file name is generated automatically by the IIO core from the channel’s type (IIO_VOLTAGE), its indexed/channel fields, and the requested IIO_CHAN_INFO_RAW attribute — you never hand-name these sysfs files yourself.
Real-World Use Cases
- Battery fuel-gauge and power-monitor ICs reporting voltage/current over I2C
- MEMS accelerometers and gyroscopes in phones, drones, and IMUs
- Ambient light and proximity sensors for display backlight control
- Precision DACs used to generate reference voltages or waveforms
- Industrial pressure and temperature transmitters on SPI or I2C buses
Common Mistakes and Troubleshooting
| Mistake | Fix |
|---|---|
Using plain iio_device_register() and forgetting to unregister in remove() |
Prefer devm_iio_device_register() so cleanup is automatic |
Forgetting BIT(IIO_CHAN_INFO_RAW) in info_mask_separate |
The sysfs raw file will simply not appear — always declare every attribute you support |
Returning the wrong IIO_VAL_* constant from read_raw() |
Match the return type to how you filled val/val2 (e.g. IIO_VAL_INT_PLUS_MICRO for fractional scale values) |
No entry under /sys/bus/iio/devices/ after insmod |
Check dmesg for a probe failure; verify modes and info were set before calling register |
Best Practices
- Always use the
devm_*IIO allocation and registration helpers on kernel 6.x to avoid manual cleanup bugs. - Keep channel descriptions (
iio_chan_spec) asstatic constarrays — they never change at runtime. - Return
-EINVALfromread_raw()/write_raw()for any unhandled mask value instead of silently ignoring it. - Name your driver’s private struct clearly and access it only via
iio_priv(), never via global variables.
Summary and Key Takeaways
- IIO is the generic Linux kernel subsystem for ADC/DAC style sensors and converters.
- Every IIO driver is built around a device (the chip) and one or more channels (the acquisition lines).
- User space reaches an IIO driver through sysfs for simple reads and through
/dev/iio:deviceXfor buffered, continuous capture. - Modern kernel 6.x drivers should use
devm_iio_device_alloc()anddevm_iio_device_register()for automatic cleanup. - The next lecture in this free linux device drivers course dives into the
iio_devstructure and its operating modes in detail.
Conclusion
The linux iio framework gives every measurement chip — regardless of vendor or bus — a single, predictable way to expose data to user space. By separating the device (chip) from its channels (acquisition lines), and by offering both a simple sysfs path and a high-throughput character-device path, IIO covers everything from a one-off voltage read to continuous, triggered, multi-channel sampling. The minimal driver you built in this lecture is the same pattern used by real accelerometer, ADC, and sensor drivers shipped in the mainline kernel today. In the next part of this free linux kernel development course we open up the iio_dev structure itself and look at operating modes, buffering, and how the IIO core decides what a driver can do.
Frequently Asked Questions
What does IIO stand for in the Linux kernel?
IIO stands for Industrial I/O, the kernel subsystem for analog-to-digital and digital-to-analog conversion devices such as sensors and converters.
What is the difference between an IIO device and an IIO channel?
The device represents the whole chip, while a channel represents one acquisition line on that chip — a 3-axis sensor is one device with three channels.
Where do IIO drivers expose data in user space?
Through two paths: the sysfs directory at /sys/bus/iio/devices/iio:deviceX/ for simple reads, and the character device at /dev/iio:deviceX for buffered/event data.
Which function should modern IIO drivers use to register a device?
devm_iio_device_register(), paired with devm_iio_device_alloc(), so the IIO core automatically unregisters and frees resources on driver removal.
Do I need linux/iio/buffer.h for every IIO driver?
No. It is only required once you add triggered buffer support for continuous capture; a simple sysfs-only driver does not need it.
What does IIO_CHAN_INFO_RAW mean?
It is the info mask flag that tells the IIO core your channel supports a raw (unscaled) value read, exposed as an in_<type><index>_raw sysfs file.
Is this free linux kernel development course suitable for beginners?
Yes. It assumes only that you have completed the earlier platform driver and device tree lectures in this free linux device drivers course.
Can IIO drivers work without a device tree node?
Yes, as shown in this lecture with platform_device_register_simple(); production drivers typically match through device tree instead, as covered in earlier chapters.
Continue the Free Linux Device Drivers Course
Next: iio_dev structure, operating modes, and channel specification in detail.
