admin管理员组文章数量:1794759
uboot
initf_dm 在代码重定位之前运行.
initf_dm
779 static int initf_dm(void)780 {781 #if defined(CONFIG_DM) && CONFIG_VAL(SYS_MALLOC_F_LEN)782 int ret;785 ret = dm_init_and_scan(true);797 return 0;798 }
dm_init_and_scan
421 int dm_init_and_scan(bool pre_reloc_only)422 {423 int ret;424425 ret = dm_init(CONFIG_IS_ENABLED(OF_LIVE));430 if (!CONFIG_IS_ENABLED(OF_PLATDATA_INST)) {431 ret = dm_scan(pre_reloc_only);436 }437 if (CONFIG_IS_ENABLED(DM_EVENT)) {438 ret = event_notify_null(EVT_DM_POST_INIT);441 }442443 return 0;444 }
dm_init
169 int dm_init(bool of_live)170 {171 int ret;180 gd->uclass_root = &DM_UCLASS_ROOT_S_NON_CONST;181 INIT_LIST_HEAD(DM_UCLASS_ROOT_NON_CONST);197 ret = device_bind_by_name(NULL, false, &root_info,198 &DM_ROOT_NON_CONST);201 if (CONFIG_IS_ENABLED(OF_CONTROL))202 dev_set_ofnode(DM_ROOT_NON_CONST, ofnode_root());203 ret = device_probe(DM_ROOT_NON_CONST);208 INIT_LIST_HEAD((struct list_head *)&gd->dmtag_list);209210 return 0;211 }395 #define DM_ROOT_NON_CONST (((gd_t *)gd)->dm_root)396 #define DM_UCLASS_ROOT_NON_CONST (((gd_t *)gd)->uclass_root)397 #define DM_UCLASS_ROOT_S_NON_CONST (((gd_t *)gd)->uclass_root_s)35 static struct driver_info root_info = {36 .name = "root_driver",37 };
of_live == false;
device_bind_by_name
256 int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,257 const struct driver_info *info, struct udevice **devp)258 {259 struct driver *drv;260 uint plat_size = 0;261 int ret;262263 drv = lists_driver_lookup_name(info->name);266 if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC))267 return -EPERM;272 ret = device_bind_common(parent, drv, info->name, (void *)info->plat, 0,273 ofnode_null(), plat_size, devp);277 return ret;278 }
lists_driver_lookup_name
23 struct driver *lists_driver_lookup_name(const char *name)24 {25 struct driver *drv =26 ll_entry_start(struct driver, driver);27 const int n_ents = ll_entry_count(struct driver, driver);28 struct driver *entry;2930 for (entry = drv; entry != drv + n_ents; entry++) {31 if (!strcmp(name, entry->name))32 return entry;33 }37 }125 #define ll_entry_start(_type, _list) \126 ({ \127 static char start[0] __aligned(CONFIG_LINKER_LIST_ALIGN) \128 __attribute__((unused)) \129 __section(".u_boot_list_2_"#_list"_1"); \130 (_type *)&start; \131 })177 #define ll_entry_count(_type, _list) \178 ({ \179 _type *start = ll_entry_start(_type, _list); \180 _type *end = ll_entry_end(_type, _list); \181 unsigned int _ll_result = end - start; \182 _ll_result; \183 })152 #define ll_entry_end(_type, _list) \153 ({ \154 static char end[0] __aligned(4) __attribute__((unused)) \155 __section(".u_boot_list_2_"#_list"_3"); \156 (_type *)&end; \157 })
遍历".u_boot_list_2_driver_1"和".u_boot_list_2_driver_3"这两个段中间,所有struct driver.
所有struct driver定义时,就指定保存在这两个段中.
U_BOOT_DRIVER
464 U_BOOT_DRIVER(root_driver) = {465 .name = "root_driver",466 .id = UCLASS_ROOT,468 };396 #define U_BOOT_DRIVER(__name) \397 ll_entry_declare(struct driver, __name, driver)70 #define ll_entry_declare(_type, _name, _list) \71 _type _u_boot_list_2_##_list##_2_##_name __aligned(4) \72 __attribute__((unused)) \73 __section(".u_boot_list_2_"#_list"_2_"#_name)
宏定义展开后:
struct driver _u_boot_list_2_driver_root_driver __aligned(4) \__attribute__((unused)) \__section(".u_boot_list_2_driver_2_root_driver")
定义_u_boot_list_2_driver_root_driver全局变量,保存在".u_boot_list_2_driver_2_root_driver"段中.
device_bind_by_name
39 static int device_bind_common(struct udevice *parent, const struct driver *drv,40 const char *name, void *plat,41 ulong driver_data, ofnode node,42 uint of_plat_size, struct udevice **devp)43 {44 struct udevice *dev;45 struct uclass *uc;46 int size, ret = 0;47 bool auto_seq = true;48 void *ptr;58 ret = uclass_get(drv->id, &uc);64 dev = calloc(1, sizeof(struct udevice));68 INIT_LIST_HEAD(&dev->sibling_node);69 INIT_LIST_HEAD(&dev->child_head);70 INIT_LIST_HEAD(&dev->uclass_node);71 #if CONFIG_IS_ENABLED(DEVRES)72 INIT_LIST_HEAD(&dev->devres_head);73 #endif74 dev_set_plat(dev, plat);75 dev->driver_data = driver_data;76 dev->name = name;77 dev_set_ofnode(dev, node);78 dev->parent = parent;79 dev->driver = drv;80 dev->uclass = uc;8182 dev->seq_ = -1;83 if (CONFIG_IS_ENABLED(DM_SEQ_ALIAS) &&84 (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS)) {85 /*86 * Some devices, such as a SPI bus, I2C bus and serial ports87 * are numbered using aliases.88 */89 if (CONFIG_IS_ENABLED(OF_CONTROL) &&90 !CONFIG_IS_ENABLED(OF_PLATDATA)) {91 if (uc->uc_drv->name && ofnode_valid(node)) {92 if (!dev_read_alias_seq(dev, &dev->seq_)) {93 auto_seq = false;95 }96 }97 }98 }99 if (auto_seq && !(uc->uc_drv->flags & DM_UC_FLAG_NO_AUTO_SEQ))100 dev->seq_ = uclass_find_next_free_seq(uc);101102 /* Check if we need to allocate plat */103 if (drv->plat_auto) {104 bool alloc = !plat;116 if (alloc) {117 dev_or_flags(dev, DM_FLAG_ALLOC_PDATA);118 ptr = calloc(1, drv->plat_auto);130 dev_set_plat(dev, ptr);131 }132 }133134 size = uc->uc_drv->per_device_plat_auto;135 if (size) {136 dev_or_flags(dev, DM_FLAG_ALLOC_UCLASS_PDATA);137 ptr = calloc(1, size);142 dev_set_uclass_plat(dev, ptr);143 }144145 if (parent) {146 size = parent->driver->per_child_plat_auto;147 if (!size)148 size = parent->uclass->uc_drv->per_child_plat_auto;149 if (size) {150 dev_or_flags(dev, DM_FLAG_ALLOC_PARENT_PDATA);151 ptr = calloc(1, size);156 dev_set_parent_plat(dev, ptr);157 }158 /* put dev into parent's successor list */159 list_add_tail(&dev->sibling_node, &parent->child_head);160 }161162 ret = uclass_bind_device(dev);167 if (drv->bind) {168 ret = drv->bind(dev);171 }172 if (parent && parent->driver->child_post_bind) {173 ret = parent->driver->child_post_bind(dev);176 }177 if (uc->uc_drv->post_bind) {178 ret = uc->uc_drv->post_bind(dev);181 }185 if (devp)186 *devp = dev;187188 dev_or_flags(dev, DM_FLAG_BOUND);189190 return 0;
devices分配内存,并初始化.
uclass_get
145 int uclass_get(enum uclass_id id, struct uclass **ucp)146 {147 struct uclass *uc;153 uc = uclass_find(id);154 if (!uc) {157 return uclass_add(id, ucp);158 }159 *ucp = uc;160161 return 0;162 }
uclass_find
26 struct uclass *uclass_find(enum uclass_id key)27 {28 struct uclass *uc;2930 if (!gd->dm_root)31 return NULL;37 list_for_each_entry(uc, gd->uclass_root, sibling_node) {38 if (uc->uc_drv->id == key)39 return uc;40 }4142 return NULL;43 }
此时gd->dm_root还未初始化, return NULL.
uclass_add
54 static int uclass_add(enum uclass_id id, struct uclass **ucp)55 {56 struct uclass_driver *uc_drv;57 struct uclass *uc;58 int ret;5960 *ucp = NULL;61 uc_drv = lists_uclass_lookup(id);72 uc = calloc(1, sizeof(*uc));75 if (uc_drv->priv_auto) {76 void *ptr;7778 ptr = calloc(1, uc_drv->priv_auto);83 uclass_set_priv(uc, ptr);84 }85 uc->uc_drv = uc_drv;86 INIT_LIST_HEAD(&uc->sibling_node);87 INIT_LIST_HEAD(&uc->dev_head);88 list_add(&uc->sibling_node, DM_UCLASS_ROOT_NON_CONST);8990 if (uc_drv->init) {91 ret = uc_drv->init(uc);94 }9596 *ucp = uc;9798 return 0;
查找对应id的uclass_driver.
uclass分配内存.
uclass保存到gd->uclass_root.
lists_uclass_lookup
39 struct uclass_driver *lists_uclass_lookup(enum uclass_id id)40 {41 struct uclass_driver *uclass =42 ll_entry_start(struct uclass_driver, uclass_driver);43 const int n_ents = ll_entry_count(struct uclass_driver, uclass_driver);44 struct uclass_driver *entry;4546 for (entry = uclass; entry != uclass + n_ents; entry++) {47 if (entry->id == id)48 return entry;49 }5051 return NULL;52 }
uclass_driver 和 driver 匹配id号.
UCLASS_DRIVER
471 UCLASS_DRIVER(root) = {472 .name = "root",473 .id = UCLASS_ROOT,474 };111 #define UCLASS_DRIVER(__name) \112 ll_entry_declare(struct uclass_driver, __name, uclass_driver)
ll_entry_declare前面分析过, 定义一个全局变量保存在指定段中,方便后面遍历.
uclass_bind_device
684 int uclass_bind_device(struct udevice *dev)685 {686 struct uclass *uc;687 int ret;688689 uc = dev->uclass;690 list_add_tail(&dev->uclass_node, &uc->dev_head);691692 if (dev->parent) {693 struct uclass_driver *uc_drv = dev->parent->uclass->uc_drv;694695 if (uc_drv->child_post_bind) {696 ret = uc_drv->child_post_bind(dev);699 }700 }701702 return 0;708 }
device_probe
486 int device_probe(struct udevice *dev)487 {488 const struct driver *drv;489 int ret;497 ret = device_notify(dev, EVT_DM_PRE_PROBE);501 drv = dev->driver;502 assert(drv);503504 ret = device_of_to_plat(dev);508 /* Ensure all parents are probed */509 if (dev->parent) {510 ret = device_probe(dev->parent);514 /*515 * The device might have already been probed during516 * the call to device_probe() on its parent device517 * (e.g. PCI bridge devices). Test the flags again518 * so that we don't mess up the device.519 */520 if (dev_get_flags(dev) & DM_FLAG_ACTIVATED)521 return 0;522 }523524 dev_or_flags(dev, DM_FLAG_ACTIVATED);549 if (dev->parent && device_get_uclass_id(dev) != UCLASS_PINCTRL) {550 ret = pinctrl_select_state(dev, "default");554 }563 ret = device_get_dma_constraints(dev);567 ret = uclass_pre_probe_device(dev);571 if (dev->parent && dev->parent->driver->child_pre_probe) {572 ret = dev->parent->driver->child_pre_probe(dev);575 }588 if (drv->probe) {589 ret = drv->probe(dev);592 }593594 ret = uclass_post_probe_device(dev);598 if (dev->parent && device_get_uclass_id(dev) == UCLASS_PINCTRL) {599 ret = pinctrl_select_state(dev, "default");603 }604605 ret = device_notify(dev, EVT_DM_POST_PROBE);609 return 0;621 }
调用probe,设置引脚属性.
394 int device_of_to_plat(struct udevice *dev)395 {396 const struct driver *drv;397 int ret;409 if (!CONFIG_IS_ENABLED(OF_PLATDATA_NO_BIND)) {410 /* Ensure all parents have ofdata */411 if (dev->parent) {412 ret = device_of_to_plat(dev->parent);416 /*417 * The device might have already been probed during418 * the call to device_probe() on its parent device419 * (e.g. PCI bridge devices). Test the flags again420 * so that we don't mess up the device.421 */422 if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID)423 return 0;424 }425426 ret = device_alloc_priv(dev);429 }430 drv = dev->driver;431 assert(drv);432433 if (drv->of_to_plat &&434 (CONFIG_IS_ENABLED(OF_PLATDATA) || dev_has_ofnode(dev))) {435 ret = drv->of_to_plat(dev);438 }439440 dev_or_flags(dev, DM_FLAG_PLATDATA_VALID);441442 return 0;447 }
device_of_to_plat 分配存放平台数据的内存,调用drv->of_to_plat解析设备树.
dm_scan
396 static int dm_scan(bool pre_reloc_only)397 {398 int ret;399400 ret = dm_scan_plat(pre_reloc_only);406 if (CONFIG_IS_ENABLED(OF_REAL)) {407 ret = dm_extended_scan(pre_reloc_only);412 }413414 ret = dm_scan_other(pre_reloc_only);418 return dm_probe_devices(gd->dm_root, pre_reloc_only);419 }
dm_scan_plat
233 int dm_scan_plat(bool pre_reloc_only)234 {235 int ret;248 ret = lists_bind_drivers(DM_ROOT_NON_CONST, pre_reloc_only);254 return ret;255 }
lists_bind_drivers
109 int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only)110 {111 int result = 0;112 int pass;113114 /*115 * 10 passes is 10 levels deep in the devicetree, which is plenty. If116 * OF_PLATDATA_PARENT is not enabled, then bind_drivers_pass() will117 * always succeed on the first pass.118 */119 for (pass = 0; pass < 10; pass++) {120 int ret;121122 ret = bind_drivers_pass(parent, pre_reloc_only);127 }128129 return result;130 }
bind_drivers_pass
54 static int bind_drivers_pass(struct udevice *parent, bool pre_reloc_only)55 {56 struct driver_info *info =57 ll_entry_start(struct driver_info, driver_info);58 const int n_ents = ll_entry_count(struct driver_info, driver_info);59 bool missing_parent = false;60 int result = 0;61 int idx;6263 /*64 * Do one iteration through the driver_info records. For of-platdata,65 * bind only devices whose parent is already bound. If we find any66 * device we can't bind, set missing_parent to true, which will cause67 * this function to be called again.68 */69 for (idx = 0; idx < n_ents; idx++) {70 struct udevice *par = parent;71 const struct driver_info *entry = info + idx;72 struct driver_rt *drt = gd_dm_driver_rt() + idx;73 struct udevice *dev;74 int ret;95 ret = device_bind_by_name(par, pre_reloc_only, entry, &dev);104 }105106 return result ? result : missing_parent ? -EAGAIN : 0;107 }
这里调用device_bind_by_name绑定设备,但pre_reloc_only等于true,没有设置DM_FLAG_PRE_RELOC
的driver不进行绑定.
321 int dm_extended_scan(bool pre_reloc_only)322 {323 int ret, i;324 const char * const nodes[] = {325 "/chosen",326 "/clocks",327 "/firmware"328 };329330 ret = dm_scan_fdt(pre_reloc_only);336 /* Some nodes aren't devices themselves but may contain some */337 for (i = 0; i < ARRAY_SIZE(nodes); i++) {338 ret = dm_scan_fdt_ofnode_path(nodes[i], pre_reloc_only);344 }345346 return ret;347 }
dm_scan_plat
307 int dm_scan_fdt(bool pre_reloc_only)308 {309 return dm_scan_fdt_node(gd->dm_root, ofnode_root(), pre_reloc_only);310 }270 static int dm_scan_fdt_node(struct udevice *parent, ofnode parent_node,271 bool pre_reloc_only)272 {273 int ret = 0, err = 0;274 ofnode node;275276 if (!ofnode_valid(parent_node))277 return 0;278279 for (node = ofnode_first_subnode(parent_node);280 ofnode_valid(node);281 node = ofnode_next_subnode(node)) {282 const char *node_name = ofnode_get_name(node);283284 if (!ofnode_is_enabled(node)) {285 pr_debug(" - ignoring disabled device\n");286 continue;287 }288 err = lists_bind_fdt(parent, node, NULL, NULL, pre_reloc_only);293 }298 return ret;299 }
遍历设备树所有状态是’okay’的node.
lists_bind_fdt
184 int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp,185 struct driver *drv, bool pre_reloc_only)186 {187 struct driver *driver = ll_entry_start(struct driver, driver);188 const int n_ents = ll_entry_count(struct driver, driver);189 const struct udevice_id *id;190 struct driver *entry;191 struct udevice *dev;192 bool found = false;193 const char *name, *compat_list, *compat;194 int compat_length, i;195 int result = 0;196 int ret = 0;197198 if (devp)199 *devp = NULL;200 name = ofnode_get_name(node);203 compat_list = ofnode_get_property(node, "compatible", &compat_length);215 /*216 * Walk through the compatible string list, attempting to match each217 * compatible string in order such that we match in order of priority218 * from the first string to the last.219 */220 for (i = 0; i < compat_length; i += strlen(compat) + 1) {221 compat = compat_list + i;225 for (entry = driver; entry != driver + n_ents; entry++) {226 ret = driver_check_compatible(entry->of_match, &id,227 compat);228 if ((drv) && (drv == entry))229 break;230 if (!ret)231 break;232 }233 if (entry == driver + n_ents)234 continue;235236 if (pre_reloc_only) {237 if (!ofnode_pre_reloc(node) &&238 !(entry->flags & DM_FLAG_PRE_RELOC)) {239 log_debug("Skipping device pre-relocation\n");240 return 0;241 }242 }247 ret = device_bind_with_driver_data(parent, entry, name,248 id->data, node, &dev);258 found = true;259 if (devp)260 *devp = dev;262 break;263 }268 return result;269 }
pre_reloc_only 等于true, driver和设备树node同时支持pre_reloc,才进行bind.
364 static int dm_probe_devices(struct udevice *dev, bool pre_reloc_only)365 {366 u32 mask = DM_FLAG_PROBE_AFTER_BIND;367 u32 flags = dev_get_flags(dev);368 struct udevice *child;369 int ret;370371 if (pre_reloc_only)372 mask |= DM_FLAG_PRE_RELOC;373374 if ((flags & mask) == mask) {375 ret = device_probe(dev);376 if (ret)377 return ret;378 }379380 list_for_each_entry(child, &dev->child_head, sibling_node)381 dm_probe_devices(child, pre_reloc_only);382383 return 0;384 }
udevice 设置对应标志才调用,device_probe.否则只是probe子设备.
本文标签: uboot
版权声明:本文标题:uboot 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1731223994a1020228.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论