这里接着上一篇来吧:
https://blog.csdn.net/zhaozhi0810/article/details/141927053
本文主要是dm_init_and_scan函数的分析,这个内容比较复杂,我也是第一次阅读,错误之处在所难免,请多指教。
uboot的dm框架需要了解一下,看了几行代码发现看不下去了,有点深啊。
(这篇没有写完,有点偷懒了,先发出来,后面再编辑更新吧。因为发现后面的函数都比较简单,要不先把后面的写了。)
我慢慢琢磨一下。
一、c的入口 board_init_f
1.3.11 initf_dm (common/board_f.c)
1.3.11.1 dm_init_and_scan (drivers/core/root.c)
参数 pre_reloc_only 为true
int dm_init_and_scan(bool pre_reloc_only)
{int ret;ret = dm_init(IS_ENABLED(CONFIG_OF_LIVE)); //初始化if (ret) {debug("dm_init() failed: %d\n", ret);return ret;}ret = dm_scan_platdata(pre_reloc_only); //扫描if (ret) {debug("dm_scan_platdata() failed: %d\n", ret);return ret;}if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {ret = dm_extended_scan_fdt(gd->fdt_blob, pre_reloc_only);if (ret) {debug("dm_extended_scan_dt() failed: %d\n", ret);return ret;}}ret = dm_scan_other(pre_reloc_only); //其他设备扫描if (ret)return ret;return 0;
}
1.3.11.1.1 dm_init
参数of_live 等于true
int dm_init(bool of_live)
{int ret;if (gd->dm_root) { //指针不为空则报出警告,并返回dm_warn("Virtual root driver already exists!\n");return -EINVAL;}INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST); //初始化队列((gd_t *)gd)->uclass_root#if defined(CONFIG_NEEDS_MANUAL_RELOC) //宏没有定义,略过fix_drivers();fix_uclass();fix_devices();
#endifret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST); //使用名字绑定设备?if (ret)return ret;
#if CONFIG_IS_ENABLED(OF_CONTROL) //宏有效
# if CONFIG_IS_ENABLED(OF_LIVE) //宏有效if (of_live)DM_ROOT_NON_CONST->node = np_to_ofnode(gd->of_root); //执行else
#endifDM_ROOT_NON_CONST->node = offset_to_ofnode(0);
#endifret = device_probe(DM_ROOT_NON_CONST); //设备探索,这里是个递归函数。貌似比较复杂if (ret)return ret;return 0;
}
1.3.11.1.1.1 device_bind_by_name
从函数名来看,是通过名称来绑定设备。
参数parent = NULL;
pre_reloc_only = false;
info = &root_info
devp = &DM_ROOT_NON_CONST 实际就是 &((((gd_t *)gd)->dm_root))
int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,const struct driver_info *info, struct udevice **devp)
{struct driver *drv;uint platdata_size = 0;drv = lists_driver_lookup_name(info->name); //参数为“root_driver”if (!drv)return -ENOENT;if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC))//pre_reloc_only 为false,不执行return -EPERM;#if CONFIG_IS_ENABLED(OF_PLATDATA) //宏未定义,跳过platdata_size = info->platdata_size;
#endifreturn device_bind_common(parent, drv, info->name,(void *)info->platdata, 0, ofnode_null(), platdata_size,devp);
}
1.3.11.1.1.1.1 lists_driver_lookup_name函数
参数为:root_driver
这里发现找代码属性段的时候,需要用到的是u-boot.map文件,刚刚也把前面的文章改了过来。
.u_boot_list_2_driver_1
0x00000000002d25c0 0x0 drivers/built-in.o
.u_boot_list_2_driver_2_analogix_dp
0x00000000002d25c0 0x78 drivers/built-in.o
0x00000000002d25c0 _u_boot_list_2_driver_2_analogix_dp
.u_boot_list_2_driver_2_arasan_sdhci_drv
0x00000000002d2638 0x78 drivers/built-in.o
0x00000000002d2638 _u_boot_list_2_driver_2_arasan_sdhci_drv
.u_boot_list_2_driver_2_clk_fixed_rate
0x00000000002d26b0 0x78 drivers/built-in.o
0x00000000002d26b0 _u_boot_list_2_driver_2_clk_fixed_rate
.u_boot_list_2_driver_2_clk_rk3399
0x00000000002d2728 0x78 drivers/built-in.o
0x00000000002d2728 _u_boot_list_2_driver_2_clk_rk3399
.u_boot_list_2_driver_2_dmc_rk3399
0x00000000002d27a0 0x78 drivers/built-in.o
0x00000000002d27a0 _u_boot_list_2_driver_2_dmc_rk3399
.u_boot_list_2_driver_2_dw_mipi_dsi
0x00000000002d2818 0x78 drivers/built-in.o
0x00000000002d2818 _u_boot_list_2_driver_2_dw_mipi_dsi
.u_boot_list_2_driver_2_ehci_generic
0x00000000002d2890 0x78 drivers/usb/host/built-in.o
0x00000000002d2890 _u_boot_list_2_driver_2_ehci_generic
.u_boot_list_2_driver_2_eth_designware
0x00000000002d2908 0x78 drivers/net/built-in.o
0x00000000002d2908 _u_boot_list_2_driver_2_eth_designware
.u_boot_list_2_driver_2_eth_gmac_rockchip
0x00000000002d2980 0x78 drivers/net/built-in.o
0x00000000002d2980 _u_boot_list_2_driver_2_eth_gmac_rockchip
.u_boot_list_2_driver_2_fixed_regulator
0x00000000002d29f8 0x78 drivers/power/regulator/built-in.o
0x00000000002d29f8 _u_boot_list_2_driver_2_fixed_regulator
.u_boot_list_2_driver_2_generic_syscon
0x00000000002d2a70 0x78 drivers/built-in.o
0x00000000002d2a70 _u_boot_list_2_driver_2_generic_syscon
.u_boot_list_2_driver_2_gpio_rockchip
0x00000000002d2ae8 0x78 drivers/gpio/built-in.o
0x00000000002d2ae8 _u_boot_list_2_driver_2_gpio_rockchip
.u_boot_list_2_driver_2_i2c_generic_chip_drv
0x00000000002d2b60 0x78 drivers/i2c/built-in.o
0x00000000002d2b60 _u_boot_list_2_driver_2_i2c_generic_chip_drv
.u_boot_list_2_driver_2_i2c_rockchip
0x00000000002d2bd8 0x78 drivers/i2c/built-in.o
0x00000000002d2bd8 _u_boot_list_2_driver_2_i2c_rockchip
.u_boot_list_2_driver_2_mmc
0x00000000002d2c50 0x78 drivers/built-in.o
0x00000000002d2c50 _u_boot_list_2_driver_2_mmc
.u_boot_list_2_driver_2_mmc_blk
0x00000000002d2cc8 0x78 drivers/built-in.o
0x00000000002d2cc8 _u_boot_list_2_driver_2_mmc_blk
.u_boot_list_2_driver_2_ns16550_serial
0x00000000002d2d40 0x78 drivers/serial/built-in.o
0x00000000002d2d40 _u_boot_list_2_driver_2_ns16550_serial
.u_boot_list_2_driver_2_ohci_generic
0x00000000002d2db8 0x78 drivers/usb/host/built-in.o
0x00000000002d2db8 _u_boot_list_2_driver_2_ohci_generic
.u_boot_list_2_driver_2_pinconfig_generic
0x00000000002d2e30 0x78 drivers/built-in.o
0x00000000002d2e30 _u_boot_list_2_driver_2_pinconfig_generic
.u_boot_list_2_driver_2_pinctrl_rockchip
0x00000000002d2ea8 0x78 drivers/built-in.o
0x00000000002d2ea8 _u_boot_list_2_driver_2_pinctrl_rockchip
.u_boot_list_2_driver_2_pmic_rk8xx
0x00000000002d2f20 0x78 drivers/power/pmic/built-in.o
0x00000000002d2f20 _u_boot_list_2_driver_2_pmic_rk8xx
.u_boot_list_2_driver_2_psci
0x00000000002d2f98 0x78 drivers/built-in.o
0x00000000002d2f98 _u_boot_list_2_driver_2_psci
.u_boot_list_2_driver_2_psci_sysreset
0x00000000002d3010 0x78 drivers/built-in.o
0x00000000002d3010 _u_boot_list_2_driver_2_psci_sysreset
.u_boot_list_2_driver_2_pwm_backlight
0x00000000002d3088 0x78 drivers/built-in.o
0x00000000002d3088 _u_boot_list_2_driver_2_pwm_backlight
.u_boot_list_2_driver_2_pwm_regulator
0x00000000002d3100 0x78 drivers/power/regulator/built-in.o
0x00000000002d3100 _u_boot_list_2_driver_2_pwm_regulator
.u_boot_list_2_driver_2_rk8xx_buck
0x00000000002d3178 0x78 drivers/power/regulator/built-in.o
0x00000000002d3178 _u_boot_list_2_driver_2_rk8xx_buck
.u_boot_list_2_driver_2_rk8xx_ldo
0x00000000002d31f0 0x78 drivers/power/regulator/built-in.o
0x00000000002d31f0 _u_boot_list_2_driver_2_rk8xx_ldo
.u_boot_list_2_driver_2_rk8xx_switch
0x00000000002d3268 0x78 drivers/power/regulator/built-in.o
0x00000000002d3268 _u_boot_list_2_driver_2_rk8xx_switch
.u_boot_list_2_driver_2_rk_pwm
0x00000000002d32e0 0x78 drivers/built-in.o
0x00000000002d32e0 _u_boot_list_2_driver_2_rk_pwm
.u_boot_list_2_driver_2_rockchip_crypto_v1
0x00000000002d3358 0x78 drivers/built-in.o
0x00000000002d3358 _u_boot_list_2_driver_2_rockchip_crypto_v1
.u_boot_list_2_driver_2_rockchip_display
0x00000000002d33d0 0x78 drivers/built-in.o
0x00000000002d33d0 _u_boot_list_2_driver_2_rockchip_display
.u_boot_list_2_driver_2_rockchip_dw_hdmi
0x00000000002d3448 0x78 drivers/built-in.o
0x00000000002d3448 _u_boot_list_2_driver_2_rockchip_dw_hdmi
.u_boot_list_2_driver_2_rockchip_dwmmc_drv
0x00000000002d34c0 0x78 drivers/built-in.o
0x00000000002d34c0 _u_boot_list_2_driver_2_rockchip_dwmmc_drv
.u_boot_list_2_driver_2_rockchip_efuse
0x00000000002d3538 0x78 drivers/built-in.o
0x00000000002d3538 _u_boot_list_2_driver_2_rockchip_efuse
.u_boot_list_2_driver_2_rockchip_lvds
0x00000000002d35b0 0x78 drivers/built-in.o
0x00000000002d35b0 _u_boot_list_2_driver_2_rockchip_lvds
.u_boot_list_2_driver_2_rockchip_panel
0x00000000002d3628 0x78 drivers/built-in.o
0x00000000002d3628 _u_boot_list_2_driver_2_rockchip_panel
.u_boot_list_2_driver_2_rockchip_reset
0x00000000002d36a0 0x78 drivers/built-in.o
0x00000000002d36a0 _u_boot_list_2_driver_2_rockchip_reset
.u_boot_list_2_driver_2_rockchip_rgb
0x00000000002d3718 0x78 drivers/built-in.o
0x00000000002d3718 _u_boot_list_2_driver_2_rockchip_rgb
.u_boot_list_2_driver_2_rockchip_rk3399_pmuclk
0x00000000002d3790 0x78 drivers/built-in.o
0x00000000002d3790 _u_boot_list_2_driver_2_rockchip_rk3399_pmuclk
.u_boot_list_2_driver_2_rockchip_saradc
0x00000000002d3808 0x78 drivers/built-in.o
0x00000000002d3808 _u_boot_list_2_driver_2_rockchip_saradc
.u_boot_list_2_driver_2_rockchip_usb2phy
0x00000000002d3880 0x78 drivers/built-in.o
0x00000000002d3880 _u_boot_list_2_driver_2_rockchip_usb2phy
.u_boot_list_2_driver_2_rockchip_usb2phy_port
0x00000000002d38f8 0x78 drivers/built-in.o
0x00000000002d38f8 _u_boot_list_2_driver_2_rockchip_usb2phy_port
.u_boot_list_2_driver_2_rockchip_vop
0x00000000002d3970 0x78 drivers/built-in.o
0x00000000002d3970 _u_boot_list_2_driver_2_rockchip_vop
.u_boot_list_2_driver_2_root_driver
0x00000000002d39e8 0x78 drivers/built-in.o
0x00000000002d39e8 _u_boot_list_2_driver_2_root_driver
.u_boot_list_2_driver_2_simple_bus_drv
0x00000000002d3a60 0x78 drivers/built-in.o
0x00000000002d3a60 _u_boot_list_2_driver_2_simple_bus_drv
.u_boot_list_2_driver_2_simple_panel
0x00000000002d3ad8 0x78 drivers/built-in.o
0x00000000002d3ad8 _u_boot_list_2_driver_2_simple_panel
.u_boot_list_2_driver_2_spi_generic_drv
0x00000000002d3b50 0x78 drivers/spi/built-in.o
0x00000000002d3b50 _u_boot_list_2_driver_2_spi_generic_drv
.u_boot_list_2_driver_2_syscon_rk3399
0x00000000002d3bc8 0x78 arch/arm/mach-rockchip/built-in.o
0x00000000002d3bc8 _u_boot_list_2_driver_2_syscon_rk3399
.u_boot_list_2_driver_2_sysreset_rockchip
0x00000000002d3c40 0x78 drivers/built-in.o
0x00000000002d3c40 _u_boot_list_2_driver_2_sysreset_rockchip
.u_boot_list_2_driver_2_sysreset_syscon_reboot
0x00000000002d3cb8 0x78 drivers/built-in.o
0x00000000002d3cb8 _u_boot_list_2_driver_2_sysreset_syscon_reboot
.u_boot_list_2_driver_2_usb_dev_generic_drv
0x00000000002d3d30 0x78 drivers/usb/host/built-in.o
0x00000000002d3d30 _u_boot_list_2_driver_2_usb_dev_generic_drv
.u_boot_list_2_driver_2_usb_generic_hub
0x00000000002d3da8 0x78 common/built-in.o
0x00000000002d3da8 _u_boot_list_2_driver_2_usb_generic_hub
.u_boot_list_2_driver_2_usb_mass_storage
0x00000000002d3e20 0x78 common/built-in.o
0x00000000002d3e20 _u_boot_list_2_driver_2_usb_mass_storage
.u_boot_list_2_driver_2_usb_storage_blk
0x00000000002d3e98 0x78 common/built-in.o
0x00000000002d3e98 _u_boot_list_2_driver_2_usb_storage_blk
.u_boot_list_2_driver_2_vidconsole_normal
0x00000000002d3f10 0x78 drivers/built-in.o
0x00000000002d3f10 _u_boot_list_2_driver_2_vidconsole_normal
.u_boot_list_2_driver_2_xhci_dwc3
0x00000000002d3f88 0x78 drivers/usb/host/built-in.o
0x00000000002d3f88 _u_boot_list_2_driver_2_xhci_dwc3
.u_boot_list_2_driver_3
0x00000000002d4000 0x0 drivers/built-in.o
.u_boot_list_2_driver_1 是驱动开始标记
.u_boot_list_2_driver_3 是驱动结束标记
.u_boot_list_2_driver_2_xx 就是加入的设备驱动。(粗略数了一下,有56个驱动)。
要查找的root_driver也是存在的!!
结构体的首地址,很有可能就是0x00000000002d39e8
用这几个驱动的地址相减得到的差值0x78来看,应该就是结构体的首地址。
1.3.11.1.1.1.2 device_bind_common 函数
稍微看了一下代码之后,这次这个函数的目的是新建root_driver的设备。
参数:
parent --> NULL
drv --> drv指针,应该就是root_driver 的首地址
name --> root_driver
platdata --> info.platdata --> NULL
driver_data --> 0
node --> 一个空的node (ofnode类型)
of_platdata_size -->platdata_size --> 0
devp --> &(((gd_t *)gd)->dm_root)
static int device_bind_common(struct udevice *parent, const struct driver *drv,const char *name, void *platdata,ulong driver_data, ofnode node,uint of_platdata_size, struct udevice **devp)
{struct udevice *dev;struct uclass *uc;int size, ret = 0;if (devp) //指针不为空,执行*devp = NULL; //指向空,在函数最后会赋值if (!name) //有一个字符串“root_driver”return -EINVAL;ret = uclass_get(drv->id, &uc); //id也是有的,在结构体中,UCLASS_ROOT,在文件root.c中if (ret) {debug("Missing uclass for driver %s\n", drv->name);return ret;}#ifdef CONFIG_USING_KERNEL_DTB //这个宏定义了。if (gd->flags & GD_FLG_RELOC) { //这个flag没有设置,需要到board_r.c的阶段,这个if不执行/* For mmc/nand/spiflash, just update from kernel dtb instead bind again*/if (drv->id == UCLASS_MMC || drv->id == UCLASS_RKNAND ||drv->id == UCLASS_SPI_FLASH || drv->id == UCLASS_MTD) {list_for_each_entry(dev, &uc->dev_head, uclass_node) {if (!strcmp(name, dev->name)) {debug("%s do not bind dev already in list %s\n",__func__, dev->name);/** There is no clearly reason for this* legacy code, but remain it here since* everything seems fine with or without* this. Maybe removed in the future.*/dev->node = node;return 0;}}}/* Use other nodes from kernel dtb */struct udevice *n;list_for_each_entry_safe(dev, n, &uc->dev_head, uclass_node) {if (!strcmp(name, dev->name) &&(dev_read_bool(dev, "u-boot,dm-pre-reloc") ||dev_read_bool(dev, "u-boot,dm-spl"))) {/* Always use crypto node from U-Boot dtb */if (drv->id == UCLASS_CRYPTO) {debug("%s do not delete uboot dev: %s\n",__func__, dev->name);return 0;} else {list_del_init(&dev->uclass_node);}}}}
#endifdev = calloc(1, sizeof(struct udevice)); //分配struct udevice空间if (!dev)return -ENOMEM;INIT_LIST_HEAD(&dev->sibling_node); //初始化列表INIT_LIST_HEAD(&dev->child_head);INIT_LIST_HEAD(&dev->uclass_node);
#ifdef CONFIG_DEVRES //宏未定义INIT_LIST_HEAD(&dev->devres_head);
#endifdev->platdata = platdata; //赋值,NULLdev->driver_data = driver_data; //0dev->name = name; //“root_driver”dev->node = node; //一个空的nodedev->parent = parent; //NULL,dev->driver = drv; //对应root_driver结构体首地址dev->uclass = uc; //前文中获取,id对应UCLASS_ROOTdev->seq = -1; //-1==nonedev->req_seq = -1; //-1==anyif (CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DM_SEQ_ALIAS)) { //查看.config,两个宏都有定义/** Some devices, such as a SPI bus, I2C bus and serial ports* are numbered using aliases.** This is just a 'requested' sequence, and will be* resolved (and ->seq updated) when the device is probed.*/if (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS) { //没有设置该flagif (uc->uc_drv->name && ofnode_valid(node)) {dev_read_alias_seq(dev, &dev->req_seq);}}}if (drv->platdata_auto_alloc_size) { //没有设置,root.cbool alloc = !platdata;if (CONFIG_IS_ENABLED(OF_PLATDATA)) {if (of_platdata_size) {dev->flags |= DM_FLAG_OF_PLATDATA;if (of_platdata_size <drv->platdata_auto_alloc_size)alloc = true;}}if (alloc) {dev->flags |= DM_FLAG_ALLOC_PDATA;dev->platdata = calloc(1,drv->platdata_auto_alloc_size);if (!dev->platdata) {ret = -ENOMEM;goto fail_alloc1;}if (CONFIG_IS_ENABLED(OF_PLATDATA) && platdata) {memcpy(dev->platdata, platdata,of_platdata_size);}}}size = uc->uc_drv->per_device_platdata_auto_alloc_size; //没有设置,root.cif (size) {dev->flags |= DM_FLAG_ALLOC_UCLASS_PDATA;dev->uclass_platdata = calloc(1, size);if (!dev->uclass_platdata) {ret = -ENOMEM;goto fail_alloc2;}}if (parent) { //parent = NULL,不执行size = parent->driver->per_child_platdata_auto_alloc_size;if (!size) {size = parent->uclass->uc_drv->per_child_platdata_auto_alloc_size;}if (size) {dev->flags |= DM_FLAG_ALLOC_PARENT_PDATA;dev->parent_platdata = calloc(1, size);if (!dev->parent_platdata) {ret = -ENOMEM;goto fail_alloc3;}}}/* put dev into parent's successor list */if (parent)//parent = NULL,不执行list_add_tail(&dev->sibling_node, &parent->child_head);ret = uclass_bind_device(dev); //插入到链表中if (ret)goto fail_uclass_bind;/* if we fail to bind we remove device from successors and free it */if (drv->bind) { //没有实现该函数ret = drv->bind(dev);if (ret)goto fail_bind;}if (parent && parent->driver->child_post_bind) { //parent = NULL,不执行 ret = parent->driver->child_post_bind(dev);if (ret)goto fail_child_post_bind;}if (uc->uc_drv->post_bind) {//驱动中没有,不执行ret = uc->uc_drv->post_bind(dev);if (ret)goto fail_uclass_post_bind;}if (parent)//parent = NULL,不执行pr_debug("Bound device %s to %s\n", dev->name, parent->name);if (devp)*devp = dev; //dev通过参数返回dev->flags |= DM_FLAG_BOUND;return 0;fail_uclass_post_bind:/* There is no child unbind() method, so no clean-up required */
fail_child_post_bind:if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {if (drv->unbind && drv->unbind(dev)) {dm_warn("unbind() method failed on dev '%s' on error path\n",dev->name);}}fail_bind:if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {if (uclass_unbind_device(dev)) {dm_warn("Failed to unbind dev '%s' on error path\n",dev->name);}}
fail_uclass_bind:if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {list_del(&dev->sibling_node);if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {free(dev->parent_platdata);dev->parent_platdata = NULL;}}
fail_alloc3:if (dev->flags & DM_FLAG_ALLOC_UCLASS_PDATA) {free(dev->uclass_platdata);dev->uclass_platdata = NULL;}
fail_alloc2:if (dev->flags & DM_FLAG_ALLOC_PDATA) {free(dev->platdata);dev->platdata = NULL;}
fail_alloc1:devres_release_all(dev);free(dev);return ret;
}