今天学习了platform平台总线,用来对驱动进行管理和注册,平台设备是指处理器上集成的额外功能的附加设备,如Watch Dog,IIC,IIS,RTC,ADC等设备。这些额外功能设备是为了节约硬件成本、减少产品功耗、缩小产品形状而集成到处理器内部的。需要注意的是,平台设备并不是与字符设备、块设备和网络设备并列的概念,而是一种平行的概念,其从另一个角度对设备进行了概括。如果从内核开发者的角度来看,平台设备的引入,是为了更容易开发字符设备、块设备和网络设备驱动。 当一个驱动注册[platform_driver_register()]的时候,他会遍历所有总线上的设备来寻找匹配,在启动的过程驱动的注册一般比较晚,或者在模块载入的时候 当一个驱动注册[platform_driver_probe()]的时候, 功能上和使用platform_driver_register()是一样的,唯一的区别是它不能被以后其他的device probe了,也就是说这个driver只能和一个device绑定。 分离思想:设备信息和驱动进行分离。 ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200306203515343.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xqMTk5OTA4MjQ=,size_16,color_FFFFFF,t_70) **驱动端:**
struct platform_driver { int (*probe)(struct platform_device *); //获取设备信息,在匹配成功调用 int (*remove)(struct platform_device *); //在移除的时候调用 struct device_driver driver; const struct platform_device_id *id_table; //id_table表}; struct device_driver { const char *name; //名字 匹配 struct bus_type *bus; //总线信息结构体 struct module *owner; // THIS_MODULE const struct of_device_id *of_match_table; //设备树的相关信息}; struct platform_device_id { char name[PLATFORM_NAME_SIZE]; //名字 kernel_ulong_t driver_dat; }; int platform_driver_register(struct platform_driver *pdrv); 功能:platform平台总线驱动端注册函数 参数: @pdrv platform平台总线驱动端结构体指针 返回值:成功返回0,失败返回负数错误码 void platform_driver_unregister(struct platform_driver *);
platform驱动注册过程:platform_driver_register —>>>driver_register(&drv->driver); —>>>bus_add_driver(drv); —>>>driver_attach(drv); //驱动绑定设备 /遍历设备端的链表,完成匹配/ —>>>bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); —>>>__driver_attach —>>>driver_match_device(drv, dev)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); /和设备树进行匹配/ if (of_driver_match_device(dev, drv)) return 1; / 和id_table表进行匹配 / if (pdrv->id_table) return platform_match_id(pdrv->id_table, pdev) != NULL; / 和名字进行匹配/ return (strcmp(pdev->name, drv->name) == 0);} 设备树 > id_table >name
如果匹配成功,调用driver_probe_device函数,进行获取设备信息
设备端
struct platform_device { const char * name; //名字 int id; //-1 struct device dev; //通用设备信息结构体 u32 num_resources; //资源个数 struct resource * resource; //资源结构体指针}; struct device { struct device_driver *driver; struct device_node *of_node; u32 id; void (*release)(struct device *dev); //设备端卸载的时候,须调用的函数 } struct resource { resource_size_t start; //起始地址 resource_size_t end; //结束地址 const char *name; //资源名字 unsigned long flags; //标志 IORESOURCE_IO IORESOURCE_MEM // IORESOURCE_IRQ}; int platform_device_register(struct platform_device *pdev); 功能:platfrom平台总线设备注册 参数: @pdev platform平台总线设备端结构体指针返回值:成功返回0,失败返回负数错误码 void platform_device_unregister(struct platform_device *);
platform设备端注册:platform_device_register —>>>platform_device_add(pdev); —>>>device_add(&pdev->dev); —>>>bus_probe_device(dev); —>>>device_attach(dev); —>>>bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
总结:platform平台总线,设备和驱动在注册的过程中,都会遍历对方的链表,来查找是否有匹配的,如果有匹配的,就会调用驱动中的probe探测函数,获取设备信息。