总线设备驱动模型之platform

platform 设备

  • 匹配
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 为 NULL

2. 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,在启动过程中被修改为100
module_param(num,int,S_IRUGO);
// 修改处
kernel/params.c
	parse_one
		params[i].ops->set(val, &params[i]); // 修改num为 100

  • sys 节点
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);
  • pdev 结构体变量
int pdr_probe(struct platform_device * pdev);
name:node-platform-node
id:-1
id_auto:0
num_resources:1
resources:9f59f240
id_entry:  (null) // %p为  (null)// 前面有两个空格
driver_override:  (null)
  • driver sys 目录
/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)
  • device sys 目录
/sys/devices/platform/yyy/:
total 0
lrwxrwxrwx    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-nodeTCvendor-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 到 pdev
struct platform_device * pdev = s2mps11_clks->pdev

---

// 设置 pdev 的私有数据
platform_set_drvdata(pdev, s2mps11_clks);
// 拿 pdev 的私有数据
struct s2mps11_clk *s2mps11_clks = platform_get_drvdata(pdev);

你可能感兴趣的:(驱动)