u-boot nand spl代码整体流程
/* SPL阶段函数调用过程 */
u-boot-spl.lds(arch/arm/cpu/arm/u-boot-spl.lds)
|--> vectors.S(arch/arm/lib/vectors.S)
|--> start.S(arch/arm/cpu/arm926ejs/start.S)
|--> /*set SVC mode .. disable FIQ and IRQ*/
|--> cpu_init_crit(arch/arm/cpu/armv7/start.S)
|--> /* flush D cache before disabling it*/
|--> /* disable MMU and D cache it, enable I cache if SYS_ICACHE_OFF is not defined*/
|--> lowlevel_init(arch/arm/cpu/arm926ejs/nuc970/lowlevel_init.S) /* 板级初始化,设置栈空间 */
|--> _main(arch/arm/lib/crt0.S )
|--> /* Set up initial C runtime environment and call board_init_f(0).*/
|--> board_init_f_alloc_reserve(common/init/board_init.c)
|--> board_init_f_init_reserve(common/init/board_init.c)
|--> board_init_f(common/spl/spl.c)
|--> spl_early_init(common/spl/spl.c)
|--> spl_common_init(true) (common/spl/spl.c)
|--> gd->malloc_limit = CONFIG_VAL(SYS_MALLOC_F_LEN);
|--> gd->malloc_ptr = 0;
|--> bootstage_init(u_boot_first_phase())(include/bootstage.c)
|--> bootstage_unstash(#ifdef CONFIG_BOOTSTAGE_STASH) (include/bootstage.c)
|--> bootstage_mark_name(include/bootstage.c)
|--> log_init(common/log.c)
|--> fdtdec_setup()(lib/fdtdec.c)
|--> gd->fdt_blob = board_fdt_blob_setup()(lib/fdtdec.c)
|--> fdtdec_prepare_fdt() (lib/fdtdec.c)
|--> bootstage_start(include/bootstage.c)
|--> dm_init_and_scan(drivers/core/root.c)
|--> dm_init (drivers/core/root.c)
//#define DM_UCLASS_ROOT_NON_CONST (((gd_t *)gd)->uclass_root) 创建头结点gd->uclass_root
|--> INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST) (drivers/core/root.c)
|--> device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST) (drivers/core/device.c)
//lists_driver_lookup_name("root_driver")
|--> drv = lists_driver_lookup_name(info->name) (drivers/core/device.c)
//通过上篇分析,此处得到的是uboot_list_2_driver_1的地址
|--> struct driver *drv =ll_entry_start(struct driver, driver);
//uboot_list_2_driver_3-uboot_list_2_driver_1即得到长度
|--> const int n_ents = ll_entry_count(struct driver, driver)
//遍历,通过name字段匹配,匹配成功得到driver结构体地址
|--> for (entry = drv; entry != drv + n_ents; entry++)
|--> device_bind_common(drv, "root_driver", gd->dm_root) (drivers/core/device.c)
//通过上面得到的drv中的id字段(UCLASS_ROOT)进行匹配,匹配成功得到对应的uclass_driver结构体地址
|--> uclass_get(drv->id, &uc)
|-->uc = uclass_find(id);
|-->return uclass_add(id, ucp);
|--> uc->uc_drv = uc_drv; //uclass root的uclass_driver指向uclass_driver root
|--> INIT_LIST_HEAD(&uc->sibling_node);
|--> INIT_LIST_HEAD(&uc->dev_head);
|--> list_add(&uc->sibling_node, &DM_UCLASS_ROOT_NON_CONST);
|--> dev = calloc(1, sizeof(struct udevice))
/* put dev into parent's successor list */
|--> list_add_tail(&dev->sibling_node, &parent->child_head);
|--> ret = uclass_bind_device(dev);
/* if we fail to bind we remove device from successors and free it */
|--> DM_ROOT_NON_CONST->node =
|--> np_to_ofnode, offset_to_ofnode()
|--> device_probe (drivers/core/device.c)
|--> if (dev->flags & DM_FLAG_ACTIVATED)
|--> device_ofdata_to_platdata (drivers/core/device.c)
|--> /* Ensure all parents are probed */
|--> seq = uclass_resolve_seq(dev) (drivers/core/uclass.c)
|--> uclass_find_device_by_seq
|--> dev->flags |= DM_FLAG_ACTIVATED
|--> pinctrl_select_state
|--> dev_power_domain_on
|--> uclass_pre_probe_device
|--> uclass_pre_probe_device
|--> /* Only handle devices that have a valid ofnode */
|--> clk_set_defaults
|--> drv->probe
|--> uclass_post_probe_device
|--> pinctrl_select_state
|--> ret = dm_scan_platdata(pre_reloc_only); (drivers/core/root.c) //搜索使用宏U_BOOT_DEVICE定义的设备进行驱动匹配,也就是bind子节点
|--> ret = dm_extended_scan_fdt(gd->fdt_blob, pre_reloc_only); (drivers/core/root.c) //在其他地方(设备树)搜索设备并进行驱动匹配,然后bind
|--> dm_scan_fdt//在设备树种搜索设备并进行驱动匹配,然后bind
|--> ret = dm_scan_other(pre_reloc_only); (drivers/core/root.c)
|--> bootstage_accum(include/bootstage.c)
|--> gd->flags |= GD_FLG_SPL_EARLY_INIT (common/spl/spl.c)
|--> preloader_console_init (common/spl/spl.c)
|--> gd->baudrate = CONFIG_BAUDRATE(common/spl/spl.c)
|--> serial_init (drivers/serail/serial-uclass.c)
|--> serial_find_console_or_panic(drivers/serail/serial-uclass.c)
|--> /* Live tree has support for stdout */
|--> ogd->cur_serial_dev <- uclass_get_device_by_ofnode
|--> ogd->cur_serial_dev <- serial_check_stdout
|--> gd->flags |= GD_FLG_SERIAL_READY
|--> gd->have_console = 1
|--> board_init_r(common/spl/spl.c)
|--> spl_set_bd();gd->bd = &bdata /* gd是保存在r9寄存器的,即r9保存的是指向gdata的指针 */
|--> timer_init(arch/arm/cpu/armv7/sunxi/timer.c) /* 初始化时钟 */
ret = bloblist_init();
ret = setup_spl_handoff();
|--> spl_board_init()
|--> initr_watchdog();
|--> dram_init_banksize();
|--> bootcount_inc();
|--> memset(&spl_image, '\0', sizeof(spl_image));
|--> board_boot_order(spl_boot_list);
|--> boot_from_devices(common/spl/spl.c)
|--> spl_ll_find_loader(common/spl/spl.c)
|--> ll_entry_start(include/linker_lists.h)
|--> SPL_LOAD_IMAGE_METHOD("NAND", 1, BOOT_DEVICE_NAND, spl_nand_load_image); (common/spl/spl_nand.c)
|--> loader->load_image(spl_image, &bootdev); spl_nand_load_image (common/spl/spl_nand.c)
|--> nand_init(); (common/spl/spl_mmc.c)
|--> spl_get_load_buffer(0, sizeof(*header)); (common/spl/spl_mmc.c)
|--> spl_nand_load_element
|--> /* Load u-boot */spl_nand_load_element(spl_image, spl_nand_get_uboot_raw_page(), header);
|--> nand_deselect(); (common/spl/spl.c) /* 解析 header */
|--> spl_perform_fixups(&spl_image);
|--> ret = write_spl_handoff();
|--> ret = bloblist_finish(); /* 结束SPL过程,跳转到u-boot */
|--> bootstage_mark_name
|--> bootstage_stash
|--> spl_board_prepare_for_boot();
|--> jump_to_image_no_args(&spl_image);