Linus Torvalds 在 2011 年 3 月 17 日的 ARM Linux 邮件列表宣称“this whole ARM thing is a f*cking pain in the ass”,引发 ARM Linux 社区的地震,随后 ARM 社区进行了一系列 的重大修正。在过去的 ARM Linux 中,arch/arm/plat-xxx 和 arch/arm/mach-xxx 中充斥着大 量的垃圾代码,相当多数的代码只是在描述板级细节,而这些板级细节对于内核来讲,不 过是垃圾,如板上的 platform 设备、resource、i2c_board_info、spi_board_info 以及各种硬 件的 platform_data。读者有兴趣可以统计下常见的 s3c2410、s3c6410 等板级目录,代码量 在数万行。
社区必须改变这种局面,于是 PowerPC 等其他体系架构下已经使用的 Flattened Device Tree(FDT)进入 ARM 社区的视野。Device Tree 是一种描述硬件的数据结构,它起源于 OpenFirmware (OF)。在 Linux 2.6 中,ARM 架构的板极硬件细节过多地被硬编码在 arch/arm/plat-xxx 和 arch/arm/mach-xxx,采用 Device Tree 后,许多硬件的细节可以直接透 过它传递给 Linux,而不再需要在 kernel 中进行大量的冗余编码。
所以现在有节操的代码中,可能没有了resource的定义,设备相关的描述统一的放在了arch/arm(arm64)/boot/dts路径下的dts文件中,dt的内容本文不做讨论。
在加入dt以后,驱动程序的变化是,不再需要对设备资源有描述,没有了platfrom_device_register函数来注册设备,这些工作都由内核来替我们完成(解析dt的代码为of_*开头的源文件), 驱动只要做driver相关的定义和注册即可。相应的如果想要使用本设备的资源,依然是调用platform_get_resource函数获取;如果想要使用其他设备的资源,则需要获取该设备的节点,再获取其resource内容。
假如DT的一个节点如下:
点击(此处)折叠或打开
device01{
compatible = "compa ny,device01";
reg = <0 0x30040000 0 0xA0000 //设备资源的描述
0 0x20F00000 0 0x300000>;
interrupts = <0 86 0x0>;
}
如果使用dt,驱动中还要给platform_driver中.driver的.of_match_table填充一个of_device_id结构,比如:
点击(此处)折叠或打开
static const struct of_device_id of_match[] = {
{ .compatible = "company,device01", },
{ }
};
static struct platform_driver xx_driver = {
.probe = xx_probe,
.remove = xx_remove,
.suspend = xx_suspend,
.resume = xx_resume,
.driver = {
.owner = THIS_MODULE,
.name = "device01",
.of_match_table = of_match
}
}
如果驱动中想要使用其他节点(设备)定义的资源,由于没有相应platform device在本驱动中,不能简单的通过platform_get_resource来获取,platform_get_resource第一个参数就是paltform device,即本设备。则需要通过一系列的of_*开头的函数来获取。在driver/of目录下有相关的源文件,比如下面广两个函数可以满足简单需求:
获取dt节点:
struct device_node *of_find_compatible_node (struct device_node *from, const char *type, const char *compatible)
struct device_node *of_find_node_by_name(struct device_node *from, const char *name)
将节点中的指定资源,转到resource变量中:
int of_address_to_resource (struct device_node *dev, int index, struct resource *r)
最后:在项目过程中,感觉简单的字符设备应用并不常见,有的完全可以用misc设备代替,并且platform引入以后,linux下大部分的驱动都可以以此框架实现,所以platfrom更为常见,并可配合misc设备向上提供节点,供引用层使用。也可以配合sys节点,创建设备的属性文件,供上层使用,方便并且容易实现。