DTS 驱动分析
1、clk框架
时钟父子节点关系
clk_prepare_enable如何使能父节点enable函数
在DTS中时钟配置功能
注册时钟:clk_provider
寻找时钟:从DTS树中分析节点,of_parse_phandle_with_args函数,再到clkprovider中找到匹配的时钟,也可以通过时钟名字匹配。
2、watch-dog框架
时钟获取
sp805-wdt-rpoble
devm-clk-get
clk-get
of_clk_get_by_name
of_clk_get
of_parse_phandle_with_args
fclk_get_from_provider
3、of-platform框架
为每个dts中根节点创建平台设备,以及符合的特定总线设备。
/**
410 *of_platform_bus_probe() - Probe the device-tree for platform buses
411 * @root: parent of thefirst level to probe or NULL for the root of the tree
412 * @matches: match tablefor bus nodes
413 * @parent: parent tohook devices from, NULL for toplevel
414 *
415 * Note that children ofthe provided root are not instantiated as devices
416 * unless the specifiedroot itself matches the bus list and is not NULL.
417 */
418 intof_platform_bus_probe(struct device_node *root,
419 conststruct of_device_id *matches,
420 structdevice *parent)
421 {
422 struct device_node*child;
423 int rc = 0;
424
425 root = root ?of_node_get(root) : of_find_node_by_path("/");
426 if (!root)
427 return -EINVAL;
428
429 pr_debug("of_platform_bus_probe()\n");
430 pr_debug("starting at: %s\n", root->full_name);
431
432 /* Do a self checkof bus type, if there's a match, create children */
433 if(of_match_node(matches, root)) {
434 rc =of_platform_bus_create(root, matches, NULL, parent, false);
435 } elsefor_each_child_of_node(root, child) {
436 if(!of_match_node(matches, child))
437 continue;
438 rc =of_platform_bus_create(child, matches, NULL, parent, false);
439 if (rc)
440 break;
441 }
442
443 of_node_put(root);
444 return rc;
445 }
446EXPORT_SYMBOL(of_platform_bus_probe);
447
//先把每个子节点创建完成,若子节点符合匹配,再为每个子节点的子节点创建平台设备。
450 * @root: parent of thefirst level to probe or NULL for the root of the tree
451 * @matches: matchtable, NULL to use the default
452 * @lookup: auxdatatable for matching id and platform_data with device nodes
453 * @parent: parent tohook devices from, NULL for toplevel
454 *
455 * Similar toof_platform_bus_probe(), this function walks the device tree
456 * and creates devicesfrom nodes. It differs in that it follows the modern
457 * convention ofrequiring all device nodes to have a 'compatible' property,
458 * and it is suitablefor creating devices which are children of the root
459 * node(of_platform_bus_probe will only createchildren of the root which
460 *are selected by the @matches argument).
461 *
462 * New board supportshould be using this function instead of
463 *of_platform_bus_probe().
464 *
465 * Returns 0 on success,< 0 on failure.
466 */
467 intof_platform_populate(struct device_node *root,
468 const structof_device_id *matches,
469 const structof_dev_auxdata *lookup,
470 structdevice *parent)
471 {
472 struct device_node*child;
473 int rc = 0;
474
475 root = root ?of_node_get(root) : of_find_node_by_path("/");
476 if (!root)
477 return -EINVAL;
478
479 for_each_child_of_node(root, child) {
480 rc =of_platform_bus_create(child, matches, lookup, parent, true);
481 if (rc)
482 break;
483 }
484
485 of_node_put(root);
486 return rc;
487 }
488EXPORT_SYMBOL_GPL(of_platform_populate);
static intof_platform_bus_create(struct device_node *bus,
361 conststruct of_device_id *matches,
362 conststruct of_dev_auxdata *lookup,
363 structdevice *parent, bool strict)
364 {
365 const structof_dev_auxdata *auxdata;
366 struct device_node*child;
367 structplatform_device *dev;
368 const char *bus_id =NULL;
369 void *platform_data= NULL;
370 int rc = 0;
371
372 /* Make sure it hasa compatible property */
373 if (strict &&(!of_get_property(bus, "compatible", NULL))) {
374 pr_debug("%s()- skipping %s, no compatible prop\n",
375 __func__,bus->full_name);
376 return 0;
377 }
378
379 auxdata =of_dev_lookup(lookup, bus);
380 if (auxdata) {
381 bus_id =auxdata->name;
382 platform_data =auxdata->platform_data;
383 }
384
385 if(of_device_is_compatible(bus, "arm,primecell")) {
386 /*
387 * Don't returnan error here to keep compatibility with older
388 * device treefiles.
389 */