Platform Bus Driver Implementation in Linux

Understanding the Platform Bus

The platform bus is a virtual bus within the Linux kernel architecture, designed to unify the device and driver model. Unlike physical buses such as PCI or USB, the platform bus does not correspond to any physical hardware. It exists to manage devices that do not naturally fit into other bus models, ensuring a consistent device model across the system.

Bus Framework Architecture

Within the platform bus model, three main entities are involved: the bus itself, the devices, and the drivers. The bus acts as an intermediary that matches devices with drivers. This matching occurs during device or driver registration, allowing the system to dynamically bind drivers to devices based on compatibility.

The bus framework improves code maintainability and portability by centralizing device-driver management with in the kernel. This appproach reduces the need for device-specific glue code and promotes modular driver development.

Platform Bus and Device Tree

Platform devices can be registered in two primary ways: programmatically using platform_device_register, or declaratively through the Device Tree Blob (DTB). The Linux kernel parses the device tree during initialization, creating platform devices based on the hardware descriptions provided.

Driver Framework Implementation

The platform driver framework involves several core components:

  1. Registering a platform_driver
  2. Registering character device numbers and file operations
  3. Creating device nodes via class_create

Driver Initialization Example


#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/platform_device.h>

static dev_t dev_num;
static struct cdev *my_cdev;
static struct class *my_class;

static int my_open(struct inode *inode, struct file *file) {
    // Implementation
    return 0;
}

static ssize_t my_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) {
    // Implementation
    return count;
}

static ssize_t my_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) {
    // Implementation
    return count;
}

static const struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = my_open,
    .read = my_read,
    .write = my_write,
};

static int my_probe(struct platform_device *pdev) {
    alloc_chrdev_region(&dev_num, 0, 1, "my_device");
    my_cdev = cdev_alloc();
    cdev_init(my_cdev, &fops);
    cdev_add(my_cdev, dev_num, 1);

    my_class = class_create(THIS_MODULE, "my_class");
    device_create(my_class, NULL, dev_num, NULL, "my_device");

    return 0;
}

static int my_remove(struct platform_device *pdev) {
    device_destroy(my_class, dev_num);
    class_destroy(my_class);
    cdev_del(my_cdev);
    unregister_chrdev_region(dev_num, 1);
    return 0;
}

static struct platform_driver my_platform_driver = {
    .probe = my_probe,
    .remove = my_remove,
    .driver = {
        .name = "my_device",
        .owner = THIS_MODULE,
    },
};

static int __init my_init(void) {
    return platform_driver_register(&my_platform_driver);
}

static void __exit my_exit(void) {
    platform_driver_unregister(&my_platform_driver);
}

module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");

Device Registration

Platform devices are described using the platform_device structure, which contains device-specific information such as memory resources and device name.

Platform Device Structure


struct platform_device {
    const char *name;
    int id;
    struct device dev;
    u32 num_resources;
    struct resource *resource;
};

Resource Structure


struct resource {
    const char *name;
    unsigned long start, end;
    unsigned long flags;
};

Device Registrasion Example


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

static struct resource my_resources[] = {
    [0] = {
        .start = 0x40000000,
        .end = 0x4000FFFF,
        .flags = IORESOURCE_MEM,
    },
};

static void my_device_release(struct device *dev) {
    // Cleanup implementation
}

static struct platform_device my_device = {
    .name = "my_device",
    .id = -1,
    .num_resources = ARRAY_SIZE(my_resources),
    .resource = my_resources,
    .dev = {
        .release = my_device_release,
    },
};

static int __init my_device_init(void) {
    return platform_device_register(&my_device);
}

static void __exit my_device_exit(void) {
    platform_device_unregister(&my_device);
}

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

Tags: Linux kernel platform bus device driver platform device Device Tree

Posted on Sun, 26 Jul 2026 16:17:08 +0000 by dasding