依据Linux设备模型可知,一个实际的Linux设备和驱动一般都需求挂接在一种总线上,关于自身依附于PCI、USB等的设备而言,这天然不是问题,但是在嵌入式体系里边,SoC体系中集成的独立的外设控制器、挂接在 SoC 内存空间的外设等却不依附于此类总线。根据这一布景,Linux规划了一种虚拟的总线,称为platform总线,相应的设备称为platform_device,而驱动称为platform_driver。
规划意图
兼容设备模型
使得设备被挂接在一个总线上,因而,契合 Linux 2.6 的设备模型。其结果是,配套的sysfs结点、设备电源办理都成为可能。
BSP和驱动阻隔
在BSP中界说platform设备和设备运用的资源、设备的详细装备信息。而在驱动中,只需求经过通用API去获取资源和数据,做到了板相关代码和驱动代码的别离,使得驱动具有更好的可扩展性和跨渠道性。
软件架构
内核中Platform设备有关的完成坐落include/linux/platform_device.h和drivers/base/platform.c两个文件中,它的软件架构如下:
由图片可知,Platform设备在内核中的完成首要包括三个部分:
Platform Bus,根据底层bus模块,笼统出一个虚拟的Platform bus,用于挂载Platform设备;
Platform Device,根据底层device模块,笼统出Platform Device,用于表明Platform设备;
Platform Driver,根据底层device_driver模块,笼统出Platform Driver,用于驱动Platform设备。
platform_device
留意,所谓的platform_device并不是与字符设备、块设备和网络设备并排的概念,而是Linux体系供给的一种附加手法,例如,在S3C2440处理器中,把内部集成的I2C、RTC、SPI、LCD、看门狗等控制器都概括为platform_device,而它们自身便是字符设备。
/* defined in */struct platform_device { const char * name; / * 设备名 */ u32 id; /* 用于标识该设备的ID */ struct device dev; /* 真实的设备(Platform设备仅仅一个特别的设备,因而其中心逻辑仍是由底层的模块完成)*/ u32 num_resources; / * 设备所运用各类资源数量 */ struct resource * resource; / * 资源 */};/* defined in */struct resource { resource_size_t start; /* 资源开始 */ resource_size_t end; /* 完毕 */ const char *name; unsigned long flags; /* 类型 */ struct resource *parent, *sibling, *child;};/* 设备驱动获取BSP界说的resource */struct resource *platform_get_resource(struct platform_device *, unsigned int flags, unsigned int num);#include int platform_device_register(struct platform_device *); void platform_device_unregister(struct platform_device *);
Tip: 和板级严密相关的资源描绘放在dev.paltform_data中。
paltform_driver
platform_driver这个结构体中包括probe()、remove()、shutdown()、suspend()、resume()函数,一般也需求由驱动完成:
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 (*suspend_late)(struct platform_device *, pm_message_t state); int (*resume_early)(struct platform_device *); int (*resume)(struct platform_device *); struct device_driver driver;};#include int platform_driver_register(struct platform_driver *); void platform_driver_unregister(struct platform_driver *);
platform_bus
体系中为platform总线界说了一个bus_type的实例platform_bus_type:
struct bus_type platform_bus_type = { .name = “platform”, .dev_attrs = platform_dev_attrs, .match = platform_match, .uevent = platform_uevent, .pm = PLATFORM_PM_OPS_PTR,};EXPORT_SYMBOL_GPL(platform_bus_type);
这儿要要点重视其 match()成员函数,正是此成员函数确认了 platform_device 和 platform_driver之间怎么匹配:
staTIc int platform_match(struct device *dev, struct device_driver *drv){ struct platform_device *pdev; pdev = container_of(dev, struct platform_device, dev); return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);}