[PATCH v7 2/5] board: siemens: Add support for SIMATIC IOT2050 devices

Jan Kiszka
2021-08-03T14:24:26Z

From: Jan Kiszka <jan.kiszka@siemens.com>

This adds support for the IOT2050 Basic and Advanced devices. The Basic
used the dual-core AM6528 GP processor, the Advanced one the AM6548 HS
quad-core version.

Both variants are booted via a Siemens-provided FSBL that runs on the R5
cores. Consequently, U-Boot support is targeting the A53 cores. U-Boot
SPL, ATF and TEE have to reside in SPI flash.

Full integration into a bootable image can be found on
https://github.com/siemens/meta-iot2050

Based on original board support by Le Jin, Gao Nian and Chao Zeng.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
arch/arm/mach-k3/Kconfig | 1 +
board/siemens/iot2050/Kconfig | 32 ++++
board/siemens/iot2050/MAINTAINERS | 9 +
board/siemens/iot2050/Makefile | 10 ++
board/siemens/iot2050/board.c | 284 ++++++++++++++++++++++++++++++
board/siemens/iot2050/config.mk | 8 +
configs/iot2050_defconfig | 132 ++++++++++++++
doc/board/index.rst | 1 +
doc/board/siemens/index.rst | 9 +
doc/board/siemens/iot2050.rst | 76 ++++++++
include/configs/iot2050.h | 62 +++++++
11 files changed, 624 insertions(+)
create mode 100644 board/siemens/iot2050/Kconfig
create mode 100644 board/siemens/iot2050/MAINTAINERS
create mode 100644 board/siemens/iot2050/Makefile
create mode 100644 board/siemens/iot2050/board.c
create mode 100644 board/siemens/iot2050/config.mk
create mode 100644 configs/iot2050_defconfig
create mode 100644 doc/board/siemens/index.rst
create mode 100644 doc/board/siemens/iot2050.rst
create mode 100644 include/configs/iot2050.h

diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig
index fa8d134b42..526f5f8b76 100644
--- a/arch/arm/mach-k3/Kconfig
+++ b/arch/arm/mach-k3/Kconfig
@@ -168,4 +168,5 @@ config K3_DM_FW
source "board/ti/am65x/Kconfig"
source "board/ti/am64x/Kconfig"
source "board/ti/j721e/Kconfig"
+source "board/siemens/iot2050/Kconfig"
endif
diff --git a/board/siemens/iot2050/Kconfig b/board/siemens/iot2050/Kconfig
new file mode 100644
index 0000000000..8f634c172c
--- /dev/null
+++ b/board/siemens/iot2050/Kconfig
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) Siemens AG, 2018-2021
+#
+# Authors:
+# Le Jin <le.jin@siemens.com>
+# Jan Kiszka <jan.kiszka@siemens.com>
+
+config TARGET_IOT2050_A53
+ bool "IOT2050 running on A53"
+ select ARM64
+ select SOC_K3_AM6
+ select BOARD_LATE_INIT
+ select SYS_DISABLE_DCACHE_OPS
+ select BINMAN
+
+if TARGET_IOT2050_A53
+
+config SYS_BOARD
+ default "iot2050"
+
+config SYS_VENDOR
+ default "siemens"
+
+config SYS_CONFIG_NAME
+ default "iot2050"
+
+config IOT2050_BOOT_SWITCH
+ bool "Disable eMMC boot via USER button (Advanced version only)"
+ default y
+
+endif
diff --git a/board/siemens/iot2050/MAINTAINERS b/board/siemens/iot2050/MAINTAINERS
new file mode 100644
index 0000000000..1b525356c2
--- /dev/null
+++ b/board/siemens/iot2050/MAINTAINERS
@@ -0,0 +1,9 @@
+IOT2050 BOARD
+M: Le Jin <le.jin@siemens.com>
+M: Jan Kiszka <jan.kiszka@siemens.com>
+S: Maintained
+F: board/siemens/iot2050/
+F: include/configs/iot2050.h
+F: configs/iot2050_defconfig
+F: arch/arm/dts/iot2050-*
+F: doc/board/siemens/iot2050.rst
diff --git a/board/siemens/iot2050/Makefile b/board/siemens/iot2050/Makefile
new file mode 100644
index 0000000000..619594ab8e
--- /dev/null
+++ b/board/siemens/iot2050/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Makefile for Siemens IOT2050 board
+# Copyright (c) Siemens AG, 2018-2021
+#
+# Authors:
+# Le Jin <le.jin@siemens.com>
+#
+
+obj-y += board.o
diff --git a/board/siemens/iot2050/board.c b/board/siemens/iot2050/board.c
new file mode 100644
index 0000000000..cc84081296
--- /dev/null
+++ b/board/siemens/iot2050/board.c
@@ -0,0 +1,284 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Board specific initialization for IOT2050
+ * Copyright (c) Siemens AG, 2018-2021
+ *
+ * Authors:
+ * Le Jin <le.jin@siemens.com>
+ * Jan Kiszka <jan.kiszka@siemens.com>
+ */
+
+#include <common.h>
+#include <bootstage.h>
+#include <dm.h>
+#include <i2c.h>
+#include <led.h>
+#include <malloc.h>
+#include <net.h>
+#include <phy.h>
+#include <spl.h>
+#include <version.h>
+#include <linux/delay.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/hardware.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+
+#define IOT2050_INFO_MAGIC 0x20502050
+
+struct iot2050_info {
+ u32 magic;
+ u16 size;
+ char name[20 + 1];
+ char serial[16 + 1];
+ char mlfb[18 + 1];
+ char uuid[32 + 1];
+ char a5e[18 + 1];
+ u8 mac_addr_cnt;
+ u8 mac_addr[8][ARP_HLEN];
+ char seboot_version[40 + 1];
+} __packed;
+
+/*
+ * Scratch SRAM (available before DDR RAM) contains extracted EEPROM data.
+ */
+#define IOT2050_INFO_DATA ((struct iot2050_info *) \
+ TI_SRAM_SCRATCH_BOARD_EEPROM_START)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static bool board_is_advanced(void)
+{
+ struct iot2050_info *info = IOT2050_INFO_DATA;
+
+ return info->magic == IOT2050_INFO_MAGIC &&
+ !strcmp((char *)info->name, "IOT2050-ADVANCED");
+}
+
+static void remove_mmc1_target(void)
+{
+ char *boot_targets = strdup(env_get("boot_targets"));
+ char *mmc1 = strstr(boot_targets, "mmc1");
+
+ if (mmc1) {
+ memmove(mmc1, mmc1 + 4, strlen(mmc1 + 4) + 1);
+ env_set("boot_targets", boot_targets);
+ }
+
+ free(boot_targets);
+}
+
+void set_board_info_env(void)
+{
+ struct iot2050_info *info = IOT2050_INFO_DATA;
+ u8 __maybe_unused mac_cnt;
+
+ if (info->magic != IOT2050_INFO_MAGIC) {
+ pr_err("IOT2050: Board info parsing error!\n");
+ return;
+ }
+
+ if (env_get("board_uuid"))
+ return;
+
+ env_set("board_name", info->name);
+ env_set("board_serial", info->serial);
+ env_set("mlfb", info->mlfb);
+ env_set("board_uuid", info->uuid);
+ env_set("board_a5e", info->a5e);
+ env_set("fw_version", PLAIN_VERSION);
+ env_set("seboot_version", info->seboot_version);
+
+ if (IS_ENABLED(CONFIG_NET)) {
+ /* MAC address */
+ for (mac_cnt = 0; mac_cnt < info->mac_addr_cnt; mac_cnt++) {
+ if (is_valid_ethaddr(info->mac_addr[mac_cnt]))
+ eth_env_set_enetaddr_by_index("eth",
+ mac_cnt + 1,
+ info->mac_addr[mac_cnt]);
+ }
+
+ /*
+ * Set the MAC address environment variable that ICSSG0-PRU eth0 will
+ * use in u-boot
+ */
+ env_set("ethaddr", env_get("eth1addr"));
+ }
+
+ if (board_is_advanced()) {
+ env_set("fdtfile", "ti/k3-am6548-iot2050-advanced.dtb");
+ } else {
+ env_set("fdtfile", "ti/k3-am6528-iot2050-basic.dtb");
+ /* remove the unavailable eMMC (mmc1) from the list */
+ remove_mmc1_target();
+ }
+
+ env_save();
+}
+
+int board_init(void)
+{
+ return 0;
+}
+
+int dram_init(void)
+{
+ if (board_is_advanced())
+ gd->ram_size = SZ_2G;
+ else
+ gd->ram_size = SZ_1G;
+
+ return 0;
+}
+
+int dram_init_banksize(void)
+{
+ dram_init();
+
+ /* Bank 0 declares the memory available in the DDR low region */
+ gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
+ gd->bd->bi_dram[0].size = gd->ram_size;
+
+ /* Bank 1 declares the memory available in the DDR high region */
+ gd->bd->bi_dram[1].start = 0;
+ gd->bd->bi_dram[1].size = 0;
+
+ return 0;
+}
+
+#ifdef CONFIG_SPL_LOAD_FIT
+int board_fit_config_name_match(const char *name)
+{
+ struct iot2050_info *info = IOT2050_INFO_DATA;
+ char upper_name[32];
+
+ if (info->magic != IOT2050_INFO_MAGIC ||
+ strlen(name) >= sizeof(upper_name))
+ return -1;
+
+ str_to_upper(name, upper_name, sizeof(upper_name));
+ if (!strcmp(upper_name, (char *)info->name))
+ return 0;
+
+ return -1;
+}
+#endif
+
+int do_board_detect(void)
+{
+ return 0;
+}
+
+#ifdef CONFIG_IOT2050_BOOT_SWITCH
+static bool user_button_pressed(void)
+{
+ struct udevice *red_led = NULL;
+ unsigned long count = 0;
+ struct gpio_desc gpio;
+
+ memset(&gpio, 0, sizeof(gpio));
+
+ if (dm_gpio_lookup_name("25", &gpio) < 0 ||
+ dm_gpio_request(&gpio, "USER button") < 0 ||
+ dm_gpio_set_dir_flags(&gpio, GPIOD_IS_IN) < 0)
+ return false;
+
+ if (dm_gpio_get_value(&gpio) == 1)
+ return false;
+
+ printf("USER button pressed - booting from external media only\n");
+
+ led_get_by_label("status-led-red", &red_led);
+
+ if (red_led)
+ led_set_state(red_led, LEDST_ON);
+
+ while (dm_gpio_get_value(&gpio) == 0 && count++ < 10000)
+ mdelay(1);
+
+ if (red_led)
+ led_set_state(red_led, LEDST_OFF);
+
+ return true;
+}
+#endif
+
+#define SERDES0_LANE_SELECT 0x00104080
+
+int board_late_init(void)
+{
+ /* change CTRL_MMR register to let serdes0 not output USB3.0 signals. */
+ writel(0x3, SERDES0_LANE_SELECT);
+
+ set_board_info_env();
+
+ /* remove the eMMC if requested via button */
+ if (IS_ENABLED(CONFIG_IOT2050_BOOT_SWITCH) && board_is_advanced() &&
+ user_button_pressed())
+ remove_mmc1_target();
+
+ return 0;
+}
+
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
+int ft_board_setup(void *blob, struct bd_info *bd)
+{
+ int ret;
+
+ ret = fdt_fixup_msmc_ram(blob, "/bus@100000", "sram@70000000");
+ if (ret < 0)
+ ret = fdt_fixup_msmc_ram(blob, "/interconnect@100000",
+ "sram@70000000");
+ if (ret)
+ pr_err("%s: fixing up msmc ram failed %d\n", __func__, ret);
+
+ return ret;
+}
+#endif
+
+void spl_board_init(void)
+{
+}
+
+/* RJ45 LED configuration */
+#define DP83867_DEVADDR 0x1f
+
+#define DP83867_LEDCR_1 0x0018
+
+#define DP83867_LED_1000_BT_LINK 0x5
+#define DP83867_LED_100_BTX_LINK 0x6
+#define DP83867_LED_LINK_BLINK_ACTIVE 0xb
+#define DP83867_LED_SET(n, v) ((v) << ((n) * 4))
+
+#define DP83867_LED_SETTINGS \
+ (DP83867_LED_SET(0, DP83867_LED_LINK_BLINK_ACTIVE) | \
+ DP83867_LED_SET(1, DP83867_LED_1000_BT_LINK) | \
+ DP83867_LED_SET(2, DP83867_LED_100_BTX_LINK) | \
+ DP83867_LED_SET(3, DP83867_LED_100_BTX_LINK))
+
+int board_phy_config(struct phy_device *phydev)
+{
+ return phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_LEDCR_1,
+ DP83867_LED_SETTINGS);
+}
+
+#if CONFIG_IS_ENABLED(LED) && CONFIG_IS_ENABLED(BOOTSTAGE)
+/*
+ * Indicate any error or (accidental?) entering of CLI via the red status LED.
+ */
+void show_boot_progress(int progress)
+{
+ struct udevice *dev;
+ int ret;
+
+ if (progress < 0 || progress == BOOTSTAGE_ID_ENTER_CLI_LOOP) {
+ ret = led_get_by_label("status-led-green", &dev);
+ if (ret == 0)
+ led_set_state(dev, LEDST_OFF);
+
+ ret = led_get_by_label("status-led-red", &dev);
+ if (ret == 0)
+ led_set_state(dev, LEDST_ON);
+ }
+}
+#endif
diff --git a/board/siemens/iot2050/config.mk b/board/siemens/iot2050/config.mk
new file mode 100644
index 0000000000..267ec76c4e
--- /dev/null
+++ b/board/siemens/iot2050/config.mk
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) Siemens AG, 2020-2021
+#
+# Authors:
+# Jan Kiszka <jan.kiszka@siemens.com>
+
+flash.bin: all
diff --git a/configs/iot2050_defconfig b/configs/iot2050_defconfig
new file mode 100644
index 0000000000..6af8971aa5
--- /dev/null
+++ b/configs/iot2050_defconfig
@@ -0,0 +1,132 @@
+CONFIG_ARM=y
+CONFIG_ARCH_K3=y
+CONFIG_SPL_GPIO=y
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x8000
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_SOC_K3_AM6=y
+CONFIG_TARGET_IOT2050_A53=y
+CONFIG_ENV_SIZE=0x20000
+CONFIG_ENV_OFFSET=0x680000
+CONFIG_ENV_SECT_SIZE=0x20000
+CONFIG_SYS_SPI_U_BOOT_OFFS=0x280000
+CONFIG_DM_GPIO=y
+CONFIG_SPL_DM_SPI=y
+CONFIG_DEFAULT_DEVICE_TREE="k3-am6528-iot2050-basic"
+CONFIG_SPL_TEXT_BASE=0x80080000
+CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_SPL_STACK_R_ADDR=0x82000000
+CONFIG_ENV_OFFSET_REDUND=0x6a0000
+CONFIG_SPL_SPI_FLASH_SUPPORT=y
+CONFIG_SPL_SPI_SUPPORT=y
+CONFIG_DISTRO_DEFAULTS=y
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL_LOAD_FIT=y
+# CONFIG_USE_SPL_FIT_GENERATOR is not set
+CONFIG_OF_BOARD_SETUP=y
+CONFIG_BOOTSTAGE=y
+CONFIG_CONSOLE_MUX=y
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_SPL_BOARD_INIT=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_SEPARATE_BSS=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1400
+CONFIG_SPL_DM_MAILBOX=y
+CONFIG_SPL_DM_SPI_FLASH=y
+CONFIG_SPL_DM_RESET=y
+CONFIG_SPL_POWER_DOMAIN=y
+# CONFIG_SPL_SPI_FLASH_TINY is not set
+CONFIG_SPL_SPI_FLASH_SFDP_SUPPORT=y
+CONFIG_SPL_SPI_LOAD=y
+CONFIG_SYS_PROMPT="IOT2050> "
+CONFIG_CMD_ASKENV=y
+CONFIG_CMD_DFU=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PCI=y
+CONFIG_CMD_REMOTEPROC=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TIME=y
+# CONFIG_ISO_PARTITION is not set
+CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_LIST="k3-am6528-iot2050-basic k3-am6548-iot2050-advanced"
+CONFIG_SPL_MULTI_DTB_FIT=y
+CONFIG_SPL_OF_LIST="k3-am65-iot2050-spl"
+CONFIG_SPL_MULTI_DTB_FIT_NO_COMPRESSION=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
+# CONFIG_NET is not set
+CONFIG_DM=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SPL_OF_TRANSLATE=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_CLK_TI_SCI=y
+CONFIG_DFU_MMC=y
+CONFIG_DFU_RAM=y
+CONFIG_DFU_SF=y
+CONFIG_DMA_CHANNELS=y
+CONFIG_TI_K3_NAVSS_UDMA=y
+CONFIG_TI_SCI_PROTOCOL=y
+CONFIG_DA8XX_GPIO=y
+CONFIG_DM_PCA953X=y
+CONFIG_DM_I2C=y
+CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
+CONFIG_SYS_I2C_OMAP24XX=y
+CONFIG_LED=y
+CONFIG_SPL_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_SPL_LED_GPIO=y
+CONFIG_DM_MAILBOX=y
+CONFIG_K3_SEC_PROXY=y
+CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_ADMA=y
+CONFIG_MMC_SDHCI_AM654=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH_SFDP_SUPPORT=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_WINBOND=y
+# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
+CONFIG_DM_ETH=y
+CONFIG_PCI=y
+CONFIG_PCI_KEYSTONE=y
+CONFIG_PHY=y
+CONFIG_AM654_PHY=y
+CONFIG_OMAP_USB2_PHY=y
+CONFIG_PINCTRL=y
+# CONFIG_PINCTRL_GENERIC is not set
+CONFIG_SPL_PINCTRL=y
+# CONFIG_SPL_PINCTRL_GENERIC is not set
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_TI_SCI_POWER_DOMAIN=y
+CONFIG_REMOTEPROC_TI_K3_R5F=y
+CONFIG_DM_RESET=y
+CONFIG_RESET_TI_SCI=y
+CONFIG_DM_SERIAL=y
+CONFIG_SOC_DEVICE=y
+CONFIG_SOC_DEVICE_TI_K3=y
+CONFIG_SOC_TI=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_CADENCE_QSPI=y
+CONFIG_SYSRESET=y
+CONFIG_SPL_SYSRESET=y
+CONFIG_SYSRESET_TI_SCI=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_GENERIC=y
+CONFIG_USB_KEYBOARD=y
+CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/doc/board/index.rst b/doc/board/index.rst
index 9e90978891..9baa01e519 100644
--- a/doc/board/index.rst
+++ b/doc/board/index.rst
@@ -22,6 +22,7 @@ Board-specific doc
openpiton/index
qualcomm/index
rockchip/index
+ siemens/index
sifive/index
sipeed/index
socionext/index
diff --git a/doc/board/siemens/index.rst b/doc/board/siemens/index.rst
new file mode 100644
index 0000000000..082936ea7e
--- /dev/null
+++ b/doc/board/siemens/index.rst
@@ -0,0 +1,9 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Siemens
+=======
+
+.. toctree::
+ :maxdepth: 2
+
+ iot2050
diff --git a/doc/board/siemens/iot2050.rst b/doc/board/siemens/iot2050.rst
new file mode 100644
index 0000000000..1a5f7b1e6b
--- /dev/null
+++ b/doc/board/siemens/iot2050.rst
@@ -0,0 +1,76 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. sectionauthor:: Jan Kiszka <jan.kiszka@siemens.com>
+
+SIMATIC IOT2050 BASIC and ADVANCED
+==================================
+
+The SIMATIC IOT2050 is an open industrial IoT gateway that is using the TI
+AM6528 GP (Basic variant) or the AM6548 HS (Advanced variant). The Advanced
+variant is prepared for secure boot.
+
+The IOT2050 starts only from OSPI. It loads a Siemens-provided bootloader
+called SE-Boot for the MCU domain (R5F cores), then hands over to ATF and
+OP-TEE, before booting U-Boot on the A53 cores. This describes how to build all
+open artifacts into a flashable image for the OSPI flash. The flash image will
+work on both variants.
+
+Dependencies
+------------
+
+ATF: Upstream release 2.4 or newer
+OP-TEE: Upstream release 3.10.0 or newer
+
+Binary dependencies can be found in
+https://github.com/siemens/meta-iot2050/tree/master/recipes-bsp/u-boot/files/prebuild.
+The following binaries from that source need to be present in the build folder:
+
+ - tiboot3.bin
+ - sysfw.itb
+ - sysfw.itb_HS
+
+Building
+--------
+
+Make sure that CROSS_COMPILE is set appropriately:
+
+.. code-block:: text
+
+ $ export CROSS_COMPILE=aarch64-linux-gnu-
+
+ATF:
+
+.. code-block:: text
+
+ $ make PLAT=k3 SPD=opteed K3_USART=1
+
+OP-TEE:
+
+.. code-block:: text
+
+ $ make PLATFORM=k3-am65x CFG_ARM64_core=y CFG_TEE_CORE_LOG_LEVEL=2 CFG_CONSOLE_UART=1
+
+U-Boot:
+
+.. code-block:: text
+
+ $ export ATF=/path/to/bl31.bin
+ $ export TEE=/path/to/tee-pager_v2.bin
+ $ make iot2050_defconfig
+ $ make
+
+Flashing
+--------
+
+Via U-Boot:
+
+.. code-block:: text
+
+ IOT2050> sf probe
+ IOT2050> load mmc 0:1 $loadaddr /path/to/flash.bin
+ IOT2050> sf update $loadaddr 0x0 $filesize
+
+Via external programmer Dediprog SF100 or SF600:
+
+.. code-block:: text
+
+ $ dpcmd --vcc 2 -v -u flash.bin
diff --git a/include/configs/iot2050.h b/include/configs/iot2050.h
new file mode 100644
index 0000000000..6e00b905cc
--- /dev/null
+++ b/include/configs/iot2050.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Configuration header file for IOT2050
+ * Copyright (c) Siemens AG, 2018-2021
+ *
+ * Authors:
+ * Le Jin <le.jin@siemens.com>
+ * Jan Kiszka <jan.kiszk@siemens.com>
+ */
+
+#ifndef __CONFIG_IOT2050_H
+#define __CONFIG_IOT2050_H
+
+#include <linux/sizes.h>
+
+/* SPL Loader Configuration */
+#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + \
+ CONFIG_SYS_K3_NON_SECURE_MSRAM_SIZE)
+
+#define CONFIG_SKIP_LOWLEVEL_INIT
+
+#define CONFIG_SPL_MAX_SIZE CONFIG_SYS_K3_MAX_DOWNLODABLE_IMAGE_SIZE
+
+#define CONFIG_SYS_BOOTM_LEN SZ_64M
+
+/* U-Boot general configuration */
+#define EXTRA_ENV_IOT2050_BOARD_SETTINGS \
+ "usb_pgood_delay=900\0"
+
+#ifndef CONFIG_SPL_BUILD
+
+#if CONFIG_IS_ENABLED(CMD_USB)
+# define BOOT_TARGET_USB(func) \
+ func(USB, usb, 0) \
+ func(USB, usb, 1) \
+ func(USB, usb, 2)
+#else
+# define BOOT_TARGET_USB(func)
+#endif
+
+/*
+ * This defines all MMC devices, even if the basic variant has no mmc1.
+ * The non-supported device will be removed from the boot targets during
+ * runtime, when that board was detected.
+ */
+#define BOOT_TARGET_DEVICES(func) \
+ func(MMC, mmc, 1) \
+ func(MMC, mmc, 0) \
+ BOOT_TARGET_USB(func)
+
+#include <config_distro_bootcmd.h>
+
+#endif
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ DEFAULT_LINUX_BOOT_ENV \
+ BOOTENV \
+ EXTRA_ENV_IOT2050_BOARD_SETTINGS
+
+#include <configs/ti_armv7_common.h>
+
+#endif /* __CONFIG_IOT2050_H */
--
2.31.1