How to Develop a Platform Driver From Scratch

On: April 18, 2026
How to Develop a Platform Driver From Scratch

Learn platform driver development from scratch with this beginner-friendly guide. Covers Linux platform drivers, probe functions, Device Tree binding, real code examples, and debugging tips. No fluff, just working code.

1. What Is a Platform Driver and Why Should You Care?

Let’s start with the honest version, not the textbook one. When you plug in a USB mouse, the kernel already knows roughly how to find it because USB has a proper discovery protocol. It can enumerate devices, ask them who they are, and load the right driver automatically. That’s clean and tidy.

But a ton of hardware out there, especially on embedded systems and SoCs (System-on-Chip boards like Raspberry Pi, BeagleBone, or Qualcomm Snapdragon boards), is just soldered directly onto the board. There’s no plug, no discovery, no handshake. The kernel has no idea those peripherals even exist unless you tell it explicitly. That’s exactly the problem the Linux platform driver model was designed to solve.

A platform driver is a kernel-level software component that manages hardware devices which are not automatically discoverable. Think UARTs, timers, GPIO controllers, real-time clocks, and watchdog timers all of these sit on the platform bus and need a platform driver to function.

Think of it this way: A USB driver is like a hotel front desk that checks in any guest who walks through the door. A platform driver is like a host who already has a guest list — the hardware is expected, described in advance, and the driver is pre-matched to it.

Understanding platform driver development is one of the most valuable skills you can pick up in embedded Linux work. Whether you’re dealing with an AMD platform driver for power management, an Intel platform driver for thermal control, or writing a custom driver for your own hardware peripheral, the concepts are almost identical.

And no, you don’t have to be a kernel wizard to get started. By the end of this guide, you’ll have written, compiled, and loaded a working platform driver. Let’s get into it.

2. Platform Driver vs Device Driver vs Character Driver : The Real Difference

This is probably the most-searched question in this space, and it’s worth taking five minutes to get it straight before you write a single line of code.

What Is a Device Driver?

The term “device driver” is actually an umbrella term. Every driver in Linux — platform, character, block, network — is technically a device driver. So when someone asks about platform driver vs device driver, they usually mean: what makes a platform driver different from a generic character driver or a bus-specific driver?

What Is a Character Driver?

A character driver is one of the simplest driver types. It exposes a device as a character device file (like /dev/ttyS0 or /dev/mydevice) and processes data byte by byte. When you write a character driver, you’re implementing file operations: open, read, write, ioctl, and release.

The key thing about a character driver: it doesn’t care how the hardware is connected. It’s just an interface between user space and kernel space. You still need something to describe and bind the physical hardware — and that’s where the platform driver comes in.

Character Driver vs Platform Driver — When to Use Which

AspectCharacter DriverPlatform Driver
Primary roleUser-space interface (read/write)Hardware binding and initialization
Hardware discoveryDoesn’t handle itMatches device to driver via platform bus
Where hardware is describedElsewhere (platform layer)Device Tree or board file
Typical useSerial ports, custom I/O devicesSoC peripherals, onboard hardware
Can they coexist?Yes — a platform driver often registers a character device internally

In practice, many drivers combine both. The platform driver handles the hardware side (initialization, resource allocation, IRQ setup), while internally it creates a character device for user-space access. The difference between platform driver and device driver is more about role and bus binding than anything fundamentally different in structure.

3. How the Linux Platform Driver Model Works Under the Hood

Linux uses a device model built around three key abstractions: bus, device, and driver. The platform bus is a virtual bus — it doesn’t correspond to physical wires, it’s just a logical container for devices that can’t be autodiscovered.

Here’s the flow of what happens when the kernel boots and encounters a platform device:

  1. The hardware is described — either in a Device Tree (.dts file) or a legacy board file (platform_device struct).
  2. The kernel registers this as a platform_device on the platform bus.
  3. Your driver registers itself as a platform_driver with a list of compatible strings (or IDs).
  4. The kernel’s bus layer tries to match each device to a driver using those compatible strings.
  5. When a match is found, the kernel calls your driver’s probe() function.
  6. Your probe() function does the actual hardware setup.

That’s the entire dance. Everything in platform driver development revolves around this match-and-probe cycle. Understanding it deeply will save you hours of confusion later.

The Platform Bus Matching Logic

The matching happens in platform_match() inside the kernel. It checks (in order): Device Tree compatible strings, ACPI IDs, then platform_device_id table entries. If any match, probe is called. If none match, your driver just sits there doing nothing — no errors, no logs unless you dig into dmesg.

4. Setting Up Your Development Environment

Before writing a single line, get your environment ready. You need a Linux system (physical or virtual), kernel headers, and a build system. Here’s what to install on Ubuntu/Debian:

# Install kernel headers and build tools
sudo apt update
sudo apt install build-essential linux-headers-$(uname -r) git vim

# Verify kernel headers are present
ls /lib/modules/$(uname -r)/build

For embedded targets like Raspberry Pi or BeagleBone, you’ll also want a cross-compiler. But for learning, your local x86 Linux machine is perfect. You can write, build, and test everything there without touching real hardware.

💡 Pro Tip

Use a virtual machine (VirtualBox or QEMU) for kernel driver development. A buggy driver can panic your system. Working in a VM means you just restart instead of losing work. QEMU is especially useful for ARM platform driver development.

Your Makefile

Every kernel module needs a Makefile. Here’s the one you’ll use throughout this guide:

obj-m += my_platform_driver.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

5. The Anatomy of a Platform Driver Structure

At the heart of every Linux platform driver is the platform_driver structure. Let’s look at it and understand what each field actually does — because this is the skeleton everything else hangs off of.

struct platform_driver {
    int (*probe)(struct platform_device *);
    int (*remove)(struct platform_device *);
    void (*shutdown)(struct platform_device *);
    int (*suspend)(struct platform_device *, pm_message_t state);
    int (*resume)(struct platform_device *);
    struct device_driver driver;
    const struct platform_device_id *id_table;
    bool prevent_deferred_probe;
};

Here’s what each part means in plain English:

  • probe: Called when the kernel finds a matching device. This is where you initialize hardware, allocate resources, and set everything up. Most of your interesting code goes here.
  • remove: Called when the device is removed or the module is unloaded. Clean up everything you allocated in probe — memory, IRQs, clocks, all of it.
  • shutdown: Called during system shutdown. Usually you just power down the hardware cleanly.
  • suspend / resume: Power management hooks. Used by the dynamic platform and thermal framework driver and similar power-aware drivers on laptops and mobile SoCs.
  • driver: Embedded device_driver — this is where your driver name and owner go, plus the Device Tree compatible string table.
  • id_table: Used for non-Device-Tree matching (legacy board files).

6. Writing Your First Linux Platform Driver From Scratch

Alright, enough theory. Let’s write a real, working platform driver example from scratch. We’ll build a minimal but complete driver that you can load on any x86 Linux machine, see in dmesg, and actually interact with.

Step 1: The Minimal Platform Driver

/* my_platform_driver.c - A minimal Linux platform driver example */

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/init.h>

/* Probe: called when kernel matches device to this driver */
static int my_driver_probe(struct platform_device *pdev)
{
    dev_info(&pdev->dev, "Platform driver probed successfully!\n");
    /* Hardware initialization goes here */
    return 0;   /* 0 = success */
}

/* Remove: called when driver/device is unregistered */
static int my_driver_remove(struct platform_device *pdev)
{
    dev_info(&pdev->dev, "Platform driver removed.\n");
    return 0;
}

/* Device Tree compatible strings for matching */
static const struct of_device_id my_driver_of_match[] = {
    { .compatible = "myvendor,my-device" },
    { },   /* Sentinel - always end with empty entry */
};
MODULE_DEVICE_TABLE(of, my_driver_of_match);

/* Platform driver structure */
static struct platform_driver my_platform_driver = {
    .probe  = my_driver_probe,
    .remove = my_driver_remove,
    .driver = {
        .name           = "my-platform-device",
        .of_match_table = my_driver_of_match,
        .owner          = THIS_MODULE,
    },
};

/* Register driver with kernel */
module_platform_driver(my_platform_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Minimal Linux Platform Driver Example");
MODULE_VERSION("1.0");

That’s a complete, real platform driver. It compiles, loads, and works. Let’s walk through what the important parts do before we make it more useful.

The module_platform_driver Macro

Notice we didn’t write module_init() or module_exit() manually. The module_platform_driver() macro generates both for you. It calls platform_driver_register() at init and platform_driver_unregister() at exit. Less boilerplate, same result.

Step 2: Adding a Platform Device (for Testing Without Real Hardware)

To test this on your x86 machine without a Device Tree, you need to register a platform device manually. Add this to your file or create a separate module:

/* my_platform_device.c - registers a fake device for testing */

#include <linux/module.h>
#include <linux/platform_device.h>

static struct platform_device *my_pdev;

static int __init my_device_init(void)
{
    my_pdev = platform_device_alloc("my-platform-device", -1);
    if (!my_pdev)
        return -ENOMEM;

    return platform_device_add(my_pdev);
}

static void __exit my_device_exit(void)
{
    platform_device_unregister(my_pdev);
}

module_init(my_device_init);
module_exit(my_device_exit);
MODULE_LICENSE("GPL");

Step 3: Build and Load

# Build both modules
make

# Load the device module first (creates the platform_device)
sudo insmod my_platform_device.ko

# Load the driver (probe() fires immediately on match)
sudo insmod my_platform_driver.ko

# Check kernel logs
dmesg | tail -20

# You should see: "Platform driver probed successfully!"

# Unload in reverse order
sudo rmmod my_platform_driver
sudo rmmod my_platform_device

If you see the probe message in dmesg, congratulations — you just wrote your first Linux platform device driver. That’s the real thing, running in kernel space.

7. Platform Device Registration and the Device Tree

Manual device registration like above is fine for testing, but real production platform driver development uses Device Tree (DT) on ARM and RISC-V boards, and ACPI on x86 machines.

What Is the Device Tree?

The Device Tree is a data structure that describes hardware to the Linux kernel. It’s written in DTS (Device Tree Source) format and compiled into a DTB (Device Tree Blob) that the bootloader passes to the kernel. Think of it as a hardware configuration file — it tells the kernel what peripherals exist, where they live in memory, and what interrupt lines they use.

A Device Tree Node for Your Driver

/* Fragment to add to your board's .dts file */
my_device: my_device@40010000 {
    compatible = "myvendor,my-device";
    reg = <0x40010000 0x1000>;      /* base address + size */
    interrupts = <0 42 4>;          /* GIC IRQ */
    clocks = <&apb_pclk>;
    status = "okay";
};

The compatible string here — "myvendor,my-device" — must exactly match what’s in your driver’s of_match_table. This is the bridge between hardware description and software driver. One mismatch in this string and probe never gets called. No error, just silence.

⚠️ Common Gotcha

The compatible string is case-sensitive and format matters. Convention is "vendor,device-name" in all lowercase with a hyphen separator. "MyVendor,My-Device" and "myvendor,my-device" are different strings to the kernel.

ACPI on x86 — The Intel and AMD World

On x86 systems — the territory of Intel platform drivers and AMD platform drivers — hardware description happens through ACPI tables instead of Device Tree. The matching logic uses ACPI IDs. This is how drivers like the Intel Dynamic Platform and Thermal Framework driver (INT3400) or AMD platform driver for power management get loaded automatically on laptops. You’ll see them in /sys/bus/platform/devices/.

8. The Probe and Remove Functions Explained

The probe() function is where your driver actually does its job. Everything else — the structure, the module macros, the DT binding — is just ceremony to get probe called correctly. Let’s build a more realistic probe function.

A Realistic Probe Function

struct my_device_data {
    void __iomem *base;      /* mapped register address */
    int irq;
    struct clk *clk;
    struct device *dev;
};

static int my_driver_probe(struct platform_device *pdev)
{
    struct my_device_data *data;
    struct resource *res;
    int ret;

    /* Allocate driver private data using managed allocation */
    data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
    if (!data)
        return -ENOMEM;

    data->dev = &pdev->dev;

    /* Get memory resource from Device Tree */
    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

    /* Map it into virtual address space */
    data->base = devm_ioremap_resource(&pdev->dev, res);
    if (IS_ERR(data->base))
        return PTR_ERR(data->base);

    /* Get IRQ number */
    data->irq = platform_get_irq(pdev, 0);
    if (data->irq < 0)
        return data->irq;

    /* Request the IRQ */
    ret = devm_request_irq(&pdev->dev, data->irq,
                            my_irq_handler, 0,
                            "my-device", data);
    if (ret)
        return ret;

    /* Store private data for later use in other callbacks */
    platform_set_drvdata(pdev, data);

    dev_info(&pdev->dev, "Probed at %p, IRQ %d\n", data->base, data->irq);
    return 0;
}

Why devm_ Functions Are Your Best Friends

Notice we’re using devm_kzalloc, devm_ioremap_resource, and devm_request_irq instead of their non-devm counterparts. The devm_ prefix means “device-managed” — the kernel automatically releases these resources when the device is detached or the driver is removed. This means your remove() function is often nearly empty, and you can’t forget to free something because the framework handles it. Use devm_ everywhere you can.

The Remove Function

static int my_driver_remove(struct platform_device *pdev)
{
    struct my_device_data *data = platform_get_drvdata(pdev);

    /* devm_ resources freed automatically; just do extra cleanup */
    dev_info(&pdev->dev, "Device removed cleanly.\n");
    return 0;
}

9. Handling Resources: IRQs, Memory, and Clocks

Real hardware needs real resources. The platform framework provides clean APIs for getting everything your device needs.

Memory-Mapped I/O

Most SoC peripherals are memory-mapped — they appear at a specific physical address. You read and write registers by reading and writing memory locations. In your driver, you get this resource from the Device Tree and map it:

/* Get the first memory resource */
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

/* Map physical address to virtual address */
void __iomem *base = devm_ioremap_resource(&pdev->dev, res);

/* Read a register at offset 0x04 */
u32 val = readl(base + 0x04);

/* Write to a register at offset 0x08 */
writel(0x1, base + 0x08);

Never use pointer arithmetic or direct casting for hardware registers. Always use readl()/writel() (or readb/writeb for 8-bit, readw/writew for 16-bit). These functions handle memory barriers and endianness correctly.

Interrupts

/* IRQ handler — runs in interrupt context, keep it fast */
static irqreturn_t my_irq_handler(int irq, void *dev_id)
{
    struct my_device_data *data = dev_id;

    /* Read status register to see what happened */
    u32 status = readl(data->base + STATUS_REG);

    if (!(status & MY_INTERRUPT_BIT))
        return IRQ_NONE;   /* Not our interrupt */

    /* Clear the interrupt */
    writel(status, data->base + STATUS_REG);

    return IRQ_HANDLED;
}

⚠️ Interrupt Context Rules

In an interrupt handler you cannot sleep, cannot allocate memory with GFP_KERNEL, and cannot call most kernel functions that might block. Keep handlers short. Use threaded IRQs or workqueues for heavy processing.

Clocks

Many peripherals need a clock to operate. The Common Clock Framework handles this:

/* Get the clock described in Device Tree as "apb_pclk" */
struct clk *clk = devm_clk_get(&pdev->dev, "apb_pclk");
if (IS_ERR(clk))
    return PTR_ERR(clk);

/* Enable the clock */
int ret = clk_prepare_enable(clk);
if (ret)
    return ret;

/* Read clock rate in Hz */
unsigned long rate = clk_get_rate(clk);
dev_info(&pdev->dev, "Clock running at %lu Hz\n", rate);

10. Debugging Your Platform Driver

Things will go wrong. Knowing how to debug a platform driver is just as important as knowing how to write one. Here are the tools you’ll actually use day to day.

dmesg — Your First Stop

# Watch kernel logs live while loading your module
sudo dmesg -w &

# Or filter for your driver specifically
sudo dmesg | grep -i "my-platform"

# See full detail with timestamps
sudo dmesg -T | tail -50

The /sys/bus/platform/ Filesystem

The sysfs virtual filesystem lets you inspect the platform bus state without writing code:

# List all registered platform devices
ls /sys/bus/platform/devices/

# List all registered platform drivers
ls /sys/bus/platform/drivers/

# Check if your driver is bound to a device
ls /sys/bus/platform/drivers/my-platform-device/

# Check device attributes
cat /sys/bus/platform/devices/my-platform-device/modalias

Why Is Probe Not Being Called?

This is the most common frustration in platform driver development. Here’s a checklist:

  1. Does the compatible string in your DTS exactly match the one in of_match_table?
  2. Is the device node’s status set to "okay" in the DTS?
  3. Did you compile and deploy the updated DTB to your board?
  4. Is the driver module actually loaded? (lsmod | grep my_driver)
  5. Is there a deferred probe happening? Check /sys/kernel/debug/devices_deferred.

Enabling Dynamic Debug

# Enable dev_dbg() messages for your driver at runtime
echo "module my_platform_driver +p" > /sys/kernel/debug/dynamic_debug/control

# Or enable for a specific file
echo "file my_platform_driver.c +p" > /sys/kernel/debug/dynamic_debug/control

KASAN and KFENCE

If you’re seeing mysterious crashes or memory corruption, build your kernel with KASAN (Kernel Address SANitizer) enabled. It catches use-after-free, buffer overflows, and other memory bugs that would otherwise be invisible. Configure it with make menuconfig → Kernel Hacking → Memory Debugging.

11. Real-World Platform Driver Examples

Theory is great, but looking at real drivers in the kernel source is how you truly level up. The Linux kernel’s drivers/ directory is a treasure trove of platform driver examples.

Intel Dynamic Platform and Thermal Framework Driver

The Intel Dynamic Platform and Thermal Framework driver (DPTF) manages thermal policies on Intel laptops. You’ll find its driver at drivers/thermal/intel/int340x_thermal/ in the kernel source. It’s a great example of how complex power management integrates with the platform driver model. The Intel Innovation Platform Framework driver builds on similar concepts for newer hardware generations.

AMD Platform Driver

The AMD platform driver stack (often called AMD platform driver 11 or similar in Windows driver contexts) handles power, GPIO, and SPI peripherals on AMD SoC platforms. On Linux, look at drivers/platform/x86/amd/ for reference implementations.

A Simple GPIO Platform Driver

Here’s a stripped-down GPIO controller driver — this is the style of thing you’d write for a custom FPGA or microcontroller peripheral:

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/gpio/driver.h>
#include <linux/io.h>

#define GPIO_DIR_REG    0x00
#define GPIO_DATA_REG   0x04

struct my_gpio {
    struct gpio_chip chip;
    void __iomem *base;
};

static int my_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
    struct my_gpio *gpio = gpiochip_get_data(chip);
    return !!(readl(gpio->base + GPIO_DATA_REG) & BIT(offset));
}

static void my_gpio_set(struct gpio_chip *chip,
                         unsigned int offset, int value)
{
    struct my_gpio *gpio = gpiochip_get_data(chip);
    u32 reg = readl(gpio->base + GPIO_DATA_REG);
    if (value)
        reg |= BIT(offset);
    else
        reg &= ~BIT(offset);
    writel(reg, gpio->base + GPIO_DATA_REG);
}

static int my_gpio_probe(struct platform_device *pdev)
{
    struct my_gpio *gpio;
    struct resource *res;

    gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
    if (!gpio) return -ENOMEM;

    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    gpio->base = devm_ioremap_resource(&pdev->dev, res);
    if (IS_ERR(gpio->base)) return PTR_ERR(gpio->base);

    gpio->chip.label     = "my-gpio";
    gpio->chip.parent    = &pdev->dev;
    gpio->chip.ngpio     = 32;
    gpio->chip.base      = -1;    /* dynamic base */
    gpio->chip.get       = my_gpio_get;
    gpio->chip.set       = my_gpio_set;

    return devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
}

static const struct of_device_id my_gpio_ids[] = {
    { .compatible = "myvendor,my-gpio" },
    {}
};
MODULE_DEVICE_TABLE(of, my_gpio_ids);

static struct platform_driver my_gpio_driver = {
    .probe  = my_gpio_probe,
    .driver = { .name = "my-gpio", .of_match_table = my_gpio_ids },
};
module_platform_driver(my_gpio_driver);
MODULE_LICENSE("GPL");

12. Common Mistakes and How to Avoid Them

After working through several platform driver development projects, here are the mistakes that bite people most often.

1. Not Handling Probe Deferral

Sometimes your driver probes before a dependency (like a clock, regulator, or GPIO) is ready. The kernel handles this with -EPROBE_DEFER — when a resource isn’t available yet, return that error code and the kernel will retry your probe later. Always check for it:

struct clk *clk = devm_clk_get(&pdev->dev, "my_clk");
if (IS_ERR(clk)) {
    if (PTR_ERR(clk) == -EPROBE_DEFER)
        return -EPROBE_DEFER;    /* Try again later */
    return PTR_ERR(clk);
}

2. Sleeping in Interrupt Context

This will cause a kernel panic or BUG() message. In IRQ handlers, tasklets, or spinlock-held sections, you cannot call anything that might sleep: kmalloc(GFP_KERNEL), mutex_lock(), schedule(), etc.

3. Forgetting the Sentinel in ID Tables

Both of_device_id[] and platform_device_id[] arrays must end with an empty entry { }. The kernel iterates until it hits this sentinel. Without it, you’re reading garbage memory.

4. Using the Wrong Memory Barriers

When accessing hardware registers, use the appropriate I/O functions (readl, writel) which include memory barriers. Don’t use plain pointer dereferencing for MMIO — the compiler or CPU might reorder your accesses.

5. Reference Counting Bugs

If you register a device (chardev, netdev, etc.) in probe, make sure you deregister it in remove — even when using devm. Some subsystems (like misc_register) don’t have devm wrappers and need explicit cleanup.

6. Driver Not Intended for This Platform

If you see “driver is not intended for this platform” errors — common with third-party drivers on Windows and sometimes Linux — it usually means the driver was compiled for a different architecture or kernel ABI version. In Linux, rebuild the module against the exact running kernel version. For cross-compiled drivers, ensure your toolchain targets match.

Going Further: I2C, SPI, and the Bigger Ecosystem

Platform drivers are one piece of a larger puzzle. Many real-world embedded drivers combine a platform driver with another bus driver layer.

I2C Platform Driver Pattern

An I2C controller on a SoC is itself a platform device. You write a platform driver for the I2C controller, which then registers an i2c_adapter. Devices connected to that I2C bus (sensors, displays) get their own i2c_driver. This layering is how the Linux I2C subsystem works — and it’s elegant once you see the structure.

/* Simplified I2C controller platform driver registration */
static int my_i2c_probe(struct platform_device *pdev)
{
    struct my_i2c_dev *dev;
    /* ... setup ... */

    dev->adapter.owner   = THIS_MODULE;
    dev->adapter.algo    = &my_i2c_algo;
    dev->adapter.dev.parent = &pdev->dev;
    i2c_set_adapdata(&dev->adapter, dev);

    return i2c_add_adapter(&dev->adapter);
}

The vfio-platform Driver

The vfio platform driver is an interesting case — it allows platform devices to be passed through to virtual machines via VFIO (Virtual Function I/O). If you’re doing virtualization work with ARM SoCs and want a guest VM to directly own a hardware peripheral, this is the kernel subsystem to study.

Platform Driver and Power Management

Production drivers must handle suspend and resume correctly. This is especially important for the platform power management driver on mobile SoCs and for drivers that interact with thermal frameworks. Use the dev_pm_ops structure:

static int my_suspend(struct device *dev)
{
    struct my_device_data *data = dev_get_drvdata(dev);
    /* Disable hardware, save state */
    clk_disable_unprepare(data->clk);
    return 0;
}

static int my_resume(struct device *dev)
{
    struct my_device_data *data = dev_get_drvdata(dev);
    /* Re-enable hardware, restore state */
    return clk_prepare_enable(data->clk);
}

static const struct dev_pm_ops my_pm_ops = {
    SET_SYSTEM_SLEEP_PM_OPS(my_suspend, my_resume)
};

/* Then in platform_driver.driver: */
.pm = &my_pm_ops,

FAQ: Everything People Ask About Platform Drivers

What is a platform driver in Linux?

A platform driver is a kernel module that manages hardware devices registered on the Linux platform bus. These are typically SoC peripherals — UARTs, GPIO controllers, timers, I2C controllers — that can’t be auto-discovered. The driver binds to a device using a compatible string from the Device Tree or an ACPI ID.

What is the platform driver meaning in simple terms?

Think of it as glue between the kernel and a piece of hardware that the kernel can’t find by itself. You describe the hardware (in a Device Tree or board file), and the platform driver handles everything the kernel needs to use it.

What is the difference between a platform driver and a character driver?

A platform driver handles hardware binding and initialization. A character driver provides a user-space interface (like a file in /dev/). They’re different layers and often used together — the platform driver sets up the hardware, and internally creates a character device for applications to interact with.

Why is my platform driver probe not called?

Most likely, the compatible string doesn’t match between your DTS node and your driver’s of_match_table. Also check: the device node has status = "okay", the DTB is actually deployed to your board, and the module is loaded. Use dmesg and /sys/bus/platform/ to investigate.

Can you drive in platform shoes?

This one comes up in searches alongside platform driver content — totally different topic! In most countries it’s legal but not recommended. Thick-soled platform shoes can reduce pedal sensitivity and braking feel. Some motorsport regulations and highway codes advise against it. Flat shoes are always safer at the wheel.

What is the Intel Dynamic Platform and Thermal Framework driver?

The Intel Dynamic Platform and Thermal Framework driver (DPTF, or INT3400 on Linux) is an Intel platform driver for laptop thermal management. It coordinates between the CPU, GPU, and various temperature sensors to manage heat under load. On Linux, it’s managed through the thermal subsystem and integrates with the Intel Innovation Platform Framework driver stack on newer generations.

What is the AMD platform driver?

The AMD platform driver refers to a collection of drivers for AMD SoC peripherals — GPIO, SPI, I2C, power management, and more. The AMD platform driver 11 version often referenced in Windows contexts handles PCIe, USB, and storage interfaces on Ryzen-based systems.

What is a vfio platform driver?

The vfio platform driver allows non-PCI platform devices (like those on ARM SoCs) to be assigned directly to guest VMs using VFIO. It provides an IOMMU-backed safe passthrough mechanism. Useful for real-time virtualization on embedded systems.

What is the Intel Platform Monitoring Technology driver?

The Intel Platform Monitoring Technology (PMT) driver provides access to hardware telemetry data — power consumption, temperatures, CPU performance metrics — from userspace. It’s part of the Intel platform driver stack and visible under /sys/class/intel_pmt/.

What is the Trusted Platform Module driver?

The Trusted Platform Module (TPM) driver provides cryptographic functions for secure boot, disk encryption, and key storage. The Trusted Platform Module 2.0 driver is the current standard, found in most modern PCs. On Linux it shows up as /dev/tpm0 and /dev/tpmrm0. The Trusted Platform Module 2.0 driver download for Windows is typically handled through Windows Update or OEM drivers from Dell, HP, Lenovo, or Gigabyte.

What is the Windows Filtering Platform driver?

The Windows Filtering Platform (WFP) driver is a Windows network framework that lets drivers and applications intercept and filter network packets. It’s what firewalls and antivirus software use to inspect traffic. Not related to Linux platform drivers, but a common search crossover.

What is platform fee in Uber/Ola driver apps?

Another common search crossover. In gig economy driver platforms like Uber and Ola, the platform fee is the percentage or fixed amount the platform takes from each trip as a service fee. This is separate from the driver’s earnings and varies by market. Not related to Linux kernel platform drivers at all, but worth clarifying since the searches overlap!

What is the Xilinx Platform Cable USB driver?

The Xilinx Platform Cable USB driver (also called Xilinx Platform Cable USB II driver) is a driver for Xilinx’s JTAG programming cables used to program FPGAs. On Linux, you can install it via the Xilinx cable drivers package (install_drivers script in Vivado). On Windows 10/11, it’s available from the Xilinx website. This is actually a Linux USB driver wrapping the cable’s USB interface — not a platform driver in the kernel sense.

What is the ASUSTOR Platform Driver?

The ASUSTOR platform driver is a set of Linux kernel modules for ASUSTOR NAS devices that control GPIO, LEDs, buttons, and fan management. It’s a real platform driver example for embedded x86 hardware, available on GitHub if you want to study a production out-of-tree platform driver.

For detailed understanding of Platform Devices and Drivers on Linux, refer to the Linux documentation on Platform Devices and Drivers .

Leave a Comment