三尺非寒 发表于 3 天前

linux平台总线模型

什么是平台总线模型: 是linux系统假造出来的总线, 没有对应的硬件接口
平台总线模型将一个驱动分成了两个部分
device.c: 描述硬件资源代码, 描述寄存器的地点, 中断号
driver.c: 控制硬件的驱动代码, 操作寄存器, 处理中断
这两个部分通过相同的name进行匹配
为什么要使用平台总线, 平台总线的优点
差异的处理器的相同功能的寄存器不在一个位置, 但是使用驱动可以是同一套

[*]减少编写的重复代码, 提高服从
[*]提高代码的使用率
注册平台设备

device.c描述的硬件资源是
硬件的寄存器的地点, 中断号, 和其他硬件资源
使用下面的结构体描述
struct platform_device {
    // 名字, 和driver匹配, 可以在sys目录下看到
        const char        *name;
        // 区分不同的设备, sys目录下的设备文件的后缀(-1无后缀)
        int                id;
        bool                id_auto; // 自动设置id, 一般不用
    // 设备的通用属性部分, 必须实现里面的release函数
        struct device        dev;
        u64                platform_dma_mask;
        struct device_dma_parameters dma_parms;

    // 存储资源的个数
        u32                num_resources;
        // 存放硬件资源的结构体
        struct resource        *resource;

        const struct platform_device_id        *id_entry;
        const char *driver_override;

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

        /* arch specific additions */
        struct pdev_archdata        archdata;
};描述硬件资源的结构体
// linux-master/include/linux/ioport.h
struct resource {
        resource_size_t start;
        resource_size_t end;
        const char *name;
        unsigned long flags;
        unsigned long desc;
        struct resource *parent, *sibling, *child;
};

[*]start/end: 资源的起始信息和终止信息, 比如寄存器的起始地点和终止地点
[*]flags: 硬件资源信息的范例, 在include/linux/ioport.h路径下列举
硬件资源举例
static struct resource my_device_resources[] = {
    = {
      .start = 0xFDD60000,
      .end = 0xFDD60004,
      .flags = IORESOURCE_MEM, // 内存类型或寄存器
    },
    = {
      .start = 13,
      .end = 13,
      .flags= IORESOURCE_IRQ, // 中断类型
    },
};platform设备加卸载函数: 把设备加载到总线上
int platform_device_register(struct platform_device *pdev)
void platform_device_unregister(struct platform_device *pdev)注册平台驱动

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

[*]probe: 必须实现, 当设备和驱动匹配乐成之后, 自动执行
[*]remove: 移出一个设备的时候执行
[*]shutdown: 电源管理, 关掉设备时执行
[*]suspend: 电源管理, 挂起时执行
[*]resume: 电源管理, 恢复时执行
[*]driver: 设备共用的一些属性
[*]id_table: 设备的ID表
platform驱动加卸载函数
const struct platform_device_id mydriver_id_table = {
    .name = "mydevice",
};

struct platform driver platform driver test ={
    .probe = mydriver_probe,
    .remove =mydriver_remove,
    .driver = {
      .name ="mydevice",
      .owner = THIS_MODULE,
    }
    // id_table的优先级大于drive中的name
    .id_table = &mydriver_id_table,
}

int platform_driver_register(struct platform_driver *drv, struct module *owner)
void platform_driver_unregister(struct platform_driver *drv);设备和驱动的匹配方法

平台设备和驱动的匹配方法

[*]先通过platform_driver中的id_table
[*]假如id_table不存在,则只是简单的比较设备中的name字段和驱动中的name字段是否相同
static int platform_match(struct device *dev, struct device_driver *drv)
{
    ...
        /* 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_get_resource: 返回设备指定范例的第num个资源
struct resource *platform_get_resource(struct platform_device *dev,
                                     unsigned int type, unsigned int num)
{
        u32 i;

        for (i = 0; i < dev->num_resources; i++) {
                struct resource *r = &dev->resource;

                if (type == resource_type(r) && num-- == 0)
                        return r;
        }
        return NULL;
}用户程序通过平台总线访问设备寄存器的例子

https://img2024.cnblogs.com/blog/3591076/202501/3591076-20250111165813396-1117421623.jpg

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: linux平台总线模型