platform_device(platoform怎么玩)

:暂无数据 2026-06-15 05:50:01 :0

platform_device(platoform怎么玩)

“platform_device”相关信息最新大全有哪些,这是大家都非常关心的,接下来就一起看看platform_device(platoform怎么玩)!

本文目录

platoform怎么玩

platform的灵魂是:device(设备)driver(驱动)platform_bus(platform总线),其特点是设备,驱动分层动态的管理和加载
其中platform_bus是一个虚拟的总线,当我们将设备和驱动注册到虚拟总线上(内核)时,如果该设备是该驱动的设备,该驱动是该设备的驱动,在他们注册时,会互相寻找
一次对方(只在注册的时候寻找一次,找完了就玩了)。这个找的过程是platform_bus来完成的,我们暂不管他如何让寻找。如果device和driver中的name这个字符串是想相同的话
platform_bus就会调用driver中的.probe函数.这个匹配到调用probe的过程是自动的,有总线自己完成。这个过程从注册开始,从probe结束
设备和驱动的关系是多对一的关系,即多个相同设备可使用一个driver,靠device(设备)中的id号来区别
platform的使用其实就四步:
1)初始化 resource 结构变量
2)初始化 platform_device 结构变量
3)向系统注册设备:platform_device_register。
4)想系统注册驱动:[platform_driver_register()]
登录后复制
drvier和device匹配的方法有3种:
* 当一个设备注册的时候,他会在总线上寻找匹配的driver,platform device一般在系统启动很早的时候就注册了
* 当一个驱动注册[platform_driver_register()]的时候,他会遍历所有总线上的设备来寻找匹配,在启动的过程驱动的注册一般比较晚,或者在模块载入的时候
* 当一个驱动注册[platform_driver_probe()]的时候, 功能上和使用platform_driver_register()是一样的,唯一的区别是它不能被以后其他的device probe了,也就是说这个driver只能和 一个device绑定
eg:定义一个driver

platform device 中的 device怎么构建

1. 在比较新的linux内核中,设备树dts已经取代了传统的machine board device description,dts在内核中以各种device node的形式存在,而这些device node对于大部分的内核驱动模块platform_driver来说,最终需要有对应的platform device来与他匹配才可以完成一次device和driver的probe过程。
所有有必要将dts中需要加载为device的device node转为platform device,而这个过程是交给of_platform_populate来完成的(dts相关的device node tree是在start_kernel的setup_arch-》unflatten_device_tree来加载dtb并解析)。
of_platform_populate的入口一般是处于init_machine中,对于arm架构而言位于board.c中的DT_MACHINE_START()的init_machine中定义,而init_machine的调用是以一个module的形式而存在的,该module被加载后的目的,就是做device的create,在以前旧的board中,会将board.c中定义的相关device info转换为对应的device,以便后面的driver加载时可以match到相应的device。在基于dts的设备管理中,这个功能由of_platform_populate来实现

[cpp] view plain copy
static int __init customize_machine(void)
{
/* customizes platform devices, or adds new ones */
if (machine_desc-》init_machine)
machine_desc-》init_machine();
return 0;
}
arch_initcall(customize_machine);
[cpp] view plain copy
static int __init customize_machine(void)
{
/* customizes platform devices, or adds new ones */
if (machine_desc-》init_machine)
machine_desc-》init_machine();
return 0;
}
arch_initcall(customize_machine);
该module的initcall等级相比内核核心的core module来说是较低的,但一般比device module来的高,所以内核中是先存着device然后再当不同的driver被call加载后,完成一次驱动和设备的probe交互。在dts下这种过程典型的是platform device和driver的形式而存在。

2. of_platform_populate函数做了哪些事情

[cpp] view plain copy
int of_platform_populate(struct device_node *root,
const struct of_device_id *matches,
const struct of_dev_auxdata *lookup,
struct device *parent)//NULL/NULL
{
struct device_node *child;
int rc = 0;

root = root ? of_node_get(root) : of_find_node_by_path(“/“);//根节点,可以从非根节点/开始加载
if (!root)
return -EINVAL;

for_each_child_of_node(root, child) {
rc = of_platform_bus_create(child, matches, lookup, parent, true);
if (rc)
break;
}

of_node_put(root);
return rc;
}
[cpp] view plain copy
int of_platform_populate(struct device_node *root,
const struct of_device_id *matches,
const struct of_dev_auxdata *lookup,
struct device *parent)//NULL/NULL
{
struct device_node *child;
int rc = 0;

root = root ? of_node_get(root) : of_find_node_by_path(“/“);//根节点,可以从非根节点/开始加载
if (!root)
return -EINVAL;

for_each_child_of_node(root, child) {
rc = of_platform_bus_create(child, matches, lookup, parent, true);
if (rc)
break;
}

of_node_put(root);
return rc;
}
该该函数的功能主要可以总结如下:

a.根据所选择的device node根节点,来递归式的遍历从root node开始以下的所有device node
b.将device node转变为一个platform_device并将其作为device 通过device_add到内核
c.可以判断哪些device node是需要转为device到内核的。
d. 如果传入的root=NULL,则表明从dts的\节点开始逐一的递归处理,否则根据所选择的device node作为root,做递归处理。
e. struct of_device_id *matches,该match table重点是后续节点递归处理时,需要和该table mach后才可以继续递归处理。

需要说明的是dts中定义的各种device node,往往只是用来辅助核心的device node而存在的,也就是说这些node存在并不需要加载为platform device,那么哪些device node是不会在of_platform_populate中被解析为device的呢,具体可以从以下几个方面展开:

[html] view plain copy
static int of_platform_bus_cof_platform_populatereate(struct device_node *bus,
const struct of_device_id *matches,
const struct of_dev_auxdata *lookup,
struct device *parent, bool strict)
{
const struct of_dev_auxdata *auxdata;
struct device_node *child;
struct platform_device *dev;
const char *bus_id = NULL;
void *platform_data = NULL;
int rc = 0;

/* Make sure it has a compatible property */
if (strict && (!of_get_property(bus, “compatible“, NULL))) {
pr_debug(“%s() - skipping %s, no compatible prop\n“,
__func__, bus-》full_name);
return 0;
}

auxdata = of_dev_lookup(lookup, bus);//初始设备树解析时lookup为Null
if (auxdata) {
bus_id = auxdata-》name;
platform_data = auxdata-》platform_data;
}

if (of_device_is_compatible(bus, “arm,primecell“)) {
of_amba_device_create(bus, bus_id, platform_data, parent);
return 0;
}

dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent);//创建platform device
if (!dev || !of_match_node(matches, bus))//看该bus即父节点是否属于要继续加载子节点
return 0;//matches需要用户的驱动支持of_platform_populate

for_each_child_of_node(bus, child) {//子设备的解析处理
pr_debug(“ create child: %s\n“, child-》full_name);
rc = of_platform_bus_create(child, matches, lookup, &dev-》dev, strict);//父节点下的子设备节点创建
if (rc) {
of_node_put(child);
break;
}
}
return rc;
}
[html] view plain copy
static int of_platform_bus_cof_platform_populatereate(struct device_node *bus,
const struct of_device_id *matches,
const struct of_dev_auxdata *lookup,
struct device *parent, bool strict)
{
const struct of_dev_auxdata *auxdata;
struct device_node *child;
struct platform_device *dev;
const char *bus_id = NULL;
void *platform_data = NULL;
int rc = 0;

/* Make sure it has a compatible property */
if (strict && (!of_get_property(bus, “compatible“, NULL))) {
pr_debug(“%s() - skipping %s, no compatible prop\n“,
__func__, bus-》full_name);
return 0;
}

auxdata = of_dev_lookup(lookup, bus);//初始设备树解析时lookup为Null
if (auxdata) {
bus_id = auxdata-》name;
platform_data = auxdata-》platform_data;
}

if (of_device_is_compatible(bus, “arm,primecell“)) {
of_amba_device_create(bus, bus_id, platform_data, parent);
return 0;
}

dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent);//创建platform device
if (!dev || !of_match_node(matches, bus))//看该bus即父节点是否属于要继续加载子节点
return 0;//matches需要用户的驱动支持of_platform_populate

for_each_child_of_node(bus, child) {//子设备的解析处理
pr_debug(“ create child: %s\n“, child-》full_name);
rc = of_platform_bus_create(child, matches, lookup, &dev-》dev, strict);//父节点下的子设备节点创建
if (rc) {
of_node_put(child);
break;
}
}
return rc;
}
可以看到是有一个类似bus的root device node下来逐步展开的,而这个root node可以不是函数重点关注的是:

a. of_get_property(“compatible“),如果这个节点root device属性不存在,则表明其不需要生成为platform device
b. 随着root device node由函数of_platform_device_create_pdata创建为platform device后,需要检查当前节点的compatible是否和match table中定义的table list相互匹配:

[html] view plain copy
const struct of_device_id *of_match_node(const struct of_device_id *matches,
const struct device_node *node)
{
if (!matches)
return NULL;

while (matches-》name || matches-》type || matches-》compatible) {
int match = 1;
if (matches-》name)
match &= node-》name
&& !strcmp(matches-》name, node-》name);
if (matches-》type)
match &= node-》type
&& !strcmp(matches-》type, node-》type);
if (matches-》compatible)
match &= of_device_is_compatible(node,
matches-》compatible);
if (match)
return matches;
matches++;
}
return NULL;
}
[html] view plain copy
const struct of_device_id *of_match_node(const struct of_device_id *matches,
const struct device_node *node)
{
if (!matches)
return NULL;

while (matches-》name || matches-》type || matches-》compatible) {
int match = 1;
if (matches-》name)
match &= node-》name
&& !strcmp(matches-》name, node-》name);
if (matches-》type)
match &= node-》type
&& !strcmp(matches-》type, node-》type);
if (matches-》compatible)
match &= of_device_is_compatible(node,
matches-》compatible);
if (match)
return matches;
matches++;
}
return NULL;
}
如果当该device node在被创建为platform device后,就不在和match table相匹配时,其对应的child node就不会再被创建platform device,即无论child node是否定义了“compatible“,其对应的platform device均不会被生成。

c.对于dts中定义的device node,只有其所属的parent node所属的compatible属性和调用of_platform_populate时传入的of_device_id相互匹配,则说明如果当前的device node只要包含有compatible属性就会被创建为platform device。

以一个简单的dts为例:

[html] view plain copy
/{
soc0{
compatible = “my, soc0“;
node1{
compatible = “my, node1“;
node1_1{
compatible = “my, node1_1“;
node1_1_1{
compatible = “my, node1_1_1“;
}
}
}
node2{ }
}
soc1{ compatible = “my, soc1“; }
}
[html] view plain copy
/{
soc0{
compatible = “my, soc0“;
node1{
compatible = “my, node1“;
node1_1{
compatible = “my, node1_1“;
node1_1_1{
compatible = “my, node1_1_1“;
}
}
}
node2{ }
}
soc1{ compatible = “my, soc1“; }
}

a.假设现在在init_machine中调用of_platform_populate()时传入的root node为NULL,且mach id为”my, soc0“,“my,node1“

则最终soc0会被首先作为/ root node的child node被加载为platform device,然后依次是node1,由于其相应的compatible和match id匹配,则其对应的child node允许被继续调用of_platform_bus_create,并且对含有compatible的device node生成为platform device,如本例中的node1。同理对于node1而言会加载node1_1节点,但当node1_1生成为device后,由于无法匹配match id,则其无法再递归的处理其下的子节点,从而使得node1_1_1不会被生成为platform device。而这需要说明的是,这个device虽然不会被自动加载为platform device但在node1_1的device driver实现时,可以将node1_1_1形成一种特定的device,如i2c_client等,只是不会生成platform device。从而解释了为何该device node只是以一个device 的形式存在于内核而不是即是i2c_client和platform device。
而soc0下的node2由于不存在compatible属性,同样不会被生成device,以及其child node下的各级device node也都不会被加载。
b,假设传入的root node为soc1,且mach id为“my,node1“时
这个过程会加载node1,然后是node1_1,同样的node1_1_1不会被生成为platform_device.

3.总结
对于of_platform_populate如何选择性的加载device node为platform device在系统启动阶段,可以只关注该device node所属的parent node的compatible属于match id。
一旦自身包含compatible,则会自动调用of_platform_device_create_pdata生成一个platform device。

C语言中int (*probe)(struct platform_device *);这个定义怎么理解,感谢了

这是声明了一个函数指针probe,它的参数是一个platform_device类的指针,返回值是int。
比如说我们声明了一个函数int func(struct platform_device *),那么可以令probe = func,对func()调用可以用probe()代替。

关于platform_device和platoform怎么玩的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

platform_device(platoform怎么玩)

本文编辑:admin

更多文章:


majority of(the majority of 和 a majority of的区别以及用法例句)

majority of(the majority of 和 a majority of的区别以及用法例句)

这篇文章给大家聊聊关于majority of,以及the majority of 和 a majority of的区别以及用法例句对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。

2026年10月11日 07:40

汉字机内码查询表(1个汉字的机内码是几位谢谢)

汉字机内码查询表(1个汉字的机内码是几位谢谢)

大家好,关于汉字机内码查询表很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于1个汉字的机内码是几位谢谢的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,希望对各位有所帮助!

2026年10月11日 07:20

promote翻译(英语翻译倡导怎么说)

promote翻译(英语翻译倡导怎么说)

其实promote翻译的问题并不复杂,但是又很多的朋友都不太了解英语翻译倡导怎么说,因此呢,今天小编就来为大家分享promote翻译的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!

2026年10月11日 06:30

用手机如何导航?开车用手机导航哪个软件最好

用手机如何导航?开车用手机导航哪个软件最好

今天给各位分享用手机如何导航的知识,其中也会对用手机如何导航进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

2026年10月11日 06:20

多线程技术有什么用(多线程有什么作用)

多线程技术有什么用(多线程有什么作用)

其实多线程技术有什么用的问题并不复杂,但是又很多的朋友都不太了解多线程有什么作用,因此呢,今天小编就来为大家分享多线程技术有什么用的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!

2026年10月11日 05:40

another time(another time和other time的区别)

another time(another time和other time的区别)

大家好,another time相信很多的网友都不是很明白,包括another time和other time的区别也是一样,不过没有关系,接下来就来为大家分享关于another time和another time和other time的区

2026年10月11日 05:00

java开发工具包jdk(JDK是什么意思)

java开发工具包jdk(JDK是什么意思)

其实java开发工具包jdk的问题并不复杂,但是又很多的朋友都不太了解JDK是什么意思,因此呢,今天小编就来为大家分享java开发工具包jdk的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!

2026年10月11日 04:50

mysql 命令(MySQL的基本命令)

mysql 命令(MySQL的基本命令)

大家好,如果您还对mysql 命令不太了解,没有关系,今天就由本站为大家分享mysql 命令的知识,包括MySQL的基本命令的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!

2026年10月11日 03:00

手机云备份是什么意思?手机上的云备份有什么用 怎么用呢

手机云备份是什么意思?手机上的云备份有什么用 怎么用呢

各位老铁们,大家好,今天由我来为大家分享云备份,以及手机云备份是什么意思的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站,您的支持是我们最大的动力,谢谢大家了哈,下面我们开始吧!

2026年10月11日 02:40

java遍历map的key(java Map 怎么遍历)

java遍历map的key(java Map 怎么遍历)

大家好,java遍历map的key相信很多的网友都不是很明白,包括java Map 怎么遍历也是一样,不过没有关系,接下来就来为大家分享关于java遍历map的key和java Map 怎么遍历的一些知识点,大家可以关注收藏,免得下次来找不

2026年10月11日 02:20

最近更新

majority of(the majority of 和 a majority of的区别以及用法例句)
2026-10-11 07:40:02 浏览:0
promote翻译(英语翻译倡导怎么说)
2026-10-11 06:30:03 浏览:0
热门文章

标签列表