devicetree中数据和structdevice有什么关系
总体来说,devicetree与structdevice的关系应该还是在其生成platformdevice的时候,一直传递的structdevice*parent参数。下面先把其源码中传递过程描述如下(仍以At91rm9200为例):
1,
DT_MACHINE_START(at91sam_dt,"Atmel AT91SAM (Device Tree)")
/*Maintainer:Atmel */
.timer=&at91sam926x_timer,
.map_io=at91_map_io,
.init_early=at91_dt_initialize,
.init_irq=at91_dt_init_irq,
.init_machine =at91_dt_device_init,
.dt_compat=at91_dt_board_compat,
MACHINE_END
2,
staticvoid__init at91_dt_device_init(void)
{
of_platform_populate(NULL,of_default_bus_match_table,NULL, NULL);
}
3,
/**
*of_platform_populate()- Populate platform_devices from device treedata
*@root: parentof the first level to probe or NULL for the root of thetree
*@matches:match table, NULL to use the default
*@parent: parent to hook devicesfrom, NULL fortoplevel
*
*Similar toof_platform_bus_probe(), this function walks the devicetree
*and createsdevices from nodes. It differs in that it follows themodern
*convention ofrequiring all device nodes to have a 'compatible'property,
*and it issuitable for creating devices which are children of theroot
*node(of_platform_bus_probe will only create children of the rootwhich
*are selectedby the @matches argument).
*
*New boardsupport should be using this function instead of
*of_platform_bus_probe().
*
*Returns 0 onsuccess, < 0 on failure.
*/
//从devicetree数据中populateplatform devices。
intof_platform_populate(structdevice_node *root,
conststructof_device_id *matches,
conststructof_dev_auxdata *lookup,
structdevice*parent)
{
structdevice_node*child;
intrc = 0;
root= root ?of_node_get(root) : of_find_node_by_path("/");
if(!root)
return-EINVAL;
for_each_child_of_node(root,child){
//生成platformdevice
rc= of_platform_bus_create(child,matches, lookup, parent,true);
if(rc)
break;
}
of_node_put(root);
returnrc;
}
4,
/**
*of_platform_bus_create()- Create a device for a node and itschildren.
*@bus: devicenode of the bus to instantiate
*@matches:match table for bus nodes
*@lookup:auxdata table for matching id and platform_data with devicenodes
*@parent:parent for new device, or NULL for top level.
*@strict:require compatible property
*
*Creates aplatform_device for the provided device_node, andoptionally
*recursivelycreate devices for all the child nodes.
*/
//为节点和其孩子节点生成一个设备文件。
staticint of_platform_bus_create(structdevice_node *bus,
const structof_device_id *matches,
const structof_dev_auxdata *lookup,
struct device*parent, boolstrict)
{
conststructof_dev_auxdata *auxdata;
structdevice_node*child;
structplatform_device*dev;
constchar*bus_id = NULL;
void*platform_data= NULL;
intrc = 0;
/*Make sure ithas a compatible property */
if(strict&& (!of_get_property(bus, "compatible",NULL))) {
pr_debug("%s()-skipping %s, no compatible prop\n",
__func__,bus->full_name);
return0;
}
auxdata=of_dev_lookup(lookup, bus);
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);
return0;
}
dev= of_platform_device_create_pdata(bus,bus_id, platform_data, parent);
if(!dev ||!of_match_node(matches, bus))
return0;
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;
}
}
returnrc;
}
代码在这儿分了两步走:4.1和4.2。
4.1
staticstructamba_device *of_amba_device_create(structdevice_node *node,
const char*bus_id,
void*platform_data,
struct device*parent)
{
structamba_device*dev;
constvoid*prop;
inti, ret;
pr_debug("Creatingambadevice %s\n", node->full_name);
if(!of_device_is_available(node))
returnNULL;
dev=amba_device_alloc(NULL, 0, 0);
if(!dev)
returnNULL;
/*setup genericdevice info */
dev->dev.coherent_dma_mask=~0;
dev->dev.of_node=of_node_get(node);
dev->dev.parent=parent;
dev->dev.platform_data=platform_data;
…...
}
4.2
/**
*of_platform_device_create_pdata- Alloc, initialize and register anof_device
*@np: pointerto node to create device for
*@bus_id: nameto assign device
*@platform_data:pointer to populate platform_data pointer with
*@parent: Linux device model parentdevice.
*
*Returnspointer to created platform device, or NULL if a device wasnot
*registered.Unavailable devices will not get registered.
*/
//分配内存,初始化和注册一个of_device
structplatform_device*of_platform_device_create_pdata(
structdevice_node*np,
constchar*bus_id,
void*platform_data,
structdevice*parent)
{
structplatform_device*dev;
if(!of_device_is_available(np))
returnNULL;
dev= of_device_alloc(np,bus_id, parent);
…...
returndev;
}
4.2.1
/**
*of_device_alloc- Allocate and initialize an of_device
*@np: devicenode to assign to device
*@bus_id: Nameto assign to the device. May be null to use defaultname.
*@parent: Parent device.
*/
//分配内存和初始化of_device
structplatform_device*of_device_alloc(structdevice_node *np,
const char*bus_id,
struct device*parent)
{
structplatform_device*dev;
intrc, i,num_reg = 0, num_irq;
structresource*res, temp_res;
dev=platform_device_alloc("", -1);
if(!dev)
returnNULL;
/*count the ioand irq resources */
if(of_can_translate_address(np))
while(of_address_to_resource(np,num_reg, &temp_res) == 0)
num_reg++;
num_irq=of_irq_count(np);
/*Populate theresource table */
if(num_irq ||num_reg) {
res=kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
if(!res) {
platform_device_put(dev);
returnNULL;
}
dev->num_resources=num_reg + num_irq;
dev->resource=res;
for(i = 0; i< num_reg; i++, res++) {
rc=of_address_to_resource(np, i, res);
WARN_ON(rc);
}
WARN_ON(of_irq_to_resource_table(np,res,num_irq) != num_irq);
}
dev->dev.of_node=of_node_get(np);
#ifdefined(CONFIG_MICROBLAZE)
dev->dev.dma_mask=&dev->archdata.dma_mask;
#endif
dev->dev.parent=parent;
if(bus_id)
dev_set_name(&dev->dev,"%s",bus_id);
else
of_device_make_bus_id(&dev->dev);
returndev;
}
总的分析:parent参数开始初始化为NULL,其中一直没有赋值,直到最后赋值给platformdevice的dev.parent属性。其中关系耐人寻味。
源文档 <http://blog.csdn.net/lichengtongxiazai/article/details/38942047>