Skip to content

Platform Driver Development

Overview

Platform drivers are commonly used for on-chip peripherals that do not reside on discoverable buses such as PCIe or USB.

Typical examples include:

  • GPIO controllers
  • UART controllers
  • SPI controllers
  • I2C controllers
  • Watchdogs
  • Timers
  • SoC-specific peripherals

A platform driver obtains hardware resources from a platform device and initializes the corresponding hardware instance.


Architecture

Device Tree
    ↓
of_platform_populate()
    ↓
platform_device
    ↓
platform_match()
    ↓
platform_driver
    ↓
probe()

The platform driver does not create hardware resources.

Resources are created during platform device creation and passed to the driver during probe.


Platform Resources

Hardware resources are represented using:

struct resource

Common resource types:

Resource Type Description
IORESOURCE_MEM Memory-mapped I/O region
IORESOURCE_IRQ Interrupt resource
IORESOURCE_DMA DMA channel resource
IORESOURCE_IO Legacy I/O port resource

Resource Acquisition

Memory Resource

Acquire MMIO resources:

struct resource *res;

res = platform_get_resource(
            pdev,
            IORESOURCE_MEM,
            0);

Arguments:

Parameter Description
pdev Platform device
IORESOURCE_MEM Resource type
0 Resource index

IRQ Resource

Acquire interrupt resources:

int irq;

irq = platform_get_irq(
            pdev,
            0);

The returned value is a Linux IRQ number after irqdomain mapping.

It is not necessarily identical to the interrupt specifier defined in Device Tree.


Driver Private Data

Most platform drivers maintain instance-specific state.

Typical structure:

struct demo_priv {
    void __iomem *base;
    int irq;
};

Each device instance owns its own private data.

Avoid using global variables for per-device state.


Storing Driver Data

Attach private data to the platform device:

platform_set_drvdata(
        pdev,
        priv);

Retrieve later:

priv = platform_get_drvdata(
            pdev);

Common users:

  • remove()
  • IRQ handlers
  • sysfs callbacks
  • file_operations
  • worker threads

Managed Resource Allocation

Modern Linux drivers typically use devm-managed APIs.

Examples:

devm_kzalloc()

devm_request_irq()

devm_ioremap_resource()

Benefits:

Automatic cleanup
Reduced error handling
Simpler remove path

General flow:

probe()
    ↓
Acquire resources
    ↓
Device removed
    ↓
Resources automatically released

Interrupt Registration

Register an interrupt handler:

ret = devm_request_irq(
            &pdev->dev,
            irq,
            handler,
            flags,
            name,
            priv);

The private data pointer is passed back to the interrupt handler:

static irqreturn_t handler(
        int irq,
        void *data)
{
    struct demo_priv *priv = data;

    ...
}

Delayed Work Integration

Interrupt handlers should remain short and non-blocking.

A common pattern:

IRQ
    ↓
Schedule delayed work
    ↓
Worker executes later

Example:

mod_delayed_work(
        system_wq,
        &priv->irq_work,
        msecs_to_jiffies(50));

Common use cases:

  • GPIO debounce
  • Deferred processing
  • Event aggregation
  • Retry operations

Typical Platform Driver Probe Flow

probe()

    ↓

devm_kzalloc()

    ↓

platform_get_resource()

    ↓

platform_get_irq()

    ↓

platform_set_drvdata()

    ↓

devm_request_irq()

    ↓

Driver Ready

Relationship to Platform Bus

Linux Driver Model
        ↓
Platform Bus
        ↓
Platform Device
        ↓
Platform Driver
        ↓
Resource Acquisition
        ↓
Hardware Initialization

Platform driver development builds on the platform bus infrastructure and focuses on acquiring resources and initializing hardware.

  • Linux Driver Model Fundamentals
  • Platform Bus Internals
  • Device Tree and Platform Devices
  • GPIO Driver Development
  • Workqueue and Delayed Work
  • Threaded IRQ
  • platform_get_resource()
  • platform_get_irq()
  • platform_set_drvdata()
  • platform_get_drvdata()
  • devm_kzalloc()
  • devm_request_irq()
  • devm_ioremap_resource()