summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/dts/exynos7870-a2corelte-u-boot.dtsi26
-rw-r--r--arch/arm/dts/exynos7870-j6lte-u-boot.dtsi46
-rw-r--r--arch/arm/dts/exynos7870-on7xelte-u-boot.dtsi41
-rw-r--r--board/samsung/exynos-mobile/exynos-mobile.c335
-rw-r--r--board/samsung/exynos-mobile/exynos-mobile.env5
-rw-r--r--configs/exynos-mobile_defconfig12
-rw-r--r--doc/board/samsung/exynos-mobile.rst5
-rw-r--r--doc/board/samsung/exynos-mobile/exynos7870.rst42
-rw-r--r--drivers/phy/phy-exynos-usbdrd.c271
-rw-r--r--drivers/video/exynos/exynos_fb.c2
-rw-r--r--drivers/video/nexell/soc/s5pxx18_soc_mlc.c2
11 files changed, 549 insertions, 238 deletions
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..7d97afcc64f
--- /dev/null
+++ b/arch/arm/dts/exynos7870-a2corelte-u-boot.dtsi
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2026 Kaustabh Chakraborty <[email protected]>
+ */
+
+/ {
+ /* 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>;
+ ranges;
+
+ framebuffer@67000000 {
+ compatible = "simple-framebuffer";
+ reg = <0x0 0x67000000 (540 * 960 * 4)>;
+ width = <540>;
+ height = <960>;
+ stride = <(540 * 4)>;
+ format = "a8r8g8b8";
+ };
+ };
+};
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..aa499ecf479
--- /dev/null
+++ b/arch/arm/dts/exynos7870-j6lte-u-boot.dtsi
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) Kaustabh Chakraborty <[email protected]>
+ */
+
+/ {
+ /* 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>;
+ ranges;
+
+ framebuffer@67000000 {
+ compatible = "simple-framebuffer";
+ reg = <0x0 0x67000000 (720 * 1480 * 4)>;
+ width = <720>;
+ height = <1480>;
+ stride = <(720 * 4)>;
+ 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>;
+ };
+};
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..01c3e95b0b3
--- /dev/null
+++ b/arch/arm/dts/exynos7870-on7xelte-u-boot.dtsi
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2026 Kaustabh Chakraborty <[email protected]>
+ */
+
+/ {
+ /* 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>;
+ ranges;
+
+ framebuffer@67000000 {
+ compatible = "simple-framebuffer";
+ reg = <0x0 0x67000000 (1080 * 1920 * 4)>;
+ width = <1080>;
+ height = <1920>;
+ stride = <(1080 * 4)>;
+ 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>;
+ };
+};
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
diff --git a/configs/exynos-mobile_defconfig b/configs/exynos-mobile_defconfig
index 3a0b455b169..bff4e6c6fb7 100644
--- a/configs/exynos-mobile_defconfig
+++ b/configs/exynos-mobile_defconfig
@@ -12,7 +12,12 @@ 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
CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR=y
CONFIG_SYS_PBSIZE=1024
@@ -25,11 +30,14 @@ 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_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
+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
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 ``<dtb>`` 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=<dtb> O=.output -j$(nproc)
If successful, the U-Boot binary will be present in ``.output/u-boot.bin``.
diff --git a/doc/board/samsung/exynos-mobile/exynos7870.rst b/doc/board/samsung/exynos-mobile/exynos7870.rst
index bbd857580b8..702b21244eb 100644
--- a/doc/board/samsung/exynos-mobile/exynos7870.rst
+++ b/doc/board/samsung/exynos-mobile/exynos7870.rst
@@ -6,54 +6,20 @@ 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:
.. 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.
diff --git a/drivers/phy/phy-exynos-usbdrd.c b/drivers/phy/phy-exynos-usbdrd.c
index db5815ed184..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)
@@ -66,6 +149,11 @@
#define KHZ 1000
#define MHZ (KHZ * KHZ)
+enum exynos_usbdrd_phy_variant {
+ EXYNOS7870_USBDRD_PHY,
+ EXYNOS850_USBDRD_PHY,
+};
+
/**
* struct exynos_usbdrd_phy - driver data for Exynos USB PHY
* @reg_phy: USB PHY controller register memory base
@@ -73,6 +161,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,18 +169,23 @@ 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)
+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);
}
/*
@@ -132,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);
@@ -219,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);
@@ -254,7 +480,16 @@ static int exynos_usbdrd_phy_init(struct phy *phy)
if (ret)
return ret;
- exynos850_usbdrd_utmi_init(phy);
+ switch (phy_drd->variant) {
+ case EXYNOS7870_USBDRD_PHY:
+ exynos7870_usbdrd_utmi_init(phy);
+ break;
+ 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 +505,16 @@ static int exynos_usbdrd_phy_exit(struct phy *phy)
if (ret)
return ret;
- exynos850_usbdrd_utmi_exit(phy);
+ switch (phy_drd->variant) {
+ case EXYNOS7870_USBDRD_PHY:
+ exynos7870_usbdrd_utmi_exit(phy);
+ break;
+ 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);
@@ -289,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;
}
@@ -301,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);
@@ -359,6 +603,8 @@ static int exynos_usbdrd_phy_probe(struct udevice *dev)
return err;
}
+ phy_drd->variant = dev_get_driver_data(dev);
+
return 0;
}
@@ -371,7 +617,12 @@ 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,
},
{ }
};
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;
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;