/* * (C) Copyright 2019 Rockchip Electronics Co., Ltd * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include #include #include #include #include #include #include #include DECLARE_GLOBAL_DATA_PTR; #if 1 struct display_fixup_data { int type; int delay_prepare; int delay_enable; int delay_disable; int delay_unprepare; int delay_reset; int delay_init; int size_width; int size_height; int clock_frequency; int hactive; int hfront_porch; int hsync_len; int hback_porch; int vactive; int vfront_porch; int vsync_len; int vback_porch; int hsync_active; int vsync_active; int de_active; int pixelclk_active; /* for DSI Panel */ int flags; int format; int lanes; int init_cmd_length; u8 *init_cmd; int nodka_lvds; }; enum { PANEL_TYPE_DSI, PANEL_TYPE_EDP, PANEL_TYPE_LVDS, }; #define CUSTOM_PARTITION_NAME "baseparameter" #define LCD_PARAM_MAX_COUNT 27 int lcdParam[LCD_PARAM_MAX_COUNT]; char param_buf_temp[4*1024] = {0}; void set_lcdparam_test_edp(struct display_fixup_data *data) { data->type = PANEL_TYPE_DSI; data->delay_prepare = 100; data->delay_enable = 100; data->delay_disable = 100; data->delay_unprepare = 100; data->delay_reset = 100; data->delay_init = 100; data->size_width = 240; data->size_height = 300; data->clock_frequency = 60000000; data->hactive = 1024; data->hfront_porch = 12; data->hsync_len = 16; data->hback_porch = 48; data->vactive = 600; data->vfront_porch = 8; data->vsync_len = 4; data->vback_porch = 8; data->hsync_active = 0; data->vsync_active = 0; data->de_active = 0; data->pixelclk_active = 0; data->flags = 0; data->format = 0; data->lanes = 4; *(data->init_cmd + 0) = 0x05; *(data->init_cmd + 1) = 0x00; *(data->init_cmd + 2) = 0x01; *(data->init_cmd + 3) = 0x01; *(data->init_cmd + 4) = 0x05; *(data->init_cmd + 5) = 0x00; *(data->init_cmd + 6) = 0x01; *(data->init_cmd + 7) = 0x02; *(data->init_cmd + 8) = 0x05; *(data->init_cmd + 9) = 0x00; *(data->init_cmd + 10) = 0x01; *(data->init_cmd + 11) = 0x03; *(data->init_cmd + 12) = 0x05; *(data->init_cmd + 13) = 0x00; *(data->init_cmd + 14) = 0x01; *(data->init_cmd + 15) = 0x05; } int get_lcdparam_info_from_custom_partition(struct display_fixup_data *data) { struct blk_desc *dev_desc; disk_partition_t part_info; char *boot_partname = CUSTOM_PARTITION_NAME; int ret,i; dev_desc = rockchip_get_bootdev(); if (!dev_desc) { printf("%s: dev_desc is NULL!\n", __func__); return -ENODEV; } ret = part_get_info_by_name(dev_desc, boot_partname, &part_info); if (ret < 0) { printf("%s: failed to get %s part, ret=%d\n", __func__, boot_partname, ret); /* RKIMG can support part table without 'boot' */ return -1; } printf("block num: %lu, name %s ,type %s,block size :%lu\n",part_info.size,part_info.name,part_info.type,part_info.blksz); ret = blk_dread(dev_desc, part_info.start + 512, 1, param_buf_temp); if (ret != 1) { printf("%s: failed to read screen parameter, ret=%d\n", __func__, ret); return -1; } for (i = 0; i < LCD_PARAM_MAX_COUNT; i++) { lcdParam[i] = param_buf_temp[i * 4]; lcdParam[i] = (lcdParam[i] << 8) + param_buf_temp[i * 4 + 1]; lcdParam[i] = (lcdParam[i] << 8) + param_buf_temp[i * 4 + 2]; lcdParam[i] = (lcdParam[i] << 8) + param_buf_temp[i * 4 + 3]; if(lcdParam[i] < 0){ lcdParam[i] = -lcdParam[i]; } if(lcdParam[i] > 100000 && i != 9){ lcdParam[i] = 0; } printf("--get-- lcd_param %d\n",lcdParam[i]); } if(lcdParam[14] == 0 || lcdParam[10] == 0){ return -1; } printf("-get- crc32 = 0X%02X%02X%02X%02X\n", param_buf_temp[LCD_PARAM_MAX_COUNT * 4], param_buf_temp[LCD_PARAM_MAX_COUNT * 4 + 1], param_buf_temp[LCD_PARAM_MAX_COUNT * 4 + 2], param_buf_temp[LCD_PARAM_MAX_COUNT * 4 + 3]); data->type = lcdParam[0]; data->delay_prepare = lcdParam[4]; data->delay_enable = lcdParam[2]; data->delay_disable = lcdParam[3]; data->delay_unprepare = lcdParam[1]; data->delay_reset = lcdParam[5]; data->delay_init = lcdParam[6]; data->size_width = lcdParam[7]; data->size_height = lcdParam[8]; data->clock_frequency = lcdParam[9]; data->hactive = lcdParam[10]; data->hfront_porch = lcdParam[11]; data->hsync_len = lcdParam[12]; data->hback_porch = lcdParam[13]; data->vactive = lcdParam[14]; data->vfront_porch = lcdParam[15]; data->vsync_len = lcdParam[16]; data->vback_porch = lcdParam[17]; data->hsync_active = lcdParam[18]; data->vsync_active = lcdParam[19]; data->de_active = lcdParam[20]; data->pixelclk_active = lcdParam[21]; data->flags = lcdParam[22]; data->format = lcdParam[23]; data->lanes = lcdParam[24]; data->init_cmd_length = lcdParam[25] = 16; data->nodka_lvds = lcdParam[26]; data->init_cmd = malloc(sizeof(*(data->init_cmd)) * data->init_cmd_length); for(i = 0; i < data->init_cmd_length; i++){ *(data->init_cmd + i) = param_buf_temp[100 + i]; // printf("init cmd = %x\n",param_buf_temp[100 + i]); } // set_lcdparam_test_edp(data); return 0; } #endif static int find_connector_node(const void *blob, int node) { int phandle, remote; int nodedepth; phandle = fdt_getprop_u32_default_node(blob, node, 0, "remote-endpoint", -1); remote = fdt_node_offset_by_phandle(blob, phandle); nodedepth = fdt_node_depth(blob, remote); return fdt_supernode_atdepth_offset(blob, remote, nodedepth - 3, NULL); } static int get_panel_node(const void *blob, int conn_node) { int panel, ports, port, ep, remote, ph, nodedepth; panel = fdt_subnode_offset(blob, conn_node, "panel"); printf("panel_1=%d\n",panel); if (panel > 0) { return panel; } ports = fdt_subnode_offset(blob, conn_node, "ports"); if (ports < 0) { return -ENODEV; } fdt_for_each_subnode(port, blob, ports) { fdt_for_each_subnode(ep, blob, port) { ph = fdt_getprop_u32_default_node(blob, ep, 0, "remote-endpoint", 0); if (!ph) continue; remote = fdt_node_offset_by_phandle(blob, ph); nodedepth = fdt_node_depth(blob, remote); if (nodedepth < 2) continue; panel = fdt_supernode_atdepth_offset(blob, remote, nodedepth - 2, NULL); break; } } printf("panel_2=%d\n",panel); return panel; } static int fdt_fixup_node_status(void *blob, int node, enum fdt_status status) { int ret; // printf("My fixup %s %d\n", fdt_get_name(blob, node, NULL), status); set_status: ret = fdt_set_node_status(blob, node, status, 0); if (ret == -FDT_ERR_NOSPACE) { ret = fdt_increase_size(blob, 512); if (!ret) goto set_status; else goto err_size; } else if (ret < 0) { printf("Can't set node status: %s\n", fdt_strerror(ret)); return ret; } return 0; err_size: printf("Can't increase blob size: %s\n", fdt_strerror(ret)); return ret; } #if 0 static int fdt_fixup_panel_init_sequence(void *fdt, int node,const struct display_fixup_data *data) { #if 0 u8 init_buf[] = {0x05, 0x00, 0x01, 0x78, 0x15, 0x01, 0x02, 0x03, 0x04, 0x05, 0x05, 0x01, 0x14,0x39, 0x01, 0x03, 0x02, 0x29, 0x11}; u8 exit_buf[] = {0x05, 0x64, 0x01, 0x29, 0x05, 0x64, 0x01, 0x11}; #endif int ret; add_seq: ret = fdt_setprop(fdt, node, "panel-init-sequence", data->init_cmd, data->init_cmd_length); if (ret == -FDT_ERR_NOSPACE) { printf(" init sequence FDT_ERR_NOSPACE\n"); ret = fdt_increase_size(fdt, data->init_cmd_length * 4);//gln the length needs precision if (!ret) goto add_seq; else goto err_size; } else if (ret < 0) { printf("Can't add property: %s\n", fdt_strerror(ret)); return ret; } #if 0 add_init_seq: ret = fdt_setprop(fdt, node, "panel-init-sequence", init_buf, sizeof(init_buf)); if (ret == -FDT_ERR_NOSPACE) { printf(" init sequence FDT_ERR_NOSPACE\n"); ret = fdt_increase_size(fdt, 512);//gln the length needs precision if (!ret) goto add_init_seq; else goto err_size; } else if (ret < 0) { printf("Can't add property: %s\n", fdt_strerror(ret)); return ret; } add_exit_seq: ret = fdt_setprop(fdt, node, "panel-exit-sequence", exit_buf, sizeof(exit_buf)); if (ret == -FDT_ERR_NOSPACE) { printf(" init sequence FDT_ERR_NOSPACE\n"); ret = fdt_increase_size(fdt, 512);//gln the length needs precision if (!ret) goto add_exit_seq; else goto err_size; } else if (ret < 0) { printf("Can't add property: %s\n", fdt_strerror(ret)); return ret; } #endif return 0; err_size: printf("Can't increase blob size: %s\n", fdt_strerror(ret)); return ret; } #endif static int fdt_fixup_setprop_u32(void *fdt, int node, const char *name, u32 data) { int ret; set_prop: ret = fdt_setprop_u32(fdt, node, name, data); if (ret == -FDT_ERR_NOSPACE) { ret = fdt_increase_size(fdt, 512); if (!ret) goto set_prop; else goto err_size; } else if (ret < 0) { printf("Can't add property: %s\n", fdt_strerror(ret)); return ret; } return 0; err_size: printf("Can't increase blob size: %s\n", fdt_strerror(ret)); return ret; } static void fdt_fixup_display_timing(void *blob, int node, const struct display_fixup_data *data) { fdt_fixup_setprop_u32(blob, node, "clock-frequency", data->clock_frequency); fdt_fixup_setprop_u32(blob, node, "hactive", data->hactive); fdt_fixup_setprop_u32(blob, node, "hfront-porch", data->hfront_porch); fdt_fixup_setprop_u32(blob, node, "hsync-len", data->hsync_len); fdt_fixup_setprop_u32(blob, node, "hback-porch", data->hback_porch); fdt_fixup_setprop_u32(blob, node, "vactive", data->vactive); fdt_fixup_setprop_u32(blob, node, "vfront-porch", data->vfront_porch); fdt_fixup_setprop_u32(blob, node, "vsync-len", data->vsync_len); fdt_fixup_setprop_u32(blob, node, "vback-porch", data->vback_porch); fdt_fixup_setprop_u32(blob, node, "hsync-active", data->hsync_active); fdt_fixup_setprop_u32(blob, node, "vsync-active", data->vsync_active); fdt_fixup_setprop_u32(blob, node, "de-active", data->de_active); fdt_fixup_setprop_u32(blob, node, "pixelclk-active", data->pixelclk_active); } static void fdt_fixup_panel_node(void *blob, int node, const char *name, const struct display_fixup_data *data) { /* if (!strcmp(name, "dsi")) { fdt_setprop_u32(blob, node, "dsi,flags", data->flags); fdt_setprop_u32(blob, node, "dsi,format", data->format); fdt_setprop_u32(blob, node, "dsi,lanes", data->lanes); fdt_fixup_panel_init_sequence(blob, node,data); } */ fdt_fixup_setprop_u32(blob, node, "prepare-delay-ms", data->delay_prepare); fdt_fixup_setprop_u32(blob, node, "enable-delay-ms", data->delay_enable); fdt_fixup_setprop_u32(blob, node, "disable-delay-ms", data->delay_disable); fdt_fixup_setprop_u32(blob, node, "unprepare-delay-ms", data->delay_unprepare); fdt_fixup_setprop_u32(blob, node, "reset-delay-ms", data->delay_reset); fdt_fixup_setprop_u32(blob, node, "init-delay-ms", data->delay_init); fdt_fixup_setprop_u32(blob, node, "width-mm", data->size_width); fdt_fixup_setprop_u32(blob, node, "height-mm", data->size_height); } static void fdt_fixup_nodka_lvds(void *blob, int node, const struct display_fixup_data *data) { if ( data->nodka_lvds != 0 ) fdt_fixup_setprop_u32(blob, node, "nodka-lvds", data->nodka_lvds); } static int fdt_fixup_display_sub_route(void *blob, const char *name, enum fdt_status status, const struct display_fixup_data *data) { int route, phandle, connect, connector, panel, dt, timing, route_lvds; char path[64]; char path_lvds[16] = "/panel"; int ret; sprintf(path, "/display-subsystem/route/route-%s", name); route = fdt_path_offset(blob, path); printf("route : %d \n",route); if (route < 0) return route; route_lvds = fdt_path_offset(blob, path_lvds); if (route_lvds < 0) { printf("can not get route_lvds = %d\n",route_lvds); return route_lvds; } /* fixup lvds gpio channel*/ fdt_fixup_nodka_lvds(blob, route_lvds, data); /* fixup route status */ ret = fdt_fixup_node_status(blob, route, status); if (ret < 0) return ret; phandle = fdt_getprop_u32_default_node(blob, route, 0, "connect", -1); if (phandle < 0) return phandle; connect = fdt_node_offset_by_phandle(blob, phandle); if (connect < 0) return connect; connector = find_connector_node(blob, connect); if (connector < 0) return connector; /* fixup connector status */ ret = fdt_fixup_node_status(blob, connector, status); if (ret < 0) return ret; if (status != FDT_STATUS_OKAY) { return 0; } panel = get_panel_node(blob, connector); if (panel < 0) return panel; /* fixup panel info */ fdt_fixup_panel_node(blob, panel, name, data); dt = fdt_subnode_offset(blob, panel, "display-timings"); if (dt < 0) { return dt; } timing = fdt_subnode_offset(blob, dt, "timing"); if (timing < 0) { phandle = fdt_getprop_u32_default_node(blob, dt, 0, "native-mode", -1); if (phandle < 0) return phandle; timing = fdt_node_offset_by_phandle(blob, phandle); if (timing < 0) return timing; } /* fixup panel display timing */ fdt_fixup_display_timing(blob, timing, data); return 0; } static void fdt_fixup_display_route(void *blob, const struct display_fixup_data *data) { if (data->type == PANEL_TYPE_DSI) { fdt_fixup_display_sub_route(blob, "dsi1", FDT_STATUS_OKAY, data); fdt_fixup_display_sub_route(blob, "edp", FDT_STATUS_DISABLED, data); fdt_fixup_display_sub_route(blob, "lvds", FDT_STATUS_DISABLED, data); } else if (data->type == PANEL_TYPE_EDP) { fdt_fixup_display_sub_route(blob, "dsi1", FDT_STATUS_DISABLED, data); fdt_fixup_display_sub_route(blob, "edp", FDT_STATUS_OKAY, data); fdt_fixup_display_sub_route(blob, "lvds", FDT_STATUS_DISABLED, data); } else if (data->type == PANEL_TYPE_LVDS) { fdt_fixup_display_sub_route(blob, "lvds", FDT_STATUS_OKAY, data); fdt_fixup_display_sub_route(blob, "dsi1", FDT_STATUS_DISABLED, data); fdt_fixup_display_sub_route(blob, "edp", FDT_STATUS_DISABLED, data); } } #ifdef CONFIG_USING_KERNEL_DTB_V2 static int dm_rm_kernel_dev(void) { struct udevice *dev, *rec[10]; u32 uclass[] = { UCLASS_CRYPTO }; int i, j, k; for (i = 0, j = 0; i < ARRAY_SIZE(uclass); i++) { for (uclass_find_first_device(uclass[i], &dev); dev; uclass_find_next_device(&dev)) { if (dev->flags & DM_FLAG_KNRL_DTB) rec[j++] = dev; } for (k = 0; k < j; k++) { device_remove(rec[k], DM_REMOVE_NORMAL); device_unbind(rec[k]); } } return 0; } static int dm_rm_u_boot_dev(void) { struct udevice *dev, *rec[10]; u32 uclass[] = { UCLASS_ETH }; int del = 0; int i, j, k; for (i = 0, j = 0; i < ARRAY_SIZE(uclass); i++) { for (uclass_find_first_device(uclass[i], &dev); dev; uclass_find_next_device(&dev)) { if (dev->flags & DM_FLAG_KNRL_DTB) del = 1; else rec[j++] = dev; } /* remove u-boot dev if there is someone from kernel */ if (del) { for (k = 0; k < j; k++) { device_remove(rec[k], DM_REMOVE_NORMAL); device_unbind(rec[k]); } } } return 0; } #else /* Here, only fixup cru phandle, pmucru is not included */ static int phandles_fixup_cru(const void *fdt) { const char *props[] = { "clocks", "assigned-clocks", "resets"}; struct udevice *dev; struct uclass *uc; const char *comp; u32 id, nclocks; u32 *clocks; int phandle, ncells; int off, offset; int ret, length; int i, j; int first_phandle = -1; phandle = -ENODATA; ncells = -ENODATA; /* fdt points to kernel dtb, getting cru phandle and "#clock-cells" */ for (offset = fdt_next_node(fdt, 0, NULL); offset >= 0; offset = fdt_next_node(fdt, offset, NULL)) { comp = fdt_getprop(fdt, offset, "compatible", NULL); if (!comp) continue; /* Actually, this is not a good method to get cru node */ off = strlen(comp) - strlen("-cru"); if (off > 0 && !strncmp(comp + off, "-cru", 4)) { phandle = fdt_get_phandle(fdt, offset); ncells = fdtdec_get_int(fdt, offset, "#clock-cells", -ENODATA); break; } } if (phandle == -ENODATA || ncells == -ENODATA) return 0; debug("%s: target cru: clock-cells:%d, phandle:0x%x\n", __func__, ncells, fdt32_to_cpu(phandle)); /* Try to fixup all cru phandle from U-Boot dtb nodes */ for (id = 0; id < UCLASS_COUNT; id++) { ret = uclass_get(id, &uc); if (ret) continue; if (list_empty(&uc->dev_head)) continue; list_for_each_entry(dev, &uc->dev_head, uclass_node) { /* Only U-Boot node go further */ if (!dev_read_bool(dev, "u-boot,dm-pre-reloc") && !dev_read_bool(dev, "u-boot,dm-spl")) continue; for (i = 0; i < ARRAY_SIZE(props); i++) { if (!dev_read_prop(dev, props[i], &length)) continue; clocks = malloc(length); if (!clocks) return -ENOMEM; /* Read "props[]" which contains cru phandle */ nclocks = length / sizeof(u32); if (dev_read_u32_array(dev, props[i], clocks, nclocks)) { free(clocks); continue; } /* Fixup with kernel cru phandle */ for (j = 0; j < nclocks; j += (ncells + 1)) { /* * Check: update pmucru phandle with cru * phandle by mistake. */ if (first_phandle == -1) first_phandle = clocks[j]; if (clocks[j] != first_phandle) { debug("WARN: %s: first cru phandle=%d, this=%d\n", dev_read_name(dev), first_phandle, clocks[j]); continue; } clocks[j] = phandle; } /* * Override live dt nodes but not fdt nodes, * because all U-Boot nodes has been imported * to live dt nodes, should use "dev_xxx()". */ dev_write_u32_array(dev, props[i], clocks, nclocks); free(clocks); } } } return 0; } static int phandles_fixup_gpio(const void *fdt, void *ufdt) { struct udevice *dev; struct uclass *uc; const char *prop = "gpios"; const char *comp; char *gpio_name[10]; int gpio_off[10]; int pinctrl; int offset; int i = 0; int n = 0; pinctrl = fdt_path_offset(fdt, "/pinctrl"); if (pinctrl < 0) return 0; memset(gpio_name, 0, sizeof(gpio_name)); for (offset = fdt_first_subnode(fdt, pinctrl); offset >= 0; offset = fdt_next_subnode(fdt, offset)) { /* assume the font nodes are gpio node */ if (++i >= ARRAY_SIZE(gpio_name)) break; comp = fdt_getprop(fdt, offset, "compatible", NULL); if (!comp) continue; if (!strcmp(comp, "rockchip,gpio-bank")) { gpio_name[n] = (char *)fdt_get_name(fdt, offset, NULL); gpio_off[n] = offset; n++; } } if (!gpio_name[0]) return 0; if (uclass_get(UCLASS_KEY, &uc) || list_empty(&uc->dev_head)) return 0; list_for_each_entry(dev, &uc->dev_head, uclass_node) { u32 new_phd, phd_old; char *name; ofnode ofn; if (!dev_read_bool(dev, "u-boot,dm-pre-reloc") && !dev_read_bool(dev, "u-boot,dm-spl")) continue; if (dev_read_u32_array(dev, prop, &phd_old, 1)) continue; ofn = ofnode_get_by_phandle(phd_old); if (!ofnode_valid(ofn)) continue; name = (char *)ofnode_get_name(ofn); if (!name) continue; for (i = 0; i < ARRAY_SIZE(gpio_name); i++) { if (gpio_name[i] && !strcmp(name, gpio_name[i])) { new_phd = fdt_get_phandle(fdt, gpio_off[i]); dev_write_u32_array(dev, prop, &new_phd, 1); break; } } } return 0; } #endif __weak int board_mmc_dm_reinit(struct udevice *dev) { return 0; } static int mmc_dm_reinit(void) { struct udevice *dev; struct uclass *uc; int ret; if (uclass_get(UCLASS_MMC, &uc) || list_empty(&uc->dev_head)) return 0; list_for_each_entry(dev, &uc->dev_head, uclass_node) { ret = board_mmc_dm_reinit(dev); if (ret) return ret; } return 0; } /* Check by property: "/compatible" */ static int dtb_check_ok(void *kfdt, void *ufdt) { const char *compat; int index; /* TODO */ return 1; for (index = 0; compat = fdt_stringlist_get(ufdt, 0, "compatible", index, NULL), compat; index++) { debug("u-compat: %s\n", compat); if (!fdt_node_check_compatible(kfdt, 0, compat)) return 1; } return 0; } int init_kernel_dtb(void) { #ifndef CONFIG_USING_KERNEL_DTB_V2 void *ufdt_blob = (void *)gd->fdt_blob; #endif ulong fdt_addr = 0; int ret = -ENODEV; struct display_fixup_data fix_data; printf("DM: v%d\n", IS_ENABLED(CONFIG_USING_KERNEL_DTB_V2) ? 2 : 1); /* * If memory size <= 128MB, we firstly try to get "fdt_addr1_r". */ if (gd->ram_size <= SZ_128M) fdt_addr = env_get_ulong("fdt_addr1_r", 16, 0); if (!fdt_addr) fdt_addr = env_get_ulong("fdt_addr_r", 16, 0); if (!fdt_addr) { printf("No Found FDT Load Address.\n"); return -ENODEV; } #ifdef CONFIG_EMBED_KERNEL_DTB_ALWAYS printf("Always embed kernel dtb\n"); goto dtb_embed; #endif ret = rockchip_read_dtb_file((void *)fdt_addr); if (!ret) { if (!dtb_check_ok((void *)fdt_addr, (void *)gd->fdt_blob)) { ret = -EINVAL; printf("Kernel dtb mismatch this platform!\n"); } else { goto dtb_okay; } } #ifdef CONFIG_EMBED_KERNEL_DTB #ifdef CONFIG_EMBED_KERNEL_DTB_ALWAYS dtb_embed: #endif if (gd->fdt_blob_kern) { if (!dtb_check_ok((void *)gd->fdt_blob_kern, (void *)gd->fdt_blob)) { printf("Embedded kernel dtb mismatch this platform!\n"); return -EINVAL; } fdt_addr = (ulong)memalign(ARCH_DMA_MINALIGN, fdt_totalsize(gd->fdt_blob_kern)); if (!fdt_addr) return -ENOMEM; /* * Alloc another space for this embed kernel dtb. * Because "fdt_addr_r" *MUST* be the fdt passed to kernel. */ memcpy((void *)fdt_addr, gd->fdt_blob_kern, fdt_totalsize(gd->fdt_blob_kern)); printf("DTB: %s\n", CONFIG_EMBED_KERNEL_DTB_PATH); } else #endif { printf("Failed to get kernel dtb, ret=%d\n", ret); return -ENOENT; } dtb_okay: gd->fdt_blob = (void *)fdt_addr; hotkey_run(HK_FDT); #ifndef CONFIG_USING_KERNEL_DTB_V2 /* * There is a phandle miss match between U-Boot and kernel dtb node, * we fixup it in U-Boot live dt nodes. * * CRU: all nodes. * GPIO: key nodes. */ phandles_fixup_cru((void *)gd->fdt_blob); phandles_fixup_gpio((void *)gd->fdt_blob, (void *)ufdt_blob); #endif if (!get_lcdparam_info_from_custom_partition(&fix_data)) fdt_fixup_display_route((void *)fdt_addr, &fix_data); gd->flags |= GD_FLG_KDTB_READY; gd->of_root_f = gd->of_root; of_live_build((void *)gd->fdt_blob, (struct device_node **)&gd->of_root); dm_scan_fdt((void *)gd->fdt_blob, false); #ifdef CONFIG_USING_KERNEL_DTB_V2 dm_rm_kernel_dev(); dm_rm_u_boot_dev(); #endif /* * There maybe something for the mmc devices to do after kernel dtb * dm setup, eg: regain the clock device binding from kernel dtb. */ mmc_dm_reinit(); /* Reserve 'reserved-memory' */ ret = boot_fdt_add_sysmem_rsv_regions((void *)gd->fdt_blob); if (ret) return ret; return 0; }