先总结,主要是通过获取dts信息,然后使用ioremap进行地址映射。
对于内核来说一切皆是文件的思想,设备树与文件系统的关系,在Linux系统起来后,会将解析完成的设备树导出到用户空间,kernel启动在sys/firmware/devicetree/base目录下面为设备树展开成sysfs的目录和二进制属性文件,所有的node节点就是一个目录,所有的property属性就是一个二进制属性文件。内核中开放出来的接口函数的声明大多在include/linux/下面,关于设备树的都是以of形式开头的命名,例如:
of_address.h 地址相关的函数, 比如 of_get_address(获得reg属性中的addr, size值)
of_device.h 设备相关的函数, 比如 of_match_device、of_device_register
of_irq.h 中断相关的函数
of_fdt.h等。
在driver/of/base.c中
of_core_init函数中:
of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);//创建devicetree目录
proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base"); //内核建立软链接
即/proc/device-tree -> /sys/firmware/devicetree/base
IO/总线地址映射方法:
np = of_find_compatible_node(NULL, NULL, “xxx”);
addr = of_iomap(np, 0);
可以直接通过设备节点进行设备内存区间的ioremap(),index是内存段的索引。若设备节点的reg属性有多段,可通过index标示要ioremap()的是哪一段,在只有1段的情况,index为0
通过路径查找指定节点:
struct device_node *of_find_node_by_path(const char *path);如 node = of_find_node_by_path("/");
通过节点名查找指定节点:
of_find_node_by_name(NULL, "xxx");然后可以进行地址映射
获取内存基地址:
of_address_to_resource,该函数通过设备节点获取与它对应的内存资源的resource结构体。其本质是分析reg属性以获取内存基地址、大小等信息并填充到struct resource*r参数指向的结构体中。
解析中断:
irq_of_parse_and_map,通过设备树获得设备的中断号,实际上是从.dts中的interrupts属性里解析出中断号。若设备使用了多个中断,index指定中断的索引号
获取与节点对应的platform device:
struct platform_device *of_find_device_by_node(struct device_node *np);
通过platform_device获取device_node:
static int xxx_probe(struct platform_device *op) struct device_node *dn = op->dev.of_node;