summaryrefslogtreecommitdiff
path: root/board
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2026-02-25 08:49:28 -0600
committerTom Rini <[email protected]>2026-02-25 08:49:28 -0600
commit7995bf8dea2d5b3eb7fcb836636f4773924ec35d (patch)
tree69ea31b67d4c407d1156899de7112e5288d0b29c /board
parent78ea226ddb2aa56cd6d8c034ff34df74d210edd5 (diff)
parent336dd39b956e5f7e078da1d2b689415a41484067 (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.c335
-rw-r--r--board/samsung/exynos-mobile/exynos-mobile.env5
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