本文共 5893 字,大约阅读时间需要 19 分钟。
drivers/base/platform.c platform_match 函数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);1. 前提目前我们都用设备树,并解析设备树并创建设备贺电,这样子得到的 pdev->name 为设备节点名pdev->driver_override 为 NULL2. 5种匹配方式 2.1 pdev->driver_override // 对于这一种,为NULL,肯定是不进入的 2.2 OF // 匹配内容 为 compatible 和 .driver.of_match_table[0].compatible 这种匹配方式为多多(两方都可以写多个字符串)匹配,只要有一个匹配上就算成功 2.3 ACPI // 貌似被淘汰了,只是兼容 2.4 pdrv->id_table // id_table->name 和 pdev->name 匹配, 为单单匹配,且匹配的只能为 节点名. platform_match_id(pdrv->id_table, pdev) 2.5 (strcmp(pdev->name, drv->name) // pdev->name, drv->name 匹配 ,单单匹配,且只能是节点名 2.2 举例// 驱动端static const struct of_device_id ids[] = { { .compatible = "chip-name"}, { .compatible = "chip-name2"}, { }, // 一定要有 }; struct platform_driver pdr = { .driver= { .name = "somethingSUIBIAN_BUT_MUST_HAVE", .of_match_table = ids, // 匹配关键 } .id_table = &p_id_table, .probe = pdr_probe, .remove = pdr_remove, }platform_driver_register(&pdr);// 设备端node-platform-node { compatible = "vendor-name", "chip-name", "chip-name2","chip-name3";// 匹配关键}2.4 举例// 驱动端static const struct platform_device_id p_id_table = { .name = "node-platform-node", //匹配关键};struct platform_driver pdr = { .driver= { .name = "somethingSUIBIAN_BUT_MUST_HAVE", } .id_table = &p_id_table, .probe = pdr_probe, .remove = pdr_remove, }platform_driver_register(&pdr);// 设备端node-platform-node { // 匹配关键 compatible = "somethingSUIBIAN_BUT_MUST_HAVE";}2.5 举例// 驱动端static const struct platform_device_id p_id_table = { .name = "node-platform-node", //匹配关键 };struct platform_driver pdr = { .driver= { .name = "node-platform-node", // 匹配关键 } .probe = pdr_probe, .remove = pdr_remove, }platform_driver_register(&pdr);// 设备端node-platform-node { // 匹配关键 compatible = "somethingSUIBIAN_BUT_MUST_HAVE";}
//传参处chosen { bootargs = "node-platform-file.num=100" };//定义处node-platform-file.c 文件中static int num=10; // 初始化为10,在启动过程中被修改为100module_param(num,int,S_IRUGO);// 修改处kernel/params.c parse_one params[i].ops->set(val, ¶ms[i]); // 修改num为 100
driver 目录/sys/bus/platform/drivers/xxx //xxx 为 pdr.driver.name/sys/devices/platform/yyy // yyy 为 设备节点名sysfs_create_group(&pdev->dev.kobj, &sysfs_demo_attr_group) // 在 /sys/devices/platform/yyy
从pdev 到 其他int pdr_probe(struct platform_device * pdev);获取 dev :pdev->dev获取 设备树节点 : pdev->dev.of_node获取驱动 : pdev->dev->driver从 dev 到其他struct platform_device *pdev = to_platform_device(dev);从 drv 到其他struct platform_driver *pdrv = to_platform_driver(drv);
int pdr_probe(struct platform_device * pdev);name:node-platform-nodeid:-1id_auto:0num_resources:1resources:9f59f240id_entry: (null) // %p为 (null)// 前面有两个空格driver_override: (null)
/sys/bus/platform/drivers/xxx # --w------- 1 0 0 4096 Apr 20 10:30 bind // 用来加载驱动 // /sys/devices/platform 下面的文件夹的名字 ,如果加载之后,没有显示出yyy,表示没有匹配到设备lrwxrwxrwx 1 0 0 0 Apr 20 10:30 yyy -> ../../../../devices/platform/yyy // 匹配的设备名及设备目录 //如果没有此文件,代表该驱动没有匹配到设备--w------- 1 0 0 4096 Apr 20 10:30 uevent // 传入 add ,用来执行 udevd 规则--w------- 1 0 0 4096 Apr 20 10:30 unbind // 用来卸载驱动 写入设备名(当前目录下的yyy)
/sys/devices/platform/yyy/:total 0lrwxrwxrwx 1 0 0 0 Apr 20 10:30 driver -> ../../../bus/platform/drivers/xxx // 已经匹配到驱动,驱动目录-rw-r--r-- 1 0 0 4096 Apr 20 10:30 driver_override // pdev->driver_override 为 (null)-r--r--r-- 1 0 0 4096 Apr 20 10:30 modalias // of:Nnode-platform-nodeTCvendor-nameCchip-nameCchip-name2Cchip-name3 // 设备节点名及 compatible 属性值-rw-r--r-- 1 0 0 4096 Apr 20 10:30 node_one // sysfs_create_group 节点-r--r--r-- 1 0 0 4096 Apr 20 10:30 node_two // sysfs_create_group 节点drwxr-xr-x 2 0 0 0 Apr 20 10:30 power // power 目录,power 相关lrwxrwxrwx 1 0 0 0 Apr 20 10:30 subsystem -> ../../../bus/platform // 隶属总线-rw-r--r-- 1 0 0 4096 Apr 20 10:30 uevent // 设备下面的这个uevent 属性是干什么的 drivers/base/core.c 中的 uevent_store // 估计也是用来测试 udevd 规则的 //# cat uevent //DRIVER=noneed_to_fill_in//OF_NAME=node-platform-node//OF_FULLNAME=/node-platform-node//OF_COMPATIBLE_0=vendor-name//OF_COMPATIBLE_1=chip-name//OF_COMPATIBLE_2=chip-name2//OF_COMPATIBLE_3=chip-name3//OF_COMPATIBLE_N=4//MODALIAS=of:Nnode-platform-nodeT Cvendor-nameCchip-nameCchip-name2Cchip-name3/sys/devices/platform/yyy/power:total 0-rw-r--r-- 1 0 0 4096 Apr 20 10:31 autosuspend_delay_ms-rw-r--r-- 1 0 0 4096 Apr 20 10:31 control-r--r--r-- 1 0 0 4096 Apr 20 10:31 runtime_active_time-r--r--r-- 1 0 0 4096 Apr 20 10:31 runtime_status-r--r--r-- 1 0 0 4096 Apr 20 10:31 runtime_suspended_time
/sys/bus/platform/drivers/xxx 下面有 bind yyy unbind 表示已经匹配成功可以通过 echo yyy > unbind 来卸载驱动然后再 echo yyy > bind 来加载驱动如果没有什么问题(不会有错误堆栈打出来,不会死机),基本上去初始化是ok的
// 设置 s2mps11_clks 的数据指向s2mps11_clks->pdev = pdev;// 从 s2mps11_clks get 到 pdevstruct platform_device * pdev = s2mps11_clks->pdev---// 设置 pdev 的私有数据platform_set_drvdata(pdev, s2mps11_clks);// 拿 pdev 的私有数据struct s2mps11_clk *s2mps11_clks = platform_get_drvdata(pdev);
转载地址:http://ioigi.baihongyu.com/