众所周知2011年linux创始人Linus Torvalds在社区的一句脏话!引发了社区震动!从而导致代码大换血!Dts(device tree source)则就是这个时候被应用在我们的各种处理器中目录下的!早期这种模式被用于IBM PowerPC等体系架构下使用的Flattened Device Tree(FDT)。Device Tree是一种描述硬件的数据结构,它起源于 OpenFirmware (OF)。在Linux 2.6中,各种架构的板极硬件过多地被硬编码在arch/xxx/plat-xxx和arch/xxx/mach-xxx,采用Device Tree后,许多硬件的细节可以直接透过它传递给Linux,而不再需要在上述代码中进行大量的冗余编码。
具体Device Tree介绍等到这里查看:
凡是走platform架构的所有device都可以用于此模型:如:
CPU的数量和类别
内存基地址和大小
总线和桥
外设连接
中断控制器和中断使用情况
GPIO控制器和GPIO使用情况
Clock控制器和Clock使用情况
Ethernet控制器等等
都是可以被集成到dts中的!
一丶概述:
Platform_driver 驱动模型是内核中比较常用的一种模型!因为这是一种虚拟总线,其好处就是不管是字符设备块设备都可以通过此总线来实现设备集中!驱动模型的铁三角那就是:总线,设备,驱动!
那么首先回顾一下2.6中的platform架构驱动的写法:
常规的写法都是通过platform_deiver 和 platform_device 来进行一个类型月老牵线式的匹配!platform_driver填充
{
.probe = ,
.remove = ,
.driver = {
.name = “”,
.owner = “”,
},
}
Plarform_device 则在BSP(math-xxx)中填充:
Struct platform_device{
const char *name;
u32 id;
u32 num_resource;
sruct resource *resource;
}
然后进行匹配!主要看name字段是否相同!
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);
}
到这里就已经ok了!我们看到上述是通过一个strcncmp()进行比较的!
那么我们的3.x又是如何写的呢?
二丶开始工作?
1、dts 中的节点属性含义 --出现频率最多的就是compible这个属性
2、那么如何匹配呢?-- 月老肯定还在,但是换了一个月老(21世纪了)!
三丶添加一个自己的platform设备
static struct of_device_id nlm_common_ide_dt_ids[] = {
{.compatible = "netlogic,xlp-ide-commpact"},
};
static struct platform_driver nlm_common_ide_driver = {
.driver = {
.name = "xlp-ide-commpact",
.owner = THIS_MODULE,
.of_match_table = nlm_common_ide_dt_ids,
},
.probe = nlm_drv_ide_probe,
.remove = nlm_common_ide_remove,
};
上述就是新世纪(3.x)中的写法啦!
四、如何”被”执行?
/*
* XLP3XX Device Tree Source for SVP boards
*/
/ {
model = "netlogic,XLP-SVP";
compatible = "netlogic,xlp";
#address-cells = <2>;
#size-cells = <2>;
soc {
#address-cells = <2>;
#size-cells = <1>;
compatible = "simple-bus";
ranges = <0 0 0 0x18000000 0x04000000
1 0 0 0x16000000 0x02000000>;
serial0: serial@30000 {
.....................
};
commpact: xlp_commpact@35000 {
compatible = "netlogic,xlp-ide-commpact";
reg = <0 0x35100 0x1000>;
#interrupt-cells = <1>;
interrupts = <39>;
interrupt-controller;
};
};
chosen {
bootargs = "console=ttyS0,9600 rdinit=/sbin/init";
};
};
看到compatible了吗?
这就是他们匹配的变量!和以前一样也是判断字符串是否相等!
那么在那匹配?
在扳级硬件编码中有如下的代码
146 void __init device_tree_init(void)
147 {
148 unsigned long dt_size;
149 void *blob;
150
151 if (!initial_boot_params)
152 panic("No device tree!\n");
153
154 /*
155 * boot mem available now, make a copy of the blob, and
156 * update initial_boot_params to point there.
157 */
158 dt_size = be32_to_cpu(initial_boot_params->totalsize);
159 blob = early_init_dt_alloc_memory_arch(dt_size, 8);
160 if (blob == NULL)
161 panic("Could not allocate initial_boot_params\n");
162 memcpy(blob, initial_boot_params, dt_size);
163 nlm_fdt_blob = initial_boot_params = blob;
164 pr_info("fdt copied to %p, size %ld\n", blob, dt_size);
165
166 unflatten_device_tree();
167 }
168
169 static struct of_device_id __initdata xlp_ids[] = {
170 { .compatible = "simple-bus", },
171 {},
172 };
173
174 int __init xlp8xx_ds_publish_devices(void)
175 {
176 if (!of_have_populated_dt())
177 return 0;
178 return of_platform_bus_probe(NULL, xlp_ids, NULL);
179 }
180
181 device_initcall(xlp8xx_ds_publish_devices);
一眼就看出了是初始化device tree的代码!
看代码流程走向...
从下往上看:
device_initcall(xlp8xx_ds_publish_devices);
注册的是xlp8xx_ds_publish_devices这个函数
跳到此函数!到174行
看到执行了两个函数
一个of_have_poplated_dr()
一个of_platform_bus_probe()
第一个函数为检查dts节点是否为空的!
如果为空则返回0
第二个函数为
396 /**
397 * of_platform_bus_probe() - Probe the device-tree for platform buses
398 * @root: parent of the first level to probe or NULL for the root of the tree
399 * @matches: match table for bus nodes
400 * @parent: parent to hook devices from, NULL for toplevel
401 *
402 * Note that children of the provided root are not instantiated as devices
403 * unless the specified root itself matches the bus list and is not NULL.
404 */
可以理解为探测xlp_ids是否存在!并且是否匹配!如果匹配,创建子节点!其实就是展开子节点!
在xlp_ids 我们又看到了compible这个属性!
这里填充了simple-bus..
何为simple-bus?
这种虚拟总线可以兼容很多总线设备!
到这里基本上所有的疑惑已经解开了!
五、总结
3.x版本其实改变了很多原来的东西!可以看出来Linus一怒是非常的牛逼的!而且是带着“腥风谢雨”的!
Echo “keven”;
附注:Linux OF API
在drivers/of/platform.c下