admin管理员组

文章数量:1794759

uboot

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