Linux平台总线驱动设备模型是什么

71次阅读
没有评论

共计 6549 个字符,预计需要花费 17 分钟才能阅读完成。

这篇文章主要介绍“Linux 平台总线驱动设备模型是什么”,在日常操作中,相信很多人在 Linux 平台总线驱动设备模型是什么问题上存在疑惑,丸趣 TV 小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Linux 平台总线驱动设备模型是什么”的疑惑有所帮助!接下来,请跟着丸趣 TV 小编一起来学习吧!

platform 总线是一种虚拟的总线,相应的设备则为 platform_device,而驱动则为 platform_driver。Linux  2.6 的设备驱动模型中,把 I2C、RTC、LCD 等都归纳为 platform_device。

总线将设备和驱动绑定,在系统每注册一个设备的时候,会寻找与之匹配的驱动; 相反的,在系统每注册一个驱动的时候,会寻找与之匹配的设备,而匹配由总线完成。

Linux2.6 系统中定义了一个 bus_type 的实例 platform_bus_type

struct bus_type platform_bus_type = { .name =  platform , .dev_attrs = platform_dev_attrs, .match = platform_match, // 设备和驱动使用 match 函数来判断是否匹配  .uevent = platform_uevent, .pm = PLATFORM_PM_OPS_PTR, };
/* 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); /* match against the id table first */ 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_match 函数首先判断是否由 id_table,如果有则使用 id_table 来进行匹配,否则,判断 platform_device 和 platform_driver 成员里的 name,如果二者的 name 字段相同则匹配,如果匹配则调用 platform_driver 的 probe 函数。

platform_device 结构体的定义

struct platform_device { const char * name; /*  名字  */ int id; struct device dev; u32 num_resources; /*  资源总数  */ struct resource * resource; /*  资源  */ struct platform_device_id *id_entry; };

其中有个重要的成员是 resource,是设备的资源信息,如 IO 地址,中断号等。

struct resource { resource_size_t start; // 资源的起始值  resource_size_t end; // 资源的结束值  const char *name; unsigned long flags; // 资源的类型,如 IORESOURCE_IO,IORESOURCE_MEM,IORESOURCE_IRQ,IORESOURCE_DMA struct resource *parent, *sibling, *child; };

有的设备可能有多个资源,通常使用 platform_get_resource 函数来获取资源

/** * platform_get_resource - get a resource for a device * @dev: platform device * @type: resource type * @num: resource index */ struct resource *platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num) { int i; for (i = 0; i   dev- num_resources; i++) { struct resource *r =  dev- resource[i]; if (type == resource_type(r)   num-- == 0) return r; } return NULL; }

平台设备的注册,使用 platform_device_register 函数

int platform_device_register(struct platform_device *pdev) { device_initialize( pdev- dev); return platform_device_add(pdev); }

platform_device_register 函数先通过 device_initialize 函数初始化 platform_device 的 device 成员,然后调用 platform_device_add 向内核添加一个平台设备。

int platform_device_add(struct platform_device *pdev) { int i, ret = 0; if (!pdev) /*  如果 pdev 为空则返回 EINVAL */ return -EINVAL; /*  如果 pdev- dev.parent 为空则将 pdev- dev.parent 设置为 platform_bus */ if (!pdev- dev.parent) pdev- dev.parent =  platform_bus; pdev- dev.bus =  platform_bus_type; /*  设置总线类型  */ if (pdev- id != -1) /*  如果 id = - 1 则表示自动分配 name */ dev_set_name(pdev- dev,  %s.%d , pdev- name, pdev-  else dev_set_name( pdev- dev, pdev- name); for (i = 0; i   pdev- num_resources; i++) { struct resource *p, *r =  pdev- resource[i]; /*  获取资源  */ if (r- name == NULL) r- name = dev_name(pdev- dev); p = r- parent; if (!p) { if (resource_type(r) == IORESOURCE_MEM) /*  设置资源类型  */ p =  iomem_resource; else if (resource_type(r) == IORESOURCE_IO) p =  ioport_resource; } if (p   insert_resource(p, r)) { printk(KERN_ERR  %s: failed to claim resource %d\n , dev_name( pdev- dev), i); ret = -EBUSY; goto failed; } } pr_debug(Registering platform device  %s . Parent at %s\n , dev_name( pdev- dev), dev_name(pdev- dev.parent)); /*  向内核添加一个 device */ ret = device_add(pdev- dev); if (ret == 0) return ret; failed: while (--i  = 0) { struct resource *r =  pdev- resource[i]; unsigned long type = resource_type(r); if (type == IORESOURCE_MEM || type == IORESOURCE_IO) release_resource(r); } return ret; }

platform_device_add 最终调用 device_add 来完成平台设备的注册。

相反地,如果要注销平台设备则使用 platform_device_unregister 函数

void platform_device_unregister(struct platform_device *pdev) { platform_device_del(pdev); platform_device_put(pdev); }

platform_device_unregister 函数调用 platform_device_del 函数来注销平台设备

void platform_device_del(struct platform_device *pdev) { int i; if (pdev) { device_del( pdev- dev); for (i = 0; i   pdev- num_resources; i++) { struct resource *r =  pdev- resource[i]; unsigned long type = resource_type(r); if (type == IORESOURCE_MEM || type == IORESOURCE_IO) release_resource(r); } } }

platform_device_del 函数调用 device_del 函数来删除平台设备,相应地,要释放资源应调用 release_resource 函数,前提是资源的类型必须为 IORESOURCE_MEM 或者 IORESOURCE_IO

platform_driver 的定义:

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

device_driver 的定义:

struct device_driver { const char *name; struct bus_type *bus; struct module *owner; const char *mod_name; /* used for built-in modules */ bool suppress_bind_attrs; /* disables bind/unbind via sysfs */ const struct of_device_id *of_match_table; const struct acpi_device_id *acpi_match_table; int (*probe) (struct device *dev); int (*remove) (struct device *dev); void (*shutdown) (struct device *dev); int (*suspend) (struct device *dev, pm_message_t state); int (*resume) (struct device *dev); const struct attribute_group **groups; const struct dev_pm_ops *pm; struct driver_private *p; };

platform_driver 结构体有 device_driver 成员,该成员的各自字段如上所示,device_driver 也有 probe、remove、shutdown 等函数,在平台驱动注册的时候被初始化。

前面说过,当系统中存在有平台设备和平台驱动通过总线的 match 函数匹配后则会调用 platform_driver 的 probe 函数,参数为 platform_device,有时候也通过 id_table 来判断是否匹配。

struct platform_device_id { char name[PLATFORM_NAME_SIZE]; kernel_ulong_t driver_data __attribute__((aligned(sizeof(kernel_ulong_t)))); };

平台驱动的注册使用 platform_driver_register 函数

int platform_driver_register(struct platform_driver *drv) { drv- driver.bus =  platform_bus_type; if (drv- probe) drv- driver.probe = platform_drv_probe; if (drv- remove) drv- driver.remove = platform_drv_remove; if (drv- shutdown) drv- driver.shutdown = platform_drv_shutdown; if (drv- suspend) drv- driver.suspend = platform_drv_suspend; if (drv- resume) drv- driver.resume = platform_drv_resume; return driver_register(drv- driver); }

先初始化 platform_driver 里的 driver,该 driver 的类型为 device_driver,设置 driver 的 bus 为 platform_bus_type; 设置 driver 的 probe 为 platform_drv_probe; 设置 driver 的 remove 为 platform_drv_remove; 设置 driver 的 shutdown 为 platform_drv_shutdown; 设置 driver 的 suspend 为 platform_drv_suspend; 设置 driver 的 resume 为 platform_drv_resume,*** 调用 driver_register 函数来注册平台驱动。

相反地,要注销平台驱动的话,使用 platform_driver_unregister 函数

void platform_driver_unregister(struct platform_driver *drv) { driver_unregister( drv- driver); }

到此,关于“Linux 平台总线驱动设备模型是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注丸趣 TV 网站,丸趣 TV 小编会继续努力为大家带来更多实用的文章!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-16发表,共计6549字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)