From 1ad133066494c9875abb5e88ba9f6ef8322b1dde Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Mon, 26 Jan 2026 16:23:43 +0530 Subject: [PATCH 01/21] ARM: dts: add dtsi for exynos7870-a2corelte (Samsung Galaxy A2 Core) Add a framebuffer node to the DTSI in order to ensure that display continues to work, as since v6.19 of devicetree-rebasing sources, it uses Samsung's DECON (Display Enhancement CONtroller) for display, which is, as of yet, not supported in U-Boot. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- arch/arm/dts/exynos7870-a2corelte-u-boot.dtsi | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 arch/arm/dts/exynos7870-a2corelte-u-boot.dtsi diff --git a/arch/arm/dts/exynos7870-a2corelte-u-boot.dtsi b/arch/arm/dts/exynos7870-a2corelte-u-boot.dtsi new file mode 100644 index 00000000000..c22ed7efea5 --- /dev/null +++ b/arch/arm/dts/exynos7870-a2corelte-u-boot.dtsi @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2026 Kaustabh Chakraborty + */ + +/ { + chosen { + #address-cells = <2>; + #size-cells = <1>; + ranges; + + framebuffer@67000000 { + compatible = "simple-framebuffer"; + reg = <0x0 0x67000000 (540 * 960 * 4)>; + width = <540>; + height = <960>; + stride = <(540 * 4)>; + format = "a8r8g8b8"; + }; + }; +}; From 5689cc9c6fb590d5d62e6b137fab4179cd7a1beb Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Mon, 26 Jan 2026 16:23:44 +0530 Subject: [PATCH 02/21] ARM: dts: add dtsi for exynos7870-j6lte (Samsung Galaxy J6) Add a framebuffer node to the DTSI in order to ensure that display continues to work, as since v6.19 of devicetree-rebasing sources, it uses Samsung's DECON (Display Enhancement CONtroller) for display, which is, as of yet, not supported in U-Boot. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- arch/arm/dts/exynos7870-j6lte-u-boot.dtsi | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 arch/arm/dts/exynos7870-j6lte-u-boot.dtsi diff --git a/arch/arm/dts/exynos7870-j6lte-u-boot.dtsi b/arch/arm/dts/exynos7870-j6lte-u-boot.dtsi new file mode 100644 index 00000000000..9d944b127ee --- /dev/null +++ b/arch/arm/dts/exynos7870-j6lte-u-boot.dtsi @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Kaustabh Chakraborty + */ + +/ { + chosen { + #address-cells = <2>; + #size-cells = <1>; + ranges; + + framebuffer@67000000 { + compatible = "simple-framebuffer"; + reg = <0x0 0x67000000 (720 * 1480 * 4)>; + width = <720>; + height = <1480>; + stride = <(720 * 4)>; + format = "a8r8g8b8"; + }; + }; +}; From 3f2ab427c13e4883cb5dddb4c54d3cedc0f93669 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Mon, 26 Jan 2026 16:23:45 +0530 Subject: [PATCH 03/21] ARM: dts: add dtsi for exynos7870-on7xelte (Samsung Galaxy J7 Prime) Add a framebuffer node to the DTSI in order to ensure that display continues to work, as since v6.19 of devicetree-rebasing sources, it uses Samsung's DECON (Display Enhancement CONtroller) for display, which is, as of yet, not supported in U-Boot. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- arch/arm/dts/exynos7870-on7xelte-u-boot.dtsi | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 arch/arm/dts/exynos7870-on7xelte-u-boot.dtsi diff --git a/arch/arm/dts/exynos7870-on7xelte-u-boot.dtsi b/arch/arm/dts/exynos7870-on7xelte-u-boot.dtsi new file mode 100644 index 00000000000..c7bd7103e70 --- /dev/null +++ b/arch/arm/dts/exynos7870-on7xelte-u-boot.dtsi @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2026 Kaustabh Chakraborty + */ + +/ { + chosen { + #address-cells = <2>; + #size-cells = <1>; + ranges; + + framebuffer@67000000 { + compatible = "simple-framebuffer"; + reg = <0x0 0x67000000 (1080 * 1920 * 4)>; + width = <1080>; + height = <1920>; + stride = <(1080 * 4)>; + format = "a8r8g8b8"; + }; + }; +}; From de6b405e615232817322416b89bcde637ade40d4 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Tue, 30 Sep 2025 17:43:46 +0100 Subject: [PATCH 04/21] video: exynos: node variable should not be unsigned THe variable 'node' is assigned a value of an int, tested for being less than or equal to zero then passed as an argument to a function that takes an int so 'node' should not be unsigned. Fix it. This issue was found by Smatch. Signed-off-by: Andrew Goodbody --- drivers/video/exynos/exynos_fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/exynos/exynos_fb.c b/drivers/video/exynos/exynos_fb.c index 0407a3f51b0..1cc1bd92e57 100644 --- a/drivers/video/exynos/exynos_fb.c +++ b/drivers/video/exynos/exynos_fb.c @@ -350,7 +350,7 @@ void exynos_fimd_window_off(struct exynos_fb_priv *priv, unsigned int win_id) void exynos_fimd_disable_sysmmu(void) { u32 *sysmmufimd; - unsigned int node; + int node; int node_list[2]; int count; int i; From 548e9a254c7d0bd9796decfea43d7759070c7312 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Wed, 1 Oct 2025 11:05:10 +0100 Subject: [PATCH 05/21] video: nexell: unsigned parameter cannot be negative The parameter 'alpha' is declared as an unsigned type so cannot be negative. The code to test it as being less than zero will always fail and so is redundant and should be removed. This issue was found by Smatch. Signed-off-by: Andrew Goodbody Reviewed-by: Stefan Bosch Signed-off-by: Minkyu Kang --- drivers/video/nexell/soc/s5pxx18_soc_mlc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/video/nexell/soc/s5pxx18_soc_mlc.c b/drivers/video/nexell/soc/s5pxx18_soc_mlc.c index c8cf833f308..2c8348bf633 100644 --- a/drivers/video/nexell/soc/s5pxx18_soc_mlc.c +++ b/drivers/video/nexell/soc/s5pxx18_soc_mlc.c @@ -1641,8 +1641,6 @@ void nx_mlc_set_layer_alpha256(u32 module_index, u32 layer, u32 alpha) u32 register_data; register struct nx_mlc_register_set *pregister; - if (alpha < 0) - alpha = 0; if (alpha > 255) alpha = 255; From 3b9f3620b8a26b8b2d580371eefd140791d124e4 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 3 Feb 2026 18:38:39 +0530 Subject: [PATCH 06/21] board: samsung: exynos-mobile: simplify parsing RAM banks from device tree Remove the baked-in bank addresses used for figuring out RAM banks from device tree. Instead, sequentially fill in the bank addresses and sizes, and doing away with an extra array for specifying bases. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- board/samsung/exynos-mobile/exynos-mobile.c | 38 ++++++++------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/board/samsung/exynos-mobile/exynos-mobile.c b/board/samsung/exynos-mobile/exynos-mobile.c index 8ef38816abf..915bda64082 100644 --- a/board/samsung/exynos-mobile/exynos-mobile.c +++ b/board/samsung/exynos-mobile/exynos-mobile.c @@ -27,7 +27,6 @@ DECLARE_GLOBAL_DATA_PTR; struct exynos_board_info { const char *name; const char *chip; - const u64 *const dram_bank_bases; char serial[64]; @@ -54,10 +53,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(); @@ -157,7 +152,6 @@ 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, @@ -165,7 +159,6 @@ static struct exynos_board_info exynos_board_info_match[] = { /* 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, @@ -173,18 +166,17 @@ static struct exynos_board_info exynos_board_info_match[] = { /* 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 +191,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,17 +203,12 @@ 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[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; - } + 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++; } } } @@ -334,7 +324,7 @@ int board_early_init_f(void) return -ENODATA; board_info = (const struct exynos_board_info *)gd->board_type; - exynos_parse_dram_banks(board_info, gd->fdt_blob); + exynos_parse_dram_banks(gd->fdt_blob); /* * Some devices have multiple variants based on the amount of * memory and internal storage. The lowest bank base has been @@ -342,7 +332,7 @@ int board_early_init_f(void) * 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((const void *)get_prev_bl_fdt_addr()); return 0; } From 23ad0660c11b72a9f720362c801e2e47e9ecd4dc Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 3 Feb 2026 18:38:40 +0530 Subject: [PATCH 07/21] board: samsung: exynos-mobile: resolve env vars without board_info data Move environment variable setup procedure to exynos_env_setup(). This function is independent of data from exynos_board_info as it is due for removal in the succeding commits. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- board/samsung/exynos-mobile/exynos-mobile.c | 89 +++++++++++++++++---- 1 file changed, 72 insertions(+), 17 deletions(-) diff --git a/board/samsung/exynos-mobile/exynos-mobile.c b/board/samsung/exynos-mobile/exynos-mobile.c index 915bda64082..c17d7052b1c 100644 --- a/board/samsung/exynos-mobile/exynos-mobile.c +++ b/board/samsung/exynos-mobile/exynos-mobile.c @@ -18,6 +18,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -213,6 +214,76 @@ static void exynos_parse_dram_banks(const void *fdt_base) } } +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; + } + + /* , => platform = */ + ptr = strchr(soc_compatible, ','); + if (ptr) + soc_compatible = ptr + 1; + env_set("platform", soc_compatible); + + /* , => board = - */ + strlcpy(buf, dev_compatible, sizeof(buf) - 1); + ptr = strchr(buf, ','); + if (ptr) + *ptr = '-'; + env_set("board", buf); + + /* + * NOTE: Board name usually goes as -, but + * upstream device trees for Exynos SoCs are -. + * Extraction of 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_fastboot_setup(void) { struct blk_desc *blk_dev; @@ -371,23 +442,7 @@ 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); - - if (strlen(board_info->serial)) - env_set("serial#", board_info->serial); - - /* 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); + exynos_env_setup(); return exynos_fastboot_setup(); } From 6220037e7c1bb2086f862bc031b2bfd14009d865 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 3 Feb 2026 18:38:41 +0530 Subject: [PATCH 08/21] board: samsung: exynos-mobile: disable MULTI_DTB_FIT support MULTI_DTB_FIT allowed a single U-Boot image to be booted in multiple devices, but it was not a scalable solution; as more devices are added, the U-Boot binary is bound to increase, space taken up by devicetrees which are not even used. The other approach is to be able to build separate images for multiple devices using the same "board" defined in U-Boot. This is used by qcom_phone to support muitiple devices. Follow the said approach for Exynos devices as well, disable MULTI_DTB_FIT for this board. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- board/samsung/exynos-mobile/exynos-mobile.c | 154 -------------------- configs/exynos-mobile_defconfig | 2 - 2 files changed, 156 deletions(-) diff --git a/board/samsung/exynos-mobile/exynos-mobile.c b/board/samsung/exynos-mobile/exynos-mobile.c index c17d7052b1c..412dfa7555c 100644 --- a/board/samsung/exynos-mobile/exynos-mobile.c +++ b/board/samsung/exynos-mobile/exynos-mobile.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -25,17 +24,6 @@ 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; - - char serial[64]; - - int (*const match)(struct exynos_board_info *); - const char *match_model; - const u8 match_max_rev; -}; - /* * The memory mapping includes all DRAM banks, along with the * peripheral block, and a sentinel at the end. This is filled in @@ -85,94 +73,6 @@ 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", - .match = exynos7870_fdt_match, - .match_model = "A260", - .match_max_rev = U8_MAX, - }, { - /* Samsung Galaxy J6 */ - .name = "j6lte", - .chip = "exynos7870", - .match = exynos7870_fdt_match, - .match_model = "J600", - .match_max_rev = U8_MAX, - }, { - /* Samsung Galaxy J7 Prime */ - .name = "on7xelte", - .chip = "exynos7870", - .match = exynos7870_fdt_match, - .match_model = "G610", - .match_max_rev = U8_MAX, - }, -}; - static void exynos_parse_dram_banks(const void *fdt_base) { u64 mem_addr, mem_size = 0; @@ -331,46 +231,6 @@ static int exynos_fastboot_setup(void) return 0; } -int board_fit_config_name_match(const char *name) -{ - 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); - - return 0; -} - int timer_init(void) { ofnode timer_node; @@ -389,21 +249,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(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((const void *)get_prev_bl_fdt_addr()); return 0; } diff --git a/configs/exynos-mobile_defconfig b/configs/exynos-mobile_defconfig index 3a0b455b169..ead4ea4493e 100644 --- a/configs/exynos-mobile_defconfig +++ b/configs/exynos-mobile_defconfig @@ -25,8 +25,6 @@ CONFIG_CMD_POWEROFF=y CONFIG_CMD_FS_GENERIC=y CONFIG_EFI_PARTITION=y CONFIG_OF_UPSTREAM=y -CONFIG_OF_LIST="exynos/exynos7870-a2corelte exynos/exynos7870-j6lte exynos/exynos7870-on7xelte" -CONFIG_MULTI_DTB_FIT=y CONFIG_BUTTON=y CONFIG_BUTTON_REMAP_PHONE_KEYS=y CONFIG_CLK_EXYNOS7870=y From e215c1a558f0c01cdefd9cf90b190bb220c058b6 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 3 Feb 2026 18:38:42 +0530 Subject: [PATCH 09/21] board: samsung: exynos-mobile: enable OF_BOARD support OF_BOARD allows to choose the internal device tree in runtime. Use it to pass the external FDT as an internal one if it is not present. This approach is also used by qcom-phone, and it reduces boot image size. It is expected that an external FDT is present as U-Boot is packaged as an Android boot image. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- board/samsung/exynos-mobile/exynos-mobile.c | 9 +++++++++ configs/exynos-mobile_defconfig | 1 + 2 files changed, 10 insertions(+) diff --git a/board/samsung/exynos-mobile/exynos-mobile.c b/board/samsung/exynos-mobile/exynos-mobile.c index 412dfa7555c..1f61f28de5f 100644 --- a/board/samsung/exynos-mobile/exynos-mobile.c +++ b/board/samsung/exynos-mobile/exynos-mobile.c @@ -231,6 +231,15 @@ static int exynos_fastboot_setup(void) return 0; } +int board_fdt_blob_setup(void **fdtp) +{ + /* 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; +} + int timer_init(void) { ofnode timer_node; diff --git a/configs/exynos-mobile_defconfig b/configs/exynos-mobile_defconfig index ead4ea4493e..846f9e24bd3 100644 --- a/configs/exynos-mobile_defconfig +++ b/configs/exynos-mobile_defconfig @@ -25,6 +25,7 @@ CONFIG_CMD_POWEROFF=y CONFIG_CMD_FS_GENERIC=y CONFIG_EFI_PARTITION=y CONFIG_OF_UPSTREAM=y +CONFIG_OF_BOARD=y CONFIG_BUTTON=y CONFIG_BUTTON_REMAP_PHONE_KEYS=y CONFIG_CLK_EXYNOS7870=y From 743b91bab77ee5cb1dbc47f8d1f1245be9f01823 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 3 Feb 2026 18:38:43 +0530 Subject: [PATCH 10/21] configs: exynos-mobile: remove DEFAULT_DEVICE_TREE and add OF_UPSTREAM_BUILD_VENDOR Since the build documentation recommends using the DEVICE_TREE= make flag, and the "board" supports multiple devices, remove the default device tree option so as to enforce the make flag during build. OF_UPSTREAM_BUILD_VENDOR is added so as to build all device trees associated with the vendor with their U-Boot includes. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- configs/exynos-mobile_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/exynos-mobile_defconfig b/configs/exynos-mobile_defconfig index 846f9e24bd3..c7d206f94ac 100644 --- a/configs/exynos-mobile_defconfig +++ b/configs/exynos-mobile_defconfig @@ -7,7 +7,6 @@ CONFIG_SYS_MALLOC_LEN=0x2000000 CONFIG_SYS_MALLOC_F_LEN=0x16000 CONFIG_TARGET_EXYNOS_MOBILE=y CONFIG_NR_DRAM_BANKS=3 -CONFIG_DEFAULT_DEVICE_TREE="exynos/exynos7870-a2corelte" CONFIG_SYS_BOOTM_LEN=0x2000000 CONFIG_SYS_LOAD_ADDR=0x80000000 CONFIG_ARMV8_CNTFRQ_BROKEN=y @@ -26,6 +25,7 @@ CONFIG_CMD_FS_GENERIC=y CONFIG_EFI_PARTITION=y CONFIG_OF_UPSTREAM=y CONFIG_OF_BOARD=y +CONFIG_OF_UPSTREAM_BUILD_VENDOR=y CONFIG_BUTTON=y CONFIG_BUTTON_REMAP_PHONE_KEYS=y CONFIG_CLK_EXYNOS7870=y From ac93c4534fab65e2cb9ee18164c98d247eea844f Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 3 Feb 2026 18:38:44 +0530 Subject: [PATCH 11/21] doc: board: samsung: exynos-mobile: add DEVICE_TREE make flag in build Since there is only one internal device tree allowed in U-Boot, the DEVICE_TREE flag is required for building images for various devices. Document it in the build guide. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- doc/board/samsung/exynos-mobile.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/board/samsung/exynos-mobile.rst b/doc/board/samsung/exynos-mobile.rst index 37718af1fea..d0173b1f8cb 100644 --- a/doc/board/samsung/exynos-mobile.rst +++ b/doc/board/samsung/exynos-mobile.rst @@ -25,12 +25,13 @@ If a cross-compiler is required, install it and set it up like so: export CROSS_COMPILE=aarch64-linux-gnu- -Then, run the following commands to build U-Boot: +Then, run the following commands to build U-Boot (replace ```` with the +upstream DTB path for the target device): .. prompt:: bash $ make O=.output exynos-mobile_defconfig - make O=.output -j$(nproc) + make DEVICE_TREE= O=.output -j$(nproc) If successful, the U-Boot binary will be present in ``.output/u-boot.bin``. From be1b1cd641f058a19d2ec5e1ab3bb4d81a3e1e78 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 3 Feb 2026 18:38:45 +0530 Subject: [PATCH 12/21] doc: board: samsung: exynos-mobile: use u-boot-nodtb.bin for packaging process U-Boot for this board is programmed to use the external DTB if an internal device tree is not available. This makes it safe to build boot images using the non-DTB U-Boot binary, while taking up less space. Reflect this change in documentation. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- doc/board/samsung/exynos-mobile/exynos7870.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/board/samsung/exynos-mobile/exynos7870.rst b/doc/board/samsung/exynos-mobile/exynos7870.rst index bbd857580b8..37562e272b4 100644 --- a/doc/board/samsung/exynos-mobile/exynos7870.rst +++ b/doc/board/samsung/exynos-mobile/exynos7870.rst @@ -53,7 +53,7 @@ Finally, use ``mkbootimg`` by osm0sis [3]_ to generate the boot image: .. prompt:: bash $ mkbootimg -o u-boot.img \ - --kernel .output/u-boot.bin \ + --kernel .output/u-boot-nodtb.bin \ --dt stub-dt.img Offsets are not provided to ``mkbootimg`` as S-BOOT ignores them. From 579349593a8444166e6e7d1d65326c4b56ab104b Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 3 Feb 2026 18:38:46 +0530 Subject: [PATCH 13/21] ARM: dts: exynos7870-a2corelte: add properties to make S-BOOT happy Add properties in the DTSI file which is required for S-BOOT when used an external device tree when booting into U-Boot. S-BOOT is Samsung's proprietary bootloader, which chainloads U-Boot. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- arch/arm/dts/exynos7870-a2corelte-u-boot.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/dts/exynos7870-a2corelte-u-boot.dtsi b/arch/arm/dts/exynos7870-a2corelte-u-boot.dtsi index c22ed7efea5..7d97afcc64f 100644 --- a/arch/arm/dts/exynos7870-a2corelte-u-boot.dtsi +++ b/arch/arm/dts/exynos7870-a2corelte-u-boot.dtsi @@ -4,6 +4,11 @@ */ / { + /* These properties are required by S-BOOT. */ + model_info-chip = <7870>; + model_info-hw_rev = <0>; + model_info-hw_rev_end = <255>; + chosen { #address-cells = <2>; #size-cells = <1>; From cc77806b5d3d8f88d2d9e914fcb8224c0ef192fb Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 3 Feb 2026 18:38:47 +0530 Subject: [PATCH 14/21] ARM: dts: exynos7870-j6lte: add properties to make S-BOOT happy Add properties in the DTSI file which is required for S-BOOT when used an external device tree when booting into U-Boot. S-BOOT is Samsung's proprietary bootloader, which chainloads U-Boot. Since this device has multiple bank nodes, add memory nodes for each RAM bank. This is the format S-BOOT recognizes, and (re)populates it with the correct bank sizes. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- arch/arm/dts/exynos7870-j6lte-u-boot.dtsi | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm/dts/exynos7870-j6lte-u-boot.dtsi b/arch/arm/dts/exynos7870-j6lte-u-boot.dtsi index 9d944b127ee..aa499ecf479 100644 --- a/arch/arm/dts/exynos7870-j6lte-u-boot.dtsi +++ b/arch/arm/dts/exynos7870-j6lte-u-boot.dtsi @@ -4,6 +4,11 @@ */ / { + /* These properties are required by S-BOOT. */ + model_info-chip = <7870>; + model_info-hw_rev = <0>; + model_info-hw_rev_end = <255>; + chosen { #address-cells = <2>; #size-cells = <1>; @@ -18,4 +23,24 @@ format = "a8r8g8b8"; }; }; + + /* + * S-BOOT will populate the memory nodes stated below. Existing + * values redefine the safe memory requirements as stated in upstream + * device tree, in separate nodes for each bank. + */ + memory@40000000 { + device_type = "memory"; + reg = <0x0 0x40000000 0x3d800000>; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x40000000>; + }; + + memory@100000000 { + device_type = "memory"; + reg = <0x1 0x00000000 0x00000000>; + }; }; From d73efc6841c892c8dd06711aac97ac3de503bda8 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 3 Feb 2026 18:38:48 +0530 Subject: [PATCH 15/21] ARM: dts: exynos7870-on7xelte: add properties to make S-BOOT happy Add properties in the DTSI file which is required for S-BOOT when used an external device tree when booting into U-Boot. S-BOOT is Samsung's proprietary bootloader, which chainloads U-Boot. Since this device has multiple bank nodes, add memory nodes for each RAM bank. This is the format S-BOOT recognizes, and (re)populates it with the correct bank sizes. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- arch/arm/dts/exynos7870-on7xelte-u-boot.dtsi | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm/dts/exynos7870-on7xelte-u-boot.dtsi b/arch/arm/dts/exynos7870-on7xelte-u-boot.dtsi index c7bd7103e70..01c3e95b0b3 100644 --- a/arch/arm/dts/exynos7870-on7xelte-u-boot.dtsi +++ b/arch/arm/dts/exynos7870-on7xelte-u-boot.dtsi @@ -4,6 +4,11 @@ */ / { + /* These properties are required by S-BOOT. */ + model_info-chip = <7870>; + model_info-hw_rev = <0>; + model_info-hw_rev_end = <255>; + chosen { #address-cells = <2>; #size-cells = <1>; @@ -18,4 +23,19 @@ format = "a8r8g8b8"; }; }; + + /* + * S-BOOT will populate the memory nodes stated below. Existing + * values redefine the safe memory requirements as stated in upstream + * device tree, in separate nodes for each bank. + */ + memory@40000000 { + device_type = "memory"; + reg = <0x0 0x40000000 0x3e400000>; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x80000000>; + }; }; From 11198fa347390eb449c2a0939f5f00cf510fe285 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 3 Feb 2026 18:38:49 +0530 Subject: [PATCH 16/21] doc: board: samsung: exynos-mobile: remove requirement of stub device tree Flashing U-Boot for Exynos 7870 requires creating a stub device tree, where certain properties and nodes are defined which are populated by the previous bootloader in the phones. Since these properties are now available in the U-Boot device tree, it's now possible to use the same blob generated by U-Boot in place of the stub, when creating boot images. Update the build documentation to reflect the same. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- .../samsung/exynos-mobile/exynos7870.rst | 40 ++----------------- 1 file changed, 3 insertions(+), 37 deletions(-) diff --git a/doc/board/samsung/exynos-mobile/exynos7870.rst b/doc/board/samsung/exynos-mobile/exynos7870.rst index 37562e272b4..702b21244eb 100644 --- a/doc/board/samsung/exynos-mobile/exynos7870.rst +++ b/doc/board/samsung/exynos-mobile/exynos7870.rst @@ -6,47 +6,13 @@ Samsung Exynos 7870 Boards Preparation ----------- -Create the following device tree (named ``stub.dts``) -.. code-block:: devicetree - - /dts-v1/; - - / { - compatible = "samsung,exynos7870"; - #address-cells = <2>; - #size-cells = <1>; - - model_info-chip = <7870>; - model_info-hw_rev = <0>; - model_info-hw_rev_end = <255>; - - chosen { - }; - - memory@80000000 { - device_type = "memory"; - reg = <0x0 0x80000000 0x0>; - }; - - memory@100000000 { - device_type = "memory"; - reg = <0x1 0x00000000 0x0>; - }; - }; - -The chosen node and memory ranges are populated by S-BOOT. A certain device -model may have multiple variants, with differing amounts of RAM and storage. The -RAM capacity information is graciously provided by S-BOOT's device tree -overlays. - -Compile it to a device tree blob, then pack it in the QCDT format [1]_ using -``dtbTool-exynos`` [2]_ by issuing the following commands: +Pack the device tree blob in the QCDT format [1]_ using ``dtbTool-exynos`` [2]_ +by issuing the following commands: .. prompt:: bash $ - dtc -I dts -O dtb -o stub.dtb stub.dts - dtbTool-exynos -o stub-dt.img stub.dtb + dtbTool-exynos -o stub-dt.img .output/u-boot.dtb Finally, use ``mkbootimg`` by osm0sis [3]_ to generate the boot image: From ae1e081f83fb4b4d79e32f1bdcea3e47519ce05c Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Mon, 23 Feb 2026 19:55:23 +0530 Subject: [PATCH 17/21] phy: samsung: add enum for variants based on SoCs The variant enum is used to uniquely identify which SoC the PHY block belongs to. It is initially set in the match table, along with the compatible string, it gets copied to driver data struct during probe. SoC specific functions must only be called if the respective variant enum is set. Add switch-case blocks wherever required. Reviewed-by: Mattijs Korpershoek Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- drivers/phy/phy-exynos-usbdrd.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/phy/phy-exynos-usbdrd.c b/drivers/phy/phy-exynos-usbdrd.c index db5815ed184..4ab8da2a08f 100644 --- a/drivers/phy/phy-exynos-usbdrd.c +++ b/drivers/phy/phy-exynos-usbdrd.c @@ -66,6 +66,10 @@ #define KHZ 1000 #define MHZ (KHZ * KHZ) +enum exynos_usbdrd_phy_variant { + EXYNOS850_USBDRD_PHY, +}; + /** * struct exynos_usbdrd_phy - driver data for Exynos USB PHY * @reg_phy: USB PHY controller register memory base @@ -73,6 +77,7 @@ * @core_clk: core clock for phy (ref clock) * @reg_pmu: regmap for PMU block * @extrefclk: frequency select settings when using 'separate reference clocks' + * @variant: ID to uniquely distinguish USB PHY variant */ struct exynos_usbdrd_phy { void __iomem *reg_phy; @@ -80,6 +85,7 @@ struct exynos_usbdrd_phy { struct clk *core_clk; struct regmap *reg_pmu; u32 extrefclk; + enum exynos_usbdrd_phy_variant variant; }; static void exynos_usbdrd_phy_isol(struct regmap *reg_pmu, bool isolate) @@ -254,7 +260,13 @@ static int exynos_usbdrd_phy_init(struct phy *phy) if (ret) return ret; - exynos850_usbdrd_utmi_init(phy); + switch (phy_drd->variant) { + case EXYNOS850_USBDRD_PHY: + exynos850_usbdrd_utmi_init(phy); + break; + default: + dev_err(phy->dev, "Failed to recognize phy variant\n"); + } clk_disable_unprepare(phy_drd->clk); @@ -270,7 +282,13 @@ static int exynos_usbdrd_phy_exit(struct phy *phy) if (ret) return ret; - exynos850_usbdrd_utmi_exit(phy); + switch (phy_drd->variant) { + case EXYNOS850_USBDRD_PHY: + exynos850_usbdrd_utmi_exit(phy); + break; + default: + dev_err(phy->dev, "Failed to recognize phy variant\n"); + } clk_disable_unprepare(phy_drd->clk); @@ -359,6 +377,8 @@ static int exynos_usbdrd_phy_probe(struct udevice *dev) return err; } + phy_drd->variant = dev_get_driver_data(dev); + return 0; } @@ -372,6 +392,7 @@ static const struct phy_ops exynos_usbdrd_phy_ops = { static const struct udevice_id exynos_usbdrd_phy_of_match[] = { { .compatible = "samsung,exynos850-usbdrd-phy", + .data = EXYNOS850_USBDRD_PHY, }, { } }; From e4001865ff387b928ea3d422d673dcc7389f8665 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Mon, 23 Feb 2026 19:55:24 +0530 Subject: [PATCH 18/21] phy: samsung: add support for exynos7870 USB PHY The USB PHY used by the Exynos7870 SoC has a single USB 2.0 interface. Add its dedicated variant enum, compatible, and init/exit functions. The PHY enable bit of Exynos7870's PHY is different in contrast to that of Exynos850 and most Exynos PHYs. To allow this change, a simple if condition is added in exynos_usbdrd_phy_isol() which changes the bitmask. Since the variant enum is required, the function argument is changed to accept the driver data itself. Reviewed-by: Mattijs Korpershoek Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- drivers/phy/phy-exynos-usbdrd.c | 246 ++++++++++++++++++++++++++++++-- 1 file changed, 238 insertions(+), 8 deletions(-) diff --git a/drivers/phy/phy-exynos-usbdrd.c b/drivers/phy/phy-exynos-usbdrd.c index 4ab8da2a08f..c5eed29a2c8 100644 --- a/drivers/phy/phy-exynos-usbdrd.c +++ b/drivers/phy/phy-exynos-usbdrd.c @@ -21,6 +21,7 @@ /* Offset of PMU register controlling USB PHY output isolation */ #define EXYNOS_USBDRD_PHY_CONTROL 0x0704 #define EXYNOS_PHY_ENABLE BIT(0) +#define EXYNOS7870_PHY_ENABLE BIT(1) /* Exynos USB PHY registers */ #define EXYNOS5_FSEL_9MHZ6 0x0 @@ -32,6 +33,88 @@ #define EXYNOS5_FSEL_26MHZ 0x6 #define EXYNOS5_FSEL_50MHZ 0x7 +/* Exynos5: USB DRD PHY registers */ +#define EXYNOS5_DRD_LINKSYSTEM 0x04 +#define LINKSYSTEM_XHCI_VERSION_CONTROL BIT(27) +#define LINKSYSTEM_FORCE_VBUSVALID BIT(8) +#define LINKSYSTEM_FORCE_BVALID BIT(7) +#define LINKSYSTEM_FLADJ GENMASK(6, 1) + +#define EXYNOS5_DRD_PHYUTMI 0x08 +#define PHYUTMI_UTMI_SUSPEND_COM_N BIT(12) +#define PHYUTMI_UTMI_L1_SUSPEND_COM_N BIT(11) +#define PHYUTMI_VBUSVLDEXTSEL BIT(10) +#define PHYUTMI_VBUSVLDEXT BIT(9) +#define PHYUTMI_TXBITSTUFFENH BIT(8) +#define PHYUTMI_TXBITSTUFFEN BIT(7) +#define PHYUTMI_OTGDISABLE BIT(6) +#define PHYUTMI_IDPULLUP BIT(5) +#define PHYUTMI_DRVVBUS BIT(4) +#define PHYUTMI_DPPULLDOWN BIT(3) +#define PHYUTMI_DMPULLDOWN BIT(2) +#define PHYUTMI_FORCESUSPEND BIT(1) +#define PHYUTMI_FORCESLEEP BIT(0) + +#define EXYNOS5_DRD_PHYCLKRST 0x10 +#define PHYCLKRST_EN_UTMISUSPEND BIT(31) +#define PHYCLKRST_SSC_REFCLKSEL GENMASK(30, 23) +#define PHYCLKRST_SSC_RANGE GENMASK(22, 21) +#define PHYCLKRST_SSC_EN BIT(20) +#define PHYCLKRST_REF_SSP_EN BIT(19) +#define PHYCLKRST_REF_CLKDIV2 BIT(18) +#define PHYCLKRST_MPLL_MULTIPLIER GENMASK(17, 11) +#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF 0x19 +#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF 0x32 +#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF 0x68 +#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF 0x7d +#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF 0x02 +#define PHYCLKRST_FSEL_PIPE GENMASK(10, 8) +#define PHYCLKRST_FSEL_UTMI GENMASK(7, 5) +#define PHYCLKRST_FSEL_PAD_100MHZ 0x27 +#define PHYCLKRST_FSEL_PAD_24MHZ 0x2a +#define PHYCLKRST_FSEL_PAD_20MHZ 0x31 +#define PHYCLKRST_FSEL_PAD_19_2MHZ 0x38 +#define PHYCLKRST_RETENABLEN BIT(4) +#define PHYCLKRST_REFCLKSEL GENMASK(3, 2) +#define PHYCLKRST_REFCLKSEL_PAD_REFCLK 0x2 +#define PHYCLKRST_REFCLKSEL_EXT_REFCLK 0x3 +#define PHYCLKRST_PORTRESET BIT(1) +#define PHYCLKRST_COMMONONN BIT(0) + +#define EXYNOS5_DRD_PHYPARAM0 0x1c +#define PHYPARAM0_REF_USE_PAD BIT(31) +#define PHYPARAM0_REF_LOSLEVEL GENMASK(30, 26) +#define PHYPARAM0_REF_LOSLEVEL_VAL 0x9 +#define PHYPARAM0_TXVREFTUNE GENMASK(25, 22) +#define PHYPARAM0_TXRISETUNE GENMASK(21, 20) +#define PHYPARAM0_TXRESTUNE GENMASK(19, 18) +#define PHYPARAM0_TXPREEMPPULSETUNE BIT(17) +#define PHYPARAM0_TXPREEMPAMPTUNE GENMASK(16, 15) +#define PHYPARAM0_TXHSXVTUNE GENMASK(14, 13) +#define PHYPARAM0_TXFSLSTUNE GENMASK(12, 9) +#define PHYPARAM0_SQRXTUNE GENMASK(8, 6) +#define PHYPARAM0_OTGTUNE GENMASK(5, 3) +#define PHYPARAM0_COMPDISTUNE GENMASK(2, 0) + +#define EXYNOS5_DRD_LINKPORT 0x44 +#define LINKPORT_HOST_U3_PORT_DISABLE BIT(8) +#define LINKPORT_HOST_U2_PORT_DISABLE BIT(7) +#define LINKPORT_HOST_PORT_OVCR_U3 BIT(5) +#define LINKPORT_HOST_PORT_OVCR_U2 BIT(4) +#define LINKPORT_HOST_PORT_OVCR_U3_SEL BIT(3) +#define LINKPORT_HOST_PORT_OVCR_U2_SEL BIT(2) + +/* Exynos7870: USB DRD PHY registers */ +#define EXYNOS7870_DRD_HSPHYCTRL 0x54 +#define HSPHYCTRL_PHYSWRSTALL BIT(31) +#define HSPHYCTRL_SIDDQ BIT(6) +#define HSPHYCTRL_PHYSWRST BIT(0) + +#define EXYNOS7870_DRD_HSPHYPLLTUNE 0x70 +#define HSPHYPLLTUNE_PLL_B_TUNE BIT(6) +#define HSPHYPLLTUNE_PLL_I_TUNE GENMASK(5, 4) +#define HSPHYPLLTUNE_PLL_P_TUNE GENMASK(3, 0) + /* Exynos850: USB DRD PHY registers */ #define EXYNOS850_DRD_LINKCTRL 0x04 #define LINKCTRL_FORCE_QACT BIT(8) @@ -67,6 +150,7 @@ #define MHZ (KHZ * KHZ) enum exynos_usbdrd_phy_variant { + EXYNOS7870_USBDRD_PHY, EXYNOS850_USBDRD_PHY, }; @@ -88,16 +172,20 @@ struct exynos_usbdrd_phy { enum exynos_usbdrd_phy_variant variant; }; -static void exynos_usbdrd_phy_isol(struct regmap *reg_pmu, bool isolate) +static void exynos_usbdrd_phy_isol(struct exynos_usbdrd_phy *phy_drd, + bool isolate) { - unsigned int val; + unsigned int mask = EXYNOS_PHY_ENABLE, val; - if (!reg_pmu) + if (!phy_drd->reg_pmu) return; - val = isolate ? 0 : EXYNOS_PHY_ENABLE; - regmap_update_bits(reg_pmu, EXYNOS_USBDRD_PHY_CONTROL, - EXYNOS_PHY_ENABLE, val); + if (phy_drd->variant == EXYNOS7870_USBDRD_PHY) + mask = EXYNOS7870_PHY_ENABLE; + + val = isolate ? 0 : mask; + regmap_update_bits(phy_drd->reg_pmu, EXYNOS_USBDRD_PHY_CONTROL, + mask, val); } /* @@ -138,6 +226,111 @@ static unsigned int exynos_rate_to_clk(unsigned long rate, u32 *reg) return 0; } +static void exynos7870_usbdrd_utmi_init(struct phy *phy) +{ + struct exynos_usbdrd_phy *phy_drd = dev_get_priv(phy->dev); + void __iomem *regs_base = phy_drd->reg_phy; + u32 reg; + + reg = readl(regs_base + EXYNOS5_DRD_PHYCLKRST); + /* Use PADREFCLK as ref clock */ + reg &= ~PHYCLKRST_REFCLKSEL; + reg |= FIELD_PREP(PHYCLKRST_REFCLKSEL, PHYCLKRST_REFCLKSEL_PAD_REFCLK); + /* Select ref clock rate */ + reg &= ~PHYCLKRST_FSEL_UTMI; + reg &= ~PHYCLKRST_FSEL_PIPE; + reg |= FIELD_PREP(PHYCLKRST_FSEL_UTMI, phy_drd->extrefclk); + /* Enable suspend and reset the port */ + reg |= PHYCLKRST_EN_UTMISUSPEND; + reg |= PHYCLKRST_COMMONONN; + reg |= PHYCLKRST_PORTRESET; + writel(reg, regs_base + EXYNOS5_DRD_PHYCLKRST); + udelay(10); + + /* Clear the port reset bit */ + reg &= ~PHYCLKRST_PORTRESET; + writel(reg, regs_base + EXYNOS5_DRD_PHYCLKRST); + + /* Change PHY PLL tune value */ + reg = readl(regs_base + EXYNOS7870_DRD_HSPHYPLLTUNE); + if (phy_drd->extrefclk == EXYNOS5_FSEL_24MHZ) + reg |= HSPHYPLLTUNE_PLL_B_TUNE; + else + reg &= ~HSPHYPLLTUNE_PLL_B_TUNE; + reg &= ~HSPHYPLLTUNE_PLL_P_TUNE; + reg |= FIELD_PREP(HSPHYPLLTUNE_PLL_P_TUNE, 14); + writel(reg, regs_base + EXYNOS7870_DRD_HSPHYPLLTUNE); + + /* High-Speed PHY control */ + reg = readl(regs_base + EXYNOS7870_DRD_HSPHYCTRL); + reg &= ~HSPHYCTRL_SIDDQ; + reg &= ~HSPHYCTRL_PHYSWRST; + reg &= ~HSPHYCTRL_PHYSWRSTALL; + writel(reg, regs_base + EXYNOS7870_DRD_HSPHYCTRL); + udelay(500); + + reg = readl(regs_base + EXYNOS5_DRD_LINKSYSTEM); + /* + * Setting the Frame length Adj value[6:1] to default 0x20 + * See xHCI 1.0 spec, 5.2.4 + */ + reg |= LINKSYSTEM_XHCI_VERSION_CONTROL; + reg &= ~LINKSYSTEM_FLADJ; + reg |= FIELD_PREP(LINKSYSTEM_FLADJ, 0x20); + /* Set VBUSVALID signal as the VBUS pad is not used */ + reg |= LINKSYSTEM_FORCE_BVALID; + reg |= LINKSYSTEM_FORCE_VBUSVALID; + writel(reg, regs_base + EXYNOS5_DRD_LINKSYSTEM); + + reg = readl(regs_base + EXYNOS5_DRD_PHYUTMI); + /* Release force_sleep & force_suspend */ + reg &= ~PHYUTMI_FORCESLEEP; + reg &= ~PHYUTMI_FORCESUSPEND; + /* DP/DM pull down control */ + reg &= ~PHYUTMI_DMPULLDOWN; + reg &= ~PHYUTMI_DPPULLDOWN; + reg &= ~PHYUTMI_DRVVBUS; + /* Set DP-pull up as the VBUS pad is not used */ + reg |= PHYUTMI_VBUSVLDEXTSEL; + reg |= PHYUTMI_VBUSVLDEXT; + /* Disable OTG block and VBUS valid comparator */ + reg |= PHYUTMI_OTGDISABLE; + writel(reg, regs_base + EXYNOS5_DRD_PHYUTMI); + + /* Configure OVC IO usage */ + reg = readl(regs_base + EXYNOS5_DRD_LINKPORT); + reg |= LINKPORT_HOST_PORT_OVCR_U3_SEL | LINKPORT_HOST_PORT_OVCR_U2_SEL; + writel(reg, regs_base + EXYNOS5_DRD_LINKPORT); + + /* High-Speed PHY swrst */ + reg = readl(regs_base + EXYNOS7870_DRD_HSPHYCTRL); + reg |= HSPHYCTRL_PHYSWRST; + writel(reg, regs_base + EXYNOS7870_DRD_HSPHYCTRL); + udelay(20); + + /* Clear the PHY swrst bit */ + reg = readl(regs_base + EXYNOS7870_DRD_HSPHYCTRL); + reg &= ~HSPHYCTRL_PHYSWRST; + writel(reg, regs_base + EXYNOS7870_DRD_HSPHYCTRL); + + reg = readl(regs_base + EXYNOS5_DRD_PHYPARAM0); + reg &= ~(PHYPARAM0_TXVREFTUNE | PHYPARAM0_TXRISETUNE | + PHYPARAM0_TXRESTUNE | PHYPARAM0_TXPREEMPPULSETUNE | + PHYPARAM0_TXPREEMPAMPTUNE | PHYPARAM0_TXHSXVTUNE | + PHYPARAM0_TXFSLSTUNE | PHYPARAM0_SQRXTUNE | + PHYPARAM0_OTGTUNE | PHYPARAM0_COMPDISTUNE); + reg |= FIELD_PREP_CONST(PHYPARAM0_TXVREFTUNE, 14) | + FIELD_PREP_CONST(PHYPARAM0_TXRISETUNE, 1) | + FIELD_PREP_CONST(PHYPARAM0_TXRESTUNE, 3) | + FIELD_PREP_CONST(PHYPARAM0_TXPREEMPAMPTUNE, 0) | + FIELD_PREP_CONST(PHYPARAM0_TXHSXVTUNE, 0) | + FIELD_PREP_CONST(PHYPARAM0_TXFSLSTUNE, 3) | + FIELD_PREP_CONST(PHYPARAM0_SQRXTUNE, 6) | + FIELD_PREP_CONST(PHYPARAM0_OTGTUNE, 2) | + FIELD_PREP_CONST(PHYPARAM0_COMPDISTUNE, 3); + writel(reg, regs_base + EXYNOS5_DRD_PHYPARAM0); +} + static void exynos850_usbdrd_utmi_init(struct phy *phy) { struct exynos_usbdrd_phy *phy_drd = dev_get_priv(phy->dev); @@ -225,6 +418,33 @@ static void exynos850_usbdrd_utmi_init(struct phy *phy) writel(reg, regs_base + EXYNOS850_DRD_HSP); } +static void exynos7870_usbdrd_utmi_exit(struct phy *phy) +{ + struct exynos_usbdrd_phy *phy_drd = dev_get_priv(phy->dev); + void __iomem *regs_base = phy_drd->reg_phy; + u32 reg; + + /* + * Disable the VBUS signal and the ID pull-up resistor. + * Enable force-suspend and force-sleep modes. + */ + reg = readl(regs_base + EXYNOS5_DRD_PHYUTMI); + reg &= ~(PHYUTMI_DRVVBUS | PHYUTMI_VBUSVLDEXT | PHYUTMI_VBUSVLDEXTSEL); + reg &= ~PHYUTMI_IDPULLUP; + reg |= PHYUTMI_FORCESUSPEND | PHYUTMI_FORCESLEEP; + writel(reg, regs_base + EXYNOS5_DRD_PHYUTMI); + + /* Power down PHY analog blocks */ + reg = readl(regs_base + EXYNOS7870_DRD_HSPHYCTRL); + reg |= HSPHYCTRL_SIDDQ; + writel(reg, regs_base + EXYNOS7870_DRD_HSPHYCTRL); + + /* Clear VBUSVALID signal as the VBUS pad is not used */ + reg = readl(regs_base + EXYNOS5_DRD_LINKSYSTEM); + reg &= ~(LINKSYSTEM_FORCE_BVALID | LINKSYSTEM_FORCE_VBUSVALID); + writel(reg, regs_base + EXYNOS5_DRD_LINKSYSTEM); +} + static void exynos850_usbdrd_utmi_exit(struct phy *phy) { struct exynos_usbdrd_phy *phy_drd = dev_get_priv(phy->dev); @@ -261,6 +481,9 @@ static int exynos_usbdrd_phy_init(struct phy *phy) return ret; switch (phy_drd->variant) { + case EXYNOS7870_USBDRD_PHY: + exynos7870_usbdrd_utmi_init(phy); + break; case EXYNOS850_USBDRD_PHY: exynos850_usbdrd_utmi_init(phy); break; @@ -283,6 +506,9 @@ static int exynos_usbdrd_phy_exit(struct phy *phy) return ret; switch (phy_drd->variant) { + case EXYNOS7870_USBDRD_PHY: + exynos7870_usbdrd_utmi_exit(phy); + break; case EXYNOS850_USBDRD_PHY: exynos850_usbdrd_utmi_exit(phy); break; @@ -307,7 +533,7 @@ static int exynos_usbdrd_phy_power_on(struct phy *phy) return ret; /* Power-on PHY */ - exynos_usbdrd_phy_isol(phy_drd->reg_pmu, false); + exynos_usbdrd_phy_isol(phy_drd, false); return 0; } @@ -319,7 +545,7 @@ static int exynos_usbdrd_phy_power_off(struct phy *phy) dev_dbg(phy->dev, "Request to power_off usbdrd_phy phy\n"); /* Power-off the PHY */ - exynos_usbdrd_phy_isol(phy_drd->reg_pmu, true); + exynos_usbdrd_phy_isol(phy_drd, true); clk_disable_unprepare(phy_drd->core_clk); @@ -390,6 +616,10 @@ static const struct phy_ops exynos_usbdrd_phy_ops = { }; static const struct udevice_id exynos_usbdrd_phy_of_match[] = { + { + .compatible = "samsung,exynos7870-usbdrd-phy", + .data = EXYNOS7870_USBDRD_PHY, + }, { .compatible = "samsung,exynos850-usbdrd-phy", .data = EXYNOS850_USBDRD_PHY, From db0fe21bd38f27f570ce16670ccad567efd596f4 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 24 Feb 2026 21:07:09 +0530 Subject: [PATCH 19/21] board: samsung: exynos-mobile: use blkmap for booting from userdata subpartitions Some distributions tend to provide a single combined image with EFS and the system root filesystem. Flashing it as-is in a single partition (usually done in userdata partition as it is the largest) is not bootable as U-Boot does not understand subpartitions. Use blkmap to map the userdata partition into its own block device. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- board/samsung/exynos-mobile/exynos-mobile.c | 45 +++++++++++++++++++ board/samsung/exynos-mobile/exynos-mobile.env | 5 +++ configs/exynos-mobile_defconfig | 4 +- 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/board/samsung/exynos-mobile/exynos-mobile.c b/board/samsung/exynos-mobile/exynos-mobile.c index 1f61f28de5f..c5e1b186ae3 100644 --- a/board/samsung/exynos-mobile/exynos-mobile.c +++ b/board/samsung/exynos-mobile/exynos-mobile.c @@ -184,6 +184,45 @@ static void exynos_env_setup(void) 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; + 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 (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) { struct blk_desc *blk_dev; @@ -297,7 +336,13 @@ int board_init(void) int misc_init_r(void) { + int ret; + exynos_env_setup(); + 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 diff --git a/configs/exynos-mobile_defconfig b/configs/exynos-mobile_defconfig index c7d206f94ac..cee468d9c24 100644 --- a/configs/exynos-mobile_defconfig +++ b/configs/exynos-mobile_defconfig @@ -12,6 +12,7 @@ CONFIG_SYS_LOAD_ADDR=0x80000000 CONFIG_ARMV8_CNTFRQ_BROKEN=y # CONFIG_PSCI_RESET is not set CONFIG_BUTTON_CMD=y +CONFIG_USE_PREBOOT=y CONFIG_SAVE_PREV_BL_FDT_ADDR=y CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR=y CONFIG_SYS_PBSIZE=1024 @@ -24,8 +25,9 @@ CONFIG_CMD_POWEROFF=y CONFIG_CMD_FS_GENERIC=y CONFIG_EFI_PARTITION=y CONFIG_OF_UPSTREAM=y -CONFIG_OF_BOARD=y CONFIG_OF_UPSTREAM_BUILD_VENDOR=y +CONFIG_OF_BOARD=y +CONFIG_BLKMAP=y CONFIG_BUTTON=y CONFIG_BUTTON_REMAP_PHONE_KEYS=y CONFIG_CLK_EXYNOS7870=y From 0e61fc5364dc6b4af88b44ea2e1aa9d84c9f1ca7 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 24 Feb 2026 21:07:10 +0530 Subject: [PATCH 20/21] board: samsung: exynos-mobile: add EFI capsule update support Add support for EFI capsule updates via U-Boot's DFU. This flashes the boot partition with the new image provided in the capsule. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- board/samsung/exynos-mobile/exynos-mobile.c | 24 +++++++++++++++++++++ configs/exynos-mobile_defconfig | 6 ++++++ 2 files changed, 30 insertions(+) diff --git a/board/samsung/exynos-mobile/exynos-mobile.c b/board/samsung/exynos-mobile/exynos-mobile.c index c5e1b186ae3..6b2b1523663 100644 --- a/board/samsung/exynos-mobile/exynos-mobile.c +++ b/board/samsung/exynos-mobile/exynos-mobile.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -24,6 +26,19 @@ DECLARE_GLOBAL_DATA_PTR; #define lmb_alloc(size, addr) \ lmb_alloc_mem(LMB_MEM_ALLOC_ANY, SZ_2M, addr, size, LMB_NONE) +struct efi_fw_image fw_images[] = { + { + .fw_name = u"UBOOT_BOOT_PARTITION", + .image_index = 1, + }, +}; + +struct efi_capsule_update_info update_info = { + .dfu_string = NULL, + .images = fw_images, + .num_images = ARRAY_SIZE(fw_images), +}; + /* * The memory mapping includes all DRAM banks, along with the * peripheral block, and a sentinel at the end. This is filled in @@ -191,6 +206,7 @@ static int exynos_blk_env_setup(void) 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"; @@ -204,6 +220,14 @@ static int exynos_blk_env_setup(void) 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; diff --git a/configs/exynos-mobile_defconfig b/configs/exynos-mobile_defconfig index cee468d9c24..9a4b6a52362 100644 --- a/configs/exynos-mobile_defconfig +++ b/configs/exynos-mobile_defconfig @@ -11,6 +11,10 @@ CONFIG_SYS_BOOTM_LEN=0x2000000 CONFIG_SYS_LOAD_ADDR=0x80000000 CONFIG_ARMV8_CNTFRQ_BROKEN=y # CONFIG_PSCI_RESET is not set +CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y +CONFIG_EFI_CAPSULE_ON_DISK=y +CONFIG_EFI_CAPSULE_ON_DISK_EARLY=y +CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y CONFIG_BUTTON_CMD=y CONFIG_USE_PREBOOT=y CONFIG_SAVE_PREV_BL_FDT_ADDR=y @@ -31,6 +35,8 @@ CONFIG_BLKMAP=y CONFIG_BUTTON=y CONFIG_BUTTON_REMAP_PHONE_KEYS=y CONFIG_CLK_EXYNOS7870=y +CONFIG_DFU_MMC=y +CONFIG_SYS_DFU_DATA_BUF_SIZE=0x200000 CONFIG_USB_FUNCTION_FASTBOOT=y CONFIG_FASTBOOT_BUF_ADDR=0xdead0000 CONFIG_FASTBOOT_FLASH=y From 336dd39b956e5f7e078da1d2b689415a41484067 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 24 Feb 2026 21:07:11 +0530 Subject: [PATCH 21/21] configs: exynos-mobile: add DEFAULT_DEVICE_TREE option Add a default fallback device tree in order to allow a successful build without mentioning the DEVICE_TREE= make flag. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- configs/exynos-mobile_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/exynos-mobile_defconfig b/configs/exynos-mobile_defconfig index 9a4b6a52362..bff4e6c6fb7 100644 --- a/configs/exynos-mobile_defconfig +++ b/configs/exynos-mobile_defconfig @@ -7,6 +7,7 @@ CONFIG_SYS_MALLOC_LEN=0x2000000 CONFIG_SYS_MALLOC_F_LEN=0x16000 CONFIG_TARGET_EXYNOS_MOBILE=y CONFIG_NR_DRAM_BANKS=3 +CONFIG_DEFAULT_DEVICE_TREE="exynos/exynos7870-a2corelte" CONFIG_SYS_BOOTM_LEN=0x2000000 CONFIG_SYS_LOAD_ADDR=0x80000000 CONFIG_ARMV8_CNTFRQ_BROKEN=y