这里接着上一篇来吧:
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();
#endif
ret = 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
#endif
DM_ROOT_NON_CONST->node = offset_to_ofnode(0);
#endif
ret = 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;
#endif
return 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);
}
}
}
}
#endif
dev = 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);
#endif
dev->platdata = platdata; //赋值,NULL
dev->driver_data = driver_data; //0
dev->name = name; //“root_driver”
dev->node = node; //一个空的node
dev->parent = parent; //NULL,
dev->driver = drv; //对应root_driver结构体首地址
dev->uclass = uc; //前文中获取,id对应UCLASS_ROOT
dev->seq = -1; //-1==none
dev->req_seq = -1; //-1==any
if (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) { //没有设置该flag
if (uc->uc_drv->name && ofnode_valid(node)) {
dev_read_alias_seq(dev, &dev->req_seq);
}
}
}
if (drv->platdata_auto_alloc_size) { //没有设置,root.c
bool 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.c
if (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;
}