summaryrefslogtreecommitdiff
path: root/board
diff options
context:
space:
mode:
Diffstat (limited to 'board')
-rw-r--r--board/asus/transformer-t20/configs/sl101.config1
-rw-r--r--board/asus/transformer-t20/sl101.env15
-rw-r--r--board/gameforce/ace-rk3588s/Kconfig9
-rw-r--r--board/gameforce/ace-rk3588s/MAINTAINERS5
-rw-r--r--board/microsoft/surface-2/Kconfig13
-rw-r--r--board/microsoft/surface-2/MAINTAINERS7
-rw-r--r--board/microsoft/surface-2/Makefile6
-rw-r--r--board/microsoft/surface-2/board-info.c71
-rw-r--r--board/microsoft/surface-2/surface-2-spl.c42
-rw-r--r--board/microsoft/surface-2/surface-2.env8
-rw-r--r--board/phytec/phycore_am62ax/phycore_am62ax.env4
-rw-r--r--board/phytec/phycore_am62x/phycore_am62x.env4
-rw-r--r--board/phytec/phycore_am64x/phycore_am64x.env4
-rw-r--r--board/phytec/phycore_imx93/spl.c3
-rw-r--r--board/renesas/sparrowhawk/sparrowhawk.c130
-rw-r--r--board/rockchip/evb_rk3588/MAINTAINERS6
-rw-r--r--board/samsung/e850-96/Makefile2
-rw-r--r--board/samsung/e850-96/acpm.c169
-rw-r--r--board/samsung/e850-96/acpm.h27
-rw-r--r--board/samsung/e850-96/e850-96.c97
-rw-r--r--board/samsung/e850-96/e850-96.env2
-rw-r--r--board/samsung/e850-96/fw.c45
-rw-r--r--board/samsung/e850-96/fw.h4
-rw-r--r--board/samsung/e850-96/pmic.c144
-rw-r--r--board/samsung/e850-96/pmic.h14
-rw-r--r--board/theobroma-systems/jaguar_rk3588/jaguar_rk3588.c19
-rw-r--r--board/ti/am57xx/Kconfig12
-rw-r--r--board/ti/am57xx/am57xx.env162
-rw-r--r--board/ti/am57xx/board.c14
-rw-r--r--board/ti/dra7xx/evm.c11
-rw-r--r--board/xunlong/orangepi-5-ultra-rk3588/Kconfig12
-rw-r--r--board/xunlong/orangepi-5-ultra-rk3588/MAINTAINERS6
32 files changed, 1033 insertions, 35 deletions
diff --git a/board/asus/transformer-t20/configs/sl101.config b/board/asus/transformer-t20/configs/sl101.config
index 4f639e1b412..87c6f7a216d 100644
--- a/board/asus/transformer-t20/configs/sl101.config
+++ b/board/asus/transformer-t20/configs/sl101.config
@@ -1 +1,2 @@
+CONFIG_ENV_SOURCE_FILE="sl101"
CONFIG_DEFAULT_DEVICE_TREE="tegra20-asus-sl101"
diff --git a/board/asus/transformer-t20/sl101.env b/board/asus/transformer-t20/sl101.env
new file mode 100644
index 00000000000..f2bf298a997
--- /dev/null
+++ b/board/asus/transformer-t20/sl101.env
@@ -0,0 +1,15 @@
+#include <env/nvidia/prod_upd.env>
+
+button_cmd_0_name=Volume Down
+button_cmd_0=bootmenu
+partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}
+boot_dev=1
+
+bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu
+bootmenu_1=mount external storage=usb start && ums 0 mmc 1; bootmenu
+bootmenu_2=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu
+bootmenu_3=update bootloader=run flash_uboot
+bootmenu_4=reboot RCM=enterrcm
+bootmenu_5=reboot=reset
+bootmenu_6=power off=poweroff
+bootmenu_delay=-1
diff --git a/board/gameforce/ace-rk3588s/Kconfig b/board/gameforce/ace-rk3588s/Kconfig
new file mode 100644
index 00000000000..52f98ccf897
--- /dev/null
+++ b/board/gameforce/ace-rk3588s/Kconfig
@@ -0,0 +1,9 @@
+if TARGET_GAMEFORCE_ACE_RK3588S
+
+config SYS_BOARD
+ default "gameforce-ace-rk3588s"
+
+config SYS_VENDOR
+ default "GameForce"
+
+endif
diff --git a/board/gameforce/ace-rk3588s/MAINTAINERS b/board/gameforce/ace-rk3588s/MAINTAINERS
new file mode 100644
index 00000000000..dc18e7c8849
--- /dev/null
+++ b/board/gameforce/ace-rk3588s/MAINTAINERS
@@ -0,0 +1,5 @@
+GAMEFORCE-ACE-RK3588S
+M: Chris Morgan <macromorgan@hotmail.com>
+S: Maintained
+F: board/gameforce/ace-rk3588s/
+F: configs/gameforce-ace-rk3588s_defconfig
diff --git a/board/microsoft/surface-2/Kconfig b/board/microsoft/surface-2/Kconfig
new file mode 100644
index 00000000000..8573666dc92
--- /dev/null
+++ b/board/microsoft/surface-2/Kconfig
@@ -0,0 +1,13 @@
+if TARGET_SURFACE_2
+
+config SYS_BOARD
+ default "surface-2"
+
+config SYS_VENDOR
+ default "microsoft"
+
+config TEGRA_BOARD_STRING
+ string "Default Tegra board name"
+ default "Microsoft Surface 2"
+
+endif
diff --git a/board/microsoft/surface-2/MAINTAINERS b/board/microsoft/surface-2/MAINTAINERS
new file mode 100644
index 00000000000..57747d304cd
--- /dev/null
+++ b/board/microsoft/surface-2/MAINTAINERS
@@ -0,0 +1,7 @@
+SURFACE_2 BOARD
+M: Jonas Schwöbel <jonasschwoebel@yahoo.de>
+S: Maintained
+F: arch/arm/dts/tegra114-microsoft-surface-2*
+F: board/microsoft/surface-2/
+F: configs/surface-2_defconfig
+F: doc/board/microsoft/surface-2.rst
diff --git a/board/microsoft/surface-2/Makefile b/board/microsoft/surface-2/Makefile
new file mode 100644
index 00000000000..43bf6c66db2
--- /dev/null
+++ b/board/microsoft/surface-2/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
+
+obj-$(CONFIG_XPL_BUILD) += surface-2-spl.o
+obj-$(CONFIG_MULTI_DTB_FIT) += board-info.o
diff --git a/board/microsoft/surface-2/board-info.c b/board/microsoft/surface-2/board-info.c
new file mode 100644
index 00000000000..95a4accdc90
--- /dev/null
+++ b/board/microsoft/surface-2/board-info.c
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2025
+ * Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#include <stdio.h>
+#include <env.h>
+#include <spl_gpio.h>
+
+#include <asm/gpio.h>
+#include <asm/arch/pinmux.h>
+#include <linux/string.h>
+
+static int id_gpio_get_value(u32 pingrp, u32 pin)
+{
+ /* Configure pinmux */
+ pinmux_set_func(pingrp, PMUX_FUNC_KBC);
+ pinmux_set_pullupdown(pingrp, PMUX_PULL_DOWN);
+ pinmux_tristate_enable(pingrp);
+ pinmux_set_io(pingrp, PMUX_PIN_INPUT);
+
+ /*
+ * Since this function may be called
+ * during DM reload we should use SPL
+ * GPIO functions which do not depend
+ * on DM.
+ */
+ spl_gpio_input(NULL, pin);
+ return spl_gpio_get_value(NULL, pin);
+}
+
+static int get_board_id(void)
+{
+ u32 pcb_id0, pcb_id1, pcb_id2, pcb_id3, pcb_id4, board_id;
+
+ pcb_id0 = id_gpio_get_value(PMUX_PINGRP_KB_COL0_PQ0, TEGRA_GPIO(Q, 0));
+ pcb_id1 = id_gpio_get_value(PMUX_PINGRP_KB_COL1_PQ1, TEGRA_GPIO(Q, 1));
+ pcb_id2 = id_gpio_get_value(PMUX_PINGRP_KB_COL2_PQ2, TEGRA_GPIO(Q, 2));
+ pcb_id3 = id_gpio_get_value(PMUX_PINGRP_KB_COL3_PQ3, TEGRA_GPIO(Q, 3));
+ pcb_id4 = id_gpio_get_value(PMUX_PINGRP_KB_COL4_PQ4, TEGRA_GPIO(Q, 4));
+
+ /* Construct board ID */
+ board_id = pcb_id4 << 4 | pcb_id3 << 3 | pcb_id2 << 2 | pcb_id1 << 1 | pcb_id0;
+
+ log_debug("[SURFACE-2]: Board ID %02x\n", board_id);
+
+ return board_id & 0x1f;
+}
+
+int board_fit_config_name_match(const char *name)
+{
+ char dt_name[64] = { 0 };
+
+ snprintf(dt_name, sizeof(dt_name), "tegra114-microsoft-surface-2-%02x.dtb",
+ get_board_id());
+
+ if (!strcmp(name, dt_name))
+ return 0;
+
+ return -1;
+}
+
+void nvidia_board_late_init(void)
+{
+ char dt_path[64] = { 0 };
+
+ snprintf(dt_path, sizeof(dt_path), "tegra114-microsoft-surface-2-%02x.dtb",
+ get_board_id());
+ env_set("fdtfile", dt_path);
+}
diff --git a/board/microsoft/surface-2/surface-2-spl.c b/board/microsoft/surface-2/surface-2-spl.c
new file mode 100644
index 00000000000..16f4373c7f0
--- /dev/null
+++ b/board/microsoft/surface-2/surface-2-spl.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Surface 2 SPL stage configuration
+ *
+ * (C) Copyright 2010-2013
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * (C) Copyright 2023
+ * Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#include <asm/arch/tegra.h>
+#include <asm/arch-tegra/tegra_i2c.h>
+#include <linux/delay.h>
+
+#define TPS65913_I2C_ADDR (0x58 << 1)
+
+#define TPS65913_SMPS12_CTRL 0x20
+#define TPS65913_SMPS12_VOLTAGE 0x23
+#define TPS65913_SMPS45_CTRL 0x28
+#define TPS65913_SMPS45_VOLTAGE 0x2B
+
+#define TPS65913_SMPS12_CTRL_DATA (0x5100 | TPS65913_SMPS12_CTRL)
+#define TPS65913_SMPS12_VOLTAGE_DATA (0x3900 | TPS65913_SMPS12_VOLTAGE)
+#define TPS65913_SMPS45_CTRL_DATA (0x5100 | TPS65913_SMPS45_CTRL)
+#define TPS65913_SMPS45_VOLTAGE_DATA (0x4c00 | TPS65913_SMPS45_VOLTAGE)
+
+void pmic_enable_cpu_vdd(void)
+{
+ /* Set CORE VDD to 1.200V. */
+ tegra_i2c_ll_write(TPS65913_I2C_ADDR, TPS65913_SMPS45_VOLTAGE_DATA);
+ udelay(1000);
+ tegra_i2c_ll_write(TPS65913_I2C_ADDR, TPS65913_SMPS45_CTRL_DATA);
+
+ udelay(1000);
+
+ /* Set CPU VDD to 1.0125V. */
+ tegra_i2c_ll_write(TPS65913_I2C_ADDR, TPS65913_SMPS12_VOLTAGE_DATA);
+ udelay(1000);
+ tegra_i2c_ll_write(TPS65913_I2C_ADDR, TPS65913_SMPS12_CTRL_DATA);
+ udelay(10 * 1000);
+}
diff --git a/board/microsoft/surface-2/surface-2.env b/board/microsoft/surface-2/surface-2.env
new file mode 100644
index 00000000000..a77885a7c6d
--- /dev/null
+++ b/board/microsoft/surface-2/surface-2.env
@@ -0,0 +1,8 @@
+button_cmd_0_name=Volume Down
+button_cmd_0=bootmenu
+
+bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu
+bootmenu_1=mount external storage=usb start && ums 0 mmc 1; bootmenu
+bootmenu_2=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu
+bootmenu_4=power off=reset
+bootmenu_delay=-1
diff --git a/board/phytec/phycore_am62ax/phycore_am62ax.env b/board/phytec/phycore_am62ax/phycore_am62ax.env
index 797904013dc..ff4ab8c87b8 100644
--- a/board/phytec/phycore_am62ax/phycore_am62ax.env
+++ b/board/phytec/phycore_am62ax/phycore_am62ax.env
@@ -25,5 +25,9 @@ spi_fdt_addr=0x700000
spi_image_addr=0x800000
spi_ramdisk_addr=0x2200000
+#ifdef CONFIG_BOOTMETH_RAUC
+bootmeths=rauc script efi extlinux pxe
+#else
bootmeths=script efi extlinux pxe
+#endif
boot_targets=mmc1 mmc0 spi_flash dhcp
diff --git a/board/phytec/phycore_am62x/phycore_am62x.env b/board/phytec/phycore_am62x/phycore_am62x.env
index 797904013dc..ff4ab8c87b8 100644
--- a/board/phytec/phycore_am62x/phycore_am62x.env
+++ b/board/phytec/phycore_am62x/phycore_am62x.env
@@ -25,5 +25,9 @@ spi_fdt_addr=0x700000
spi_image_addr=0x800000
spi_ramdisk_addr=0x2200000
+#ifdef CONFIG_BOOTMETH_RAUC
+bootmeths=rauc script efi extlinux pxe
+#else
bootmeths=script efi extlinux pxe
+#endif
boot_targets=mmc1 mmc0 spi_flash dhcp
diff --git a/board/phytec/phycore_am64x/phycore_am64x.env b/board/phytec/phycore_am64x/phycore_am64x.env
index 36ab16e2f7a..cbaf45b3ace 100644
--- a/board/phytec/phycore_am64x/phycore_am64x.env
+++ b/board/phytec/phycore_am64x/phycore_am64x.env
@@ -24,5 +24,9 @@ spi_fdt_addr=0x700000
spi_image_addr=0x800000
spi_ramdisk_addr=0x2200000
+#ifdef CONFIG_BOOTMETH_RAUC
+bootmeths=rauc script efi extlinux pxe
+#else
bootmeths=script efi extlinux pxe
+#endif
boot_targets=mmc1 mmc0 spi_flash dhcp
diff --git a/board/phytec/phycore_imx93/spl.c b/board/phytec/phycore_imx93/spl.c
index 7b5d38d438f..beaa536c600 100644
--- a/board/phytec/phycore_imx93/spl.c
+++ b/board/phytec/phycore_imx93/spl.c
@@ -52,8 +52,7 @@ void spl_dram_init(void)
int ret;
enum phytec_imx93_ddr_eeprom_code ddr_opt = PHYTEC_IMX93_DDR_INVALID;
- /* NOTE: In SPL lpi2c3 is mapped to bus 0 */
- ret = phytec_eeprom_data_setup(NULL, 0, EEPROM_ADDR);
+ ret = phytec_eeprom_data_setup(NULL, 2, EEPROM_ADDR);
if (ret && !IS_ENABLED(CONFIG_PHYCORE_IMX93_RAM_TYPE_FIX))
goto out;
diff --git a/board/renesas/sparrowhawk/sparrowhawk.c b/board/renesas/sparrowhawk/sparrowhawk.c
index 8e72b5424d1..58de7f25cbd 100644
--- a/board/renesas/sparrowhawk/sparrowhawk.c
+++ b/board/renesas/sparrowhawk/sparrowhawk.c
@@ -6,8 +6,12 @@
#include <asm/io.h>
#include <compiler.h>
#include <dbsc5.h>
+#include <spi.h>
+#include <spi_flash.h>
#include <spl.h>
+#include "../../../drivers/mtd/spi/sf_internal.h"
+
#if defined(CONFIG_XPL_BUILD)
static const struct renesas_dbsc5_board_config
@@ -112,12 +116,134 @@ dbsc5_get_board_data(struct udevice *dev, const u32 modemr0)
* Use MD[19] setting to discern 8 GiB and 16 GiB DRAM Sparrow Hawk
* board variants from each other automatically.
*/
- if (modemr0 & BIT(19))
+ if ((renesas_get_cpu_rev_integer() >= 3) && (modemr0 & BIT(19)))
return &renesas_v4h_sparrowhawk_16g_5500_dbsc5_board_config;
else
return &renesas_v4h_sparrowhawk_8g_6400_dbsc5_board_config;
}
+static bool renesas_v4h_sparrowhawk_is_evta1 = false;
+
+unsigned int spl_spi_get_uboot_offs(struct spi_flash *flash)
+{
+ const u8 sf_ids_evta1[6] = { 0x01, 0x02, 0x20, 0x4d, 0x00, 0x81 };
+
+ renesas_v4h_sparrowhawk_is_evta1 = !memcmp(sf_ids_evta1, flash->info->id,
+ sizeof(sf_ids_evta1));
+
+ return CONFIG_SYS_SPI_U_BOOT_OFFS;
+}
+
+void spl_perform_fixups(struct spl_image_info *spl_image)
+{
+ void *blob = spl_image_fdt_addr(spl_image);
+ int err, offs;
+ u32 size;
+
+ if (!renesas_v4h_sparrowhawk_is_evta1)
+ return;
+
+ printf("EVTA1 board detected\n");
+
+ /*
+ * MicroSD voltage switch is not populated on Sparrow Hawk EVTA1,
+ * rewrite MicroSD slot regulator to only support 3V3 and disable
+ * UHS modes in MicroSD slot node.
+ */
+ if (!blob)
+ return;
+
+ err = fdt_check_header(blob);
+ if (err < 0) {
+ printf("Invalid FDT header: %s\n", fdt_strerror(err));
+ return;
+ }
+
+ size = fdt_totalsize(blob);
+ err = fdt_open_into(blob, blob, size + 64);
+ if (err < 0) {
+ printf("Failed to expand DT\n");
+ return;
+ }
+
+ offs = fdt_path_offset(blob, "/regulator-vcc-sdhi");
+ if (offs < 0) {
+ printf("Failed to locate MicroSD regulator node: %d\n", offs);
+ return;
+ }
+
+ err = fdt_setprop_string(blob, offs, "compatible", "regulator-fixed");
+ if (err < 0) {
+ printf("Failed to set fixed MicroSD regulator: %d\n", err);
+ return;
+ }
+
+ err = fdt_setprop_u32(blob, offs, "regulator-min-microvolt", 3300000);
+ if (err < 0) {
+ printf("Failed to set MicroSD regulator minimum voltage: %d\n", err);
+ return;
+ }
+
+ err = fdt_nop_property(blob, offs, "gpios");
+ if (err < 0) {
+ printf("Failed to remove MicroSD regulator gpios: %d\n", err);
+ return;
+ }
+
+ err = fdt_nop_property(blob, offs, "gpios-states");
+ if (err < 0) {
+ printf("Failed to remove MicroSD regulator gpio states: %d\n", err);
+ return;
+ }
+
+ err = fdt_nop_property(blob, offs, "states");
+ if (err < 0) {
+ printf("Failed to remove MicroSD regulator states: %d\n", err);
+ return;
+ }
+
+ offs = fdt_path_offset(blob, "/soc/mmc@ee140000");
+ if (offs < 0) {
+ printf("Failed to locate MicroSD device node: %d\n", offs);
+ return;
+ }
+
+ err = fdt_nop_property(blob, offs, "sd-uhs-sdr50");
+ if (err < 0) {
+ printf("Failed to disable SDR50 mode in MicroSD node: %d\n", err);
+ return;
+ }
+
+ err = fdt_nop_property(blob, offs, "sd-uhs-sdr104");
+ if (err < 0) {
+ printf("Failed to disable SDR104 mode in MicroSD node: %d\n", err);
+ return;
+ }
+
+ err = fdt_setprop_string(blob, offs, "pinctrl-names", "default");
+ if (err < 0) {
+ printf("Failed to set fixed MicroSD pin names: %d\n", err);
+ return;
+ }
+
+ err = fdt_nop_property(blob, offs, "pinctrl-1");
+ if (err < 0) {
+ printf("Failed to disable UHS pins in MicroSD node: %d\n", err);
+ return;
+ }
+
+ offs = fdt_path_offset(blob, "/soc/pinctrl@e6050000/avb0/pins-vddq18-25-avb");
+ if (offs < 0) {
+ printf("Failed to locate AVB pinctrl node: %d\n", offs);
+ return;
+ }
+
+ err = fdt_setprop_u32(blob, offs, "power-source", 2500);
+ if (err < 0) {
+ printf("Failed to set AVB IO voltage: %d\n", err);
+ return;
+ }
+}
#endif
#define RST_MODEMR0 0xe6160000
@@ -130,7 +256,7 @@ void renesas_dram_init_banksize(void)
int bank;
/* 8 GiB device, do nothing. */
- if (!(modemr0 & BIT(19)))
+ if (!((renesas_get_cpu_rev_integer() >= 3) && (modemr0 & BIT(19))))
return;
/* 16 GiB device, adjust memory map. */
diff --git a/board/rockchip/evb_rk3588/MAINTAINERS b/board/rockchip/evb_rk3588/MAINTAINERS
index 1232f05a387..379c85f48a4 100644
--- a/board/rockchip/evb_rk3588/MAINTAINERS
+++ b/board/rockchip/evb_rk3588/MAINTAINERS
@@ -48,3 +48,9 @@ S: Maintained
F: configs/orangepi-5-plus-rk3588_defconfig
F: arch/arm/dts/rk3588-orangepi-5-plus.dts
F: arch/arm/dts/rk3588-orangepi-5-plus-u-boot.dtsi
+
+ORANGEPI-5-RK3588-ULTRA
+M: Niu Zhihong <zhihong@nzhnb.com>
+S: Maintained
+F: configs/orangepi-5-ultra-rk3588_defconfig
+F: arch/arm/dts/rk3588-orangepi-5-ultra-u-boot.dtsi
diff --git a/board/samsung/e850-96/Makefile b/board/samsung/e850-96/Makefile
index 71d46ea3d2b..76b8d47994e 100644
--- a/board/samsung/e850-96/Makefile
+++ b/board/samsung/e850-96/Makefile
@@ -3,4 +3,4 @@
# Copyright (C) 2024, Linaro Limited
# Sam Protsenko <semen.protsenko@linaro.org>
-obj-y := e850-96.o fw.o
+obj-y := e850-96.o fw.o acpm.o pmic.o
diff --git a/board/samsung/e850-96/acpm.c b/board/samsung/e850-96/acpm.c
new file mode 100644
index 00000000000..1cc5c6d0e4a
--- /dev/null
+++ b/board/samsung/e850-96/acpm.c
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2025 Linaro Ltd.
+ * Author: Sam Protsenko <semen.protsenko@linaro.org>
+ *
+ * ACPM (Active Clock and Power Management) is an IPC protocol for communicating
+ * with APM (Active Power Management) core. The message exchange between AP
+ * (Application Processor) and APM is happening by using shared memory in SRAM
+ * (iRAM) and generating interrupts using Mailbox block. By using this IPC
+ * interface it's possible to offload power management tasks to APM core, which
+ * acts as a supervisor for CPU. One of the main tasks of APM is controlling
+ * PMIC chip over I3C bus. So in order to access PMIC chip registers it's
+ * recommended to do so by sending corresponding commands to APM via ACPM IPC
+ * protocol. The IPC interaction sequence looks like this:
+ *
+ * AP (CPU) <-> ACPM IPC (Mailbox + SRAM) <-> APM <-> I3C <-> PMIC
+ *
+ * This file contains functions for accessing I3C bus via APM block using
+ * ACPM IPC.
+ */
+
+#include <linux/iopoll.h>
+#include <linux/time.h>
+#include <asm/io.h>
+#include "acpm.h"
+
+/* Mailbox registers */
+#define MBOX_INTGR0 0x8 /* Interrupt Generation */
+#define MBOX_INTCR1 0x20 /* Interrupt Clear */
+#define MBOX_INTSR1 0x28 /* Interrupt Status */
+#define MBOX_INTGR_OFFSET 16
+#define MBOX_TIMEOUT (1 * USEC_PER_SEC)
+
+/* APM shared memory registers */
+#define SHMEM_SR0 0x0
+#define SHMEM_SR1 0x4
+#define SHMEM_SR2 0x8
+#define SHMEM_SR3 0xc
+
+/* IPC functions */
+#define IPC_FUNC_READ 0x0
+#define IPC_FUNC_WRITE 0x1
+/* Command 0 shifts and masks */
+#define IPC_REG_SHIFT 0
+#define IPC_REG_MASK 0xff
+#define IPC_TYPE_SHIFT 8
+#define IPC_TYPE_MASK 0xf
+#define IPC_CHANNEL_SHIFT 12
+#define IPC_CHANNEL_MASK 0xf
+/* Command 1 shifts and masks */
+#define IPC_FUNC_SHIFT 0
+#define IPC_FUNC_MASK 0xff
+#define IPC_WRITE_VAL_SHIFT 8
+#define IPC_WRITE_VAL_MASK 0xff
+/* Command 3 shifts and masks */
+#define IPC_DEST_SHIFT 8
+#define IPC_DEST_MASK 0xff
+#define IPC_RETURN_SHIFT 24
+#define IPC_RETURN_MASK 0xff
+
+/**
+ * acpm_ipc_send_data_async() - Send data to I3C block over ACPM IPC
+ * @acpm: ACPM data
+ * @cmd0: Command 0 value to send
+ * @cmd1: Command 1 value to send
+ */
+static void acpm_ipc_send_data_async(struct acpm *acpm, u32 cmd0, u32 cmd1)
+{
+ u32 irq_bit = 1 << acpm->ipc_ch;
+ u32 intgr = irq_bit << MBOX_INTGR_OFFSET;
+
+ /* Write data to the shared memory */
+ writel(cmd0, acpm->sram_base + SHMEM_SR0);
+ writel(cmd1, acpm->sram_base + SHMEM_SR1);
+ dsb();
+
+ /* Generate interrupt for I3C block */
+ writel(intgr, acpm->mbox_base + MBOX_INTGR0);
+}
+
+/**
+ * acpm_ipc_wait_resp() - Read response data from I3C block over ACPM IPC
+ * @acpm: ACPM data
+ * @cmd2: Will contain read value for command 2
+ * @cmd3: Will contain read value for command 3
+ *
+ * Return: 0 on success or negative value on error.
+ */
+static int acpm_ipc_wait_resp(struct acpm *acpm, u32 *cmd2, u32 *cmd3)
+{
+ u32 irq_bit = 1 << acpm->ipc_ch;
+ u32 reg;
+ int ret;
+
+ /* Wait for the interrupt from I3C block */
+ ret = readl_poll_timeout(acpm->mbox_base + MBOX_INTSR1, reg,
+ reg & irq_bit, MBOX_TIMEOUT);
+ if (ret < 0)
+ return ret;
+
+ /* Clear the interrupt */
+ writel(irq_bit, acpm->mbox_base + MBOX_INTCR1);
+
+ /* Read data from the shared memory */
+ *cmd2 = readl(acpm->sram_base + SHMEM_SR2);
+ *cmd3 = readl(acpm->sram_base + SHMEM_SR3);
+
+ return 0;
+}
+
+/**
+ * acpm_i3c_read() - Read an I3C register of some I3C slave device
+ * @acpm: ACPM data
+ * @ch: I3C channel (bus) number (0-15)
+ * @addr: I3C address of slave device (0-15)
+ * @reg: Address of I3C register in the slave device to read from
+ * @val: Will contain the read value
+ *
+ * Return: 0 on success or non-zero code on error (may be positive).
+ */
+int acpm_i3c_read(struct acpm *acpm, u8 ch, u8 addr, u8 reg, u8 *val)
+{
+ u32 cmd[4] = { 0 };
+ u8 ret;
+
+ cmd[0] = (ch & IPC_CHANNEL_MASK) << IPC_CHANNEL_SHIFT |
+ (addr & IPC_TYPE_MASK) << IPC_TYPE_SHIFT |
+ (reg & IPC_REG_MASK) << IPC_REG_SHIFT;
+ cmd[1] = IPC_FUNC_READ << IPC_FUNC_SHIFT;
+
+ acpm_ipc_send_data_async(acpm, cmd[0], cmd[1]);
+ ret = acpm_ipc_wait_resp(acpm, &cmd[2], &cmd[3]);
+ if (ret)
+ return ret;
+
+ *val = (cmd[3] >> IPC_DEST_SHIFT) & IPC_DEST_MASK;
+ ret = (cmd[3] >> IPC_RETURN_SHIFT) & IPC_RETURN_MASK;
+ return ret;
+}
+
+/**
+ * acpm_i3c_write() - Write an I3C register of some I3C slave device
+ * @acpm: ACPM data
+ * @ch: I3C channel (bus) number (0-15)
+ * @addr: I3C address of slave device (0-15)
+ * @reg: Address of I3C register in the slave device to write into
+ * @val: Value to write
+ *
+ * Return: 0 on success or non-zero code on error (may be positive).
+ */
+int acpm_i3c_write(struct acpm *acpm, u8 ch, u8 addr, u8 reg, u8 val)
+{
+ u32 cmd[4] = { 0 };
+ u8 ret;
+
+ cmd[0] = (ch & IPC_CHANNEL_MASK) << IPC_CHANNEL_SHIFT |
+ (addr & IPC_TYPE_MASK) << IPC_TYPE_SHIFT |
+ (reg & IPC_REG_MASK) << IPC_REG_SHIFT;
+ cmd[1] = IPC_FUNC_WRITE << IPC_FUNC_SHIFT |
+ (val & IPC_WRITE_VAL_MASK) << IPC_WRITE_VAL_SHIFT;
+
+ acpm_ipc_send_data_async(acpm, cmd[0], cmd[1]);
+ ret = acpm_ipc_wait_resp(acpm, &cmd[2], &cmd[3]);
+ if (ret)
+ return ret;
+
+ ret = (cmd[3] >> IPC_RETURN_SHIFT) & IPC_RETURN_MASK;
+ return ret;
+}
diff --git a/board/samsung/e850-96/acpm.h b/board/samsung/e850-96/acpm.h
new file mode 100644
index 00000000000..9373969209f
--- /dev/null
+++ b/board/samsung/e850-96/acpm.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2025 Linaro Ltd.
+ * Sam Protsenko <semen.protsenko@linaro.org>
+ */
+
+#ifndef __E850_96_ACPM_H
+#define __E850_96_ACPM_H
+
+#include <linux/types.h>
+
+/**
+ * struct acpm - Data for I3C communication over ACPM IPC protocol
+ * @mbox_base: Base address of APM mailbox block
+ * @sram_base: Base address of shared memory used for APM messages
+ * @ipc_ch: Mailbox channel number used for communication with I3C block (0-15)
+ */
+struct acpm {
+ void __iomem *mbox_base;
+ void __iomem *sram_base;
+ u8 ipc_ch;
+};
+
+int acpm_i3c_read(struct acpm *acpm, u8 ch, u8 addr, u8 reg, u8 *val);
+int acpm_i3c_write(struct acpm *acpm, u8 ch, u8 addr, u8 reg, u8 val);
+
+#endif /* __E850_96_ACPM_H */
diff --git a/board/samsung/e850-96/e850-96.c b/board/samsung/e850-96/e850-96.c
index a6c264d1248..3df241edde2 100644
--- a/board/samsung/e850-96/e850-96.c
+++ b/board/samsung/e850-96/e850-96.c
@@ -8,13 +8,28 @@
#include <env.h>
#include <init.h>
#include <mapmem.h>
+#include <net.h>
+#include <usb.h>
#include <asm/io.h>
#include "fw.h"
+#include "pmic.h"
/* OTP Controller base address and register offsets */
-#define EXYNOS850_OTP_BASE 0x10000000
-#define OTP_CHIPID0 0x4
-#define OTP_CHIPID1 0x8
+#define EXYNOS850_OTP_BASE 0x10000000
+#define OTP_CHIPID0 0x4
+#define OTP_CHIPID1 0x8
+
+/* ACPM and PMIC definitions */
+#define EXYNOS850_MBOX_APM2AP_BASE 0x11900000
+#define EXYNOS850_APM_SRAM_BASE 0x02039000 /* in iRAM */
+#define EXYNOS850_APM_SHMEM_OFFSET 0x3200
+#define EXYNOS850_IPC_AP_I3C 10
+
+/* LDFW firmware definitions */
+#define LDFW_NWD_ADDR 0x88000000
+#define EMMC_IFNAME "mmc"
+#define EMMC_DEV_NUM 0
+#define EMMC_ESP_PART 1
struct efi_fw_image fw_images[] = {
{
@@ -55,6 +70,13 @@ struct efi_capsule_update_info update_info = {
.images = fw_images,
};
+static struct acpm acpm = {
+ .mbox_base = (void __iomem *)EXYNOS850_MBOX_APM2AP_BASE,
+ .sram_base = (void __iomem *)(EXYNOS850_APM_SRAM_BASE +
+ EXYNOS850_APM_SHMEM_OFFSET),
+ .ipc_ch = EXYNOS850_IPC_AP_I3C,
+};
+
int dram_init(void)
{
return fdtdec_setup_mem_size_base();
@@ -92,19 +114,74 @@ static void setup_serial(void)
env_set("serial#", serial_str);
}
-int board_late_init(void)
+static void setup_ethaddr(void)
+{
+ u64 serial_num;
+ u32 mac_hi, mac_lo;
+ u8 mac_addr[6];
+
+ if (env_get("ethaddr"))
+ return;
+
+ serial_num = get_chip_id();
+ mac_lo = (u32)serial_num; /* OTP_CHIPID0 */
+ mac_hi = (u32)(serial_num >> 32UL); /* OTP_CHIPID1 */
+ mac_addr[0] = (mac_hi >> 8) & 0xff;
+ mac_addr[1] = mac_hi & 0xff;
+ mac_addr[2] = (mac_lo >> 24) & 0xff;
+ mac_addr[3] = (mac_lo >> 16) & 0xff;
+ mac_addr[4] = (mac_lo >> 8) & 0xff;
+ mac_addr[5] = mac_lo & 0xff;
+ mac_addr[0] &= ~0x1; /* make sure it's not a multicast address */
+ if (is_valid_ethaddr(mac_addr))
+ eth_env_set_enetaddr("ethaddr", mac_addr);
+}
+
+/*
+ * Call this in board_late_init() to avoid probing block devices before
+ * efi_init_early().
+ */
+void load_firmware(void)
{
+ const char *ifname;
+ ulong dev, part;
int err;
+ ifname = env_get("bootdev");
+ if (!ifname)
+ ifname = EMMC_IFNAME;
+ dev = env_get_ulong("bootdevnum", 10, EMMC_DEV_NUM);
+ part = env_get_ulong("bootdevpart", 10, EMMC_ESP_PART);
+
+ if (!strcmp(ifname, "usb")) {
+ printf("Starting USB (bootdev=usb)...\n");
+ err = usb_init();
+ if (err)
+ return;
+ }
+
+ printf("Loading LDFW firmware (from %s %ld)...\n", ifname, dev);
+ err = load_ldfw(ifname, dev, part, LDFW_NWD_ADDR);
+ if (err)
+ printf("ERROR: LDFW loading failed (%d)\n", err);
+}
+
+int board_late_init(void)
+{
setup_serial();
+ setup_ethaddr();
+ load_firmware();
- /*
- * Do this in board_late_init() to make sure MMC is not probed before
- * efi_init_early().
- */
- err = load_ldfw();
+ return 0;
+}
+
+int power_init_board(void)
+{
+ int err;
+
+ err = pmic_init(&acpm);
if (err)
- printf("ERROR: LDFW loading failed (%d)\n", err);
+ printf("ERROR: Failed to configure PMIC (%d)\n", err);
return 0;
}
diff --git a/board/samsung/e850-96/e850-96.env b/board/samsung/e850-96/e850-96.env
index aed7a71046d..992318b0ab2 100644
--- a/board/samsung/e850-96/e850-96.env
+++ b/board/samsung/e850-96/e850-96.env
@@ -5,7 +5,7 @@ fdt_addr_r=0x8c000000
scriptaddr=0x8c100000
pxefile_addr_r=0x8c200000
ramdisk_addr_r=0x8c300000
-fdtfile=CONFIG_DEFAULT_FDT_FILE
+fdtfile=exynos/exynos850-e850-96.dtb
dfu_alt_info=
rawemmc raw 0 0x747c000 mmcpart 1;
diff --git a/board/samsung/e850-96/fw.c b/board/samsung/e850-96/fw.c
index 8f64e759b43..64235c01a25 100644
--- a/board/samsung/e850-96/fw.c
+++ b/board/samsung/e850-96/fw.c
@@ -11,13 +11,9 @@
#include <linux/arm-smccc.h>
#include "fw.h"
-#define EMMC_IFACE "mmc"
-#define EMMC_DEV_NUM 0
#define LDFW_RAW_PART "ldfw"
-#define LDFW_FAT_PART "esp"
#define LDFW_FAT_PATH "/EFI/firmware/ldfw.bin"
-#define LDFW_NWD_ADDR 0x88000000
#define LDFW_MAGIC 0x10adab1e
#define SMC_CMD_LOAD_LDFW -0x500
#define SDM_HW_RESET_STATUS 0x1230
@@ -39,19 +35,23 @@ struct ldfw_header {
};
/* Load LDFW binary as a file from FAT partition */
-static int read_fw_from_fat(const char *part_name, const char *path, void *buf)
+static int read_fw_from_fat(const char *ifname, int dev, int part,
+ const char *path, void *buf)
{
- char dev_part_str[8];
+ struct blk_desc *blk_desc;
loff_t len_read;
int err;
- snprintf(dev_part_str, sizeof(dev_part_str), "%d#%s", EMMC_DEV_NUM,
- LDFW_FAT_PART);
+ blk_desc = blk_get_dev(ifname, dev);
+ if (!blk_desc) {
+ debug("%s: Can't get block device\n", __func__);
+ return -ENODEV;
+ }
- err = fs_set_blk_dev(EMMC_IFACE, dev_part_str, FS_TYPE_FAT);
+ err = fs_set_blk_dev_with_part(blk_desc, part);
if (err) {
- debug("%s: Can't set block device\n", __func__);
- return -ENODEV;
+ debug("%s: Can't set partition\n", __func__);
+ return -ENOENT;
}
err = fs_read(path, (ulong)buf, 0, 0, &len_read);
@@ -64,16 +64,17 @@ static int read_fw_from_fat(const char *part_name, const char *path, void *buf)
}
/* Load LDFW binary from raw partition on block device into RAM buffer */
-static int read_fw_from_raw(const char *part_name, void *buf)
+static int read_fw_from_raw(const char *ifname, int dev, const char *part_name,
+ void *buf)
{
struct blk_desc *blk_desc;
struct disk_partition part;
unsigned long cnt;
int part_num;
- blk_desc = blk_get_dev(EMMC_IFACE, EMMC_DEV_NUM);
+ blk_desc = blk_get_dev(ifname, dev);
if (!blk_desc) {
- debug("%s: Can't get eMMC device\n", __func__);
+ debug("%s: Can't get block device\n", __func__);
return -ENODEV;
}
@@ -92,9 +93,17 @@ static int read_fw_from_raw(const char *part_name, void *buf)
return 0;
}
-int load_ldfw(void)
+/**
+ * load_ldfw - Load the loadable firmware (LDFW)
+ * @ifname: Interface name of the block device to load the firmware from
+ * @dev: Device number
+ * @part: Partition number
+ * @addr: Temporary memory (Normal World) to use for loading the firmware
+ *
+ * Return: 0 on success or a negative value on error.
+ */
+int load_ldfw(const char *ifname, int dev, int part, phys_addr_t addr)
{
- const phys_addr_t addr = (phys_addr_t)LDFW_NWD_ADDR;
struct ldfw_header *hdr;
struct arm_smccc_res res;
void *buf = (void *)addr;
@@ -102,9 +111,9 @@ int load_ldfw(void)
int err, i;
/* First try to read LDFW from EFI partition, then from the raw one */
- err = read_fw_from_fat(LDFW_FAT_PART, LDFW_FAT_PATH, buf);
+ err = read_fw_from_fat(ifname, dev, part, LDFW_FAT_PATH, buf);
if (err) {
- err = read_fw_from_raw(LDFW_RAW_PART, buf);
+ err = read_fw_from_raw(ifname, dev, LDFW_RAW_PART, buf);
if (err)
return err;
}
diff --git a/board/samsung/e850-96/fw.h b/board/samsung/e850-96/fw.h
index 472664e4ed2..73d9615d4a9 100644
--- a/board/samsung/e850-96/fw.h
+++ b/board/samsung/e850-96/fw.h
@@ -7,6 +7,8 @@
#ifndef __E850_96_FW_H
#define __E850_96_FW_H
-int load_ldfw(void);
+#include <asm/types.h>
+
+int load_ldfw(const char *ifname, int dev, int part, phys_addr_t addr);
#endif /* __E850_96_FW_H */
diff --git a/board/samsung/e850-96/pmic.c b/board/samsung/e850-96/pmic.c
new file mode 100644
index 00000000000..037fd4844c5
--- /dev/null
+++ b/board/samsung/e850-96/pmic.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2025 Linaro Ltd.
+ * Author: Sam Protsenko <semen.protsenko@linaro.org>
+ *
+ * This file contains functions for S2MPU12 PMIC regulators configuration.
+ *
+ * Example of voltage calculation for LDO24 and LDO32:
+ * - V_min = 1800 mV
+ * - V_step = 25 mV
+ * - V_wanted = 3300 mV
+ * - register value: (V_wanted - V_min) / V_step = 60 = 0x3c
+ *
+ * NOTE: 0x3c value might mean different voltage for other LDOs.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include "pmic.h"
+
+/* PMIC definitions */
+#define S2MPU12_CHANNEL 0 /* I3C bus number of PMIC */
+#define S2MPU12_PM_ADDR 0x1 /* I3C slave addr of PM part */
+
+/* PMIC I3C registers */
+#define S2MPU12_PM_LDO1_CTRL 0x2b
+#define S2MPU12_PM_LDO_CTRL(n) (S2MPU12_PM_LDO1_CTRL + (n) - 1)
+
+/* LDOx_CTRL values */
+#define S2MPU12_LDO_CTRL_OUT_MASK (0x3 << 6)
+#define S2MPU12_LDO_CTRL_OUT_ALWAYS_ON (0x3 << 6)
+
+struct pmic_ldo {
+ u8 num; /* LDO number */
+ u8 en; /* "enable" bits value in LDOx_CTRL register */
+ u8 out; /* "output voltage" bits value in LDOx_CTRL register */
+};
+
+/* List of LDOs to enable only */
+static u8 pmic_ldos_en[] = {
+ 2, /* 1.8V/450mA: multiple lines */
+ 11, /* 3.0V/150mA: AVDD33_USB20 */
+ 23, /* 2.85V/800mA: VDD_EMMC_2P85 */
+ 27, /* 3.0V/150mA: MIPI_SWITCH_3V3 */
+ 28, /* 1.8V/150mA: HDMI_CONV_1V8 */
+ 30, /* 1.8V/150mA: NPU_VDD18 */
+};
+
+/* List of LDOs to enable and set output voltage */
+static struct pmic_ldo pmic_ldos_en_out[] = {
+ {
+ .num = 24, /* 3.0V/800mA: VDD_LAN (LAN9514) */
+ .en = S2MPU12_LDO_CTRL_OUT_ALWAYS_ON,
+ .out = 0x3c, /* means 3.3V for LDO24 */
+ }, {
+ .num = 32, /* 3.3V/300mA: CAM_VDD (RPi camera module) */
+ .en = S2MPU12_LDO_CTRL_OUT_ALWAYS_ON,
+ .out = 0x3c, /* means 3.3V for LDO32 */
+ },
+};
+
+/* Enable specified LDO */
+static int pmic_ldo_set_en(struct acpm *acpm, u8 ldo)
+{
+ const u8 reg = S2MPU12_PM_LDO_CTRL(ldo);
+ u8 val;
+ int err;
+
+ err = acpm_i3c_read(acpm, S2MPU12_CHANNEL, S2MPU12_PM_ADDR, reg, &val);
+ if (err)
+ return err;
+
+ val &= ~S2MPU12_LDO_CTRL_OUT_MASK;
+ val |= S2MPU12_LDO_CTRL_OUT_ALWAYS_ON;
+
+ return acpm_i3c_write(acpm, S2MPU12_CHANNEL, S2MPU12_PM_ADDR, reg, val);
+}
+
+/* Enable specified LDO and set its voltage to 0xc0 value */
+static int pmic_ldo_set_en_out(struct acpm *acpm, struct pmic_ldo *ldo)
+{
+ const u8 reg = S2MPU12_PM_LDO_CTRL(ldo->num);
+ const u8 val = ldo->en | ldo->out;
+
+ return acpm_i3c_write(acpm, S2MPU12_CHANNEL, S2MPU12_PM_ADDR, reg, val);
+}
+
+#ifdef DEBUG
+static void pmic_trace_ldo(struct acpm *acpm, u8 ldo)
+{
+ const u8 reg = S2MPU12_PM_LDO_CTRL(ldo);
+ u8 val;
+ int err;
+
+ err = acpm_i3c_read(acpm, S2MPU12_CHANNEL, S2MPU12_PM_ADDR, reg, &val);
+ if (err)
+ printf(" S2MPU12_PM_LDO%u_CTRL: Read error!\n", ldo);
+ else
+ printf(" S2MPU12_PM_LDO%u_CTRL: 0x%x\n", ldo, val);
+}
+
+static void pmic_trace_ldos(struct acpm *acpm)
+{
+ size_t i;
+
+ printf("Tracing LDOs...\n");
+ for (i = 0; i < ARRAY_SIZE(pmic_ldos_en); ++i)
+ pmic_trace_ldo(acpm, pmic_ldos_en[i]);
+ for (i = 0; i < ARRAY_SIZE(pmic_ldos_en_out); ++i)
+ pmic_trace_ldo(acpm, pmic_ldos_en_out[i].num);
+}
+#endif
+
+/**
+ * pmic_init() - Enable power regulators in S2MPU12 PMIC.
+ * @acpm: Data for I3C communication with PMIC over ACPM protocol
+ *
+ * Enable LDOs needed for devices used in the bootloader and kernel.
+ *
+ * Return: 0 on success or non-zero code on error.
+ */
+int pmic_init(struct acpm *acpm)
+{
+ size_t i;
+ int err;
+
+ for (i = 0; i < ARRAY_SIZE(pmic_ldos_en); ++i) {
+ err = pmic_ldo_set_en(acpm, pmic_ldos_en[i]);
+ if (err)
+ return -EIO;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pmic_ldos_en_out); ++i) {
+ err = pmic_ldo_set_en_out(acpm, &pmic_ldos_en_out[i]);
+ if (err)
+ return -EIO;
+ }
+
+#ifdef DEBUG
+ pmic_trace_ldos(acpm);
+#endif
+
+ return 0;
+}
diff --git a/board/samsung/e850-96/pmic.h b/board/samsung/e850-96/pmic.h
new file mode 100644
index 00000000000..46624c2ebd4
--- /dev/null
+++ b/board/samsung/e850-96/pmic.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2025 Linaro Ltd.
+ * Sam Protsenko <semen.protsenko@linaro.org>
+ */
+
+#ifndef __E850_96_PMIC_H
+#define __E850_96_PMIC_H
+
+#include "acpm.h"
+
+int pmic_init(struct acpm *acpm);
+
+#endif /* __E850_96_PMIC_H */
diff --git a/board/theobroma-systems/jaguar_rk3588/jaguar_rk3588.c b/board/theobroma-systems/jaguar_rk3588/jaguar_rk3588.c
index a6d44f10db3..3f484646701 100644
--- a/board/theobroma-systems/jaguar_rk3588/jaguar_rk3588.c
+++ b/board/theobroma-systems/jaguar_rk3588/jaguar_rk3588.c
@@ -51,3 +51,22 @@ int rockchip_early_misc_init_r(void)
return 0;
}
+
+#define GPIO0B7_PU_EN BIT(15)
+
+void spl_board_init(void)
+{
+ /*
+ * GPIO0_B7 is routed to CAN TX. This SoC pin has a pull-down per default.
+ * So on power-up, we block the CAN bus with a dominant zero. We want to keep
+ * this blocking time to a minimum, so we want to get this pin high in SPL.
+ *
+ * The CAN driver in Linux disables the pull-down and sets the pin to
+ * output high. We don't have a CAN driver in U-Boot and don't need one,
+ * so we just use the easiest way to get the pin high, which is setting a
+ * pull-up.
+ */
+ struct rk3588_pmu2_ioc * const ioc = (void *)PMU2_IOC_BASE;
+
+ rk_setreg(&ioc->gpio0b_p, GPIO0B7_PU_EN);
+}
diff --git a/board/ti/am57xx/Kconfig b/board/ti/am57xx/Kconfig
index 0c566820158..b6943938391 100644
--- a/board/ti/am57xx/Kconfig
+++ b/board/ti/am57xx/Kconfig
@@ -9,6 +9,18 @@ config SYS_VENDOR
config SYS_CONFIG_NAME
default "am57xx_evm"
+config ENV_SOURCE_FILE
+ default "am57xx"
+
+source "board/ti/common/Kconfig"
+
+endif
+
+if TARGET_DRA7XX_EVM
+
+config ENV_SOURCE_FILE
+ default "am57xx"
+
source "board/ti/common/Kconfig"
endif
diff --git a/board/ti/am57xx/am57xx.env b/board/ti/am57xx/am57xx.env
new file mode 100644
index 00000000000..7d029a3e859
--- /dev/null
+++ b/board/ti/am57xx/am57xx.env
@@ -0,0 +1,162 @@
+#include <env/ti/ti_common.env>
+#include <env/ti/mmc.env>
+#include <env/ti/dfu.env>
+
+bootpart=0:2
+bootdir=/boot
+get_name_kern=
+ if test $boot_fit -eq 1; then
+ setenv bootfile fitImage;
+ else
+ setenv bootfile zImage;
+ fi
+get_fit_config=setenv name_fit_config ${fdtfile}
+console=ttyS2,115200n8
+fdtfile=undefined
+finduuid=part uuid mmc 0:2 uuid
+usbtty=cdc_acm
+vram=16M
+
+#if CONFIG_CMD_AVB
+avb_verify=avb init 1; avb verify $slot_suffix;
+#endif
+
+partitions=uuid_disk=${uuid_gpt_disk};
+ name=bootloader,start=384K,size=1792K,uuid=${uuid_gpt_bootloader};
+ name=rootfs,start=2688K,size=-,uuid=${uuid_gpt_rootfs}
+ partitions_android=
+ uuid_disk=${uuid_gpt_disk};
+ name=xloader,start=128K,size=256K,uuid=${uuid_gpt_xloader};
+ name=bootloader,size=2048K,uuid=${uuid_gpt_bootloader};
+ name=uboot-env,start=2432K,size=256K,uuid=${uuid_gpt_reserved};
+ name=misc,size=128K,uuid=${uuid_gpt_misc};
+ name=boot_a,size=20M,uuid=${uuid_gpt_boot_a};
+ name=boot_b,size=20M,uuid=${uuid_gpt_boot_b};
+ name=dtbo_a,size=8M,uuid=${uuid_gpt_dtbo_a};
+ name=dtbo_b,size=8M,uuid=${uuid_gpt_dtbo_b};
+ name=vbmeta_a,size=64K,uuid=${uuid_gpt_vbmeta_a};
+ name=vbmeta_b,size=64K,uuid=${uuid_gpt_vbmeta_b};
+ name=recovery,size=64M,uuid=${uuid_gpt_recovery};
+ name=super,size=2560M,uuid=${uuid_gpt_super};
+ name=metadata,size=16M,uuid=${uuid_gpt_metadata};
+ name=userdata,size=-,uuid=${uuid_gpt_userdata}
+optargs=
+dofastboot=0
+emmc_android_boot=
+ setenv mmcdev 1;
+ mmc dev $mmcdev;
+ mmc rescan;
+#if CONFIG_CMD_BCB
+#if CONFIG_ANDROID_AB
+ if part number mmc 1 misc control_part_number; then
+ echo "misc partition number:${control_part_number};"
+ bcb ab_select slot_name mmc ${mmcdev}:${control_part_number};
+ else
+ echo "misc partition not found;"
+ exit;
+ fi;
+ setenv slot_suffix _${slot_name};
+#endif
+#endif
+if bcb load CONFIG_FASTBOOT_FLASH_MMC_DEV misc; then
+ setenv ardaddr -;
+ if bcb test command = bootonce-bootloader; then
+ echo "Android: Bootloader boot...";
+ bcb clear command; bcb store;
+ fastboot 1;
+ exit;
+ elif bcb test command = boot-recovery; then
+ echo "Android: Recovery boot...";
+ setenv ardaddr $loadaddr;
+ setenv apart recovery;
+ else
+ echo "Android: Normal boot...";
+ setenv ardaddr $loadaddr;
+ setenv apart boot${slot_suffix};
+ fi;
+else
+ echo "Warning: BCB is corrupted or does not exist";
+ echo "Android: Normal boot...";
+fi;
+setenv eval_bootargs setenv bootargs $bootargs;
+run eval_bootargs;
+setenv machid fe6;
+#if CONFIG_CMD_AVB
+if run avb_verify; then
+ echo "AVB verification OK.";
+ set bootargs $bootargs $avb_bootargs;
+else
+ echo "AVB verification failed.";
+ exit;
+fi;
+#endif
+#if CONFIG_CMD_BCB
+#if CONFIG_ANDROID_AB
+setenv bootargs_ab androidboot.slot_suffix=${slot_suffix};
+echo "A/B cmdline addition: ${bootargs_ab}";
+setenv bootargs ${bootargs} ${bootargs_ab};
+#endif
+#endif
+if part start mmc $mmcdev $apart boot_start; then
+ part size mmc $mmcdev $apart boot_size;
+ mmc read $loadaddr $boot_start $boot_size;
+ echo "Preparing FDT...";
+ if test $board_name = am57xx_evm_reva3; then
+ echo " Reading DTBO partition...";
+ part start mmc ${mmcdev} dtbo${slot_suffix} p_dtbo_start;
+ part size mmc ${mmcdev} dtbo${slot_suffix} p_dtbo_size;
+ mmc read ${dtboaddr} ${p_dtbo_start} ${p_dtbo_size};
+ echo " Reading DTB for AM57x EVM RevA3...";
+ abootimg get dtb --index=0 dtb_start dtb_size;
+ cp.b $dtb_start $fdtaddr $dtb_size;
+ fdt addr $fdtaddr 0x80000;
+ echo " Applying DTBOs for AM57x EVM RevA3...";
+ adtimg addr $dtboaddr;
+ adtimg get dt --index=0 dtbo0_addr dtbo0_size;
+ fdt apply $dtbo0_addr;
+ adtimg get dt --index=1 dtbo1_addr dtbo1_size;
+ fdt apply $dtbo1_addr;
+ elif test $board_name = beagle_x15_revc; then
+ echo " Reading DTB for Beagle X15 RevC...";
+ abootimg get dtb --index=0 dtb_start dtb_size;
+ cp.b $dtb_start $fdtaddr $dtb_size;
+ fdt addr $fdtaddr 0x80000;
+ else
+ echo "Error: Android boot is not supported for $board_name";
+ exit;
+ fi;
+ bootm $loadaddr $ardaddr $fdtaddr;
+else
+ echo "$apart partition not found";
+ exit;
+fi;
+get_overlay_mmc=
+ fdt address ${fdtaddr};
+ fdt resize 0x100000;
+ for overlay in $name_overlays;
+ do;
+ load mmc ${bootpart} ${dtboaddr} ${bootdir}/dtb/${overlay};
+ fdt apply ${dtboaddr};
+ done;
+#if CONFIG_CMD_NET
+static_ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}::off
+nfsopts=nolock
+rootpath=/export/rootfs
+netloadimage=tftp ${loadaddr} ${bootfile}
+netloadfdt=tftp ${fdtaddr} ${fdtfile}
+netargs=setenv bootargs console=${console} ${optargs}
+ root=/dev/nfs
+ nfsroot=${serverip}:${rootpath},${nfsopts} rw
+ ip=dhcp
+netboot=echo Booting from network ...;
+ setenv autoload no;
+ dhcp;
+ run netloadimage;
+ run netloadfdt;
+ run netargs;
+ bootz ${loadaddr} - ${fdtaddr}
+#endif
+#if CONFIG_MTD_RAW_NAND
+#include <env/ti/nand.env>
+#endif
+dfu_bufsiz=0x10000
diff --git a/board/ti/am57xx/board.c b/board/ti/am57xx/board.c
index fc0d87daae4..4091601d4f2 100644
--- a/board/ti/am57xx/board.c
+++ b/board/ti/am57xx/board.c
@@ -42,6 +42,7 @@
#include "../common/board_detect.h"
#include "../common/cape_detect.h"
+#include "../common/fdt_ops.h"
#include "mux_data.h"
#ifdef CONFIG_SUPPORT_EMMC_BOOT
@@ -577,6 +578,18 @@ void do_board_detect(void)
"Board: %s REV %s\n", bname, board_ti_get_rev());
}
+static struct ti_fdt_map ti_omap_am57_evm_fdt_map[] = {
+ {"beagle_x15", "ti/omap/am57xx-beagle-x15.dtb"},
+ {"beagle_x15_revb1", "ti/omap/am57xx-beagle-x15-revb1.dtb"},
+ {"beagle_x15_revc", "ti/omap/am57xx-beagle-x15-revc.dtb"},
+ {"am5729_beagleboneai", "ti/omap/am5729-beagleboneai.dtb"},
+ {"am572x_idk", "ti/omap/am572x-idk.dtb"},
+ {"am574x_idk", "ti/omap/am574x-idk.dtb"},
+ {"am57xx_evm", "ti/omap/am57xx-beagle-x15.dtb"},
+ {"am57xx_evm_reva3", "ti/omap/am57xx-beagle-x15.dtb"},
+ {"am571x_idk", "ti/omap/am571x-idk.dtb"},
+};
+
static void setup_board_eeprom_env(void)
{
char *name = "beagle_x15";
@@ -614,6 +627,7 @@ static void setup_board_eeprom_env(void)
invalid_eeprom:
set_board_info_env(name);
+ ti_set_fdt_env(name, ti_omap_am57_evm_fdt_map);
}
#endif /* CONFIG_XPL_BUILD */
diff --git a/board/ti/dra7xx/evm.c b/board/ti/dra7xx/evm.c
index 98d63e14e29..0966db2bb62 100644
--- a/board/ti/dra7xx/evm.c
+++ b/board/ti/dra7xx/evm.c
@@ -38,6 +38,7 @@
#include "mux_data.h"
#include "../common/board_detect.h"
+#include "../common/fdt_ops.h"
#define board_is_dra76x_evm() board_ti_is("DRA76/7x")
#define board_is_dra74x_evm() board_ti_is("5777xCPU")
@@ -665,6 +666,15 @@ static int device_okay(const char *path)
}
#endif
+static struct ti_fdt_map ti_omap_dra7_evm_fdt_map[] = {
+ {"omap5_uevm", "ti/omap/omap5-uevm.dtb"},
+ {"dra7xx", "ti/omap/dra7-evm.dtb"},
+ {"dra72x-revc", "ti/omap/dra72-evm-revc.dtb"},
+ {"dra72x", "ti/omap/dra72-evm.dtb"},
+ {"dra71x", "ti/omap/dra71-evm.dtb"},
+ {"dra76x_acd", "ti/omap/dra76-evm.dtb"},
+};
+
int board_late_init(void)
{
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
@@ -686,6 +696,7 @@ int board_late_init(void)
}
set_board_info_env(name);
+ ti_set_fdt_env(name, ti_omap_dra7_evm_fdt_map);
/*
* Default FIT boot on HS devices. Non FIT images are not allowed
diff --git a/board/xunlong/orangepi-5-ultra-rk3588/Kconfig b/board/xunlong/orangepi-5-ultra-rk3588/Kconfig
new file mode 100644
index 00000000000..43fc96b04c0
--- /dev/null
+++ b/board/xunlong/orangepi-5-ultra-rk3588/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_ORANGEPI_5_ULTRA_RK3588
+
+config SYS_BOARD
+ default "orangepi-5-ultra-rk3588"
+
+config SYS_VENDOR
+ default "xunlong"
+
+config SYS_CONFIG_NAME
+ default "evb_rk3588"
+
+endif
diff --git a/board/xunlong/orangepi-5-ultra-rk3588/MAINTAINERS b/board/xunlong/orangepi-5-ultra-rk3588/MAINTAINERS
new file mode 100644
index 00000000000..be9c93f6b9d
--- /dev/null
+++ b/board/xunlong/orangepi-5-ultra-rk3588/MAINTAINERS
@@ -0,0 +1,6 @@
+ORANGEPI-5-RK3588-ULTRA
+M: Niu Zhihong <zhihong@nzhnb.com>
+S: Maintained
+F: board/xunlong/orangepi-5-rk3588-ultra
+F: configs/orangepi-5-ultra-rk3588_defconfig
+F: arch/arm/dts/rk3588-orangepi-5-ultra.dts