diff options
| author | Tom Rini <[email protected]> | 2026-02-25 08:49:28 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-02-25 08:49:28 -0600 |
| commit | 7995bf8dea2d5b3eb7fcb836636f4773924ec35d (patch) | |
| tree | 69ea31b67d4c407d1156899de7112e5288d0b29c /board | |
| parent | 78ea226ddb2aa56cd6d8c034ff34df74d210edd5 (diff) | |
| parent | 336dd39b956e5f7e078da1d2b689415a41484067 (diff) | |
Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-samsung
- Assorted platform and video driver updates
Diffstat (limited to 'board')
| -rw-r--r-- | board/samsung/exynos-mobile/exynos-mobile.c | 335 | ||||
| -rw-r--r-- | board/samsung/exynos-mobile/exynos-mobile.env | 5 |
2 files changed, 157 insertions, 183 deletions
diff --git a/board/samsung/exynos-mobile/exynos-mobile.c b/board/samsung/exynos-mobile/exynos-mobile.c index 8ef38816abf..6b2b1523663 100644 --- a/board/samsung/exynos-mobile/exynos-mobile.c +++ b/board/samsung/exynos-mobile/exynos-mobile.c @@ -10,30 +10,33 @@ #include <bootflow.h> #include <ctype.h> #include <dm/ofnode.h> +#include <efi.h> +#include <efi_loader.h> #include <env.h> #include <errno.h> #include <init.h> -#include <limits.h> #include <linux/sizes.h> #include <lmb.h> #include <part.h> #include <stdbool.h> +#include <string.h> DECLARE_GLOBAL_DATA_PTR; #define lmb_alloc(size, addr) \ lmb_alloc_mem(LMB_MEM_ALLOC_ANY, SZ_2M, addr, size, LMB_NONE) -struct exynos_board_info { - const char *name; - const char *chip; - const u64 *const dram_bank_bases; - - char serial[64]; +struct efi_fw_image fw_images[] = { + { + .fw_name = u"UBOOT_BOOT_PARTITION", + .image_index = 1, + }, +}; - int (*const match)(struct exynos_board_info *); - const char *match_model; - const u8 match_max_rev; +struct efi_capsule_update_info update_info = { + .dfu_string = NULL, + .images = fw_images, + .num_images = ARRAY_SIZE(fw_images), }; /* @@ -54,10 +57,6 @@ static struct mm_region exynos_mem_map[CONFIG_NR_DRAM_BANKS + 2] = { struct mm_region *mem_map = exynos_mem_map; -static const u64 exynos7870_common_dram_bank_bases[CONFIG_NR_DRAM_BANKS] = { - 0x40000000, 0x80000000, 0x100000000, -}; - static const char *exynos_prev_bl_get_bootargs(void) { void *prev_bl_fdt_base = (void *)get_prev_bl_fdt_addr(); @@ -89,102 +88,11 @@ static const char *exynos_prev_bl_get_bootargs(void) return bootargs_prop->data; } -static int exynos7870_fdt_match(struct exynos_board_info *board_info) -{ - const char *prev_bl_bootargs; - int val, ret; - - prev_bl_bootargs = exynos_prev_bl_get_bootargs(); - if (!prev_bl_bootargs) - return -1; - - /* - * Read the cmdline property which stores the - * bootloader/firmware version. An example value of the option - * can be: "J600GDXU3ARH5". This can be used to verify the model - * of the device. - */ - ret = cmdline_get_arg(prev_bl_bootargs, "androidboot.bootloader", &val); - if (ret < 0) { - log_err("%s: unable to find property for bootloader version (%d)\n", - __func__, ret); - return -1; - } - - if (strncmp(prev_bl_bootargs + val, board_info->match_model, - strlen(board_info->match_model))) - return -1; - - /* - * Read the cmdline property which stores the hardware revision. - * This is required to allow selecting one of multiple dtbs - * available of a single device, varying in hardware changes in - * different revisions. - */ - ret = cmdline_get_arg(prev_bl_bootargs, "androidboot.revision", &val); - if (ret < 0) - ret = cmdline_get_arg(prev_bl_bootargs, "androidboot.hw_rev", &val); - if (ret < 0) { - log_err("%s: unable to find property for bootloader revision (%d)\n", - __func__, ret); - return -1; - } - - if (strtoul(prev_bl_bootargs + val, NULL, 10) > board_info->match_max_rev) - return -1; - - /* - * Read the cmdline property which stores the serial number. - * Store this in the board info struct. - */ - ret = cmdline_get_arg(prev_bl_bootargs, "androidboot.serialno", &val); - if (ret > 0) - strlcpy(board_info->serial, prev_bl_bootargs + val, ret); - - return 0; -} - -/* - * This array is used for matching the models and revisions with the - * devicetree used by U-Boot. This allows a single U-Boot to work on - * multiple devices. - * - * Entries are kept in lexicographical order of board SoCs, followed by - * board names. - */ -static struct exynos_board_info exynos_board_info_match[] = { - { - /* Samsung Galaxy A2 Core */ - .name = "a2corelte", - .chip = "exynos7870", - .dram_bank_bases = exynos7870_common_dram_bank_bases, - .match = exynos7870_fdt_match, - .match_model = "A260", - .match_max_rev = U8_MAX, - }, { - /* Samsung Galaxy J6 */ - .name = "j6lte", - .chip = "exynos7870", - .dram_bank_bases = exynos7870_common_dram_bank_bases, - .match = exynos7870_fdt_match, - .match_model = "J600", - .match_max_rev = U8_MAX, - }, { - /* Samsung Galaxy J7 Prime */ - .name = "on7xelte", - .chip = "exynos7870", - .dram_bank_bases = exynos7870_common_dram_bank_bases, - .match = exynos7870_fdt_match, - .match_model = "G610", - .match_max_rev = U8_MAX, - }, -}; - -static void exynos_parse_dram_banks(const struct exynos_board_info *board_info, - const void *fdt_base) +static void exynos_parse_dram_banks(const void *fdt_base) { u64 mem_addr, mem_size = 0; - u32 na, ns, i, j; + u32 na, ns, i; + int index = 1; int offset; if (fdt_check_header(fdt_base) < 0) @@ -199,6 +107,9 @@ static void exynos_parse_dram_banks(const struct exynos_board_info *board_info, continue; for (i = 0; ; i++) { + if (index > CONFIG_NR_DRAM_BANKS) + break; + mem_addr = fdtdec_get_addr_size_fixed(fdt_base, offset, "reg", i, na, ns, &mem_size, false); @@ -208,19 +119,132 @@ static void exynos_parse_dram_banks(const struct exynos_board_info *board_info, if (!mem_size) continue; - for (j = 0; j < CONFIG_NR_DRAM_BANKS; j++) { - if (board_info->dram_bank_bases[j] != mem_addr) - continue; + mem_map[index].phys = mem_addr; + mem_map[index].virt = mem_addr; + mem_map[index].size = mem_size; + mem_map[index].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE; + index++; + } + } +} - mem_map[j + 1].phys = mem_addr; - mem_map[j + 1].virt = mem_addr; - mem_map[j + 1].size = mem_size; - mem_map[j + 1].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | - PTE_BLOCK_INNER_SHARE; - break; - } +static void exynos_env_setup(void) +{ + const char *bootargs = exynos_prev_bl_get_bootargs(); + const char *dev_compatible, *soc_compatible; + char *ptr; + char buf[128]; + int nr_compatibles; + int offset; + int ret; + + if (bootargs) { + /* Read the cmdline property which stores the serial number. */ + ret = cmdline_get_arg(bootargs, "androidboot.serialno", &offset); + if (ret > 0) { + strlcpy(buf, bootargs + offset, ret); + env_set("serial#", buf); + } + } + + nr_compatibles = ofnode_read_string_count(ofnode_root(), "compatible"); + if (nr_compatibles < 2) { + log_warning("%s: expected 2 or more compatible strings\n", + __func__); + return; + } + + ret = ofnode_read_string_index(ofnode_root(), "compatible", + nr_compatibles - 1, &soc_compatible); + if (ret) { + log_warning("%s: failed to read SoC compatible\n", + __func__); + return; + } + + ret = ofnode_read_string_index(ofnode_root(), "compatible", 0, + &dev_compatible); + if (ret) { + log_warning("%s: failed to read device compatible\n", + __func__); + return; + } + + /* <manufacturer>,<soc> => platform = <soc> */ + ptr = strchr(soc_compatible, ','); + if (ptr) + soc_compatible = ptr + 1; + env_set("platform", soc_compatible); + + /* <manufacturer>,<codename> => board = <manufacturer>-<codename> */ + strlcpy(buf, dev_compatible, sizeof(buf) - 1); + ptr = strchr(buf, ','); + if (ptr) + *ptr = '-'; + env_set("board", buf); + + /* + * NOTE: Board name usually goes as <manufacturer>-<codename>, but + * upstream device trees for Exynos SoCs are <soc>-<codename>. + * Extraction of <codename> from the board name is required. + */ + ptr = strchr(dev_compatible, ','); + if (ptr) + dev_compatible = ptr + 1; + + /* EFI booting requires the path to correct DTB, specify it here. */ + snprintf(buf, sizeof(buf), "exynos/%s-%s.dtb", soc_compatible, + dev_compatible); + env_set("fdtfile", buf); +} + +static int exynos_blk_env_setup(void) +{ + const char *blk_ifname; + int blk_dev = 0; + struct blk_desc *blk_desc; + struct disk_partition info = {0}; + unsigned long largest_part_start = 0, largest_part_size = 0; + static char dfu_string[32]; + int i; + + blk_ifname = "mmc"; + blk_desc = blk_get_dev(blk_ifname, blk_dev); + if (!blk_desc) { + log_err("%s: required mmc device not available\n", __func__); + return -ENODEV; + } + + for (i = 1; i < CONFIG_EFI_PARTITION_ENTRIES_NUMBERS; i++) { + if (part_get_info(blk_desc, i, &info)) + continue; + + if (!update_info.dfu_string && + !strncasecmp(info.name, "boot", strlen("boot"))) { + snprintf(dfu_string, sizeof(dfu_string), + "mmc %d=u-boot.bin part %d %d", blk_dev, + blk_dev, i); + update_info.dfu_string = dfu_string; + } + + if (info.start > largest_part_size) { + largest_part_start = info.start; + largest_part_size = info.size; } } + + if (largest_part_size) { + env_set("blkmap_blk_ifname", blk_ifname); + env_set_ulong("blkmap_blk_dev", blk_dev); + env_set_ulong("blkmap_blk_nr", largest_part_start); + env_set_hex("blkmap_size_r", largest_part_size); + } else { + log_warning("%s: no qualified partition for blkmap, skipping\n", + __func__); + } + + return 0; } static int exynos_fastboot_setup(void) @@ -270,42 +294,11 @@ static int exynos_fastboot_setup(void) return 0; } -int board_fit_config_name_match(const char *name) +int board_fdt_blob_setup(void **fdtp) { - struct exynos_board_info *board_info; - char buf[128]; - unsigned int i; - int ret; - - /* - * Iterate over exynos_board_info_match[] to select the - * appropriate board info struct. If not found, exit. - */ - for (i = 0; i < ARRAY_SIZE(exynos_board_info_match); i++) { - board_info = exynos_board_info_match + i; - snprintf(buf, sizeof(buf), "%s-%s", board_info->chip, - board_info->name); - - if (!strcmp(name, buf)) - break; - } - if (i == ARRAY_SIZE(exynos_board_info_match)) - return -1; - - /* - * Execute match logic for the target board. This is separated - * as the process may be different for multiple boards. - */ - ret = board_info->match(board_info); - if (ret) - return ret; - - /* - * Store the correct board info struct in gd->board_type to - * allow other functions to access it. - */ - gd->board_type = (ulong)board_info; - log_debug("%s: device detected: %s\n", __func__, name); + /* If internal FDT is not available, use the external FDT instead. */ + if (fdt_check_header(*fdtp)) + *fdtp = (void *)get_prev_bl_fdt_addr(); return 0; } @@ -328,21 +321,7 @@ int timer_init(void) int board_early_init_f(void) { - const struct exynos_board_info *board_info; - - if (!gd->board_type) - return -ENODATA; - board_info = (const struct exynos_board_info *)gd->board_type; - - exynos_parse_dram_banks(board_info, gd->fdt_blob); - /* - * Some devices have multiple variants based on the amount of - * memory and internal storage. The lowest bank base has been - * observed to have the same memory range in all board variants. - * For variants with more memory, the previous bootloader should - * overlay the devicetree with the required extra memory ranges. - */ - exynos_parse_dram_banks(board_info, (const void *)get_prev_bl_fdt_addr()); + exynos_parse_dram_banks(gd->fdt_blob); return 0; } @@ -381,23 +360,13 @@ int board_init(void) int misc_init_r(void) { - const struct exynos_board_info *board_info; - char buf[128]; - - if (!gd->board_type) - return -ENODATA; - board_info = (const struct exynos_board_info *)gd->board_type; - - env_set("platform", board_info->chip); - env_set("board", board_info->name); + int ret; - if (strlen(board_info->serial)) - env_set("serial#", board_info->serial); + exynos_env_setup(); - /* EFI booting requires the path to correct dtb, specify it here. */ - snprintf(buf, sizeof(buf), "exynos/%s-%s.dtb", board_info->chip, - board_info->name); - env_set("fdtfile", buf); + ret = exynos_blk_env_setup(); + if (ret) + return ret; return exynos_fastboot_setup(); } diff --git a/board/samsung/exynos-mobile/exynos-mobile.env b/board/samsung/exynos-mobile/exynos-mobile.env index aa2e89afbac..33f767319b5 100644 --- a/board/samsung/exynos-mobile/exynos-mobile.env +++ b/board/samsung/exynos-mobile/exynos-mobile.env @@ -2,6 +2,11 @@ stdin=serial,button-kbd stdout=serial,vidconsole stderr=serial,vidconsole +blkmapcmd=blkmap create root; + blkmap map root 0 ${blkmap_size_r} linear ${blkmap_blk_ifname} ${blkmap_blk_dev} ${blkmap_blk_nr} + +preboot=run blkmapcmd + bootdelay=0 bootcmd=bootefi bootmgr; pause; bootmenu |
