3.0.35 platform 总线、设备与驱动

在该内核的设备驱动模型中,关心总线、设备和驱动这三个实体。

在系统每注册一个设备的时候,由总线寻找与之匹配的驱动;在系统每注册一个驱动的时候,会由总线寻找与之匹配的设备。

一个现实的linux设备和驱动通常都需要挂载在一种总线上,对于本身依附于PCI,USB,I2C,SPI等的设备而言,这不是问题

但在嵌入式系统中,SoC系统中集成了独立的外设控制器,集成于SoC中的外设却不依赖于这类总线。基于这一背景,linux

发明了一种虚拟总线,称为platform总线,platform 所描述的资源有一个共同点:在 CPU 的总线上直接取址。相应的,

设备称为platform_device,驱动称为platform_driver。

两者的工作顺序是

  • 先定义 platform_device -> 注册 platform_device
  • 再定义 platform_driver -> 注册 platform_driver

注意:所谓的platform_device并不是与字符设备、块设备、网络设备并列的概念,而是linux系统提供的一种附加手段。

platform_device 结构体的定义(include/linux/platform_device.h),如下示:

struct platform_device {
    const char    * name; // 设备名用于和驱动进行绑定
    int        id;         // 设备ID
    struct device    dev;
    u32        num_resources; // 设备所使用各类资源数量
    struct resource    * resource; // 资源

    const struct platform_device_id    *id_entry;

    /* MFD cell pointer */
    struct mfd_cell *mfd_cell;

    /* arch specific additions */
    struct pdev_archdata    archdata;
};

platform_driver 结构体的定义(include/linux/platform_device.h),如下示:

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;
};

该结构体中包含 probe(), remove(), shutdown, suspend(), resume函数,通常也需要由驱动实现。

系统中为platform 总线定义了一个bus_type 的实例 platform_bus_type(drivers/base/platform.c),其定义如下:

struct bus_type platform_bus_type = {
    .name        = "platform",
    .dev_attrs    = platform_dev_attrs,
    .match        = platform_match,
    .uevent        = platform_uevent,
    .pm        = &platform_dev_pm_ops,
};
EXPORT_SYMBOL_GPL(platform_bus_type);

这里要重点关注 match() 成员函数,正是此函数确定了 platform_device 和 platform_driver 之间是如何配置的。

platform_match 定义(drivers/base/platform.c)如下:

/**
 * platform_match - bind platform device to platform driver.
 * @dev: device.
 * @drv: driver.
 *
 * Platform device IDs are assumed to be encoded like this:
 * "<name><instance>", where <name> is a short description of the type of
 * device, like "pci" or "floppy", and <instance> is the enumerated
 * instance of the device, like ‘0‘ or ‘42‘.  Driver IDs are simply
 * "<name>".  So, extract the <name> from the platform_device structure,
 * and compare it against the name of the driver. Return whether they match
 * or not.
 */
static int platform_match(struct device *dev, struct device_driver *drv)
{
    struct platform_device *pdev = to_platform_device(dev);
    struct platform_driver *pdrv = to_platform_driver(drv);

    /* Attempt an OF style match first */
    if (of_driver_match_device(dev, drv))
        return 1;

    /* Then try to match against the id table */
    if (pdrv->id_table)
        return platform_match_id(pdrv->id_table, pdev) != NULL;

    /* fall-back to driver name match */
    return (strcmp(pdev->name, drv->name) == 0);
}

由上可知, 匹配platform_device 和 platform_driver 主要看两者的 name字段是否相同。

对platform_device 的定义通常在BSP的板文件中实现,在板文件中,将platform_device 归纳为一个数组,最终通过

platform_add_devices() 函数统一注册。其定义(drivers/base/platform.c)如下:

/**
 * platform_add_devices - add a numbers of platform devices
 * @devs: array of platform devices to add
 * @num: number of platform devices in array
 */
int platform_add_devices(struct platform_device **devs, int num)
{
    int i, ret = 0;

    for (i = 0; i < num; i++) {
        ret = platform_device_register(devs[i]);
        if (ret) {
            while (--i >= 0)
                platform_device_unregister(devs[i]);
            break;
        }
    }

    return ret;
}
EXPORT_SYMBOL_GPL(platform_add_devices);

platform_add_devices() 函数可以将平台设备添加到系统中,该函数的第一个参数为平台设备数组的指针,第二个参数为平台设备

的数量,它内部调用了platform_device_register() 函数,用于注册单个的平台设备。

时间: 2024-10-30 07:21:58

3.0.35 platform 总线、设备与驱动的相关文章

3.0.35 platform 设备资源和数据

在结构体 platform_device 的定义(include/linux/platform_device.h)中: struct platform_device { const char * name; int id; struct device dev; u32 num_resources; struct resource * resource; const struct platform_device_id *id_entry; /* MFD cell pointer */ struct

linux设备驱动归纳总结(九):1.platform总线的设备和驱动【转】

本文转载自:http://blog.chinaunix.net/uid-25014876-id-111745.html linux设备驱动归纳总结(九):1.platform总线的设备和驱动 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 这一节可以理解是第八章的延伸,从这节开始介绍platform设备驱动. xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

platform总线驱动代码分析

/************************************************************************/ Linux内核版本:2.6.35.7 运行平台:三星s5pv210 /************************************************************************/ 1.本例中通过使用Linux驱动模型中的platform总线和led驱动框架编写出来的led驱动代码来分析platform总线的工作

Linux驱动中的platform总线分析

copy from :https://blog.csdn.net/fml1997/article/details/77622860 概述 从Linux2.6内核起,引入一套新的驱动管理和注册机制:platform_device 和 platform_driver .Linux 中大部分的设备驱动,都可以使用这套机制,设备用 platform_device 表示:驱动用 platform_driver 进行注册. linux_platform_driver 机制和传统的device_driver机

linux驱动之platform总线

第一部分:设备驱动模型1.总线:bus_type结构体,关键函数是match函数和uevent函数:总线将设备和驱动绑定,在系统每注册一个设备的时候,会寻找与之匹配的驱动,相反,在系统每注册一个驱动的时候,会寻找与之匹配的设备,而匹配由总线完成. 2.设备:struct device结构体,硬件设备在内核驱动框架中的抽象: (1)device_register用于向内核驱动框架注册一个设备 (2)通常device不会单独使用,而是被包含在一个具体设备结构体中,如struct usb_device

fl2440 platform总线led字符设备驱动

首先需要知道的是,设备跟驱动是分开的.设备通过struct device来定义,也可以自己将结构体封装到自己定义的device结构体中: 例如:struct platform_device: 1 在include/linux/platform_device.h文件中: //这个位置还是个盲点,我一直没找到这个位置在哪里 2 struct platform_device { 3 const char * name 4 u32 id 5 struct device dev 6 u32 num_res

20150226 IMX257 总线设备驱动模型编程之平台总线设备platform

20150226 IMX257 总线设备驱动模型编程之平台总线设备platform 2015-02-26 李海沿 前面我们实现了总线设备驱动模型,下面我们来了解一下平台总线,平台设备驱动 分为平台设备和平台驱动两种,和前面所说的设备驱动差不多 platform总线是一种虚拟的总线,相应的设备则为platform_device,而驱动则为platform_driver.Linux 2.6的设备驱动模型中,把I2C.RTC.LCD等都归纳为platform_device. 一.平台设备介绍 1. p

fl2440 platform总线button字符设备驱动

驱动程序: 1 #include "s3c_driver.h" 2 3 #define DRV_DESC "S3C24XX button driver" 4 5 /* Driver version*/ 6 #define DRV_MAJOR_VER 1 7 #define DRV_MINOR_VER 0 8 #define DRV_REVER_VER 0 9 10 #define DEV_NAME DEV_BUTTON_NAME 11 12 //#define DE

linux 3.0.35下globalmem 字符设备驱动实现

1.Makefile KDIR=/home/xxx/s-linux-3.0.35 PWD:=$(shell pwd) # kernel modules obj-m := globalmem.o modules: make -C $(KDIR) M=$(PWD) modules clean: rm -rf *.o *.ko *.mod.c *.markesr *.order *.symvers .PHONY:modules clean 2.globalmem.c #include <linux/m