Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/deelerdev/linux/llms.txt

Use this file to discover all available pages before exploring further.

A device driver is a kernel component that manages the communication between the operating system and a specific piece of hardware. Drivers abstract hardware details so that user-space applications and other kernel subsystems can interact with devices through a uniform interface. In Linux, all drivers participate in a unified driver model that governs how devices are discovered, bound to a driver, and removed from the system.

Driver types

Linux supports several categories of drivers, each suited to a different bus topology or device class.
Platform drivers manage devices that are directly addressable from the CPU bus and are not discoverable at runtime — typically peripherals integrated into a system-on-chip (SoC). The kernel learns about these devices from the Device Tree or ACPI tables. A platform driver registers with platform_driver_register() and handles a struct platform_device.
PCI drivers bind to devices enumerated on the PCI bus. The kernel automatically discovers PCI devices at boot and matches them against registered drivers using the vendor ID and device ID in a struct pci_device_id table. PCI drivers register using pci_register_driver().
USB drivers bind to interfaces on USB devices. The USB core enumerates connected devices and matches them by vendor ID, product ID, class, or subclass. USB drivers register with usb_register().
I2C drivers control devices on the I2C bus. The I2C core matches drivers to devices by name or by a struct i2c_device_id table. Drivers register with i2c_add_driver().
Character device drivers expose a device to user space as a file under /dev. User-space programs call open(), read(), write(), and ioctl() on the device file. The driver implements these operations through a struct file_operations.
Block device drivers manage storage devices that transfer data in fixed-size blocks. They expose a request queue to the block layer, which handles I/O scheduling before dispatching requests to the driver.

Buses, devices, and drivers

The Linux driver model is built on three objects: buses, devices, and drivers.
  • A bus (struct bus_type) is a communication channel between the processor and one or more devices. Every device is attached to a bus — even devices with no physical bus use the virtual platform bus.
  • A device (struct device) represents a hardware or virtual device in the system. Each device belongs to exactly one bus and holds a reference to the driver currently managing it.
  • A driver (struct device_driver) represents a driver as a whole, not a particular device instance. A single driver can manage multiple devices simultaneously.
/* From include/linux/device/bus.h */
struct bus_type {
	const char		*name;
	const char		*dev_name;
	const struct attribute_group **bus_groups;
	const struct attribute_group **dev_groups;
	const struct attribute_group **drv_groups;

	int (*match)(struct device *dev, const struct device_driver *drv);
	int (*probe)(struct device *dev);
	void (*remove)(struct device *dev);
	int (*suspend)(struct device *dev, pm_message_t state);
	int (*resume)(struct device *dev);

	const struct dev_pm_ops *pm;
};
When a driver is registered, the bus iterates over all unbound devices and calls its match() callback for each one. When a device is registered, the bus iterates over all registered drivers and calls match() for each. A positive return from match() triggers a probe() call.

Device discovery and probe()

The probe() callback is the driver’s entry point for a specific device. The kernel calls it in task context after match() succeeds. Inside probe() the driver must:
  1. Verify that the hardware is present and behaves as expected.
  2. Allocate and initialize any data structures needed to manage the device.
  3. Claim hardware resources such as memory regions, I/O ports, and interrupt lines.
  4. Register any sub-devices or interfaces that higher-level subsystems will use.
/* From Documentation/driver-api/driver-model/driver.rst */
int (*probe)(struct device *dev);
If probe() returns 0, the driver core considers the driver successfully bound to the device. If it returns a negative error code, all claimed resources must already have been released. Return -EPROBE_DEFER if a resource the driver depends on — such as a clock, regulator, or GPIO — is not yet available; the core will retry probe() later.
Do not return -EPROBE_DEFER after you have registered child devices. Doing so can cause an infinite loop of probe() calls.

The driver lifecycle

Every driver follows the same lifecycle from the moment the kernel matches it to a device until the device is removed.
1

Match

The bus match() callback compares the device’s identity (vendor/device ID, Device Tree compatible string, or name) against the driver’s supported-device table.
2

Probe

The driver’s probe() callback runs. The driver acquires resources, initializes hardware, and signals success by returning 0.
3

Operate

The device is live. User space, other kernel subsystems, or interrupt handlers communicate with the hardware through the driver’s registered interfaces.
4

Suspend / resume (optional)

If the system enters a sleep state, the driver’s suspend() and resume() callbacks (or dev_pm_ops) quiesce and restore the device.
5

Remove

When the device is physically removed, the driver module is unloaded, or the system shuts down, the driver’s remove() callback runs. The driver must release all resources it acquired in probe().
/* From include/linux/device/driver.h */
struct device_driver {
	const char		*name;
	const struct bus_type	*bus;

	struct module		*owner;
	const char		*mod_name;

	bool suppress_bind_attrs;
	enum probe_type probe_type;

	const struct of_device_id	*of_match_table;
	const struct acpi_device_id	*acpi_match_table;

	int (*probe) (struct device *dev);
	void (*sync_state)(struct device *dev);
	int (*remove) (struct device *dev);
	void (*shutdown) (struct device *dev);
	int (*suspend) (struct device *dev, pm_message_t state);
	int (*resume) (struct device *dev);

	const struct dev_pm_ops *pm;
};

Key header files

Every driver includes a small set of core headers. The exact set depends on the bus type and features used.
HeaderPurpose
<linux/module.h>module_init(), module_exit(), MODULE_LICENSE(), and related macros
<linux/device.h>struct device, struct device_driver, device attributes
<linux/device/bus.h>struct bus_type, bus_register(), bus_for_each_dev()
<linux/platform_device.h>struct platform_device, struct platform_driver, platform_driver_register()
<linux/interrupt.h>request_irq(), free_irq(), IRQ flags
<linux/fs.h>struct file_operations for character devices
<linux/cdev.h>struct cdev, cdev_init(), cdev_add()
<linux/pm.h>struct dev_pm_ops for power management callbacks

Linux device model

Dive into struct device, struct bus_type, sysfs layout, and power management integration.

Write your first driver

Step-by-step walkthrough of a minimal character device driver and a platform driver.

Build docs developers (and LLMs) love