1、简介
基于总线、设备和驱动这样的驱动框架,Linux 内核提出来 platform 这个虚拟总线,相应的也有 platform 设备和 platform 驱动。

Linux 总线设备和驱动模式

2、platform_match函数

在drivers/base/platform.c的platform_match函数

/*** 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);/* When driver_override is set, only bind to the matching driver */if (pdev->driver_override)return !strcmp(pdev->driver_override, drv->name);/* Attempt an OF style match first */if (of_driver_match_device(dev, drv))return 1;/* Then try ACPI style match */if (acpi_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);
}

可以看出驱动和设备的匹配有四种方法

of_driver_match_device(dev, drv)

第一种匹配方式, OF 类型的匹配,也就是设备树采用的匹配方式, of_driver_match_device 函数定义在文件include/linux/of_device.h 中。device_driver 结构体(表示设备驱动)中有个名为of_match_table的成员变量,此成员变量保存着驱动的compatible匹配表, 设备树中的每个设备节点的 compatible 属性会和 of_match_table 表中的所有成员比较,查看是否有相同的条目,如果有的话就表示设备和此驱动匹配,设备和驱动匹配成功以后 probe 函数就会执行。

acpi_driver_match_device(dev, drv)
第二种匹配方式,ACPI 匹配方式。
if (pdrv->id_table)return platform_match_id(pdrv->id_table, pdev) != NULL;
第三种匹配方式,id_table 匹配,每个 platform_driver 结构体有一个 id_table 成员变量,顾名思义,保存了很多 id 信息。这些 id 信息存放着这个 platformd 驱动所支持的驱动类型。
return (strcmp(pdev->name, drv->name) == 0);
第四种匹配方式,如果第三种匹配方式的 id_table 不存在的话就直接比较驱动设备的 name 字段,看看是不是相等,如果相等的话就匹配成功。
对于支持设备树的 Linux 版本号,一般设备驱动为了兼容性都支持设备树和无设备树两种 匹配方式。也就是第一种匹配方式一般都会存在,第三种和第四种只要存在一种就可以,一般用的最多的还是第四种,也就是直接比较驱动和设备的 name 字段,毕竟这种方式最简单了。

3、设备树下的platform驱动框架


#define GPIOLED_CNT 1
#define GPIOLED_NAME "dtsplatled"
#define LEDOFF 0
#define LEDON 1/* gpioled设备结构体 */
struct gpioled_dev
{dev_t devid;int major;int minor;struct cdev cdev;struct class *class;struct device *device;struct device_node *nd;int led_gpio;
};struct gpioled_dev gpioled; /* LED */static int led_open(struct inode *inode, struct file *filp)
{filp->private_data = &gpioled;return 0;
}static int led_release(struct inode *inode, struct file *filp)
{
struct gpioled_dev *dev = filp->private_data;return 0;
}static ssize_t led_write(struct file *filp, const char __user *buf,size_t count, loff_t *ppos)
{int ret;unsigned char databuf[1];struct gpioled_dev *dev = filp->private_data;return 0;
}/* 操作集 */
static const struct file_operations led_fops = {.owner = THIS_MODULE,.write = led_write,.open = led_open,.release = led_release,
};/*platform 驱动的 probe 函数,当驱动与设备匹配以后此函数就会执行*/
static int led_probe(struct platform_device *dev)
{printk("led driver and device was matched!\r\n");int ret = 0;/* 1.申请设备号 */...code.../* 2,初始化cdev */...code.../* 3,添加cdev */...code.../* 4、创建类 */...code.../* 5,创建设备  */...code.../* 1,获取设备节点 */gpioled.nd = dev->dev.of_node;/* 2, 获取LED所对应的GPIO */gpioled.led_gpio = of_get_named_gpio(gpioled.nd, "led-gpios", 0);if (gpioled.led_gpio < 0){}/* 3,申请IO */ret = gpio_request(gpioled.led_gpio, "led-gpio");if (ret){}/* 4,使用IO,设置为输出 */ret = gpio_direction_output(gpioled.led_gpio, 1);if (ret){}/* 5,输出底电平,点亮LED灯*/gpio_set_value(gpioled.led_gpio, 0);return 0;}static int led_remove(struct platform_device *dev)
{printk("led remove\r\n");/* 关灯 */gpio_set_value(gpioled.led_gpio, 1);/* 注销字符设备驱动 */
...code.../* 释放IO */gpio_free(gpioled.led_gpio);return 0;
}struct of_device_id led_of_match[] = {{.compatible = "alientek,gpioled"},{/*Sentinel*/},};struct platform_driver led_driver = {.driver = {.name = "imx6ull-led",          /*无设备树和设备进行匹配,驱动名字*/.of_match_table = led_of_match, /*设备树匹配表*/},.probe = led_probe,.remove = led_remove,
};/*驱动加载*/
static int __init leddriver_init(void)
{return platform_driver_register(&led_driver);
}/*驱动卸载*/
static void __exit leddriver_exit(void)
{platform_driver_unregister(&led_driver);
}module_init(leddriver_init);
module_exit(leddriver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("supersmart");

注意:所谓的 platform 驱动并不是独立于字符设备驱动、块设备驱动和网络设备驱动之外的其他种类的驱动。platform 只是为了驱动的分离与分层而提出来的一种框架,其驱动的具体实现还是需要字符设备驱动、块设备驱动或网络设备驱动。

Linux 设备树下的 platform 驱动示例相关推荐

  1. Linux 设备树下的 platform 驱动实验基于正点原子IMX6ULL开发板

    1 设备树下的 platform 驱动简介 platform 驱动框架分为总线.设备和驱动,其中总线不需要我们这些驱动程序员去管理,这个是 Linux 内核提供的,我们在编写驱动的时候只要关注于设备和 ...

  2. 【正点原子MP157连载】第三十五章 设备树下的platform驱动编写-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7

    1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...

  3. 设备树下的platform 驱动编写

    目录 设备树下的platform 驱动简介 硬件原理图分析 实验程序编写 修改设备树文件 platform 驱动程序编写 编写测试APP 运行测试 编译驱动程序和测试APP 运行测试 上一章我们详细的 ...

  4. 设备树下的 platform 驱动开发框架

    1. 设备树下的platform驱动开发 platform驱动框架分为总线.设备和驱动,其中总线是由Linux内核提供,在编写驱动时只要关注于设备和驱动的具体实现即可.Linux下的platform驱 ...

  5. 设备树下的platform驱动编写

    文章目录 一.设备树下的platform驱动简介 1.在设备树中创建设备节点 2.编写 platform 驱动的时候要注意兼容属性 3.编写platform驱动 二.硬件原理图分析 三.实验程序编写 ...

  6. 设备树下的 platform 驱动

    platform 设备驱动 Linux 系统要考虑到驱动的可重用性,因此提出了驱动的分离与分层这样的软件思路,在这个思路下诞生了我们将来最常打交道的platform 设备驱动,也叫做平台设备驱动. L ...

  7. 【正点原子Linux连载】第四十四章 设备树下的LED驱动实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...

  8. 【正点原子MP157连载】第二十四章 设备树下的LED驱动实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7

    1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...

  9. linux uart寄存器 代替 printk,Linux驱动学习之设备树(设备树下的LED驱动实验),...

    Linux驱动学习之设备树(设备树下的LED驱动实验), 概念 Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离.相当于从驱动代码分离出来的配置文件,比如串口的波特率通过设 ...

最新文章

  1. JSP的7个动作include,forward,useBean。。。
  2. find your place
  3. mysql show processlist host_show processlist host 为 百分号(%)
  4. rabbitmq 同步策略_RabbitMQ高可用方案总结
  5. 安卓分辨率_免费的安卓群控1数字云免费安卓群控系统
  6. 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——收流篇:(四)example代码解析...
  7. zookeeper 学习笔记1(转)
  8. Collections.sort的两种用法
  9. 多网卡Iptables端口转发
  10. 祝刘冬冬十八周岁快乐
  11. Cadence、Pspice 软件相关汇总
  12. 普元EOS UTP自动化测试 关闭工作流
  13. iOS AVPlayer播放模式的实现(随机播放 列表循环 单曲循环)
  14. 用户故事 | 验收标准
  15. Error: The method ‘DioHttpHeaders.add‘ has fewer named arguments than those of overridden method
  16. 神仙项目,轻松上手了解前后端分离!
  17. <马哲>价值规律的内容、表现形式及其作用
  18. SUPERSCAN IIE接线图
  19. 从浏览器下载表格数据为Excel的两种实现方法
  20. linux网络编程学习笔记——epoll

热门文章

  1. [Vue warn]: Failed to mount component: template or render function not defined.解决方案
  2. Pytorch:利用迁移学习做图像分类
  3. 连接wifi推送广告
  4. 动态路由协议-OSPF原理与推举实验
  5. PDF与word互相转换
  6. 电脑小问题不求人--鼠标.软驱.打印机.硬盘.风扇.常见事故处理
  7. CF1520D Same Differences
  8. 《OOD启思录》目录—导读
  9. sublime 4 设置文件编码 GBK
  10. mysql5.7 密钥_mysql5.7密码登录的那些坑