summaryrefslogtreecommitdiffstats
path: root/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7
diff options
context:
space:
mode:
Diffstat (limited to 'bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7')
-rw-r--r--bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0001-armv8-add-lx2160acex7-build-inclusion.patch75
-rw-r--r--bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0002-armv8-lx2160acex-misc-hacks-to-get-the-sources-built.patch44
-rw-r--r--bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0003-armv8-lx2160acex7-defconfig-and-main-platform-includ.patch192
-rw-r--r--bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0004-armv8-lx2160acex7-common-files-for-platform-support.patch1720
-rw-r--r--bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0005-armv8-lx2160acex7-lx2160acex-device-tree.patch91
-rw-r--r--bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0006-armv8-lx2160acex7-board-support-files.patch519
-rw-r--r--bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0007-lx2160a-load-dpl-into-0x80001000-instead-of-0x80d000.patch47
-rw-r--r--bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0008-uboot-add-nvme-commands-and-for-distroboot.patch41
-rw-r--r--bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0009-armv8-lx2160acex7-Fix-booting-from-NVMe-drives.patch33
-rw-r--r--bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0010-nvme-add-accessor-to-namespace-id-and-eui64.patch90
-rw-r--r--bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0011-nvme-flush-dcache-on-both-r-w-and-the-prp-list.patch51
-rw-r--r--bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0012-nvme-use-page-aligned-buffer-for-identify-command.patch94
-rw-r--r--bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0013-lx2160a-cex7-move-from-lsdk-19.06-to-lsdk-19.09.patch923
-rw-r--r--bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0014-lx2160acex7-pcie-fixup-and-boot-from-eMMC-print.patch128
-rw-r--r--bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0015-lx2160a-cex7-set-mmc-dev-to-0-when-attempting-sd_boo.patch32
-rw-r--r--bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0016-lx2160acex7-Misc-fixes-to-support-LSDK-20.04.patch127
-rw-r--r--bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0017-lx2160acex7-misc-fixes-to-get-booting-from-eMMC-func.patch70
17 files changed, 4277 insertions, 0 deletions
diff --git a/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0001-armv8-add-lx2160acex7-build-inclusion.patch b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0001-armv8-add-lx2160acex7-build-inclusion.patch
new file mode 100644
index 00000000..7837bfff
--- /dev/null
+++ b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0001-armv8-add-lx2160acex7-build-inclusion.patch
@@ -0,0 +1,75 @@
+From c24c3ec7d9591cf359ac12f656bd59a5440532f4 Mon Sep 17 00:00:00 2001
+From: Rabeeh Khoury <rabeeh@solid-run.com>
+Date: Sun, 28 Jul 2019 13:26:45 +0300
+Subject: [PATCH 01/17] armv8: add lx2160acex7 build inclusion
+
+Upstream-Status: Inappropriate [Solid-Run BSP]
+
+Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
+---
+ arch/arm/Kconfig | 13 +++++++++++++
+ arch/arm/cpu/armv8/Kconfig | 2 +-
+ arch/arm/dts/Makefile | 3 ++-
+ 3 files changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index 5d33526ae9..8615e1673f 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -1189,6 +1189,18 @@ config TARGET_LX2160ARDB
+ is a high-performance development platform that supports the
+ QorIQ LX2160A/LX2120A/LX2080A Layerscape Architecture processor.
+
++config TARGET_LX2160ACEX7
++ bool "Support lx2160acex7"
++ select ARCH_LX2160A
++ select ARCH_MISC_INIT
++ select ARM64
++ select ARMV8_MULTIENTRY
++ select BOARD_LATE_INIT
++ help
++ Support for SolidRun LX2160A based com express type 7 module and
++ platform. The lx2160acex7 high-performance platform that supports the
++ QorIQ LX2160A/LX2120A/LX2080A Layerscape Architecture processor.
++
+ config TARGET_LX2160AQDS
+ bool "Support lx2160aqds"
+ select ARCH_LX2160A
+@@ -1796,6 +1808,7 @@ source "board/freescale/ls1012aqds/Kconfig"
+ source "board/freescale/ls1012ardb/Kconfig"
+ source "board/freescale/ls1012afrdm/Kconfig"
+ source "board/freescale/lx2160a/Kconfig"
++source "board/solidrun/lx2160a/Kconfig"
+ source "board/freescale/mx35pdk/Kconfig"
+ source "board/freescale/s32v234evb/Kconfig"
+ source "board/grinn/chiliboard/Kconfig"
+diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig
+index 92a2b58ed4..9df6ebdc1b 100644
+--- a/arch/arm/cpu/armv8/Kconfig
++++ b/arch/arm/cpu/armv8/Kconfig
+@@ -109,7 +109,7 @@ config PSCI_RESET
+ !TARGET_LS1046ARDB && !TARGET_LS1046AQDS && \
+ !TARGET_LS1046AFRWY && \
+ !TARGET_LS2081ARDB && !TARGET_LX2160ARDB && \
+- !TARGET_LX2160AQDS && \
++ !TARGET_LX2160AQDS && !TARGET_LX2160ACEX7 && \
+ !ARCH_UNIPHIER && !TARGET_S32V234EVB
+ help
+ Most armv8 systems have PSCI support enabled in EL3, either through
+diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
+index 8d7d5bee45..6d8d7fa09e 100644
+--- a/arch/arm/dts/Makefile
++++ b/arch/arm/dts/Makefile
+@@ -348,7 +348,8 @@ dtb-$(CONFIG_FSL_LSCH3) += fsl-ls2080a-qds.dtb \
+ fsl-ls1028a-qds-duart.dtb \
+ fsl-ls1028a-qds-lpuart.dtb \
+ fsl-lx2160a-rdb.dtb \
+- fsl-lx2160a-qds.dtb
++ fsl-lx2160a-qds.dtb \
++ fsl-lx2160a-cex7.dtb
+ dtb-$(CONFIG_FSL_LSCH2) += fsl-ls1043a-qds-duart.dtb \
+ fsl-ls1043a-qds-lpuart.dtb \
+ fsl-ls1043a-rdb.dtb \
+--
+2.17.1
+
diff --git a/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0002-armv8-lx2160acex-misc-hacks-to-get-the-sources-built.patch b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0002-armv8-lx2160acex-misc-hacks-to-get-the-sources-built.patch
new file mode 100644
index 00000000..5b8d07f1
--- /dev/null
+++ b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0002-armv8-lx2160acex-misc-hacks-to-get-the-sources-built.patch
@@ -0,0 +1,44 @@
+From a8a182b435e96a22b01d722a8df3061c1a1b7da6 Mon Sep 17 00:00:00 2001
+From: Rabeeh Khoury <rabeeh@solid-run.com>
+Date: Sun, 28 Jul 2019 13:27:46 +0300
+Subject: [PATCH 02/17] armv8: lx2160acex: misc hacks to get the sources built
+
+those hacks will be sorted out nicer in the future and this patch will
+not be needed anymore
+
+Upstream-Status: Inappropriate [Solid-Run BSP]
+
+Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
+---
+ arch/arm/cpu/armv8/fsl-layerscape/Kconfig | 1 -
+ drivers/mmc/fsl_esdhc.c | 2 +-
+ 2 files changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
+index 42ca990994..efdc31da5d 100644
+--- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
++++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
+@@ -218,7 +218,6 @@ config ARCH_LX2160A
+ select SYS_FSL_DDR_LE
+ select SYS_FSL_DDR_VER_50
+ select SYS_FSL_EC1
+- select SYS_FSL_EC2
+ select SYS_FSL_ERRATUM_A050106
+ select SYS_FSL_HAS_RGMII
+ select SYS_FSL_HAS_SEC
+diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
+index f8e6ceba06..f4a7698cfd 100644
+--- a/drivers/mmc/fsl_esdhc.c
++++ b/drivers/mmc/fsl_esdhc.c
+@@ -1020,7 +1020,7 @@ static int fsl_esdhc_probe(struct udevice *dev)
+ priv->non_removable = 0;
+ }
+
+- priv->wp_enable = 1;
++ priv->wp_enable = 0;
+
+ if (IS_ENABLED(CONFIG_CLK)) {
+ /* Assigned clock already set clock */
+--
+2.17.1
+
diff --git a/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0003-armv8-lx2160acex7-defconfig-and-main-platform-includ.patch b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0003-armv8-lx2160acex7-defconfig-and-main-platform-includ.patch
new file mode 100644
index 00000000..cb968445
--- /dev/null
+++ b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0003-armv8-lx2160acex7-defconfig-and-main-platform-includ.patch
@@ -0,0 +1,192 @@
+From caaf386e5511e8b9708abf9ee52b668019a5b094 Mon Sep 17 00:00:00 2001
+From: Rabeeh Khoury <rabeeh@solid-run.com>
+Date: Sun, 28 Jul 2019 13:29:31 +0300
+Subject: [PATCH 03/17] armv8: lx2160acex7: defconfig and main platform include
+
+This patch add lx2160acex7 main defconfig and main include file.
+Notice that the defconfig doesn't support the secured boot mode where a
+follow up patch will cover this.
+
+Upstream-Status: Inappropriate [Solid-Run BSP]
+
+Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
+---
+ configs/lx2160acex7_tfa_defconfig | 73 ++++++++++++++++++++++++++
+ include/configs/lx2160acex7.h | 85 +++++++++++++++++++++++++++++++
+ 2 files changed, 158 insertions(+)
+ create mode 100644 configs/lx2160acex7_tfa_defconfig
+ create mode 100644 include/configs/lx2160acex7.h
+
+diff --git a/configs/lx2160acex7_tfa_defconfig b/configs/lx2160acex7_tfa_defconfig
+new file mode 100644
+index 0000000000..d59de7d054
+--- /dev/null
++++ b/configs/lx2160acex7_tfa_defconfig
+@@ -0,0 +1,73 @@
++CONFIG_ARM=y
++CONFIG_TARGET_LX2160ACEX7=y
++CONFIG_SYS_TEXT_BASE=0x82000000
++CONFIG_SYS_MALLOC_F_LEN=0x6000
++CONFIG_EMC2301=y
++CONFIG_TFABOOT=y
++CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT=y
++CONFIG_SEC_FIRMWARE_ARMV8_PSCI=y
++CONFIG_AHCI=y
++CONFIG_NR_DRAM_BANKS=3
++CONFIG_FIT_VERBOSE=y
++CONFIG_OF_BOARD_SETUP=y
++CONFIG_OF_BOARD_FIXUP=y
++CONFIG_OF_STDOUT_VIA_ALIAS=y
++CONFIG_BOOTDELAY=10
++CONFIG_USE_BOOTARGS=y
++CONFIG_BOOTARGS="console=ttyAMA0,115200 root=/dev/ram0 earlycon=pl011,mmio32,0x21c0000 ramdisk_size=0x2000000 default_hugepagesz=1024m hugepagesz=1024m hugepages=2 pci=pcie_bus_perf"
++# CONFIG_USE_BOOTCOMMAND is not set
++CONFIG_CMD_GREPENV=y
++CONFIG_CMD_EEPROM=y
++CONFIG_CMD_GPT=y
++CONFIG_CMD_I2C=y
++CONFIG_CMD_MMC=y
++CONFIG_CMD_PCI=y
++CONFIG_CMD_SF=y
++CONFIG_CMD_USB=y
++CONFIG_CMD_CACHE=y
++CONFIG_MP=y
++CONFIG_OF_CONTROL=y
++CONFIG_DEFAULT_DEVICE_TREE="fsl-lx2160a-cex7"
++CONFIG_ENV_IS_IN_MMC=y
++CONFIG_ENV_IS_IN_SPI_FLASH=y
++CONFIG_NET_RANDOM_ETHADDR=y
++CONFIG_DM=y
++CONFIG_SATA_CEVA=y
++CONFIG_FSL_CAAM=y
++CONFIG_DM_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_DM_SPI_FLASH=y
++CONFIG_SPI_FLASH=y
++CONFIG_SPI_FLASH_SPANSION=y
++CONFIG_SPI_FLASH_STMICRO=y
++CONFIG_SPI_FLASH_MICRON=y
++CONFIG_SPI_FLASH_WINBOND=y
++# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
++CONFIG_PHYLIB=y
++CONFIG_NETDEVICES=y
++CONFIG_PHY_GIGE=y
++CONFIG_CMD_NET=y
++CONFIG_CMD_PING=y
++CONFIG_CMD_PXE=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_FAT=y
++CONFIG_CMD_EXT2=y
++CONFIG_PCI=y
++CONFIG_DM_PCI=y
++CONFIG_DM_PCI_COMPAT=y
++CONFIG_PCIE_LAYERSCAPE_GEN4=y
++CONFIG_PHY_ATHEROS=y
++CONFIG_E1000=y
++CONFIG_DM_SCSI=y
++CONFIG_DM_SERIAL=y
++CONFIG_SERIAL_PROBE_ALL=y
++CONFIG_SPI=y
++CONFIG_DM_SPI=y
++CONFIG_NXP_FSPI=y
++# CONFIG_SYS_NXP_FSPI_AHB=y
++CONFIG_USB=y
++CONFIG_DM_USB=y
++CONFIG_USB_XHCI_HCD=y
++CONFIG_USB_XHCI_DWC3=y
++CONFIG_EFI_LOADER_BOUNCE_BUFFER=y
+diff --git a/include/configs/lx2160acex7.h b/include/configs/lx2160acex7.h
+new file mode 100644
+index 0000000000..478cd8242f
+--- /dev/null
++++ b/include/configs/lx2160acex7.h
+@@ -0,0 +1,85 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/*
++ * Copyright 2019 SolidRun ltd.
++ */
++
++#ifndef __LX2_CEX7_H
++#define __LX2_CEX7_H
++
++#include "lx2160a_common.h"
++
++/*#define CONFIG_SYS_FSL_ESDHC_USE_PIO*/
++/* VID */
++
++#define I2C_MUX_CH_VOL_MONITOR 0x2
++/* Voltage monitor on channel 2*/
++#define I2C_VOL_MONITOR_ADDR 0x5c
++#define I2C_VOL_MONITOR_BUS_V_OFFSET 0x2
++#define I2C_VOL_MONITOR_BUS_V_OVF 0x1
++#define I2C_VOL_MONITOR_BUS_V_SHIFT 3
++#define CONFIG_VID_FLS_ENV "lx2160acex7_vdd_mv"
++#define CONFIG_VID
++
++/* The lowest and highest voltage allowed*/
++#define VDD_MV_MIN 700
++#define VDD_MV_MAX 855
++
++/* PM Bus commands code for LTC3882*/
++#define PMBUS_CMD_PAGE 0x0
++#define PMBUS_CMD_READ_VOUT 0x8B
++#define PMBUS_CMD_PAGE_PLUS_WRITE 0x05
++#define PMBUS_CMD_VOUT_COMMAND 0x21
++#define PWM_CHANNEL0 0x0
++
++#define CONFIG_VOL_MONITOR_LTC3882_SET
++#define CONFIG_VOL_MONITOR_LTC3882_READ
++
++/* RTC */
++#define CONFIG_SYS_RTC_BUS_NUM 4
++
++/* MAC/PHY configuration */
++#if defined(CONFIG_FSL_MC_ENET)
++#define CONFIG_MII
++#define CONFIG_ETHPRIME "DPMAC17@rgmii-id"
++
++#define RGMII_PHY_ADDR1 0x01
++
++#endif
++
++/* EMC2301 */
++#define I2C_MUX_CH_EMC2301 0x01
++#define I2C_EMC2301_ADDR 0x2f
++#define I2C_EMC2301_CMD 0x40
++#define I2C_EMC2301_PWM 0x80
++
++/* EEPROM */
++#undef CONFIG_ID_EEPROM /* Fixme */
++#define CONFIG_SYS_I2C_EEPROM_NXID
++#define CONFIG_SYS_EEPROM_BUS_NUM 0
++#define CONFIG_SYS_I2C_EEPROM_ADDR 0x57
++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1
++#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 3
++#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5
++
++/* Initial environment variables */
++#define CONFIG_EXTRA_ENV_SETTINGS \
++ EXTRA_ENV_SETTINGS \
++ "lx2160acex7_vdd_mv=800\0" \
++ "BOARD=lx2160acex7\0" \
++ "xspi_bootcmd=echo Trying load from flexspi..;" \
++ "sf probe 0:0 && sf read $load_addr " \
++ "$kernel_start $kernel_size ; env exists secureboot &&" \
++ "sf read $kernelheader_addr_r $kernelheader_start " \
++ "$kernelheader_size && esbc_validate ${kernelheader_addr_r}; "\
++ " bootm $load_addr#$BOARD\0" \
++ "sd_bootcmd=echo Trying load from sd card..;" \
++ "mmcinfo; mmc read $load_addr " \
++ "$kernel_addr_sd $kernel_size_sd ;" \
++ "env exists secureboot && mmc read $kernelheader_addr_r "\
++ "$kernelhdr_addr_sd $kernelhdr_size_sd " \
++ " && esbc_validate ${kernelheader_addr_r};" \
++ "bootm $load_addr#$BOARD\0"
++
++#include <asm/fsl_secure_boot.h>
++
++#endif /* __LX2_CEX7_H */
+--
+2.17.1
+
diff --git a/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0004-armv8-lx2160acex7-common-files-for-platform-support.patch b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0004-armv8-lx2160acex7-common-files-for-platform-support.patch
new file mode 100644
index 00000000..cbb2f08c
--- /dev/null
+++ b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0004-armv8-lx2160acex7-common-files-for-platform-support.patch
@@ -0,0 +1,1720 @@
+From 568555bb88a6d2880e21f736cfda0b89e89957fa Mon Sep 17 00:00:00 2001
+From: Rabeeh Khoury <rabeeh@solid-run.com>
+Date: Sun, 28 Jul 2019 13:31:47 +0300
+Subject: [PATCH 04/17] armv8: lx2160acex7: common files for platform support
+
+The patch copies and modifies NXP's common platform resources that adds
+support to the following -
+1. Secureboot
+2. Analog devices DC-DC controller
+3. EMC2301 PWM fan controller based on NXP's EMC2305 driver
+
+Upstream-Status: Inappropriate [Solid-Run BSP]
+
+Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
+---
+ board/solidrun/common/Makefile | 24 +
+ board/solidrun/common/cmd_esbc_validate.c | 85 ++
+ board/solidrun/common/emc2301.c | 31 +
+ board/solidrun/common/emc2301.h | 17 +
+ board/solidrun/common/fsl_chain_of_trust.c | 164 ++++
+ board/solidrun/common/fsl_validate.c | 962 +++++++++++++++++++++
+ board/solidrun/common/vid.c | 330 +++++++
+ board/solidrun/common/vid.h | 23 +
+ 8 files changed, 1636 insertions(+)
+ create mode 100644 board/solidrun/common/Makefile
+ create mode 100644 board/solidrun/common/cmd_esbc_validate.c
+ create mode 100644 board/solidrun/common/emc2301.c
+ create mode 100644 board/solidrun/common/emc2301.h
+ create mode 100644 board/solidrun/common/fsl_chain_of_trust.c
+ create mode 100644 board/solidrun/common/fsl_validate.c
+ create mode 100644 board/solidrun/common/vid.c
+ create mode 100644 board/solidrun/common/vid.h
+
+diff --git a/board/solidrun/common/Makefile b/board/solidrun/common/Makefile
+new file mode 100644
+index 0000000000..454a18e2f9
+--- /dev/null
++++ b/board/solidrun/common/Makefile
+@@ -0,0 +1,24 @@
++# SPDX-License-Identifier: GPL-2.0+
++#
++# (C) Copyright 2006
++# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
++
++MINIMAL=
++
++ifdef CONFIG_SPL_BUILD
++ifdef CONFIG_SPL_INIT_MINIMAL
++MINIMAL=y
++endif
++endif
++
++ifdef MINIMAL
++# necessary to create built-in.o
++obj- := __dummy__.o
++else
++obj-$(CONFIG_VID) += vid.o
++obj-$(CONFIG_EMC2301) += emc2301.o
++ifdef CONFIG_SECURE_BOOT
++obj-$(CONFIG_CMD_ESBC_VALIDATE) += fsl_validate.o cmd_esbc_validate.o
++endif
++obj-$(CONFIG_CHAIN_OF_TRUST) += fsl_chain_of_trust.o
++endif
+diff --git a/board/solidrun/common/cmd_esbc_validate.c b/board/solidrun/common/cmd_esbc_validate.c
+new file mode 100644
+index 0000000000..b06235f291
+--- /dev/null
++++ b/board/solidrun/common/cmd_esbc_validate.c
+@@ -0,0 +1,85 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright 2015 Freescale Semiconductor, Inc.
++ */
++
++#include <common.h>
++#include <command.h>
++#include <fsl_validate.h>
++
++int do_esbc_halt(cmd_tbl_t *cmdtp, int flag, int argc,
++ char * const argv[])
++{
++ if (fsl_check_boot_mode_secure() == 0) {
++ printf("Boot Mode is Non-Secure. Not entering spin loop.\n");
++ return 0;
++ }
++
++ printf("Core is entering spin loop.\n");
++loop:
++ goto loop;
++
++ return 0;
++}
++
++#ifndef CONFIG_SPL_BUILD
++static int do_esbc_validate(cmd_tbl_t *cmdtp, int flag, int argc,
++ char * const argv[])
++{
++ char *hash_str = NULL;
++ uintptr_t haddr;
++ int ret;
++ uintptr_t img_addr = 0;
++ char buf[20];
++
++ if (argc < 2)
++ return cmd_usage(cmdtp);
++ else if (argc > 2)
++ /* Second arg - Optional - Hash Str*/
++ hash_str = argv[2];
++
++ /* First argument - header address -32/64bit */
++ haddr = (uintptr_t)simple_strtoul(argv[1], NULL, 16);
++
++ /* With esbc_validate command, Image address must be
++ * part of header. So, the function is called
++ * by passing this argument as 0.
++ */
++ ret = fsl_secboot_validate(haddr, hash_str, &img_addr);
++
++ /* Need to set "img_addr" even if validation failure.
++ * Required when SB_EN in RCW set and non-fatal error
++ * to continue U-Boot
++ */
++ sprintf(buf, "%lx", img_addr);
++ env_set("img_addr", buf);
++
++ if (ret)
++ return 1;
++
++ printf("esbc_validate command successful\n");
++ return 0;
++}
++
++/***************************************************/
++static char esbc_validate_help_text[] =
++ "esbc_validate hdr_addr <hash_val> - Validates signature using\n"
++ " RSA verification\n"
++ " $hdr_addr Address of header of the image\n"
++ " to be validated.\n"
++ " $hash_val -Optional\n"
++ " It provides Hash of public/srk key to be\n"
++ " used to verify signature.\n";
++
++U_BOOT_CMD(
++ esbc_validate, 3, 0, do_esbc_validate,
++ "Validates signature on a given image using RSA verification",
++ esbc_validate_help_text
++);
++
++U_BOOT_CMD(
++ esbc_halt, 1, 0, do_esbc_halt,
++ "Put the core in spin loop (Secure Boot Only)",
++ ""
++);
++#endif
+diff --git a/board/solidrun/common/emc2301.c b/board/solidrun/common/emc2301.c
+new file mode 100644
+index 0000000000..a4780dbfcc
+--- /dev/null
++++ b/board/solidrun/common/emc2301.c
+@@ -0,0 +1,31 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright 2019 SolidRun ltd. Based on code from NXP LX2160A RDB
++ *
++ * SPDX-License-Identifier: GPL-2.0+
++ */
++
++#include <common.h>
++#include <command.h>
++#include <i2c.h>
++#include <asm/io.h>
++
++#include "emc2301.h"
++
++DECLARE_GLOBAL_DATA_PTR;
++
++void set_fan_speed(u8 data)
++{
++ if (i2c_write(I2C_EMC2301_ADDR, I2C_EMC2301_FAN, 1, &data, 1) != 0) {
++ puts("Error: failed to change fan speed\n");
++ }
++}
++
++void emc2301_init(void)
++{
++ u8 data;
++
++ data = I2C_EMC2301_CMD;
++ if (i2c_write(I2C_EMC2301_ADDR, I2C_EMC2301_CONF, 1, &data, 1) != 0)
++ puts("Error: failed to configure EMC2301\n");
++}
+diff --git a/board/solidrun/common/emc2301.h b/board/solidrun/common/emc2301.h
+new file mode 100644
+index 0000000000..a5ceb73b7c
+--- /dev/null
++++ b/board/solidrun/common/emc2301.h
+@@ -0,0 +1,17 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/*
++ * Copyright 2019 SolidRun ltd.
++ *
++ * SPDX-License-Identifier: GPL-2.0+
++ */
++
++#ifndef __EMC2301_H_
++#define __EMC2301_H_
++
++#define I2C_EMC2301_CONF 0x20
++#define I2C_EMC2301_FAN 0x30
++
++void emc2301_init(void);
++void set_fan_speed(u8 data);
++
++#endif /* __EMC2305_H_ */
+diff --git a/board/solidrun/common/fsl_chain_of_trust.c b/board/solidrun/common/fsl_chain_of_trust.c
+new file mode 100644
+index 0000000000..dddfd26a13
+--- /dev/null
++++ b/board/solidrun/common/fsl_chain_of_trust.c
+@@ -0,0 +1,164 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright 2015 Freescale Semiconductor, Inc.
++ */
++
++#include <common.h>
++#include <dm.h>
++#include <fsl_validate.h>
++#include <fsl_secboot_err.h>
++#include <fsl_sfp.h>
++#include <dm/root.h>
++
++#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_FRAMEWORK)
++#include <spl.h>
++#endif
++
++#ifdef CONFIG_ADDR_MAP
++#include <asm/mmu.h>
++#endif
++
++#ifdef CONFIG_FSL_CORENET
++#include <asm/fsl_pamu.h>
++#endif
++
++#ifdef CONFIG_ARCH_LS1021A
++#include <asm/arch/immap_ls102xa.h>
++#endif
++
++#if defined(CONFIG_MPC85xx)
++#define CONFIG_DCFG_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR
++#else
++#define CONFIG_DCFG_ADDR CONFIG_SYS_FSL_GUTS_ADDR
++#endif
++
++#ifdef CONFIG_SYS_FSL_CCSR_GUR_LE
++#define gur_in32(a) in_le32(a)
++#else
++#define gur_in32(a) in_be32(a)
++#endif
++
++/* Check the Boot Mode. If Secure, return 1 else return 0 */
++int fsl_check_boot_mode_secure(void)
++{
++ uint32_t val;
++ struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
++ struct ccsr_gur __iomem *gur = (void *)(CONFIG_DCFG_ADDR);
++
++ val = sfp_in32(&sfp_regs->ospr) & ITS_MASK;
++ if (val == ITS_MASK)
++ return 1;
++
++#if defined(CONFIG_FSL_CORENET) || !defined(CONFIG_MPC85xx)
++ /* For PBL based platforms check the SB_EN bit in RCWSR */
++ val = gur_in32(&gur->rcwsr[RCW_SB_EN_REG_INDEX - 1]) & RCW_SB_EN_MASK;
++ if (val == RCW_SB_EN_MASK)
++ return 1;
++#endif
++
++#if defined(CONFIG_MPC85xx) && !defined(CONFIG_FSL_CORENET)
++ /* For Non-PBL Platforms, check the Device Status register 2*/
++ val = gur_in32(&gur->pordevsr2) & MPC85xx_PORDEVSR2_SBC_MASK;
++ if (val != MPC85xx_PORDEVSR2_SBC_MASK)
++ return 1;
++
++#endif
++ return 0;
++}
++
++#ifndef CONFIG_SPL_BUILD
++int fsl_setenv_chain_of_trust(void)
++{
++ /* Check Boot Mode
++ * If Boot Mode is Non-Secure, no changes are required
++ */
++ if (fsl_check_boot_mode_secure() == 0)
++ return 0;
++
++ /* If Boot mode is Secure, set the environment variables
++ * bootdelay = 0 (To disable Boot Prompt)
++ * bootcmd = CONFIG_CHAIN_BOOT_CMD (Validate and execute Boot script)
++ */
++ env_set("bootdelay", "-2");
++
++#ifdef CONFIG_ARM
++ env_set("secureboot", "y");
++#else
++ env_set("bootcmd", CONFIG_CHAIN_BOOT_CMD);
++#endif
++
++ return 0;
++}
++#endif
++
++#ifdef CONFIG_SPL_BUILD
++void spl_validate_uboot(uint32_t hdr_addr, uintptr_t img_addr)
++{
++ int res;
++
++ /*
++ * Check Boot Mode
++ * If Boot Mode is Non-Secure, skip validation
++ */
++ if (fsl_check_boot_mode_secure() == 0)
++ return;
++
++ printf("SPL: Validating U-Boot image\n");
++
++#ifdef CONFIG_ADDR_MAP
++ init_addr_map();
++#endif
++
++#ifdef CONFIG_FSL_CORENET
++ if (pamu_init() < 0)
++ fsl_secboot_handle_error(ERROR_ESBC_PAMU_INIT);
++#endif
++
++#ifdef CONFIG_FSL_CAAM
++ if (sec_init() < 0)
++ fsl_secboot_handle_error(ERROR_ESBC_SEC_INIT);
++#endif
++
++/*
++ * dm_init_and_scan() is called as part of common SPL framework, so no
++ * need to call it again but in case of powerpc platforms which currently
++ * do not use common SPL framework, so need to call this function here.
++ */
++#if defined(CONFIG_SPL_DM) && (!defined(CONFIG_SPL_FRAMEWORK))
++ dm_init_and_scan(true);
++#endif
++ res = fsl_secboot_validate(hdr_addr, CONFIG_SPL_UBOOT_KEY_HASH,
++ &img_addr);
++
++ if (res == 0)
++ printf("SPL: Validation of U-boot successful\n");
++}
++
++#ifdef CONFIG_SPL_FRAMEWORK
++/* Override weak funtion defined in SPL framework to enable validation
++ * of main u-boot image before jumping to u-boot image.
++ */
++void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
++{
++ typedef void __noreturn (*image_entry_noargs_t)(void);
++ uint32_t hdr_addr;
++
++ image_entry_noargs_t image_entry =
++ (image_entry_noargs_t)(unsigned long)spl_image->entry_point;
++
++ hdr_addr = (spl_image->entry_point + spl_image->size -
++ CONFIG_U_BOOT_HDR_SIZE);
++ spl_validate_uboot(hdr_addr, (uintptr_t)spl_image->entry_point);
++ /*
++ * In case of failure in validation, spl_validate_uboot would
++ * not return back in case of Production environment with ITS=1.
++ * Thus U-Boot will not start.
++ * In Development environment (ITS=0 and SB_EN=1), the function
++ * may return back in case of non-fatal failures.
++ */
++
++ debug("image entry point: 0x%lX\n", spl_image->entry_point);
++ image_entry();
++}
++#endif /* ifdef CONFIG_SPL_FRAMEWORK */
++#endif /* ifdef CONFIG_SPL_BUILD */
+diff --git a/board/solidrun/common/fsl_validate.c b/board/solidrun/common/fsl_validate.c
+new file mode 100644
+index 0000000000..2bf9d58746
+--- /dev/null
++++ b/board/solidrun/common/fsl_validate.c
+@@ -0,0 +1,962 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright 2015 Freescale Semiconductor, Inc.
++ */
++
++#include <common.h>
++#include <dm.h>
++#include <fsl_validate.h>
++#include <fsl_secboot_err.h>
++#include <fsl_sfp.h>
++#include <fsl_sec.h>
++#include <command.h>
++#include <malloc.h>
++#include <u-boot/rsa-mod-exp.h>
++#include <hash.h>
++#include <fsl_secboot_err.h>
++#ifdef CONFIG_ARCH_LS1021A
++#include <asm/arch/immap_ls102xa.h>
++#endif
++
++#define SHA256_BITS 256
++#define SHA256_BYTES (256/8)
++#define SHA256_NIBBLES (256/4)
++#define NUM_HEX_CHARS (sizeof(ulong) * 2)
++
++#define CHECK_KEY_LEN(key_len) (((key_len) == 2 * KEY_SIZE_BYTES / 4) || \
++ ((key_len) == 2 * KEY_SIZE_BYTES / 2) || \
++ ((key_len) == 2 * KEY_SIZE_BYTES))
++#if defined(CONFIG_FSL_ISBC_KEY_EXT)
++/* Global data structure */
++static struct fsl_secboot_glb glb;
++#endif
++
++/* This array contains DER value for SHA-256 */
++static const u8 hash_identifier[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
++ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,
++ 0x04, 0x20
++ };
++
++static u8 hash_val[SHA256_BYTES];
++
++#ifdef CONFIG_ESBC_HDR_LS
++/* New Barker Code for LS ESBC Header */
++static const u8 barker_code[ESBC_BARKER_LEN] = { 0x12, 0x19, 0x20, 0x01 };
++#else
++static const u8 barker_code[ESBC_BARKER_LEN] = { 0x68, 0x39, 0x27, 0x81 };
++#endif
++
++void branch_to_self(void) __attribute__ ((noreturn));
++
++/*
++ * This function will put core in infinite loop.
++ * This will be called when the ESBC can not proceed further due
++ * to some unknown errors.
++ */
++void branch_to_self(void)
++{
++ printf("Core is in infinite loop due to errors.\n");
++self:
++ goto self;
++}
++
++#if defined(CONFIG_FSL_ISBC_KEY_EXT)
++static u32 check_ie(struct fsl_secboot_img_priv *img)
++{
++ if (img->hdr.ie_flag & IE_FLAG_MASK)
++ return 1;
++
++ return 0;
++}
++
++/* This function returns the CSF Header Address of uboot
++ * For MPC85xx based platforms, the LAW mapping for NOR
++ * flash changes in uboot code. Hence the offset needs
++ * to be calculated and added to the new NOR flash base
++ * address
++ */
++#if defined(CONFIG_MPC85xx)
++int get_csf_base_addr(u32 *csf_addr, u32 *flash_base_addr)
++{
++ struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
++ u32 csf_hdr_addr = in_be32(&gur->scratchrw[0]);
++ u32 csf_flash_offset = csf_hdr_addr & ~(CONFIG_SYS_PBI_FLASH_BASE);
++ u32 flash_addr, addr;
++ int found = 0;
++ int i = 0;
++
++ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
++ flash_addr = flash_info[i].start[0];
++ addr = flash_info[i].start[0] + csf_flash_offset;
++ if (memcmp((u8 *)addr, barker_code, ESBC_BARKER_LEN) == 0) {
++ debug("Barker found on addr %x\n", addr);
++ found = 1;
++ break;
++ }
++ }
++
++ if (!found)
++ return -1;
++
++ *csf_addr = addr;
++ *flash_base_addr = flash_addr;
++
++ return 0;
++}
++#else
++/* For platforms like LS1020, correct flash address is present in
++ * the header. So the function reqturns flash base address as 0
++ */
++int get_csf_base_addr(u32 *csf_addr, u32 *flash_base_addr)
++{
++ struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
++ u32 csf_hdr_addr = in_be32(&gur->scratchrw[0]);
++
++ if (memcmp((u8 *)(uintptr_t)csf_hdr_addr,
++ barker_code, ESBC_BARKER_LEN))
++ return -1;
++
++ *csf_addr = csf_hdr_addr;
++ *flash_base_addr = 0;
++ return 0;
++}
++#endif
++
++#if defined(CONFIG_ESBC_HDR_LS)
++static int get_ie_info_addr(uintptr_t *ie_addr)
++{
++ struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
++ /* For LS-CH3, the address of IE Table is
++ * stated in Scratch13 and scratch14 of DCFG.
++ * Bootrom validates this table while validating uboot.
++ * DCFG is LE*/
++ *ie_addr = in_le32(&gur->scratchrw[SCRATCH_IE_HIGH_ADR - 1]);
++ *ie_addr = *ie_addr << 32;
++ *ie_addr |= in_le32(&gur->scratchrw[SCRATCH_IE_LOW_ADR - 1]);
++ return 0;
++}
++#else /* CONFIG_ESBC_HDR_LS */
++static int get_ie_info_addr(uintptr_t *ie_addr)
++{
++ struct fsl_secboot_img_hdr *hdr;
++ struct fsl_secboot_sg_table *sg_tbl;
++ u32 flash_base_addr, csf_addr;
++
++ if (get_csf_base_addr(&csf_addr, &flash_base_addr))
++ return -1;
++
++ hdr = (struct fsl_secboot_img_hdr *)(uintptr_t)csf_addr;
++
++ /* For SoC's with Trust Architecture v1 with corenet bus
++ * the sg table field in CSF header has absolute address
++ * for sg table in memory. In other Trust Architecture,
++ * this field specifies the offset of sg table from the
++ * base address of CSF Header
++ */
++#if defined(CONFIG_FSL_TRUST_ARCH_v1) && defined(CONFIG_FSL_CORENET)
++ sg_tbl = (struct fsl_secboot_sg_table *)
++ (((u32)hdr->psgtable & ~(CONFIG_SYS_PBI_FLASH_BASE)) +
++ flash_base_addr);
++#else
++ sg_tbl = (struct fsl_secboot_sg_table *)(uintptr_t)(csf_addr +
++ (u32)hdr->psgtable);
++#endif
++
++ /* IE Key Table is the first entry in the SG Table */
++#if defined(CONFIG_MPC85xx)
++ *ie_addr = (uintptr_t)((sg_tbl->src_addr &
++ ~(CONFIG_SYS_PBI_FLASH_BASE)) +
++ flash_base_addr);
++#else
++ *ie_addr = (uintptr_t)sg_tbl->src_addr;
++#endif
++
++ debug("IE Table address is %lx\n", *ie_addr);
++ return 0;
++}
++#endif /* CONFIG_ESBC_HDR_LS */
++#endif
++
++#ifdef CONFIG_KEY_REVOCATION
++/* This function checks srk_table_flag in header and set/reset srk_flag.*/
++static u32 check_srk(struct fsl_secboot_img_priv *img)
++{
++#ifdef CONFIG_ESBC_HDR_LS
++ /* In LS, No SRK Flag as SRK is always present if IE not present*/
++#if defined(CONFIG_FSL_ISBC_KEY_EXT)
++ return !check_ie(img);
++#endif
++ return 1;
++#else
++ if (img->hdr.len_kr.srk_table_flag & SRK_FLAG)
++ return 1;
++
++ return 0;
++#endif
++}
++
++/* This function returns ospr's key_revoc values.*/
++static u32 get_key_revoc(void)
++{
++ struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
++ return (sfp_in32(&sfp_regs->ospr) & OSPR_KEY_REVOC_MASK) >>
++ OSPR_KEY_REVOC_SHIFT;
++}
++
++/* This function checks if selected key is revoked or not.*/
++static u32 is_key_revoked(u32 keynum, u32 rev_flag)
++{
++ if (keynum == UNREVOCABLE_KEY)
++ return 0;
++
++ if ((u32)(1 << (ALIGN_REVOC_KEY - keynum)) & rev_flag)
++ return 1;
++
++ return 0;
++}
++
++/* It read validates srk_table key lengths.*/
++static u32 read_validate_srk_tbl(struct fsl_secboot_img_priv *img)
++{
++ int i = 0;
++ u32 ret, key_num, key_revoc_flag, size;
++ struct fsl_secboot_img_hdr *hdr = &img->hdr;
++ void *esbc = (u8 *)(uintptr_t)img->ehdrloc;
++
++ if ((hdr->len_kr.num_srk == 0) ||
++ (hdr->len_kr.num_srk > MAX_KEY_ENTRIES))
++ return ERROR_ESBC_CLIENT_HEADER_INVALID_SRK_NUM_ENTRY;
++
++ key_num = hdr->len_kr.srk_sel;
++ if (key_num == 0 || key_num > hdr->len_kr.num_srk)
++ return ERROR_ESBC_CLIENT_HEADER_INVALID_KEY_NUM;
++
++ /* Get revoc key from sfp */
++ key_revoc_flag = get_key_revoc();
++ ret = is_key_revoked(key_num, key_revoc_flag);
++ if (ret)
++ return ERROR_ESBC_CLIENT_HEADER_KEY_REVOKED;
++
++ size = hdr->len_kr.num_srk * sizeof(struct srk_table);
++
++ memcpy(&img->srk_tbl, esbc + hdr->srk_tbl_off, size);
++
++ for (i = 0; i < hdr->len_kr.num_srk; i++) {
++ if (!CHECK_KEY_LEN(img->srk_tbl[i].key_len))
++ return ERROR_ESBC_CLIENT_HEADER_INV_SRK_ENTRY_KEYLEN;
++ }
++
++ img->key_len = img->srk_tbl[key_num - 1].key_len;
++
++ memcpy(&img->img_key, &(img->srk_tbl[key_num - 1].pkey),
++ img->key_len);
++
++ return 0;
++}
++#endif
++
++#ifndef CONFIG_ESBC_HDR_LS
++static u32 read_validate_single_key(struct fsl_secboot_img_priv *img)
++{
++ struct fsl_secboot_img_hdr *hdr = &img->hdr;
++ void *esbc = (u8 *)(uintptr_t)img->ehdrloc;
++
++ /* check key length */
++ if (!CHECK_KEY_LEN(hdr->key_len))
++ return ERROR_ESBC_CLIENT_HEADER_KEY_LEN;
++
++ memcpy(&img->img_key, esbc + hdr->pkey, hdr->key_len);
++
++ img->key_len = hdr->key_len;
++
++ return 0;
++}
++#endif /* CONFIG_ESBC_HDR_LS */
++
++#if defined(CONFIG_FSL_ISBC_KEY_EXT)
++
++static void install_ie_tbl(uintptr_t ie_tbl_addr,
++ struct fsl_secboot_img_priv *img)
++{
++ /* Copy IE tbl to Global Data */
++ memcpy(&glb.ie_tbl, (u8 *)ie_tbl_addr, sizeof(struct ie_key_info));
++ img->ie_addr = (uintptr_t)&glb.ie_tbl;
++ glb.ie_addr = img->ie_addr;
++}
++
++static u32 read_validate_ie_tbl(struct fsl_secboot_img_priv *img)
++{
++ struct fsl_secboot_img_hdr *hdr = &img->hdr;
++ u32 ie_key_len, ie_revoc_flag, ie_num;
++ struct ie_key_info *ie_info;
++
++ if (!img->ie_addr) {
++ if (get_ie_info_addr(&img->ie_addr))
++ return ERROR_IE_TABLE_NOT_FOUND;
++ else
++ install_ie_tbl(img->ie_addr, img);
++ }
++
++ ie_info = (struct ie_key_info *)(uintptr_t)img->ie_addr;
++ if (ie_info->num_keys == 0 || ie_info->num_keys > 32)
++ return ERROR_ESBC_CLIENT_HEADER_INVALID_IE_NUM_ENTRY;
++
++ ie_num = hdr->ie_key_sel;
++ if (ie_num == 0 || ie_num > ie_info->num_keys)
++ return ERROR_ESBC_CLIENT_HEADER_INVALID_IE_KEY_NUM;
++
++ ie_revoc_flag = ie_info->key_revok;
++ if ((u32)(1 << (ie_num - 1)) & ie_revoc_flag)
++ return ERROR_ESBC_CLIENT_HEADER_IE_KEY_REVOKED;
++
++ ie_key_len = ie_info->ie_key_tbl[ie_num - 1].key_len;
++
++ if (!CHECK_KEY_LEN(ie_key_len))
++ return ERROR_ESBC_CLIENT_HEADER_INV_IE_ENTRY_KEYLEN;
++
++ memcpy(&img->img_key, &(ie_info->ie_key_tbl[ie_num - 1].pkey),
++ ie_key_len);
++
++ img->key_len = ie_key_len;
++ return 0;
++}
++#endif
++
++
++/* This function return length of public key.*/
++static inline u32 get_key_len(struct fsl_secboot_img_priv *img)
++{
++ return img->key_len;
++}
++
++/*
++ * Handles the ESBC uboot client header verification failure.
++ * This function handles all the errors which might occur in the
++ * parsing and checking of ESBC uboot client header. It will also
++ * set the error bits in the SEC_MON.
++ */
++static void fsl_secboot_header_verification_failure(void)
++{
++ struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
++
++ /* 29th bit of OSPR is ITS */
++ u32 its = sfp_in32(&sfp_regs->ospr) >> 2;
++
++ if (its == 1)
++ set_sec_mon_state(HPSR_SSM_ST_SOFT_FAIL);
++ else
++ set_sec_mon_state(HPSR_SSM_ST_NON_SECURE);
++
++ printf("Generating reset request\n");
++ do_reset(NULL, 0, 0, NULL);
++ /* If reset doesn't coocur, halt execution */
++ do_esbc_halt(NULL, 0, 0, NULL);
++}
++
++/*
++ * Handles the ESBC uboot client image verification failure.
++ * This function handles all the errors which might occur in the
++ * public key hash comparison and signature verification of
++ * ESBC uboot client image. It will also
++ * set the error bits in the SEC_MON.
++ */
++static void fsl_secboot_image_verification_failure(void)
++{
++ struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
++
++ u32 its = (sfp_in32(&sfp_regs->ospr) & ITS_MASK) >> ITS_BIT;
++
++ if (its == 1) {
++ set_sec_mon_state(HPSR_SSM_ST_SOFT_FAIL);
++
++ printf("Generating reset request\n");
++ do_reset(NULL, 0, 0, NULL);
++ /* If reset doesn't coocur, halt execution */
++ do_esbc_halt(NULL, 0, 0, NULL);
++
++ } else {
++ set_sec_mon_state(HPSR_SSM_ST_NON_SECURE);
++ }
++}
++
++static void fsl_secboot_bootscript_parse_failure(void)
++{
++ fsl_secboot_header_verification_failure();
++}
++
++/*
++ * Handles the errors in esbc boot.
++ * This function handles all the errors which might occur in the
++ * esbc boot phase. It will call the appropriate api to log the
++ * errors and set the error bits in the SEC_MON.
++ */
++void fsl_secboot_handle_error(int error)
++{
++#ifndef CONFIG_SPL_BUILD
++ const struct fsl_secboot_errcode *e;
++
++ for (e = fsl_secboot_errcodes; e->errcode != ERROR_ESBC_CLIENT_MAX;
++ e++) {
++ if (e->errcode == error)
++ printf("ERROR :: %x :: %s\n", error, e->name);
++ }
++#else
++ printf("ERROR :: %x\n", error);
++#endif
++
++ /* If Boot Mode is secure, transition the SNVS state and issue
++ * reset based on type of failure and ITS setting.
++ * If Boot mode is non-secure, return from this function.
++ */
++ if (fsl_check_boot_mode_secure() == 0)
++ return;
++
++ switch (error) {
++ case ERROR_ESBC_CLIENT_HEADER_BARKER:
++ case ERROR_ESBC_CLIENT_HEADER_IMG_SIZE:
++ case ERROR_ESBC_CLIENT_HEADER_KEY_LEN:
++ case ERROR_ESBC_CLIENT_HEADER_SIG_LEN:
++ case ERROR_ESBC_CLIENT_HEADER_KEY_LEN_NOT_TWICE_SIG_LEN:
++ case ERROR_ESBC_CLIENT_HEADER_KEY_MOD_1:
++ case ERROR_ESBC_CLIENT_HEADER_KEY_MOD_2:
++ case ERROR_ESBC_CLIENT_HEADER_SIG_KEY_MOD:
++ case ERROR_ESBC_CLIENT_HEADER_SG_ESBC_EP:
++ case ERROR_ESBC_CLIENT_HEADER_SG_ENTIRES_BAD:
++ case ERROR_KEY_TABLE_NOT_FOUND:
++#ifdef CONFIG_KEY_REVOCATION
++ case ERROR_ESBC_CLIENT_HEADER_KEY_REVOKED:
++ case ERROR_ESBC_CLIENT_HEADER_INVALID_SRK_NUM_ENTRY:
++ case ERROR_ESBC_CLIENT_HEADER_INVALID_KEY_NUM:
++ case ERROR_ESBC_CLIENT_HEADER_INV_SRK_ENTRY_KEYLEN:
++#endif
++#if defined(CONFIG_FSL_ISBC_KEY_EXT)
++ /*@fallthrough@*/
++ case ERROR_ESBC_CLIENT_HEADER_IE_KEY_REVOKED:
++ case ERROR_ESBC_CLIENT_HEADER_INVALID_IE_NUM_ENTRY:
++ case ERROR_ESBC_CLIENT_HEADER_INVALID_IE_KEY_NUM:
++ case ERROR_ESBC_CLIENT_HEADER_INV_IE_ENTRY_KEYLEN:
++ case ERROR_IE_TABLE_NOT_FOUND:
++#endif
++ fsl_secboot_header_verification_failure();
++ break;
++ case ERROR_ESBC_SEC_RESET:
++ case ERROR_ESBC_SEC_DEQ:
++ case ERROR_ESBC_SEC_ENQ:
++ case ERROR_ESBC_SEC_DEQ_TO:
++ case ERROR_ESBC_SEC_JOBQ_STATUS:
++ case ERROR_ESBC_CLIENT_HASH_COMPARE_KEY:
++ case ERROR_ESBC_CLIENT_HASH_COMPARE_EM:
++ fsl_secboot_image_verification_failure();
++ break;
++ case ERROR_ESBC_MISSING_BOOTM:
++ fsl_secboot_bootscript_parse_failure();
++ break;
++ case ERROR_ESBC_WRONG_CMD:
++ default:
++ branch_to_self();
++ break;
++ }
++}
++
++static void fsl_secblk_handle_error(int error)
++{
++ switch (error) {
++ case ERROR_ESBC_SEC_ENQ:
++ fsl_secboot_handle_error(ERROR_ESBC_SEC_ENQ);
++ break;
++ case ERROR_ESBC_SEC_DEQ:
++ fsl_secboot_handle_error(ERROR_ESBC_SEC_DEQ);
++ break;
++ case ERROR_ESBC_SEC_DEQ_TO:
++ fsl_secboot_handle_error(ERROR_ESBC_SEC_DEQ_TO);
++ break;
++ default:
++ printf("Job Queue Output status %x\n", error);
++ fsl_secboot_handle_error(ERROR_ESBC_SEC_JOBQ_STATUS);
++ break;
++ }
++}
++
++/*
++ * Calculate hash of key obtained via offset present in ESBC uboot
++ * client hdr. This function calculates the hash of key which is obtained
++ * through offset present in ESBC uboot client header.
++ */
++static int calc_img_key_hash(struct fsl_secboot_img_priv *img)
++{
++ struct hash_algo *algo;
++ void *ctx;
++ int i, srk = 0;
++ int ret = 0;
++ const char *algo_name = "sha256";
++
++ /* Calculate hash of the esbc key */
++ ret = hash_progressive_lookup_algo(algo_name, &algo);
++ if (ret)
++ return ret;
++
++ ret = algo->hash_init(algo, &ctx);
++ if (ret)
++ return ret;
++
++ /* Update hash for ESBC key */
++#ifdef CONFIG_KEY_REVOCATION
++ if (check_srk(img)) {
++ ret = algo->hash_update(algo, ctx,
++ (u8 *)(uintptr_t)(img->ehdrloc + img->hdr.srk_tbl_off),
++ img->hdr.len_kr.num_srk * sizeof(struct srk_table), 1);
++ srk = 1;
++ }
++#endif
++ if (!srk)
++ ret = algo->hash_update(algo, ctx,
++ img->img_key, img->key_len, 1);
++ if (ret)
++ return ret;
++
++ /* Copy hash at destination buffer */
++ ret = algo->hash_finish(algo, ctx, hash_val, algo->digest_size);
++ if (ret)
++ return ret;
++
++ for (i = 0; i < SHA256_BYTES; i++)
++ img->img_key_hash[i] = hash_val[i];
++
++ return 0;
++}
++
++/*
++ * Calculate hash of ESBC hdr and ESBC. This function calculates the
++ * single hash of ESBC header and ESBC image. If SG flag is on, all
++ * SG entries are also hashed alongwith the complete SG table.
++ */
++static int calc_esbchdr_esbc_hash(struct fsl_secboot_img_priv *img)
++{
++ struct hash_algo *algo;
++ void *ctx;
++ int ret = 0;
++ int key_hash = 0;
++ const char *algo_name = "sha256";
++
++ /* Calculate the hash of the ESBC */
++ ret = hash_progressive_lookup_algo(algo_name, &algo);
++ if (ret)
++ return ret;
++
++ ret = algo->hash_init(algo, &ctx);
++ /* Copy hash at destination buffer */
++ if (ret)
++ return ret;
++
++ /* Update hash for CSF Header */
++ ret = algo->hash_update(algo, ctx,
++ (u8 *)&img->hdr, sizeof(struct fsl_secboot_img_hdr), 0);
++ if (ret)
++ return ret;
++
++ /* Update the hash with that of srk table if srk flag is 1
++ * If IE Table is selected, key is not added in the hash
++ * If neither srk table nor IE key table available, add key
++ * from header in the hash calculation
++ */
++#ifdef CONFIG_KEY_REVOCATION
++ if (check_srk(img)) {
++ ret = algo->hash_update(algo, ctx,
++ (u8 *)(uintptr_t)(img->ehdrloc + img->hdr.srk_tbl_off),
++ img->hdr.len_kr.num_srk * sizeof(struct srk_table), 0);
++ key_hash = 1;
++ }
++#endif
++#if defined(CONFIG_FSL_ISBC_KEY_EXT)
++ if (!key_hash && check_ie(img))
++ key_hash = 1;
++#endif
++#ifndef CONFIG_ESBC_HDR_LS
++/* No single key support in LS ESBC header */
++ if (!key_hash) {
++ ret = algo->hash_update(algo, ctx,
++ img->img_key, img->hdr.key_len, 0);
++ key_hash = 1;
++ }
++#endif
++ if (ret)
++ return ret;
++ if (!key_hash)
++ return ERROR_KEY_TABLE_NOT_FOUND;
++
++ /* Update hash for actual Image */
++ ret = algo->hash_update(algo, ctx,
++ (u8 *)(*(img->img_addr_ptr)), img->img_size, 1);
++ if (ret)
++ return ret;
++
++ /* Copy hash at destination buffer */
++ ret = algo->hash_finish(algo, ctx, hash_val, algo->digest_size);
++ if (ret)
++ return ret;
++
++ return 0;
++}
++
++/*
++ * Construct encoded hash EM' wrt PKCSv1.5. This function calculates the
++ * pointers for padding, DER value and hash. And finally, constructs EM'
++ * which includes hash of complete CSF header and ESBC image. If SG flag
++ * is on, hash of SG table and entries is also included.
++ */
++static void construct_img_encoded_hash_second(struct fsl_secboot_img_priv *img)
++{
++ /*
++ * RSA PKCSv1.5 encoding format for encoded message is below
++ * EM = 0x0 || 0x1 || PS || 0x0 || DER || Hash
++ * PS is Padding String
++ * DER is DER value for SHA-256
++ * Hash is SHA-256 hash
++ * *********************************************************
++ * representative points to first byte of EM initially and is
++ * filled with 0x0
++ * representative is incremented by 1 and second byte is filled
++ * with 0x1
++ * padding points to third byte of EM
++ * digest points to full length of EM - 32 bytes
++ * hash_id (DER value) points to 19 bytes before pDigest
++ * separator is one byte which separates padding and DER
++ */
++
++ size_t len;
++ u8 *representative;
++ u8 *padding, *digest;
++ u8 *hash_id, *separator;
++ int i;
++
++ len = (get_key_len(img) / 2) - 1;
++ representative = img->img_encoded_hash_second;
++ representative[0] = 0;
++ representative[1] = 1; /* block type 1 */
++
++ padding = &representative[2];
++ digest = &representative[1] + len - 32;
++ hash_id = digest - sizeof(hash_identifier);
++ separator = hash_id - 1;
++
++ /* fill padding area pointed by padding with 0xff */
++ memset(padding, 0xff, separator - padding);
++
++ /* fill byte pointed by separator */
++ *separator = 0;
++
++ /* fill SHA-256 DER value pointed by HashId */
++ memcpy(hash_id, hash_identifier, sizeof(hash_identifier));
++
++ /* fill hash pointed by Digest */
++ for (i = 0; i < SHA256_BYTES; i++)
++ digest[i] = hash_val[i];
++}
++
++/*
++ * Reads and validates the ESBC client header.
++ * This function reads key and signature from the ESBC client header.
++ * If Scatter/Gather flag is on, lengths and offsets of images
++ * present as SG entries are also read. This function also checks
++ * whether the header is valid or not.
++ */
++static int read_validate_esbc_client_header(struct fsl_secboot_img_priv *img)
++{
++ struct fsl_secboot_img_hdr *hdr = &img->hdr;
++ void *esbc = (u8 *)(uintptr_t)img->ehdrloc;
++ u8 *k, *s;
++ u32 ret = 0;
++
++ int key_found = 0;
++
++ /* check barker code */
++ if (memcmp(hdr->barker, barker_code, ESBC_BARKER_LEN))
++ return ERROR_ESBC_CLIENT_HEADER_BARKER;
++
++ /* If Image Address is not passed as argument to function,
++ * then Address and Size must be read from the Header.
++ */
++ if (*(img->img_addr_ptr) == 0) {
++ #ifdef CONFIG_ESBC_ADDR_64BIT
++ *(img->img_addr_ptr) = hdr->pimg64;
++ #else
++ *(img->img_addr_ptr) = hdr->pimg;
++ #endif
++ }
++
++ if (!hdr->img_size)
++ return ERROR_ESBC_CLIENT_HEADER_IMG_SIZE;
++
++ img->img_size = hdr->img_size;
++
++ /* Key checking*/
++#ifdef CONFIG_KEY_REVOCATION
++ if (check_srk(img)) {
++ ret = read_validate_srk_tbl(img);
++ if (ret != 0)
++ return ret;
++ key_found = 1;
++ }
++#endif
++
++#if defined(CONFIG_FSL_ISBC_KEY_EXT)
++ if (!key_found && check_ie(img)) {
++ ret = read_validate_ie_tbl(img);
++ if (ret != 0)
++ return ret;
++ key_found = 1;
++ }
++#endif
++#ifndef CONFIG_ESBC_HDR_LS
++/* Single Key Feature not available in LS ESBC Header */
++ if (key_found == 0) {
++ ret = read_validate_single_key(img);
++ if (ret != 0)
++ return ret;
++ key_found = 1;
++ }
++#endif
++ if (!key_found)
++ return ERROR_KEY_TABLE_NOT_FOUND;
++
++ /* check signaure */
++ if (get_key_len(img) == 2 * hdr->sign_len) {
++ /* check signature length */
++ if (!((hdr->sign_len == KEY_SIZE_BYTES / 4) ||
++ (hdr->sign_len == KEY_SIZE_BYTES / 2) ||
++ (hdr->sign_len == KEY_SIZE_BYTES)))
++ return ERROR_ESBC_CLIENT_HEADER_SIG_LEN;
++ } else {
++ return ERROR_ESBC_CLIENT_HEADER_KEY_LEN_NOT_TWICE_SIG_LEN;
++ }
++
++ memcpy(&img->img_sign, esbc + hdr->psign, hdr->sign_len);
++/* No SG support in LS-CH3 */
++#ifndef CONFIG_ESBC_HDR_LS
++ /* No SG support */
++ if (hdr->sg_flag)
++ return ERROR_ESBC_CLIENT_HEADER_SG;
++#endif
++
++ /* modulus most significant bit should be set */
++ k = (u8 *)&img->img_key;
++
++ if ((k[0] & 0x80) == 0)
++ return ERROR_ESBC_CLIENT_HEADER_KEY_MOD_1;
++
++ /* modulus value should be odd */
++ if ((k[get_key_len(img) / 2 - 1] & 0x1) == 0)
++ return ERROR_ESBC_CLIENT_HEADER_KEY_MOD_2;
++
++ /* Check signature value < modulus value */
++ s = (u8 *)&img->img_sign;
++
++ if (!(memcmp(s, k, hdr->sign_len) < 0))
++ return ERROR_ESBC_CLIENT_HEADER_SIG_KEY_MOD;
++
++ return ESBC_VALID_HDR;
++}
++
++static inline int str2longbe(const char *p, ulong *num)
++{
++ char *endptr;
++ ulong tmp;
++
++ if (!p) {
++ return 0;
++ } else {
++ tmp = simple_strtoul(p, &endptr, 16);
++ if (sizeof(ulong) == 4)
++ *num = cpu_to_be32(tmp);
++ else
++ *num = cpu_to_be64(tmp);
++ }
++
++ return *p != '\0' && *endptr == '\0';
++}
++/* Function to calculate the ESBC Image Hash
++ * and hash from Digital signature.
++ * The Two hash's are compared to yield the
++ * result of signature validation.
++ */
++static int calculate_cmp_img_sig(struct fsl_secboot_img_priv *img)
++{
++ int ret;
++ uint32_t key_len;
++ struct key_prop prop;
++#if !defined(USE_HOSTCC)
++ struct udevice *mod_exp_dev;
++#endif
++ ret = calc_esbchdr_esbc_hash(img);
++ if (ret)
++ return ret;
++
++ /* Construct encoded hash EM' wrt PKCSv1.5 */
++ construct_img_encoded_hash_second(img);
++
++ /* Fill prop structure for public key */
++ memset(&prop, 0, sizeof(struct key_prop));
++ key_len = get_key_len(img) / 2;
++ prop.modulus = img->img_key;
++ prop.public_exponent = img->img_key + key_len;
++ prop.num_bits = key_len * 8;
++ prop.exp_len = key_len;
++
++ ret = uclass_get_device(UCLASS_MOD_EXP, 0, &mod_exp_dev);
++ if (ret) {
++ printf("RSA: Can't find Modular Exp implementation\n");
++ return -EINVAL;
++ }
++
++ ret = rsa_mod_exp(mod_exp_dev, img->img_sign, img->hdr.sign_len,
++ &prop, img->img_encoded_hash);
++ if (ret)
++ return ret;
++
++ /*
++ * compare the encoded messages EM' and EM wrt RSA PKCSv1.5
++ * memcmp returns zero on success
++ * memcmp returns non-zero on failure
++ */
++ ret = memcmp(&img->img_encoded_hash_second, &img->img_encoded_hash,
++ img->hdr.sign_len);
++
++ if (ret)
++ return ERROR_ESBC_CLIENT_HASH_COMPARE_EM;
++
++ return 0;
++}
++/* Function to initialize img priv and global data structure
++ */
++static int secboot_init(struct fsl_secboot_img_priv **img_ptr)
++{
++ *img_ptr = malloc(sizeof(struct fsl_secboot_img_priv));
++
++ struct fsl_secboot_img_priv *img = *img_ptr;
++
++ if (!img)
++ return -ENOMEM;
++ memset(img, 0, sizeof(struct fsl_secboot_img_priv));
++
++#if defined(CONFIG_FSL_ISBC_KEY_EXT)
++ if (glb.ie_addr)
++ img->ie_addr = glb.ie_addr;
++#endif
++ return 0;
++}
++
++
++/* haddr - Address of the header of image to be validated.
++ * arg_hash_str - Option hash string. If provided, this
++ * overrides the key hash in the SFP fuses.
++ * img_addr_ptr - Optional pointer to address of image to be validated.
++ * If non zero addr, this overrides the addr of image in header,
++ * otherwise updated to image addr in header.
++ * Acts as both input and output of function.
++ * This pointer shouldn't be NULL.
++ */
++int fsl_secboot_validate(uintptr_t haddr, char *arg_hash_str,
++ uintptr_t *img_addr_ptr)
++{
++ struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
++ ulong hash[SHA256_BYTES/sizeof(ulong)];
++ char hash_str[NUM_HEX_CHARS + 1];
++ struct fsl_secboot_img_priv *img;
++ struct fsl_secboot_img_hdr *hdr;
++ void *esbc;
++ int ret, i, hash_cmd = 0;
++ u32 srk_hash[8];
++
++ if (arg_hash_str != NULL) {
++ const char *cp = arg_hash_str;
++ int i = 0;
++
++ if (*cp == '0' && *(cp + 1) == 'x')
++ cp += 2;
++
++ /* The input string expected is in hex, where
++ * each 4 bits would be represented by a hex
++ * sha256 hash is 256 bits long, which would mean
++ * num of characters = 256 / 4
++ */
++ if (strlen(cp) != SHA256_NIBBLES) {
++ printf("%s is not a 256 bits hex string as expected\n",
++ arg_hash_str);
++ return -1;
++ }
++
++ for (i = 0; i < sizeof(hash)/sizeof(ulong); i++) {
++ strncpy(hash_str, cp + (i * NUM_HEX_CHARS),
++ NUM_HEX_CHARS);
++ hash_str[NUM_HEX_CHARS] = '\0';
++ if (!str2longbe(hash_str, &hash[i])) {
++ printf("%s is not a 256 bits hex string ",
++ arg_hash_str);
++ return -1;
++ }
++ }
++
++ hash_cmd = 1;
++ }
++
++ ret = secboot_init(&img);
++ if (ret)
++ goto exit;
++
++ /* Update the information in Private Struct */
++ hdr = &img->hdr;
++ img->ehdrloc = haddr;
++ img->img_addr_ptr = img_addr_ptr;
++ esbc = (u8 *)img->ehdrloc;
++
++ memcpy(hdr, esbc, sizeof(struct fsl_secboot_img_hdr));
++
++ /* read and validate esbc header */
++ ret = read_validate_esbc_client_header(img);
++
++ if (ret != ESBC_VALID_HDR) {
++ fsl_secboot_handle_error(ret);
++ goto exit;
++ }
++
++ /* SRKH present in SFP */
++ for (i = 0; i < NUM_SRKH_REGS; i++)
++ srk_hash[i] = srk_in32(&sfp_regs->srk_hash[i]);
++
++ /*
++ * Calculate hash of key obtained via offset present in
++ * ESBC uboot client hdr
++ */
++ ret = calc_img_key_hash(img);
++ if (ret) {
++ fsl_secblk_handle_error(ret);
++ goto exit;
++ }
++
++ /* Compare hash obtained above with SRK hash present in SFP */
++ if (hash_cmd)
++ ret = memcmp(&hash, &img->img_key_hash, SHA256_BYTES);
++ else
++ ret = memcmp(srk_hash, img->img_key_hash, SHA256_BYTES);
++
++#if defined(CONFIG_FSL_ISBC_KEY_EXT)
++ if (!hash_cmd && check_ie(img))
++ ret = 0;
++#endif
++
++ if (ret != 0) {
++ fsl_secboot_handle_error(ERROR_ESBC_CLIENT_HASH_COMPARE_KEY);
++ goto exit;
++ }
++
++ ret = calculate_cmp_img_sig(img);
++ if (ret) {
++ fsl_secboot_handle_error(ret);
++ goto exit;
++ }
++
++exit:
++ /* Free Img as it was malloc'ed*/
++ free(img);
++ return ret;
++}
+diff --git a/board/solidrun/common/vid.c b/board/solidrun/common/vid.c
+new file mode 100644
+index 0000000000..cc81e80c37
+--- /dev/null
++++ b/board/solidrun/common/vid.c
+@@ -0,0 +1,330 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright 2014 Freescale Semiconductor, Inc.
++ * Copyright 2018 NXP
++ */
++#include <common.h>
++#include <command.h>
++#include <i2c.h>
++#include <asm/io.h>
++#ifdef CONFIG_FSL_LSCH2
++#include <asm/arch/immap_lsch2.h>
++#elif defined(CONFIG_FSL_LSCH3)
++#include <asm/arch/immap_lsch3.h>
++#else
++#include <asm/immap_85xx.h>
++#endif
++#include "vid.h"
++
++int __weak i2c_multiplexer_select_vid_channel(u8 channel)
++{
++ return 0;
++}
++
++/*
++ * Compensate for a board specific voltage drop between regulator and SoC
++ * return a value in mV
++ */
++int __weak board_vdd_drop_compensation(void)
++{
++ return 0;
++}
++
++/*
++ * Board specific settings for specific voltage value
++ */
++int __weak board_adjust_vdd(int vdd)
++{
++ return 0;
++}
++
++/* Maximum loop count waiting for new voltage to take effect */
++#define MAX_LOOP_WAIT_NEW_VOL 100
++/* Maximum loop count waiting for the voltage to be stable */
++#define MAX_LOOP_WAIT_VOL_STABLE 100
++/*
++ * read_voltage from sensor on I2C bus
++ * We use average of 4 readings, waiting for WAIT_FOR_ADC before
++ * another reading
++ */
++#define NUM_READINGS 4 /* prefer to be power of 2 for efficiency */
++
++/* If an INA220 chip is available, we can use it to read back the voltage
++ * as it may have a higher accuracy than the IR chip for the same purpose
++ */
++#ifdef CONFIG_VOL_MONITOR_INA220
++#define WAIT_FOR_ADC 532 /* wait for 532 microseconds for ADC */
++#define ADC_MIN_ACCURACY 4
++#else
++#define WAIT_FOR_ADC 138 /* wait for 138 microseconds for ADC */
++#define ADC_MIN_ACCURACY 4
++#endif
++
++/* read the current value of the LTC Regulator Voltage */
++static int read_voltage_from_LTC(int i2caddress)
++{
++ int ret, vcode = 0;
++ u8 chan = PWM_CHANNEL0;
++
++ /* select the PAGE 0 using PMBus commands PAGE for VDD*/
++ ret = i2c_write(I2C_VOL_MONITOR_ADDR,
++ PMBUS_CMD_PAGE, 1, &chan, 1);
++ if (ret) {
++ printf("VID: failed to select VDD Page 0\n");
++ return ret;
++ }
++
++ /*read the output voltage using PMBus command READ_VOUT*/
++ ret = i2c_read(I2C_VOL_MONITOR_ADDR,
++ PMBUS_CMD_READ_VOUT, 1, (void *)&vcode, 2);
++ if (ret) {
++ printf("VID: failed to read the volatge\n");
++ return ret;
++ }
++
++ /* Scale down to the real mV as LTC resolution is 1/4096V,rounding up */
++ vcode = DIV_ROUND_UP(vcode * 1000, 4096);
++
++ return vcode;
++}
++
++static int read_voltage(int i2caddress)
++{
++ int voltage_read;
++ voltage_read = read_voltage_from_LTC(i2caddress);
++ return voltage_read;
++}
++
++/* this function sets the VDD and returns the value set */
++static int set_voltage_to_LTC(int i2caddress, int vdd)
++{
++ int ret, vdd_last, vdd_target = vdd;
++ int count = 100, temp = 0;
++
++ /* Scale up to the LTC resolution is 1/4096V */
++ vdd = (vdd * 4096) / 1000;
++
++ /* 5-byte buffer which needs to be sent following the
++ * PMBus command PAGE_PLUS_WRITE.
++ */
++ u8 buff[5] = {0x04, PWM_CHANNEL0, PMBUS_CMD_VOUT_COMMAND,
++ vdd & 0xFF, (vdd & 0xFF00) >> 8};
++
++ /* Write the desired voltage code to the regulator */
++ ret = i2c_write(I2C_VOL_MONITOR_ADDR,
++ PMBUS_CMD_PAGE_PLUS_WRITE, 1, (void *)&buff, 5);
++ if (ret) {
++ printf("VID: I2C failed to write to the volatge regulator\n");
++ return -1;
++ }
++
++ /* Wait for the volatge to get to the desired value */
++ do {
++ vdd_last = read_voltage_from_LTC(i2caddress);
++ if (vdd_last < 0) {
++ printf("VID: Couldn't read sensor abort VID adjust\n");
++ return -1;
++ }
++ count--;
++ temp = vdd_last - vdd_target;
++ } while ((abs(temp) > 2) && (count > 0));
++
++ return vdd_last;
++}
++
++static int set_voltage(int i2caddress, int vdd)
++{
++ int vdd_last = -1;
++
++ vdd_last = set_voltage_to_LTC(i2caddress, vdd);
++ return vdd_last;
++}
++
++int adjust_vdd(ulong vdd_override)
++{
++ int re_enable = disable_interrupts();
++ struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
++ u32 fusesr;
++ u8 vid;
++ int vdd_target, vdd_current, vdd_last;
++ int ret, i2caddress;
++ unsigned long vdd_string_override;
++ char *vdd_string;
++ static const u16 vdd[32] = {
++ 8250,
++ 7875,
++ 7750,
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 8000,
++ 8125,
++ 8250,
++ 0, /* reserved */
++ 8500,
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ };
++ struct vdd_drive {
++ u8 vid;
++ unsigned voltage;
++ };
++ ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
++ if (ret) {
++ debug("VID: I2C failed to switch channel\n");
++ ret = -1;
++ goto exit;
++ }
++ /* get the voltage ID from fuse status register */
++ fusesr = in_le32(&gur->dcfg_fusesr);
++ vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT) &
++ FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK;
++ if ((vid == 0) || (vid == FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK)) {
++ vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_VID_SHIFT) &
++ FSL_CHASSIS3_DCFG_FUSESR_VID_MASK;
++ }
++ vdd_target = vdd[vid];
++ printf ("vid FUSE index %d (vdd_target = %d)\n",vid,vdd_target);
++
++ /* check override variable for overriding VDD */
++ vdd_string = env_get(CONFIG_VID_FLS_ENV);
++ if (vdd_override == 0 && vdd_string &&
++ !strict_strtoul(vdd_string, 10, &vdd_string_override))
++ vdd_override = vdd_string_override;
++
++ if (vdd_override >= VDD_MV_MIN && vdd_override <= VDD_MV_MAX) {
++ vdd_target = vdd_override * 10; /* convert to 1/10 mV */
++ debug("VDD override is %lu\n", vdd_override);
++ } else if (vdd_override != 0) {
++ printf("Invalid value.\n");
++ }
++
++ /* divide and round up by 10 to get a value in mV */
++ vdd_target = DIV_ROUND_UP(vdd_target, 10);
++ if (vdd_target == 0) {
++ debug("VID: VID not used\n");
++ ret = 0;
++ goto exit;
++ } else if (vdd_target < VDD_MV_MIN || vdd_target > VDD_MV_MAX) {
++ /* Check vdd_target is in valid range */
++ printf("VID: Target VID %d mV is not in range.\n",
++ vdd_target);
++ ret = -1;
++ goto exit;
++ } else {
++ debug("VID: vid = %d mV\n", vdd_target);
++ }
++
++ /*
++ * Read voltage monitor to check real voltage.
++ */
++ vdd_last = read_voltage(i2caddress);
++ if (vdd_last < 0) {
++ printf("VID: Couldn't read sensor abort VID adjustment\n");
++ ret = -1;
++ goto exit;
++ }
++ vdd_current = vdd_last;
++ debug("VID: Core voltage is currently at %d mV\n", vdd_last);
++
++ /* Set the target voltage */
++ vdd_last = vdd_current = set_voltage(i2caddress, vdd_target);
++ if (board_adjust_vdd(vdd_target) < 0) {
++ ret = -1;
++ goto exit;
++ }
++
++ if (vdd_last > 0)
++ printf("VID: Core voltage after adjustment is at %d mV\n",
++ vdd_last);
++ else
++ ret = -1;
++exit:
++ if (re_enable)
++ enable_interrupts();
++ i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
++ return ret;
++}
++
++static int print_vdd(void)
++{
++ int vdd_last, ret, i2caddress;
++
++ ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
++ if (ret) {
++ debug("VID : I2c failed to switch channel\n");
++ return -1;
++ }
++ /*
++ * Read voltage monitor to check real voltage.
++ */
++ vdd_last = read_voltage(i2caddress);
++ if (vdd_last < 0) {
++ printf("VID: Couldn't read sensor abort VID adjustment\n");
++ goto exit;
++ }
++ printf("VID: Core voltage is at %d mV\n", vdd_last);
++exit:
++ i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
++
++ return ret < 0 ? -1 : 0;
++
++}
++
++static int do_vdd_override(cmd_tbl_t *cmdtp,
++ int flag, int argc,
++ char * const argv[])
++{
++ ulong override;
++
++ if (argc < 2)
++ return CMD_RET_USAGE;
++
++ if (!strict_strtoul(argv[1], 10, &override))
++ adjust_vdd(override); /* the value is checked by callee */
++ else
++ return CMD_RET_USAGE;
++ return 0;
++}
++
++static int do_vdd_read(cmd_tbl_t *cmdtp,
++ int flag, int argc,
++ char * const argv[])
++{
++ if (argc < 1)
++ return CMD_RET_USAGE;
++ print_vdd();
++
++ return 0;
++}
++
++U_BOOT_CMD(
++ vdd_override, 2, 0, do_vdd_override,
++ "override VDD",
++ " - override with the voltage specified in mV, eg. 1050"
++);
++
++U_BOOT_CMD(
++ vdd_read, 1, 0, do_vdd_read,
++ "read VDD",
++ " - Read the voltage specified in mV"
++)
+diff --git a/board/solidrun/common/vid.h b/board/solidrun/common/vid.h
+new file mode 100644
+index 0000000000..99778e9a93
+--- /dev/null
++++ b/board/solidrun/common/vid.h
+@@ -0,0 +1,23 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/*
++ * Copyright 2014 Freescale Semiconductor, Inc.
++ */
++
++#ifndef __VID_H_
++#define __VID_H_
++
++#define IR36021_LOOP1_MANUAL_ID_OFFSET 0x6A
++#define IR36021_LOOP1_VOUT_OFFSET 0x9A
++#define IR36021_MFR_ID_OFFSET 0x92
++#define IR36021_MFR_ID 0x43
++#define IR36021_INTEL_MODE_OOFSET 0x14
++#define IR36021_MODE_MASK 0x20
++#define IR36021_INTEL_MODE 0x00
++#define IR36021_AMD_MODE 0x20
++
++/* step the IR regulator in 5mV increments */
++#define IR_VDD_STEP_DOWN 5
++#define IR_VDD_STEP_UP 5
++int adjust_vdd(ulong vdd_override);
++
++#endif /* __VID_H_ */
+--
+2.17.1
+
diff --git a/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0005-armv8-lx2160acex7-lx2160acex-device-tree.patch b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0005-armv8-lx2160acex7-lx2160acex-device-tree.patch
new file mode 100644
index 00000000..51acc55b
--- /dev/null
+++ b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0005-armv8-lx2160acex7-lx2160acex-device-tree.patch
@@ -0,0 +1,91 @@
+From bd96fd21fafd7560dba1d5a6f893e4a7d0b7ee74 Mon Sep 17 00:00:00 2001
+From: Rabeeh Khoury <rabeeh@solid-run.com>
+Date: Sun, 28 Jul 2019 13:37:22 +0300
+Subject: [PATCH 05/17] armv8: lx2160acex7: lx2160acex device tree
+
+Based on NXP's LX2160ARDB device tree; it defines -
+1. MX35X based SPI flash
+2. SDHC0 (SD card) and SDHC1 (eMMC)
+3. 4 SATA ports that depending on SERDES configuration they can get
+connected to external SATA drives
+
+Upstream-Status: Inappropriate [Solid-Run BSP]
+
+Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
+---
+ arch/arm/dts/fsl-lx2160a-cex7.dts | 63 +++++++++++++++++++++++++++++++
+ 1 file changed, 63 insertions(+)
+ create mode 100644 arch/arm/dts/fsl-lx2160a-cex7.dts
+
+diff --git a/arch/arm/dts/fsl-lx2160a-cex7.dts b/arch/arm/dts/fsl-lx2160a-cex7.dts
+new file mode 100644
+index 0000000000..4fbcaafb0e
+--- /dev/null
++++ b/arch/arm/dts/fsl-lx2160a-cex7.dts
+@@ -0,0 +1,63 @@
++// SPDX-License-Identifier: GPL-2.0+ OR X11
++/*
++ * SolidRun LX2160ACEX7 device tree source
++ *
++ * Author: Rabeeh Khoury <rabeeh@solid-run.com>
++ *
++ * Copyright 2019 SolidRun ltd.
++ *
++ */
++
++/dts-v1/;
++
++#include "fsl-lx2160a.dtsi"
++
++/ {
++ model = "SolidRun LX2160ACEX7 COM express type 7 based board";
++ compatible = "fsl,lx2160acex7", "fsl,lx2160a";
++
++ aliases {
++ spi0 = &fspi;
++ };
++};
++
++&fspi {
++ bus-num = <0>;
++ status = "okay";
++
++ qflash0: MT35XU512ABA1G12@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "spi-flash";
++ spi-max-frequency = <50000000>;
++ reg = <0>;
++ /* The following setting enables 1-1-8 (CMD-ADDR-DATA) mode */
++ fspi-rx-bus-width = <8>; /* 8 FSPI Rx lines */
++ fspi-tx-bus-width = <1>; /* 1 FSPI Tx line */
++ };
++
++};
++
++&esdhc0 {
++ status = "okay";
++};
++
++&esdhc1 {
++ status = "okay";
++};
++
++&sata0 {
++ status = "okay";
++};
++
++&sata1 {
++ status = "okay";
++};
++
++&sata2 {
++ status = "okay";
++};
++
++&sata3 {
++ status = "okay";
++};
+--
+2.17.1
+
diff --git a/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0006-armv8-lx2160acex7-board-support-files.patch b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0006-armv8-lx2160acex7-board-support-files.patch
new file mode 100644
index 00000000..c38abbf9
--- /dev/null
+++ b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0006-armv8-lx2160acex7-board-support-files.patch
@@ -0,0 +1,519 @@
+From c42a926fb0ff087b8c5cb774a67fb64aa1a566ce Mon Sep 17 00:00:00 2001
+From: Rabeeh Khoury <rabeeh@solid-run.com>
+Date: Sun, 28 Jul 2019 13:45:24 +0300
+Subject: [PATCH 06/17] armv8: lx2160acex7: board support files
+
+The lx2160acex7 board support files does the following -
+1. Initializes 1GBps PHY address according to SERDES1 block config.
+2. Sets uart0 as the console
+3. Sets EMC2301 PWM fan controller to it's default value
+4. Misc FDT fixups prior to booting Linux
+
+Upstream-Status: Inappropriate [Solid-Run BSP]
+
+Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
+---
+ board/solidrun/lx2160a/Kconfig | 22 ++
+ board/solidrun/lx2160a/MAINTAINERS | 8 +
+ board/solidrun/lx2160a/Makefile | 9 +
+ board/solidrun/lx2160a/ddr.c | 20 ++
+ board/solidrun/lx2160a/eth_lx2160acex7.c | 104 ++++++++
+ board/solidrun/lx2160a/lx2160a.c | 288 +++++++++++++++++++++++
+ 6 files changed, 451 insertions(+)
+ create mode 100644 board/solidrun/lx2160a/Kconfig
+ create mode 100644 board/solidrun/lx2160a/MAINTAINERS
+ create mode 100644 board/solidrun/lx2160a/Makefile
+ create mode 100644 board/solidrun/lx2160a/ddr.c
+ create mode 100644 board/solidrun/lx2160a/eth_lx2160acex7.c
+ create mode 100644 board/solidrun/lx2160a/lx2160a.c
+
+diff --git a/board/solidrun/lx2160a/Kconfig b/board/solidrun/lx2160a/Kconfig
+new file mode 100644
+index 0000000000..85abac9bfc
+--- /dev/null
++++ b/board/solidrun/lx2160a/Kconfig
+@@ -0,0 +1,22 @@
++if TARGET_LX2160ACEX7
++
++config SYS_BOARD
++ default "lx2160a"
++
++config SYS_VENDOR
++ default "solidrun"
++
++config SYS_SOC
++ default "fsl-layerscape"
++
++config SYS_CONFIG_NAME
++ default "lx2160acex7"
++
++config EMC2301
++ bool "Fan controller"
++ help
++ Enable the EMC2301 fan controller for configuration of fan
++ speed.
++
++source "board/freescale/common/Kconfig"
++endif
+diff --git a/board/solidrun/lx2160a/MAINTAINERS b/board/solidrun/lx2160a/MAINTAINERS
+new file mode 100644
+index 0000000000..688ff66afa
+--- /dev/null
++++ b/board/solidrun/lx2160a/MAINTAINERS
+@@ -0,0 +1,8 @@
++LX2160ACEX7 BOARD
++M: Rabeeh Khoury <rabeeh@solid-run.com>
++S: Maintained
++F: board/solidrun/lx2160a/
++F: include/configs/lx2160a_common.h
++F: include/configs/lx2160acex7.h
++F: configs/lx2160acex7_tfa_defconfig
++F: arch/arm/dts/fsl-lx2160a-cex7.dts
+diff --git a/board/solidrun/lx2160a/Makefile b/board/solidrun/lx2160a/Makefile
+new file mode 100644
+index 0000000000..c92266f322
+--- /dev/null
++++ b/board/solidrun/lx2160a/Makefile
+@@ -0,0 +1,9 @@
++#
++# Copyright 2019 SolidRun ltd.
++#
++# SPDX-License-Identifier: GPL-2.0+
++#
++
++obj-y += lx2160a.o
++obj-y += ddr.o
++obj-$(CONFIG_TARGET_LX2160ACEX7) += eth_lx2160acex7.o
+diff --git a/board/solidrun/lx2160a/ddr.c b/board/solidrun/lx2160a/ddr.c
+new file mode 100644
+index 0000000000..9c7bd10475
+--- /dev/null
++++ b/board/solidrun/lx2160a/ddr.c
+@@ -0,0 +1,20 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright 2019 SolidRun ltd.
++ */
++
++#include <common.h>
++#include <fsl_ddr_sdram.h>
++#include <fsl_ddr_dimm_params.h>
++
++DECLARE_GLOBAL_DATA_PTR;
++
++int fsl_initdram(void)
++{
++ gd->ram_size = tfa_get_dram_size();
++
++ if (!gd->ram_size)
++ gd->ram_size = fsl_ddr_sdram_size();
++
++ return 0;
++}
+diff --git a/board/solidrun/lx2160a/eth_lx2160acex7.c b/board/solidrun/lx2160a/eth_lx2160acex7.c
+new file mode 100644
+index 0000000000..97e414838f
+--- /dev/null
++++ b/board/solidrun/lx2160a/eth_lx2160acex7.c
+@@ -0,0 +1,104 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright 2019 SolidRun ltd.
++ *
++ */
++
++#include <common.h>
++#include <command.h>
++#include <netdev.h>
++#include <malloc.h>
++#include <fsl_mdio.h>
++#include <miiphy.h>
++#include <phy.h>
++#include <fm_eth.h>
++#include <asm/io.h>
++#include <exports.h>
++#include <asm/arch/fsl_serdes.h>
++#include <fsl-mc/fsl_mc.h>
++#include <fsl-mc/ldpaa_wriop.h>
++
++DECLARE_GLOBAL_DATA_PTR;
++
++int board_eth_init(bd_t *bis)
++{
++#if defined(CONFIG_FSL_MC_ENET)
++ struct memac_mdio_info mdio_info;
++ struct memac_mdio_controller *reg;
++ int i, interface;
++ struct mii_dev *dev;
++ struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
++ u32 srds_s1;
++
++ srds_s1 = in_le32(&gur->rcwsr[28]) &
++ FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK;
++ srds_s1 >>= FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT;
++
++ reg = (struct memac_mdio_controller *)CONFIG_SYS_FSL_WRIOP1_MDIO1;
++ mdio_info.regs = reg;
++ mdio_info.name = DEFAULT_WRIOP_MDIO1_NAME;
++
++ /* Register the EMI 1 */
++ fm_memac_mdio_init(bis, &mdio_info);
++
++ wriop_set_phy_address(WRIOP1_DPMAC17, 0,
++ RGMII_PHY_ADDR1);
++ reg = (struct memac_mdio_controller *)CONFIG_SYS_FSL_WRIOP1_MDIO2;
++ switch (srds_s1) {
++ case 3:
++ case 5:
++ case 8:
++ case 13:
++ case 14:
++ case 15:
++ case 17:
++ case 20:
++ case 23:
++ wriop_set_phy_address(WRIOP1_DPMAC17, 0,
++ RGMII_PHY_ADDR1);
++ break;
++
++ default:
++ printf("SerDes1 protocol 0x%x is not supported on LX2160ACEX7\n",
++ srds_s1);
++ goto next;
++ }
++ for (i = WRIOP1_DPMAC17; i <= WRIOP1_DPMAC17; i++) {
++ interface = wriop_get_enet_if(i);
++ switch (interface) {
++ case PHY_INTERFACE_MODE_RGMII:
++ case PHY_INTERFACE_MODE_RGMII_ID:
++ dev = miiphy_get_dev_by_name(DEFAULT_WRIOP_MDIO1_NAME);
++ wriop_set_mdio(i, dev);
++ break;
++ default:
++ break;
++ }
++ }
++
++next:
++ cpu_eth_init(bis);
++#endif /* CONFIG_FSL_MC_ENET */
++
++ return pci_eth_init(bis);
++}
++
++#if defined(CONFIG_RESET_PHY_R)
++void reset_phy(void)
++{
++#if defined(CONFIG_FSL_MC_ENET)
++ mc_env_boot();
++#endif
++}
++#endif /* CONFIG_RESET_PHY_R */
++
++int fdt_fixup_board_phy(void *fdt)
++{
++ int mdio_offset;
++ int ret;
++ struct mii_dev *dev;
++
++ ret = 0;
++
++ return ret;
++}
+diff --git a/board/solidrun/lx2160a/lx2160a.c b/board/solidrun/lx2160a/lx2160a.c
+new file mode 100644
+index 0000000000..b0d9f1012e
+--- /dev/null
++++ b/board/solidrun/lx2160a/lx2160a.c
+@@ -0,0 +1,288 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright 2019 SolidRun ltd.
++ */
++
++#include <common.h>
++#include <dm.h>
++#include <dm/platform_data/serial_pl01x.h>
++#include <i2c.h>
++#include <malloc.h>
++#include <errno.h>
++#include <netdev.h>
++#include <fsl_ddr.h>
++#include <fsl_sec.h>
++#include <asm/io.h>
++#include <fdt_support.h>
++#include <linux/libfdt.h>
++#include <fsl-mc/fsl_mc.h>
++#include <environment.h>
++#include <efi_loader.h>
++#include <asm/arch/mmu.h>
++#include <hwconfig.h>
++#include <asm/arch/fsl_serdes.h>
++#include <asm/arch/soc.h>
++#include "../../freescale/common/vid.h"
++#include <fsl_immap.h>
++
++#ifdef CONFIG_EMC2301
++#include "../common/emc2301.h"
++#endif
++
++
++DECLARE_GLOBAL_DATA_PTR;
++
++static struct pl01x_serial_platdata serial0 = {
++#if CONFIG_CONS_INDEX == 0
++ .base = CONFIG_SYS_SERIAL0,
++#elif CONFIG_CONS_INDEX == 1
++ .base = CONFIG_SYS_SERIAL1,
++#else
++#error "Unsupported console index value."
++#endif
++ .type = TYPE_PL011,
++};
++
++U_BOOT_DEVICE(nxp_serial0) = {
++ .name = "serial_pl01x",
++ .platdata = &serial0,
++};
++
++static struct pl01x_serial_platdata serial1 = {
++ .base = CONFIG_SYS_SERIAL1,
++ .type = TYPE_PL011,
++};
++
++U_BOOT_DEVICE(nxp_serial1) = {
++ .name = "serial_pl01x",
++ .platdata = &serial1,
++};
++
++int select_i2c_ch_pca9547(u8 ch)
++{
++ int ret;
++
++ ret = i2c_write(I2C_MUX_PCA_ADDR_PRI, 0, 1, &ch, 1);
++ if (ret) {
++ puts("PCA: failed to select proper channel\n");
++ return ret;
++ }
++
++ return 0;
++}
++
++static void uart_get_clock(void)
++{
++ serial0.clock = get_serial_clock();
++ serial1.clock = get_serial_clock();
++}
++
++int board_early_init_f(void)
++{
++#ifdef CONFIG_SYS_I2C_EARLY_INIT
++ i2c_early_init_f();
++#endif
++ /* get required clock for UART IP */
++ uart_get_clock();
++
++#ifdef CONFIG_EMC2301
++ select_i2c_ch_pca9547(I2C_MUX_CH_EMC2301);
++ emc2301_init();
++ set_fan_speed(I2C_EMC2301_PWM);
++ select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT);
++#endif
++ fsl_lsch3_early_init_f();
++ return 0;
++}
++
++#ifdef CONFIG_OF_BOARD_FIXUP
++int board_fix_fdt(void *fdt)
++{
++ return 0;
++}
++#endif
++
++int esdhc_status_fixup(void *blob, const char *compat)
++{
++ /* Enable both esdhc DT nodes for LX2160ARDB */
++ do_fixup_by_compat(blob, compat, "status", "okay",
++ sizeof("okay"), 1);
++ return 0;
++}
++
++#if defined(CONFIG_VID)
++int i2c_multiplexer_select_vid_channel(u8 channel)
++{
++ return select_i2c_ch_pca9547(channel);
++}
++
++#endif
++
++int checkboard(void)
++{
++ enum boot_src src = get_boot_src();
++ char buf[64];
++ cpu_name(buf);
++ printf("Board: %s-CEX7, ", buf);
++
++ if (src == BOOT_SOURCE_SD_MMC) {
++ puts("SD\n");
++ }
++ puts("SERDES1 Reference: Clock1 = 161.13MHz Clock2 = 100MHz\n");
++ puts("SERDES2 Reference: Clock1 = 100MHz Clock2 = 100MHz\n");
++ puts("SERDES3 Reference: Clock1 = 100MHz Clock2 = 100Hz\n");
++ return 0;
++}
++
++int config_board_mux(void)
++{
++ return 0;
++}
++
++unsigned long get_board_sys_clk(void)
++{
++ return 100000000;
++}
++
++unsigned long get_board_ddr_clk(void)
++{
++ return 100000000;
++}
++
++int board_init(void)
++{
++#ifdef CONFIG_ENV_IS_NOWHERE
++ gd->env_addr = (ulong)&default_environment[0];
++#endif
++
++ select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT);
++
++#ifdef CONFIG_FSL_CAAM
++ sec_init();
++#endif
++
++ return 0;
++}
++
++void detail_board_ddr_info(void)
++{
++ int i;
++ u64 ddr_size = 0;
++
++ puts("\nDDR ");
++ for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
++ ddr_size += gd->bd->bi_dram[i].size;
++ print_size(ddr_size, "");
++ print_ddr_info(0);
++}
++
++#if defined(CONFIG_ARCH_MISC_INIT)
++int arch_misc_init(void)
++{
++ config_board_mux();
++
++ return 0;
++}
++#endif
++
++#ifdef CONFIG_FSL_MC_ENET
++extern int fdt_fixup_board_phy(void *fdt);
++
++void fdt_fixup_board_enet(void *fdt)
++{
++ int offset;
++
++ offset = fdt_path_offset(fdt, "/soc/fsl-mc");
++
++ if (offset < 0)
++ offset = fdt_path_offset(fdt, "/fsl-mc");
++
++ if (offset < 0) {
++ printf("%s: fsl-mc node not found in device tree (error %d)\n",
++ __func__, offset);
++ return;
++ }
++
++ if (get_mc_boot_status() == 0 &&
++ (is_lazy_dpl_addr_valid() || get_dpl_apply_status() == 0)) {
++ fdt_status_okay(fdt, offset);
++ fdt_fixup_board_phy(fdt);
++ } else {
++ fdt_status_fail(fdt, offset);
++ }
++}
++
++void board_quiesce_devices(void)
++{
++ fsl_mc_ldpaa_exit(gd->bd);
++}
++#endif
++
++#ifdef CONFIG_OF_BOARD_SETUP
++
++int ft_board_setup(void *blob, bd_t *bd)
++{
++ int i;
++ bool mc_memory_bank = false;
++
++ u64 *base;
++ u64 *size;
++ u64 mc_memory_base = 0;
++ u64 mc_memory_size = 0;
++ u16 total_memory_banks;
++
++ ft_cpu_setup(blob, bd);
++
++ fdt_fixup_mc_ddr(&mc_memory_base, &mc_memory_size);
++
++ if (mc_memory_base != 0)
++ mc_memory_bank = true;
++
++ total_memory_banks = CONFIG_NR_DRAM_BANKS + mc_memory_bank;
++
++ base = calloc(total_memory_banks, sizeof(u64));
++ size = calloc(total_memory_banks, sizeof(u64));
++
++ /* fixup DT for the three GPP DDR banks */
++ for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
++ base[i] = gd->bd->bi_dram[i].start;
++ size[i] = gd->bd->bi_dram[i].size;
++ }
++
++#ifdef CONFIG_RESV_RAM
++ /* reduce size if reserved memory is within this bank */
++ if (gd->arch.resv_ram >= base[0] &&
++ gd->arch.resv_ram < base[0] + size[0])
++ size[0] = gd->arch.resv_ram - base[0];
++ else if (gd->arch.resv_ram >= base[1] &&
++ gd->arch.resv_ram < base[1] + size[1])
++ size[1] = gd->arch.resv_ram - base[1];
++ else if (gd->arch.resv_ram >= base[2] &&
++ gd->arch.resv_ram < base[2] + size[2])
++ size[2] = gd->arch.resv_ram - base[2];
++#endif
++
++ if (mc_memory_base != 0) {
++ for (i = 0; i <= total_memory_banks; i++) {
++ if (base[i] == 0 && size[i] == 0) {
++ base[i] = mc_memory_base;
++ size[i] = mc_memory_size;
++ break;
++ }
++ }
++ }
++
++ fdt_fixup_memory_banks(blob, base, size, total_memory_banks);
++
++#ifdef CONFIG_USB
++ fsl_fdt_fixup_dr_usb(blob, bd);
++#endif
++
++#ifdef CONFIG_FSL_MC_ENET
++ fdt_fsl_mc_fixup_iommu_map_entry(blob);
++ fdt_fixup_board_enet(blob);
++#endif
++
++ return 0;
++}
++#endif
+--
+2.17.1
+
diff --git a/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0007-lx2160a-load-dpl-into-0x80001000-instead-of-0x80d000.patch b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0007-lx2160a-load-dpl-into-0x80001000-instead-of-0x80d000.patch
new file mode 100644
index 00000000..b5d2d161
--- /dev/null
+++ b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0007-lx2160a-load-dpl-into-0x80001000-instead-of-0x80d000.patch
@@ -0,0 +1,47 @@
+From 422b44970b160ee2e8752552a6232e50106a7bd8 Mon Sep 17 00:00:00 2001
+From: Rabeeh Khoury <rabeeh@solid-run.com>
+Date: Mon, 4 May 2020 23:09:52 +0300
+Subject: [PATCH 07/17] lx2160a: load dpl into 0x80001000 instead of 0x80d00000
+
+and enlarge the image size to 0x1000 blocks
+
+Upstream-Status: Inappropriate [Solid-Run BSP]
+
+Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
+---
+ include/configs/lx2160a_common.h | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/include/configs/lx2160a_common.h b/include/configs/lx2160a_common.h
+index c6a6a96ff0..5b9808b2ef 100644
+--- a/include/configs/lx2160a_common.h
++++ b/include/configs/lx2160a_common.h
+@@ -293,21 +293,21 @@ int select_i2c_ch_pca9547_sec(unsigned char ch);
+
+ #define SD_BOOTCOMMAND \
+ "env exists mcinitcmd && mmcinfo; " \
+- "mmc read 0x80d00000 0x6800 0x800; " \
++ "mmc read 0x80001000 0x6800 0x1000; " \
+ "env exists mcinitcmd && env exists secureboot " \
+ " && mmc read 0x806C0000 0x3600 0x20 " \
+ "&& esbc_validate 0x806C0000;env exists mcinitcmd " \
+- "&& fsl_mc lazyapply dpl 0x80d00000;" \
++ "&& fsl_mc lazyapply dpl 0x80001000;" \
+ "run distro_bootcmd;run sd_bootcmd;" \
+ "env exists secureboot && esbc_halt;"
+
+ #define SD2_BOOTCOMMAND \
+ "mmc dev 1; env exists mcinitcmd && mmcinfo; " \
+- "mmc read 0x80d00000 0x6800 0x800; " \
++ "mmc read 0x80001000 0x6800 0x1000; " \
+ "env exists mcinitcmd && env exists secureboot " \
+ " && mmc read 0x806C0000 0x3600 0x20 " \
+ "&& esbc_validate 0x806C0000;env exists mcinitcmd " \
+- "&& fsl_mc lazyapply dpl 0x80d00000;" \
++ "&& fsl_mc lazyapply dpl 0x80001000;" \
+ "run distro_bootcmd;run emmc_bootcmd;" \
+ "env exists secureboot && esbc_halt;"
+
+--
+2.17.1
+
diff --git a/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0008-uboot-add-nvme-commands-and-for-distroboot.patch b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0008-uboot-add-nvme-commands-and-for-distroboot.patch
new file mode 100644
index 00000000..6ea81105
--- /dev/null
+++ b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0008-uboot-add-nvme-commands-and-for-distroboot.patch
@@ -0,0 +1,41 @@
+From 8fa576d659e4710eae0b62aadd7717846c64746c Mon Sep 17 00:00:00 2001
+From: Rabeeh Khoury <rabeeh@solid-run.com>
+Date: Mon, 11 Nov 2019 23:45:31 +0200
+Subject: [PATCH 08/17] uboot - add nvme commands and for distroboot
+
+Upstream-Status: Inappropriate [Solid-Run BSP]
+
+Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
+---
+ configs/lx2160acex7_tfa_defconfig | 2 ++
+ include/configs/lx2160a_common.h | 1 +
+ 2 files changed, 3 insertions(+)
+
+diff --git a/configs/lx2160acex7_tfa_defconfig b/configs/lx2160acex7_tfa_defconfig
+index d59de7d054..3891d2a7c4 100644
+--- a/configs/lx2160acex7_tfa_defconfig
++++ b/configs/lx2160acex7_tfa_defconfig
+@@ -25,6 +25,8 @@ CONFIG_CMD_PCI=y
+ CONFIG_CMD_SF=y
+ CONFIG_CMD_USB=y
+ CONFIG_CMD_CACHE=y
++CONFIG_CMD_NVME=y
++CONFIG_NVME=y
+ CONFIG_MP=y
+ CONFIG_OF_CONTROL=y
+ CONFIG_DEFAULT_DEVICE_TREE="fsl-lx2160a-cex7"
+diff --git a/include/configs/lx2160a_common.h b/include/configs/lx2160a_common.h
+index 5b9808b2ef..e31738d3a3 100644
+--- a/include/configs/lx2160a_common.h
++++ b/include/configs/lx2160a_common.h
+@@ -316,6 +316,7 @@ int select_i2c_ch_pca9547_sec(unsigned char ch);
+ func(MMC, mmc, 0) \
+ func(MMC, mmc, 1) \
+ func(SCSI, scsi, 0) \
++ func(NVME, nvme, 0) \
+ func(DHCP, dhcp, na)
+ #include <config_distro_bootcmd.h>
+
+--
+2.17.1
+
diff --git a/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0009-armv8-lx2160acex7-Fix-booting-from-NVMe-drives.patch b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0009-armv8-lx2160acex7-Fix-booting-from-NVMe-drives.patch
new file mode 100644
index 00000000..e813e423
--- /dev/null
+++ b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0009-armv8-lx2160acex7-Fix-booting-from-NVMe-drives.patch
@@ -0,0 +1,33 @@
+From aeefed55fa39f4fc5acb2bd22fdde4dc97924d22 Mon Sep 17 00:00:00 2001
+From: Rabeeh Khoury <rabeeh@solid-run.com>
+Date: Mon, 23 Mar 2020 13:32:09 +0200
+Subject: [PATCH 09/17] armv8: lx2160acex7: Fix booting from NVMe drives
+
+Currently NVMe is not initialized so u-boot fails to read kernel from
+NVMe drive. This patch modifies default environment so it initializes
+NVMe as part of default startup script...
+
+Credit to Damjan Marion <dmarion@me.com> on fixing that on LSDK-19.09.
+
+Upstream-Status: Inappropriate [Solid-Run BSP]
+
+Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
+---
+ include/configs/lx2160a_common.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/include/configs/lx2160a_common.h b/include/configs/lx2160a_common.h
+index e31738d3a3..91e9a2470f 100644
+--- a/include/configs/lx2160a_common.h
++++ b/include/configs/lx2160a_common.h
+@@ -261,6 +261,7 @@ int select_i2c_ch_pca9547_sec(unsigned char ch);
+ BOOTENV \
+ "mcmemsize=0x70000000\0" \
+ XSPI_MC_INIT_CMD \
++ "nvme_need_init=true\0" \
+ "scan_dev_for_boot_part=" \
+ "part list ${devtype} ${devnum} devplist; " \
+ "env exists devplist || setenv devplist 1; " \
+--
+2.17.1
+
diff --git a/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0010-nvme-add-accessor-to-namespace-id-and-eui64.patch b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0010-nvme-add-accessor-to-namespace-id-and-eui64.patch
new file mode 100644
index 00000000..d8de8a38
--- /dev/null
+++ b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0010-nvme-add-accessor-to-namespace-id-and-eui64.patch
@@ -0,0 +1,90 @@
+From 89dbced60971ec1d01386b0457c20e045cbfe5ad Mon Sep 17 00:00:00 2001
+From: Patrick Wildt <patrick@blueri.se>
+Date: Thu, 3 Oct 2019 13:48:47 +0200
+Subject: [PATCH 10/17] nvme: add accessor to namespace id and eui64
+
+This adds a function which can be used by e.g. EFI to retrieve
+the namespace identifier and EUI64. For that it adds the EUI64
+to its driver internal namespace structure and copies the EUI64
+during namespace identification.
+
+Upstream-Status: Backport [Solid-Run BSP]
+
+Signed-off-by: Patrick Wildt <patrick@blueri.se>
+Tested-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+(cherry picked from commit c50b2883dfc1ce355dc37238741ef97cd2c5d000)
+Signed-off-by: Olof Johansson <olof@lixom.net>
+---
+ drivers/nvme/nvme.c | 13 +++++++++++++
+ drivers/nvme/nvme.h | 1 +
+ include/nvme.h | 12 ++++++++++++
+ 3 files changed, 26 insertions(+)
+
+diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
+index 47f101e280..ee6b581d9e 100644
+--- a/drivers/nvme/nvme.c
++++ b/drivers/nvme/nvme.c
+@@ -621,6 +621,18 @@ static int nvme_get_info_from_identify(struct nvme_dev *dev)
+ return 0;
+ }
+
++int nvme_get_namespace_id(struct udevice *udev, u32 *ns_id, u8 *eui64)
++{
++ struct nvme_ns *ns = dev_get_priv(udev);
++
++ if (ns_id)
++ *ns_id = ns->ns_id;
++ if (eui64)
++ memcpy(eui64, ns->eui64, sizeof(ns->eui64));
++
++ return 0;
++}
++
+ int nvme_scan_namespace(void)
+ {
+ struct uclass *uc;
+@@ -657,6 +669,7 @@ static int nvme_blk_probe(struct udevice *udev)
+ if (nvme_identify(ndev, ns->ns_id, 0, (dma_addr_t)(long)id))
+ return -EIO;
+
++ memcpy(&ns->eui64, &id->eui64, sizeof(id->eui64));
+ flbas = id->flbas & NVME_NS_FLBAS_LBA_MASK;
+ ns->flbas = flbas;
+ ns->lba_shift = id->lbaf[flbas].ds;
+diff --git a/drivers/nvme/nvme.h b/drivers/nvme/nvme.h
+index 922f7abfe8..0e8cb221a7 100644
+--- a/drivers/nvme/nvme.h
++++ b/drivers/nvme/nvme.h
+@@ -637,6 +637,7 @@ struct nvme_ns {
+ struct list_head list;
+ struct nvme_dev *dev;
+ unsigned ns_id;
++ u8 eui64[8];
+ int devnum;
+ int lba_shift;
+ u8 flbas;
+diff --git a/include/nvme.h b/include/nvme.h
+index 2c3d14d241..2cdf8ce320 100644
+--- a/include/nvme.h
++++ b/include/nvme.h
+@@ -78,4 +78,16 @@ int nvme_scan_namespace(void);
+ */
+ int nvme_print_info(struct udevice *udev);
+
++/**
++ * nvme_get_namespace_id - return namespace identifier
++ *
++ * This returns the namespace identifier.
++ *
++ * @udev: NVMe controller device
++ * @ns_id: Place where to put the name space identifier
++ * @eui64: Place where to put the IEEE Extended Unique Identifier
++ * @return: 0 on success, -ve on error
++ */
++int nvme_get_namespace_id(struct udevice *udev, u32 *ns_id, u8 *eui64);
++
+ #endif /* __NVME_H__ */
+--
+2.17.1
+
diff --git a/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0011-nvme-flush-dcache-on-both-r-w-and-the-prp-list.patch b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0011-nvme-flush-dcache-on-both-r-w-and-the-prp-list.patch
new file mode 100644
index 00000000..0e0c8d54
--- /dev/null
+++ b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0011-nvme-flush-dcache-on-both-r-w-and-the-prp-list.patch
@@ -0,0 +1,51 @@
+From bdc721890d0a68d297959052394da75112080bfe Mon Sep 17 00:00:00 2001
+From: Patrick Wildt <patrick@blueri.se>
+Date: Wed, 16 Oct 2019 23:22:50 +0200
+Subject: [PATCH 11/17] nvme: flush dcache on both r/w, and the prp list
+
+It's possible that the data cache for the buffer still holds data
+to be flushed to memory, since the buffer was probably used as stack
+before. Thus we need to make sure to flush it also on reads, since
+it's possible that the cache is automatically flused to memory after
+the NVMe DMA transfer happened, thus overwriting the NVMe transfer's
+data. Also add a missing dcache flush for the prp list.
+
+Upstream-Status: Backport [Solid-Run BSP]
+
+Signed-off-by: Patrick Wildt <patrick@blueri.se>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+(cherry picked from commit 8c403402ca691c967516481b6bc2c879d683a73d)
+Signed-off-by: Olof Johansson <olof@lixom.net>
+---
+ drivers/nvme/nvme.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
+index ee6b581d9e..53ff6e89aa 100644
+--- a/drivers/nvme/nvme.c
++++ b/drivers/nvme/nvme.c
+@@ -123,6 +123,9 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
+ }
+ *prp2 = (ulong)dev->prp_pool;
+
++ flush_dcache_range((ulong)dev->prp_pool, (ulong)dev->prp_pool +
++ dev->prp_entry_num * sizeof(u64));
++
+ return 0;
+ }
+
+@@ -705,9 +708,8 @@ static ulong nvme_blk_rw(struct udevice *udev, lbaint_t blknr,
+ u16 lbas = 1 << (dev->max_transfer_shift - ns->lba_shift);
+ u64 total_lbas = blkcnt;
+
+- if (!read)
+- flush_dcache_range((unsigned long)buffer,
+- (unsigned long)buffer + total_len);
++ flush_dcache_range((unsigned long)buffer,
++ (unsigned long)buffer + total_len);
+
+ c.rw.opcode = read ? nvme_cmd_read : nvme_cmd_write;
+ c.rw.flags = 0;
+--
+2.17.1
+
diff --git a/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0012-nvme-use-page-aligned-buffer-for-identify-command.patch b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0012-nvme-use-page-aligned-buffer-for-identify-command.patch
new file mode 100644
index 00000000..c82cd649
--- /dev/null
+++ b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0012-nvme-use-page-aligned-buffer-for-identify-command.patch
@@ -0,0 +1,94 @@
+From f6b1bf35c4423eb1f038eca80df4f7d6862f338a Mon Sep 17 00:00:00 2001
+From: Patrick Wildt <patrick@blueri.se>
+Date: Wed, 16 Oct 2019 08:42:04 +0200
+Subject: [PATCH 12/17] nvme: use page-aligned buffer for identify command
+
+Change the stack-allocated buffer for the identification command
+to explicitly allocate page-aligned buffers. Even though the spec
+seems to allow having admin queue commands on non page-aligned
+buffers, it seems to not be possible on my i.MX8MQ board with a
+a Silicon Power P34A80. Since all of the NVMe drivers I have seen
+always do admin commands on a page-aligned buffer, which does work
+on my system, it makes sense for us to do that as well.
+
+Upstream-Status: Backport [Solid-Run BSP]
+
+Signed-off-by: Patrick Wildt <patrick@blueri.se>
+Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
+(cherry picked from commit 2f83481dff9c4f253a6ac341911d78d4984ca07b)
+Signed-off-by: Olof Johansson <olof@lixom.net>
+---
+ drivers/nvme/nvme.c | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
+index 53ff6e89aa..f915817aaa 100644
+--- a/drivers/nvme/nvme.c
++++ b/drivers/nvme/nvme.c
+@@ -583,14 +583,19 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
+
+ static int nvme_get_info_from_identify(struct nvme_dev *dev)
+ {
+- ALLOC_CACHE_ALIGN_BUFFER(char, buf, sizeof(struct nvme_id_ctrl));
+- struct nvme_id_ctrl *ctrl = (struct nvme_id_ctrl *)buf;
++ struct nvme_id_ctrl *ctrl;
+ int ret;
+ int shift = NVME_CAP_MPSMIN(dev->cap) + 12;
+
++ ctrl = memalign(dev->page_size, sizeof(struct nvme_id_ctrl));
++ if (!ctrl)
++ return -ENOMEM;
++
+ ret = nvme_identify(dev, 0, 1, (dma_addr_t)(long)ctrl);
+- if (ret)
++ if (ret) {
++ free(ctrl);
+ return -EIO;
++ }
+
+ dev->nn = le32_to_cpu(ctrl->nn);
+ dev->vwc = ctrl->vwc;
+@@ -621,6 +626,7 @@ static int nvme_get_info_from_identify(struct nvme_dev *dev)
+ dev->max_transfer_shift = 20;
+ }
+
++ free(ctrl);
+ return 0;
+ }
+
+@@ -661,16 +667,21 @@ static int nvme_blk_probe(struct udevice *udev)
+ struct blk_desc *desc = dev_get_uclass_platdata(udev);
+ struct nvme_ns *ns = dev_get_priv(udev);
+ u8 flbas;
+- ALLOC_CACHE_ALIGN_BUFFER(char, buf, sizeof(struct nvme_id_ns));
+- struct nvme_id_ns *id = (struct nvme_id_ns *)buf;
+ struct pci_child_platdata *pplat;
++ struct nvme_id_ns *id;
++
++ id = memalign(ndev->page_size, sizeof(struct nvme_id_ns));
++ if (!id)
++ return -ENOMEM;
+
+ memset(ns, 0, sizeof(*ns));
+ ns->dev = ndev;
+ /* extract the namespace id from the block device name */
+ ns->ns_id = trailing_strtol(udev->name) + 1;
+- if (nvme_identify(ndev, ns->ns_id, 0, (dma_addr_t)(long)id))
++ if (nvme_identify(ndev, ns->ns_id, 0, (dma_addr_t)(long)id)) {
++ free(id);
+ return -EIO;
++ }
+
+ memcpy(&ns->eui64, &id->eui64, sizeof(id->eui64));
+ flbas = id->flbas & NVME_NS_FLBAS_LBA_MASK;
+@@ -689,6 +700,7 @@ static int nvme_blk_probe(struct udevice *udev)
+ memcpy(desc->product, ndev->serial, sizeof(ndev->serial));
+ memcpy(desc->revision, ndev->firmware_rev, sizeof(ndev->firmware_rev));
+
++ free(id);
+ return 0;
+ }
+
+--
+2.17.1
+
diff --git a/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0013-lx2160a-cex7-move-from-lsdk-19.06-to-lsdk-19.09.patch b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0013-lx2160a-cex7-move-from-lsdk-19.06-to-lsdk-19.09.patch
new file mode 100644
index 00000000..0ccb2eb9
--- /dev/null
+++ b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0013-lx2160a-cex7-move-from-lsdk-19.06-to-lsdk-19.09.patch
@@ -0,0 +1,923 @@
+From 4672d506d0abfba7890b2719b7b53f3694b88d06 Mon Sep 17 00:00:00 2001
+From: Rabeeh Khoury <rabeeh@solid-run.com>
+Date: Mon, 3 Feb 2020 14:26:55 +0200
+Subject: [PATCH 13/17] lx2160a-cex7 : move from lsdk-19.06 to lsdk-19.09
+
+Following is a list of changes -
+1. I2C moved to DM model
+2. removed emc2301 support
+3. synchronized vid.c with NXP's driver. But it is still not functional
+in u-boot
+4. Added eMMC to distroboot target list
+
+Upstream-Status: Inappropriate [Solid-Run BSP]
+
+Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
+---
+ arch/arm/dts/fsl-lx2160a-cex7.dts | 14 +
+ board/solidrun/common/Makefile | 1 -
+ board/solidrun/common/emc2301.c | 31 --
+ board/solidrun/common/vid.c | 638 +++++++++++++++++++++++++++++-
+ board/solidrun/lx2160a/lx2160a.c | 8 +
+ configs/lx2160acex7_tfa_defconfig | 8 +-
+ 6 files changed, 665 insertions(+), 35 deletions(-)
+ delete mode 100644 board/solidrun/common/emc2301.c
+
+diff --git a/arch/arm/dts/fsl-lx2160a-cex7.dts b/arch/arm/dts/fsl-lx2160a-cex7.dts
+index 4fbcaafb0e..4ca67df25a 100644
+--- a/arch/arm/dts/fsl-lx2160a-cex7.dts
++++ b/arch/arm/dts/fsl-lx2160a-cex7.dts
+@@ -46,6 +46,20 @@
+ status = "okay";
+ };
+
++&i2c0 {
++ status = "okay";
++ u-boot,dm-pre-reloc;
++};
++
++&i2c4 {
++ status = "okay";
++
++ rtc@51 {
++ compatible = "pcf2127-rtc";
++ reg = <0x51>;
++ };
++};
++
+ &sata0 {
+ status = "okay";
+ };
+diff --git a/board/solidrun/common/Makefile b/board/solidrun/common/Makefile
+index 454a18e2f9..c335c658d4 100644
+--- a/board/solidrun/common/Makefile
++++ b/board/solidrun/common/Makefile
+@@ -16,7 +16,6 @@ ifdef MINIMAL
+ obj- := __dummy__.o
+ else
+ obj-$(CONFIG_VID) += vid.o
+-obj-$(CONFIG_EMC2301) += emc2301.o
+ ifdef CONFIG_SECURE_BOOT
+ obj-$(CONFIG_CMD_ESBC_VALIDATE) += fsl_validate.o cmd_esbc_validate.o
+ endif
+diff --git a/board/solidrun/common/emc2301.c b/board/solidrun/common/emc2301.c
+deleted file mode 100644
+index a4780dbfcc..0000000000
+--- a/board/solidrun/common/emc2301.c
++++ /dev/null
+@@ -1,31 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0+
+-/*
+- * Copyright 2019 SolidRun ltd. Based on code from NXP LX2160A RDB
+- *
+- * SPDX-License-Identifier: GPL-2.0+
+- */
+-
+-#include <common.h>
+-#include <command.h>
+-#include <i2c.h>
+-#include <asm/io.h>
+-
+-#include "emc2301.h"
+-
+-DECLARE_GLOBAL_DATA_PTR;
+-
+-void set_fan_speed(u8 data)
+-{
+- if (i2c_write(I2C_EMC2301_ADDR, I2C_EMC2301_FAN, 1, &data, 1) != 0) {
+- puts("Error: failed to change fan speed\n");
+- }
+-}
+-
+-void emc2301_init(void)
+-{
+- u8 data;
+-
+- data = I2C_EMC2301_CMD;
+- if (i2c_write(I2C_EMC2301_ADDR, I2C_EMC2301_CONF, 1, &data, 1) != 0)
+- puts("Error: failed to configure EMC2301\n");
+-}
+diff --git a/board/solidrun/common/vid.c b/board/solidrun/common/vid.c
+index cc81e80c37..c7a626fd4f 100644
+--- a/board/solidrun/common/vid.c
++++ b/board/solidrun/common/vid.c
+@@ -1,8 +1,9 @@
+ // SPDX-License-Identifier: GPL-2.0+
+ /*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+- * Copyright 2018 NXP
++ * Copyright 2019 NXP
+ */
++
+ #include <common.h>
+ #include <command.h>
+ #include <i2c.h>
+@@ -38,6 +39,52 @@ int __weak board_adjust_vdd(int vdd)
+ return 0;
+ }
+
++#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
++ defined(CONFIG_VOL_MONITOR_IR36021_READ)
++/*
++ * Get the i2c address configuration for the IR regulator chip
++ *
++ * There are some variance in the RDB HW regarding the I2C address configuration
++ * for the IR regulator chip, which is likely a problem of external resistor
++ * accuracy. So we just check each address in a hopefully non-intrusive mode
++ * and use the first one that seems to work
++ *
++ * The IR chip can show up under the following addresses:
++ * 0x08 (Verified on T1040RDB-PA,T4240RDB-PB,X-T4240RDB-16GPA)
++ * 0x09 (Verified on T1040RDB-PA)
++ * 0x38 (Verified on T2080QDS, T2081QDS, T4240RDB)
++ */
++static int find_ir_chip_on_i2c(void)
++{
++ int i2caddress;
++ int ret;
++ u8 byte;
++ int i;
++ const int ir_i2c_addr[] = {0x38, 0x08, 0x09};
++#ifdef CONFIG_DM_I2C
++ struct udevice *dev;
++#endif
++
++ /* Check all the address */
++ for (i = 0; i < (sizeof(ir_i2c_addr)/sizeof(ir_i2c_addr[0])); i++) {
++ i2caddress = ir_i2c_addr[i];
++#ifndef CONFIG_DM_I2C
++ ret = i2c_read(i2caddress,
++ IR36021_MFR_ID_OFFSET, 1, (void *)&byte,
++ sizeof(byte));
++#else
++ ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
++ if (!ret)
++ ret = dm_i2c_read(dev, IR36021_MFR_ID_OFFSET,
++ (void *)&byte, sizeof(byte));
++#endif
++ if ((ret >= 0) && (byte == IR36021_MFR_ID))
++ return i2caddress;
++ }
++ return -1;
++}
++#endif
++
+ /* Maximum loop count waiting for new voltage to take effect */
+ #define MAX_LOOP_WAIT_NEW_VOL 100
+ /* Maximum loop count waiting for the voltage to be stable */
+@@ -60,23 +107,135 @@ int __weak board_adjust_vdd(int vdd)
+ #define ADC_MIN_ACCURACY 4
+ #endif
+
++#ifdef CONFIG_VOL_MONITOR_INA220
++static int read_voltage_from_INA220(int i2caddress)
++{
++ int i, ret, voltage_read = 0;
++ u16 vol_mon;
++ u8 buf[2];
++#ifdef CONFIG_DM_I2C
++ struct udevice *dev;
++#endif
++
++ for (i = 0; i < NUM_READINGS; i++) {
++#ifndef CONFIG_DM_I2C
++ ret = i2c_read(I2C_VOL_MONITOR_ADDR,
++ I2C_VOL_MONITOR_BUS_V_OFFSET, 1,
++ (void *)&buf, 2);
++#else
++ ret = i2c_get_chip_for_busnum(0, I2C_VOL_MONITOR_ADDR, 1, &dev);
++ if (!ret)
++ ret = dm_i2c_read(dev, I2C_VOL_MONITOR_BUS_V_OFFSET,
++ (void *)&buf, 2);
++#endif
++ if (ret) {
++ printf("VID: failed to read core voltage\n");
++ return ret;
++ }
++ vol_mon = (buf[0] << 8) | buf[1];
++ if (vol_mon & I2C_VOL_MONITOR_BUS_V_OVF) {
++ printf("VID: Core voltage sensor error\n");
++ return -1;
++ }
++ debug("VID: bus voltage reads 0x%04x\n", vol_mon);
++ /* LSB = 4mv */
++ voltage_read += (vol_mon >> I2C_VOL_MONITOR_BUS_V_SHIFT) * 4;
++ udelay(WAIT_FOR_ADC);
++ }
++ /* calculate the average */
++ voltage_read /= NUM_READINGS;
++
++ return voltage_read;
++}
++#endif
++
++/* read voltage from IR */
++#ifdef CONFIG_VOL_MONITOR_IR36021_READ
++static int read_voltage_from_IR(int i2caddress)
++{
++ int i, ret, voltage_read = 0;
++ u16 vol_mon;
++ u8 buf;
++#ifdef CONFIG_DM_I2C
++ struct udevice *dev;
++#endif
++
++ for (i = 0; i < NUM_READINGS; i++) {
++#ifndef CONFIG_DM_I2C
++ ret = i2c_read(i2caddress,
++ IR36021_LOOP1_VOUT_OFFSET,
++ 1, (void *)&buf, 1);
++#else
++ ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
++ if (!ret)
++ ret = dm_i2c_read(dev, IR36021_LOOP1_VOUT_OFFSET,
++ (void *)&buf, 1);
++#endif
++ if (ret) {
++ printf("VID: failed to read vcpu\n");
++ return ret;
++ }
++ vol_mon = buf;
++ if (!vol_mon) {
++ printf("VID: Core voltage sensor error\n");
++ return -1;
++ }
++ debug("VID: bus voltage reads 0x%02x\n", vol_mon);
++ /* Resolution is 1/128V. We scale up here to get 1/128mV
++ * and divide at the end
++ */
++ voltage_read += vol_mon * 1000;
++ udelay(WAIT_FOR_ADC);
++ }
++ /* Scale down to the real mV as IR resolution is 1/128V, rounding up */
++ voltage_read = DIV_ROUND_UP(voltage_read, 128);
++
++ /* calculate the average */
++ voltage_read /= NUM_READINGS;
++
++ /* Compensate for a board specific voltage drop between regulator and
++ * SoC before converting into an IR VID value
++ */
++ voltage_read -= board_vdd_drop_compensation();
++
++ return voltage_read;
++}
++#endif
++
++#ifdef CONFIG_VOL_MONITOR_LTC3882_READ
+ /* read the current value of the LTC Regulator Voltage */
+ static int read_voltage_from_LTC(int i2caddress)
+ {
+ int ret, vcode = 0;
+ u8 chan = PWM_CHANNEL0;
+
++#ifndef CONFIG_DM_I2C
+ /* select the PAGE 0 using PMBus commands PAGE for VDD*/
+ ret = i2c_write(I2C_VOL_MONITOR_ADDR,
+ PMBUS_CMD_PAGE, 1, &chan, 1);
++#else
++ struct udevice *dev;
++
++ ret = i2c_get_chip_for_busnum(0, I2C_VOL_MONITOR_ADDR, 1, &dev);
++ if (!ret)
++ ret = dm_i2c_write(dev, PMBUS_CMD_PAGE, &chan, 1);
++#endif
+ if (ret) {
+ printf("VID: failed to select VDD Page 0\n");
+ return ret;
+ }
+
++#ifndef CONFIG_DM_I2C
+ /*read the output voltage using PMBus command READ_VOUT*/
+ ret = i2c_read(I2C_VOL_MONITOR_ADDR,
+ PMBUS_CMD_READ_VOUT, 1, (void *)&vcode, 2);
++#else
++ ret = dm_i2c_read(dev, PMBUS_CMD_READ_VOUT, (void *)&vcode, 2);
++ if (ret) {
++ printf("VID: failed to read the volatge\n");
++ return ret;
++ }
++#endif
+ if (ret) {
+ printf("VID: failed to read the volatge\n");
+ return ret;
+@@ -87,14 +246,131 @@ static int read_voltage_from_LTC(int i2caddress)
+
+ return vcode;
+ }
++#endif
+
+ static int read_voltage(int i2caddress)
+ {
+ int voltage_read;
++#ifdef CONFIG_VOL_MONITOR_INA220
++ voltage_read = read_voltage_from_INA220(i2caddress);
++#elif defined CONFIG_VOL_MONITOR_IR36021_READ
++ voltage_read = read_voltage_from_IR(i2caddress);
++#elif defined CONFIG_VOL_MONITOR_LTC3882_READ
+ voltage_read = read_voltage_from_LTC(i2caddress);
++#else
++ return -1;
++#endif
+ return voltage_read;
+ }
+
++#ifdef CONFIG_VOL_MONITOR_IR36021_SET
++/*
++ * We need to calculate how long before the voltage stops to drop
++ * or increase. It returns with the loop count. Each loop takes
++ * several readings (WAIT_FOR_ADC)
++ */
++static int wait_for_new_voltage(int vdd, int i2caddress)
++{
++ int timeout, vdd_current;
++
++ vdd_current = read_voltage(i2caddress);
++ /* wait until voltage starts to reach the target. Voltage slew
++ * rates by typical regulators will always lead to stable readings
++ * within each fairly long ADC interval in comparison to the
++ * intended voltage delta change until the target voltage is
++ * reached. The fairly small voltage delta change to any target
++ * VID voltage also means that this function will always complete
++ * within few iterations. If the timeout was ever reached, it would
++ * point to a serious failure in the regulator system.
++ */
++ for (timeout = 0;
++ abs(vdd - vdd_current) > (IR_VDD_STEP_UP + IR_VDD_STEP_DOWN) &&
++ timeout < MAX_LOOP_WAIT_NEW_VOL; timeout++) {
++ vdd_current = read_voltage(i2caddress);
++ }
++ if (timeout >= MAX_LOOP_WAIT_NEW_VOL) {
++ printf("VID: Voltage adjustment timeout\n");
++ return -1;
++ }
++ return timeout;
++}
++
++/*
++ * this function keeps reading the voltage until it is stable or until the
++ * timeout expires
++ */
++static int wait_for_voltage_stable(int i2caddress)
++{
++ int timeout, vdd_current, vdd;
++
++ vdd = read_voltage(i2caddress);
++ udelay(NUM_READINGS * WAIT_FOR_ADC);
++
++ /* wait until voltage is stable */
++ vdd_current = read_voltage(i2caddress);
++ /* The maximum timeout is
++ * MAX_LOOP_WAIT_VOL_STABLE * NUM_READINGS * WAIT_FOR_ADC
++ */
++ for (timeout = MAX_LOOP_WAIT_VOL_STABLE;
++ abs(vdd - vdd_current) > ADC_MIN_ACCURACY &&
++ timeout > 0; timeout--) {
++ vdd = vdd_current;
++ udelay(NUM_READINGS * WAIT_FOR_ADC);
++ vdd_current = read_voltage(i2caddress);
++ }
++ if (timeout == 0)
++ return -1;
++ return vdd_current;
++}
++
++/* Set the voltage to the IR chip */
++static int set_voltage_to_IR(int i2caddress, int vdd)
++{
++ int wait, vdd_last;
++ int ret;
++ u8 vid;
++
++ /* Compensate for a board specific voltage drop between regulator and
++ * SoC before converting into an IR VID value
++ */
++ vdd += board_vdd_drop_compensation();
++#ifdef CONFIG_FSL_LSCH2
++ vid = DIV_ROUND_UP(vdd - 265, 5);
++#else
++ vid = DIV_ROUND_UP(vdd - 245, 5);
++#endif
++
++#ifndef CONFIG_DM_I2C
++ ret = i2c_write(i2caddress, IR36021_LOOP1_MANUAL_ID_OFFSET,
++ 1, (void *)&vid, sizeof(vid));
++#else
++ struct udevice *dev;
++
++ ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
++ if (!ret)
++ ret = dm_i2c_write(dev, IR36021_LOOP1_MANUAL_ID_OFFSET,
++ (void *)&vid, sizeof(vid));
++
++#endif
++ if (ret) {
++ printf("VID: failed to write VID\n");
++ return -1;
++ }
++ wait = wait_for_new_voltage(vdd, i2caddress);
++ if (wait < 0)
++ return -1;
++ debug("VID: Waited %d us\n", wait * NUM_READINGS * WAIT_FOR_ADC);
++
++ vdd_last = wait_for_voltage_stable(i2caddress);
++ if (vdd_last < 0)
++ return -1;
++ debug("VID: Current voltage is %d mV\n", vdd_last);
++ return vdd_last;
++}
++
++#endif
++
++#ifdef CONFIG_VOL_MONITOR_LTC3882_SET
+ /* this function sets the VDD and returns the value set */
+ static int set_voltage_to_LTC(int i2caddress, int vdd)
+ {
+@@ -111,8 +387,17 @@ static int set_voltage_to_LTC(int i2caddress, int vdd)
+ vdd & 0xFF, (vdd & 0xFF00) >> 8};
+
+ /* Write the desired voltage code to the regulator */
++#ifndef CONFIG_DM_I2C
+ ret = i2c_write(I2C_VOL_MONITOR_ADDR,
+ PMBUS_CMD_PAGE_PLUS_WRITE, 1, (void *)&buff, 5);
++#else
++ struct udevice *dev;
++
++ ret = i2c_get_chip_for_busnum(0, I2C_VOL_MONITOR_ADDR, 1, &dev);
++ if (!ret)
++ ret = dm_i2c_write(dev, PMBUS_CMD_PAGE_PLUS_WRITE,
++ (void *)&buff, 5);
++#endif
+ if (ret) {
+ printf("VID: I2C failed to write to the volatge regulator\n");
+ return -1;
+@@ -131,25 +416,39 @@ static int set_voltage_to_LTC(int i2caddress, int vdd)
+
+ return vdd_last;
+ }
++#endif
+
+ static int set_voltage(int i2caddress, int vdd)
+ {
+ int vdd_last = -1;
+
++#ifdef CONFIG_VOL_MONITOR_IR36021_SET
++ vdd_last = set_voltage_to_IR(i2caddress, vdd);
++#elif defined CONFIG_VOL_MONITOR_LTC3882_SET
+ vdd_last = set_voltage_to_LTC(i2caddress, vdd);
++#else
++ #error Specific voltage monitor must be defined
++#endif
+ return vdd_last;
+ }
+
++#ifdef CONFIG_FSL_LSCH3
+ int adjust_vdd(ulong vdd_override)
+ {
+ int re_enable = disable_interrupts();
+ struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+ u32 fusesr;
++#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
++ defined(CONFIG_VOL_MONITOR_IR36021_READ)
++ u8 vid, buf;
++#else
+ u8 vid;
++#endif
+ int vdd_target, vdd_current, vdd_last;
+ int ret, i2caddress;
+ unsigned long vdd_string_override;
+ char *vdd_string;
++#ifdef CONFIG_ARCH_LX2160A
+ static const u16 vdd[32] = {
+ 8250,
+ 7875,
+@@ -184,16 +483,129 @@ int adjust_vdd(ulong vdd_override)
+ 0, /* reserved */
+ 0, /* reserved */
+ };
++#else
++#ifdef CONFIG_ARCH_LS1088A
++ static const uint16_t vdd[32] = {
++ 10250,
++ 9875,
++ 9750,
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 9000,
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 10000, /* 1.0000V */
++ 10125,
++ 10250,
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ };
++
++#else
++ static const uint16_t vdd[32] = {
++ 10500,
++ 0, /* reserved */
++ 9750,
++ 0, /* reserved */
++ 9500,
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 9000, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 10000, /* 1.0000V */
++ 0, /* reserved */
++ 10250,
++ 0, /* reserved */
++ 10500,
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ 0, /* reserved */
++ };
++#endif
++#endif
+ struct vdd_drive {
+ u8 vid;
+ unsigned voltage;
+ };
++
+ ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
+ if (ret) {
+ debug("VID: I2C failed to switch channel\n");
+ ret = -1;
+ goto exit;
+ }
++#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
++ defined(CONFIG_VOL_MONITOR_IR36021_READ)
++ ret = find_ir_chip_on_i2c();
++ if (ret < 0) {
++ printf("VID: Could not find voltage regulator on I2C.\n");
++ ret = -1;
++ goto exit;
++ } else {
++ i2caddress = ret;
++ debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
++ }
++
++ /* check IR chip work on Intel mode*/
++#ifndef CONFIG_DM_I2C
++ ret = i2c_read(i2caddress,
++ IR36021_INTEL_MODE_OOFSET,
++ 1, (void *)&buf, 1);
++#else
++ struct udevice *dev;
++
++ ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
++ if (!ret)
++ ret = dm_i2c_read(dev, IR36021_INTEL_MODE_OOFSET,
++ (void *)&buf, 1);
++#endif
++ if (ret) {
++ printf("VID: failed to read IR chip mode.\n");
++ ret = -1;
++ goto exit;
++ }
++
++ if ((buf & IR36021_MODE_MASK) != IR36021_INTEL_MODE) {
++ printf("VID: IR Chip is not used in Intel mode.\n");
++ ret = -1;
++ goto exit;
++ }
++#endif
++
+ /* get the voltage ID from fuse status register */
+ fusesr = in_le32(&gur->dcfg_fusesr);
+ vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT) &
+@@ -203,7 +615,6 @@ int adjust_vdd(ulong vdd_override)
+ FSL_CHASSIS3_DCFG_FUSESR_VID_MASK;
+ }
+ vdd_target = vdd[vid];
+- printf ("vid FUSE index %d (vdd_target = %d)\n",vid,vdd_target);
+
+ /* check override variable for overriding VDD */
+ vdd_string = env_get(CONFIG_VID_FLS_ENV);
+@@ -246,8 +657,28 @@ int adjust_vdd(ulong vdd_override)
+ vdd_current = vdd_last;
+ debug("VID: Core voltage is currently at %d mV\n", vdd_last);
+
++#ifdef CONFIG_VOL_MONITOR_LTC3882_SET
+ /* Set the target voltage */
+ vdd_last = vdd_current = set_voltage(i2caddress, vdd_target);
++#else
++ /*
++ * Adjust voltage to at or one step above target.
++ * As measurements are less precise than setting the values
++ * we may run through dummy steps that cancel each other
++ * when stepping up and then down.
++ */
++ while (vdd_last > 0 &&
++ vdd_last < vdd_target) {
++ vdd_current += IR_VDD_STEP_UP;
++ vdd_last = set_voltage(i2caddress, vdd_current);
++ }
++ while (vdd_last > 0 &&
++ vdd_last > vdd_target + (IR_VDD_STEP_DOWN - 1)) {
++ vdd_current -= IR_VDD_STEP_DOWN;
++ vdd_last = set_voltage(i2caddress, vdd_current);
++ }
++
++#endif
+ if (board_adjust_vdd(vdd_target) < 0) {
+ ret = -1;
+ goto exit;
+@@ -264,6 +695,197 @@ exit:
+ i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
+ return ret;
+ }
++#else /* !CONFIG_FSL_LSCH3 */
++int adjust_vdd(ulong vdd_override)
++{
++ int re_enable = disable_interrupts();
++#if defined(CONFIG_FSL_LSCH2)
++ struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
++#else
++ ccsr_gur_t __iomem *gur =
++ (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
++#endif
++ u32 fusesr;
++ u8 vid, buf;
++ int vdd_target, vdd_current, vdd_last;
++ int ret, i2caddress;
++ unsigned long vdd_string_override;
++ char *vdd_string;
++ static const uint16_t vdd[32] = {
++ 0, /* unused */
++ 9875, /* 0.9875V */
++ 9750,
++ 9625,
++ 9500,
++ 9375,
++ 9250,
++ 9125,
++ 9000,
++ 8875,
++ 8750,
++ 8625,
++ 8500,
++ 8375,
++ 8250,
++ 8125,
++ 10000, /* 1.0000V */
++ 10125,
++ 10250,
++ 10375,
++ 10500,
++ 10625,
++ 10750,
++ 10875,
++ 11000,
++ 0, /* reserved */
++ };
++ struct vdd_drive {
++ u8 vid;
++ unsigned voltage;
++ };
++
++ ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
++ if (ret) {
++ debug("VID: I2C failed to switch channel\n");
++ ret = -1;
++ goto exit;
++ }
++#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
++ defined(CONFIG_VOL_MONITOR_IR36021_READ)
++ ret = find_ir_chip_on_i2c();
++ if (ret < 0) {
++ printf("VID: Could not find voltage regulator on I2C.\n");
++ ret = -1;
++ goto exit;
++ } else {
++ i2caddress = ret;
++ debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
++ }
++
++ /* check IR chip work on Intel mode*/
++#ifndef CONFIG_DM_I2C
++ ret = i2c_read(i2caddress,
++ IR36021_INTEL_MODE_OOFSET,
++ 1, (void *)&buf, 1);
++#else
++ struct udevice *dev;
++
++ ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
++ if (!ret)
++ ret = dm_i2c_read(dev, IR36021_INTEL_MODE_OOFSET,
++ (void *)&buf, 1);
++#endif
++ if (ret) {
++ printf("VID: failed to read IR chip mode.\n");
++ ret = -1;
++ goto exit;
++ }
++ if ((buf & IR36021_MODE_MASK) != IR36021_INTEL_MODE) {
++ printf("VID: IR Chip is not used in Intel mode.\n");
++ ret = -1;
++ goto exit;
++ }
++#endif
++
++ /* get the voltage ID from fuse status register */
++ fusesr = in_be32(&gur->dcfg_fusesr);
++ /*
++ * VID is used according to the table below
++ * ---------------------------------------
++ * | DA_V |
++ * |-------------------------------------|
++ * | 5b00000 | 5b00001-5b11110 | 5b11111 |
++ * ---------------+---------+-----------------+---------|
++ * | D | 5b00000 | NO VID | VID = DA_V | NO VID |
++ * | A |----------+---------+-----------------+---------|
++ * | _ | 5b00001 |VID = | VID = |VID = |
++ * | V | ~ | DA_V_ALT| DA_V_ALT | DA_A_VLT|
++ * | _ | 5b11110 | | | |
++ * | A |----------+---------+-----------------+---------|
++ * | L | 5b11111 | No VID | VID = DA_V | NO VID |
++ * | T | | | | |
++ * ------------------------------------------------------
++ */
++#ifdef CONFIG_FSL_LSCH2
++ vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_ALTVID_SHIFT) &
++ FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK;
++ if ((vid == 0) || (vid == FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK)) {
++ vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_VID_SHIFT) &
++ FSL_CHASSIS2_DCFG_FUSESR_VID_MASK;
++ }
++#else
++ vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_ALTVID_SHIFT) &
++ FSL_CORENET_DCFG_FUSESR_ALTVID_MASK;
++ if ((vid == 0) || (vid == FSL_CORENET_DCFG_FUSESR_ALTVID_MASK)) {
++ vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_VID_SHIFT) &
++ FSL_CORENET_DCFG_FUSESR_VID_MASK;
++ }
++#endif
++ vdd_target = vdd[vid];
++
++ /* check override variable for overriding VDD */
++ vdd_string = env_get(CONFIG_VID_FLS_ENV);
++ if (vdd_override == 0 && vdd_string &&
++ !strict_strtoul(vdd_string, 10, &vdd_string_override))
++ vdd_override = vdd_string_override;
++ if (vdd_override >= VDD_MV_MIN && vdd_override <= VDD_MV_MAX) {
++ vdd_target = vdd_override * 10; /* convert to 1/10 mV */
++ debug("VDD override is %lu\n", vdd_override);
++ } else if (vdd_override != 0) {
++ printf("Invalid value.\n");
++ }
++ if (vdd_target == 0) {
++ debug("VID: VID not used\n");
++ ret = 0;
++ goto exit;
++ } else {
++ /* divide and round up by 10 to get a value in mV */
++ vdd_target = DIV_ROUND_UP(vdd_target, 10);
++ debug("VID: vid = %d mV\n", vdd_target);
++ }
++
++ /*
++ * Read voltage monitor to check real voltage.
++ */
++ vdd_last = read_voltage(i2caddress);
++ if (vdd_last < 0) {
++ printf("VID: Couldn't read sensor abort VID adjustment\n");
++ ret = -1;
++ goto exit;
++ }
++ vdd_current = vdd_last;
++ debug("VID: Core voltage is currently at %d mV\n", vdd_last);
++ /*
++ * Adjust voltage to at or one step above target.
++ * As measurements are less precise than setting the values
++ * we may run through dummy steps that cancel each other
++ * when stepping up and then down.
++ */
++ while (vdd_last > 0 &&
++ vdd_last < vdd_target) {
++ vdd_current += IR_VDD_STEP_UP;
++ vdd_last = set_voltage(i2caddress, vdd_current);
++ }
++ while (vdd_last > 0 &&
++ vdd_last > vdd_target + (IR_VDD_STEP_DOWN - 1)) {
++ vdd_current -= IR_VDD_STEP_DOWN;
++ vdd_last = set_voltage(i2caddress, vdd_current);
++ }
++
++ if (vdd_last > 0)
++ printf("VID: Core voltage after adjustment is at %d mV\n",
++ vdd_last);
++ else
++ ret = -1;
++exit:
++ if (re_enable)
++ enable_interrupts();
++
++ i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
++
++ return ret;
++}
++#endif
+
+ static int print_vdd(void)
+ {
+@@ -274,6 +896,18 @@ static int print_vdd(void)
+ debug("VID : I2c failed to switch channel\n");
+ return -1;
+ }
++#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
++ defined(CONFIG_VOL_MONITOR_IR36021_READ)
++ ret = find_ir_chip_on_i2c();
++ if (ret < 0) {
++ printf("VID: Could not find voltage regulator on I2C.\n");
++ goto exit;
++ } else {
++ i2caddress = ret;
++ debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
++ }
++#endif
++
+ /*
+ * Read voltage monitor to check real voltage.
+ */
+diff --git a/board/solidrun/lx2160a/lx2160a.c b/board/solidrun/lx2160a/lx2160a.c
+index b0d9f1012e..3713e91351 100644
+--- a/board/solidrun/lx2160a/lx2160a.c
++++ b/board/solidrun/lx2160a/lx2160a.c
+@@ -62,7 +62,15 @@ int select_i2c_ch_pca9547(u8 ch)
+ {
+ int ret;
+
++#ifndef CONFIG_DM_I2C
+ ret = i2c_write(I2C_MUX_PCA_ADDR_PRI, 0, 1, &ch, 1);
++#else
++ struct udevice *dev;
++
++ ret = i2c_get_chip_for_busnum(0, I2C_MUX_PCA_ADDR_PRI, 1, &dev);
++ if (!ret)
++ ret = dm_i2c_write(dev, 0, &ch, 1);
++#endif
+ if (ret) {
+ puts("PCA: failed to select proper channel\n");
+ return ret;
+diff --git a/configs/lx2160acex7_tfa_defconfig b/configs/lx2160acex7_tfa_defconfig
+index 3891d2a7c4..89a47adb23 100644
+--- a/configs/lx2160acex7_tfa_defconfig
++++ b/configs/lx2160acex7_tfa_defconfig
+@@ -2,7 +2,6 @@ CONFIG_ARM=y
+ CONFIG_TARGET_LX2160ACEX7=y
+ CONFIG_SYS_TEXT_BASE=0x82000000
+ CONFIG_SYS_MALLOC_F_LEN=0x6000
+-CONFIG_EMC2301=y
+ CONFIG_TFABOOT=y
+ CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT=y
+ CONFIG_SEC_FIRMWARE_ARMV8_PSCI=y
+@@ -73,3 +72,10 @@ CONFIG_DM_USB=y
+ CONFIG_USB_XHCI_HCD=y
+ CONFIG_USB_XHCI_DWC3=y
+ CONFIG_EFI_LOADER_BOUNCE_BUFFER=y
++CONFIG_DM_I2C=y
++CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
++CONFIG_I2C_DEFAULT_BUS_NUMBER=0
++CONFIG_DM_RTC=y
++CONFIG_DM_GPIO=y
++CONFIG_CMD_DATE=y
++CONFIG_RTC_PCF2127=y
+--
+2.17.1
+
diff --git a/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0014-lx2160acex7-pcie-fixup-and-boot-from-eMMC-print.patch b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0014-lx2160acex7-pcie-fixup-and-boot-from-eMMC-print.patch
new file mode 100644
index 00000000..4505f2cf
--- /dev/null
+++ b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0014-lx2160acex7-pcie-fixup-and-boot-from-eMMC-print.patch
@@ -0,0 +1,128 @@
+From 5d45e2ab0e00cc809c11a3d0a412022f25639c58 Mon Sep 17 00:00:00 2001
+From: Rabeeh Khoury <rabeeh@solid-run.com>
+Date: Mon, 23 Mar 2020 12:53:48 +0200
+Subject: [PATCH 14/17] lx2160acex7: pcie fixup and boot from eMMC print
+
+Upstream-Status: Inappropriate [Solid-Run BSP]
+
+Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
+---
+ board/solidrun/lx2160a/lx2160a.c | 66 +++++++++++++++++++++++++++++++
+ configs/lx2160acex7_tfa_defconfig | 3 +-
+ 2 files changed, 68 insertions(+), 1 deletion(-)
+
+diff --git a/board/solidrun/lx2160a/lx2160a.c b/board/solidrun/lx2160a/lx2160a.c
+index 3713e91351..b7211a2d5c 100644
+--- a/board/solidrun/lx2160a/lx2160a.c
++++ b/board/solidrun/lx2160a/lx2160a.c
+@@ -20,6 +20,8 @@
+ #include <efi_loader.h>
+ #include <asm/arch/mmu.h>
+ #include <hwconfig.h>
++#include <asm/arch/clock.h>
++#include <asm/arch/config.h>
+ #include <asm/arch/fsl_serdes.h>
+ #include <asm/arch/soc.h>
+ #include "../../freescale/common/vid.h"
+@@ -106,6 +108,66 @@ int board_early_init_f(void)
+ #ifdef CONFIG_OF_BOARD_FIXUP
+ int board_fix_fdt(void *fdt)
+ {
++ char *reg_name, *old_str, *new_str;
++ const char *reg_names;
++ int names_len, old_str_len, new_str_len, remaining_str_len;
++ struct str_map {
++ char *old_str;
++ char *new_str;
++ } reg_names_map[] = {
++ { "ccsr", "dbi" },
++ { "pf_ctrl", "ctrl" }
++ };
++ int off = -1, i;
++
++ if (IS_SVR_REV(get_svr(), 1, 0))
++ return 0;
++
++ off = fdt_node_offset_by_compatible(fdt, -1, "fsl,lx2160a-pcie");
++ while (off != -FDT_ERR_NOTFOUND) {
++ fdt_setprop(fdt, off, "compatible", "fsl,ls-pcie",
++ strlen("fsl,ls-pcie") + 1);
++
++ reg_names = fdt_getprop(fdt, off, "reg-names", &names_len);
++ if (!reg_names)
++ continue;
++
++ reg_name = (char *)reg_names;
++ remaining_str_len = names_len - (reg_name - reg_names);
++ i = 0;
++ while ((i < ARRAY_SIZE(reg_names_map)) && remaining_str_len) {
++ old_str = reg_names_map[i].old_str;
++ new_str = reg_names_map[i].new_str;
++ old_str_len = strlen(old_str);
++ new_str_len = strlen(new_str);
++ if (memcmp(reg_name, old_str, old_str_len) == 0) {
++ /* first only leave required bytes for new_str
++ * and copy rest of the string after it
++ */
++ memcpy(reg_name + new_str_len,
++ reg_name + old_str_len,
++ remaining_str_len - old_str_len);
++ /* Now copy new_str */
++ memcpy(reg_name, new_str, new_str_len);
++ names_len -= old_str_len;
++ names_len += new_str_len;
++ i++;
++ }
++
++ reg_name = memchr(reg_name, '\0', remaining_str_len);
++ if (!reg_name)
++ break;
++
++ reg_name += 1;
++
++ remaining_str_len = names_len - (reg_name - reg_names);
++ }
++
++ fdt_setprop(fdt, off, "reg-names", reg_names, names_len);
++ off = fdt_node_offset_by_compatible(fdt, off,
++ "fsl,lx2160a-pcie");
++ }
++
+ return 0;
+ }
+ #endif
+@@ -135,6 +197,10 @@ int checkboard(void)
+
+ if (src == BOOT_SOURCE_SD_MMC) {
+ puts("SD\n");
++ } else if (src == BOOT_SOURCE_SD_MMC2) {
++ puts("eMMC\n");
++ } else {
++ puts("FlexSPI DEV#0\n");
+ }
+ puts("SERDES1 Reference: Clock1 = 161.13MHz Clock2 = 100MHz\n");
+ puts("SERDES2 Reference: Clock1 = 100MHz Clock2 = 100MHz\n");
+diff --git a/configs/lx2160acex7_tfa_defconfig b/configs/lx2160acex7_tfa_defconfig
+index 89a47adb23..2a3441d263 100644
+--- a/configs/lx2160acex7_tfa_defconfig
++++ b/configs/lx2160acex7_tfa_defconfig
+@@ -2,6 +2,7 @@ CONFIG_ARM=y
+ CONFIG_TARGET_LX2160ACEX7=y
+ CONFIG_SYS_TEXT_BASE=0x82000000
+ CONFIG_SYS_MALLOC_F_LEN=0x6000
++CONFIG_FSPI_AHB_EN_4BYTE=y
+ CONFIG_TFABOOT=y
+ CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT=y
+ CONFIG_SEC_FIRMWARE_ARMV8_PSCI=y
+@@ -58,7 +59,7 @@ CONFIG_PCI=y
+ CONFIG_DM_PCI=y
+ CONFIG_DM_PCI_COMPAT=y
+ CONFIG_PCIE_LAYERSCAPE_GEN4=y
+-CONFIG_PHY_ATHEROS=y
++CONFIG_PCIE_LAYERSCAPE=y
+ CONFIG_E1000=y
+ CONFIG_DM_SCSI=y
+ CONFIG_DM_SERIAL=y
+--
+2.17.1
+
diff --git a/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0015-lx2160a-cex7-set-mmc-dev-to-0-when-attempting-sd_boo.patch b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0015-lx2160a-cex7-set-mmc-dev-to-0-when-attempting-sd_boo.patch
new file mode 100644
index 00000000..ce8dec3f
--- /dev/null
+++ b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0015-lx2160a-cex7-set-mmc-dev-to-0-when-attempting-sd_boo.patch
@@ -0,0 +1,32 @@
+From 47923a2f4cf159963d20acd1744619b44c9d5b02 Mon Sep 17 00:00:00 2001
+From: Rabeeh Khoury <rabeeh@solid-run.com>
+Date: Mon, 23 Mar 2020 15:13:11 +0200
+Subject: [PATCH 15/17] lx2160a-cex7: set mmc dev to 0 when attempting
+ sd_bootcmd
+
+When attempting sd_bootcmd which is the fallback of failed distroboot
+then set mmc dev to 0; since distroboot already set that variable to 1.
+
+Upstream-Status: Inappropriate [Solid-Run BSP]
+
+Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
+---
+ include/configs/lx2160acex7.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/configs/lx2160acex7.h b/include/configs/lx2160acex7.h
+index 478cd8242f..7116e038a1 100644
+--- a/include/configs/lx2160acex7.h
++++ b/include/configs/lx2160acex7.h
+@@ -73,7 +73,7 @@
+ "$kernelheader_size && esbc_validate ${kernelheader_addr_r}; "\
+ " bootm $load_addr#$BOARD\0" \
+ "sd_bootcmd=echo Trying load from sd card..;" \
+- "mmcinfo; mmc read $load_addr " \
++ "mmc dev 0; mmcinfo; mmc read $load_addr " \
+ "$kernel_addr_sd $kernel_size_sd ;" \
+ "env exists secureboot && mmc read $kernelheader_addr_r "\
+ "$kernelhdr_addr_sd $kernelhdr_size_sd " \
+--
+2.17.1
+
diff --git a/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0016-lx2160acex7-Misc-fixes-to-support-LSDK-20.04.patch b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0016-lx2160acex7-Misc-fixes-to-support-LSDK-20.04.patch
new file mode 100644
index 00000000..83e2139c
--- /dev/null
+++ b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0016-lx2160acex7-Misc-fixes-to-support-LSDK-20.04.patch
@@ -0,0 +1,127 @@
+From eacde91ef9d8b05ad4df8b6755dd3726e40fb75c Mon Sep 17 00:00:00 2001
+From: Rabeeh Khoury <rabeeh@solid-run.com>
+Date: Mon, 4 May 2020 22:52:02 +0300
+Subject: [PATCH 16/17] lx2160acex7: Misc fixes to support LSDK-20.04
+
+Upstream-Status: Inappropriate [Solid-Run BSP]
+
+Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
+---
+ arch/arm/Kconfig | 1 +
+ board/solidrun/lx2160a/lx2160a.c | 4 +++-
+ configs/lx2160acex7_tfa_defconfig | 24 ++++++++++++------------
+ 3 files changed, 16 insertions(+), 13 deletions(-)
+
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index 8615e1673f..c78e17a0ed 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -1195,6 +1195,7 @@ config TARGET_LX2160ACEX7
+ select ARCH_MISC_INIT
+ select ARM64
+ select ARMV8_MULTIENTRY
++ select ARCH_SUPPORT_TFABOOT
+ select BOARD_LATE_INIT
+ help
+ Support for SolidRun LX2160A based com express type 7 module and
+diff --git a/board/solidrun/lx2160a/lx2160a.c b/board/solidrun/lx2160a/lx2160a.c
+index b7211a2d5c..975431fd53 100644
+--- a/board/solidrun/lx2160a/lx2160a.c
++++ b/board/solidrun/lx2160a/lx2160a.c
+@@ -16,7 +16,7 @@
+ #include <fdt_support.h>
+ #include <linux/libfdt.h>
+ #include <fsl-mc/fsl_mc.h>
+-#include <environment.h>
++#include <env_internal.h>
+ #include <efi_loader.h>
+ #include <asm/arch/mmu.h>
+ #include <hwconfig.h>
+@@ -26,6 +26,8 @@
+ #include <asm/arch/soc.h>
+ #include "../../freescale/common/vid.h"
+ #include <fsl_immap.h>
++#include <asm/arch-fsl-layerscape/fsl_icid.h>
++#include <asm/gic-v3.h>
+
+ #ifdef CONFIG_EMC2301
+ #include "../common/emc2301.h"
+diff --git a/configs/lx2160acex7_tfa_defconfig b/configs/lx2160acex7_tfa_defconfig
+index 2a3441d263..d2e62a6e91 100644
+--- a/configs/lx2160acex7_tfa_defconfig
++++ b/configs/lx2160acex7_tfa_defconfig
+@@ -1,16 +1,15 @@
+ CONFIG_ARM=y
+ CONFIG_TARGET_LX2160ACEX7=y
++CONFIG_TFABOOT=y
+ CONFIG_SYS_TEXT_BASE=0x82000000
+ CONFIG_SYS_MALLOC_F_LEN=0x6000
+ CONFIG_FSPI_AHB_EN_4BYTE=y
+-CONFIG_TFABOOT=y
++CONFIG_NR_DRAM_BANKS=3
+ CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT=y
+ CONFIG_SEC_FIRMWARE_ARMV8_PSCI=y
+ CONFIG_AHCI=y
+-CONFIG_NR_DRAM_BANKS=3
+ CONFIG_FIT_VERBOSE=y
+ CONFIG_OF_BOARD_SETUP=y
+-CONFIG_OF_BOARD_FIXUP=y
+ CONFIG_OF_STDOUT_VIA_ALIAS=y
+ CONFIG_BOOTDELAY=10
+ CONFIG_USE_BOOTARGS=y
+@@ -29,6 +28,7 @@ CONFIG_CMD_NVME=y
+ CONFIG_NVME=y
+ CONFIG_MP=y
+ CONFIG_OF_CONTROL=y
++CONFIG_OF_BOARD_FIXUP=y
+ CONFIG_DEFAULT_DEVICE_TREE="fsl-lx2160a-cex7"
+ CONFIG_ENV_IS_IN_MMC=y
+ CONFIG_ENV_IS_IN_SPI_FLASH=y
+@@ -36,6 +36,10 @@ CONFIG_NET_RANDOM_ETHADDR=y
+ CONFIG_DM=y
+ CONFIG_SATA_CEVA=y
+ CONFIG_FSL_CAAM=y
++CONFIG_DM_GPIO=y
++CONFIG_DM_I2C=y
++CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
++CONFIG_I2C_DEFAULT_BUS_NUMBER=0
+ CONFIG_DM_MMC=y
+ CONFIG_FSL_ESDHC=y
+ CONFIG_DM_SPI_FLASH=y
+@@ -55,28 +59,24 @@ CONFIG_CMD_MII=y
+ CONFIG_CMD_DHCP=y
+ CONFIG_CMD_FAT=y
+ CONFIG_CMD_EXT2=y
++CONFIG_E1000=y
+ CONFIG_PCI=y
+ CONFIG_DM_PCI=y
+ CONFIG_DM_PCI_COMPAT=y
+ CONFIG_PCIE_LAYERSCAPE_GEN4=y
+ CONFIG_PCIE_LAYERSCAPE=y
+-CONFIG_E1000=y
++CONFIG_DM_RTC=y
++CONFIG_RTC_PCF2127=y
++
+ CONFIG_DM_SCSI=y
+ CONFIG_DM_SERIAL=y
+-CONFIG_SERIAL_PROBE_ALL=y
+ CONFIG_SPI=y
+ CONFIG_DM_SPI=y
+ CONFIG_NXP_FSPI=y
+-# CONFIG_SYS_NXP_FSPI_AHB=y
+ CONFIG_USB=y
+ CONFIG_DM_USB=y
+ CONFIG_USB_XHCI_HCD=y
+ CONFIG_USB_XHCI_DWC3=y
+ CONFIG_EFI_LOADER_BOUNCE_BUFFER=y
+-CONFIG_DM_I2C=y
+-CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
+-CONFIG_I2C_DEFAULT_BUS_NUMBER=0
+-CONFIG_DM_RTC=y
+-CONFIG_DM_GPIO=y
+ CONFIG_CMD_DATE=y
+-CONFIG_RTC_PCF2127=y
++CONFIG_GIC_V3_ITS=y
+--
+2.17.1
+
diff --git a/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0017-lx2160acex7-misc-fixes-to-get-booting-from-eMMC-func.patch b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0017-lx2160acex7-misc-fixes-to-get-booting-from-eMMC-func.patch
new file mode 100644
index 00000000..053da1cf
--- /dev/null
+++ b/bsp/meta-freescale-3rdparty/recipes-bsp/u-boot/u-boot-qoriq-lx2160acex7/0017-lx2160acex7-misc-fixes-to-get-booting-from-eMMC-func.patch
@@ -0,0 +1,70 @@
+From ce6a26cf0aa2af3a93b1183bd3543a9913e0656e Mon Sep 17 00:00:00 2001
+From: Rabeeh Khoury <rabeeh@solid-run.com>
+Date: Tue, 5 May 2020 01:01:01 +0300
+Subject: [PATCH 17/17] lx2160acex7: misc fixes to get booting from eMMC
+ functional
+
+Upstream-Status: Inappropriate [Solid-Run BSP]
+
+Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
+---
+ include/configs/lx2160a_common.h | 10 ++++++++++
+ include/configs/lx2160acex7.h | 14 ++++++++------
+ 2 files changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/include/configs/lx2160a_common.h b/include/configs/lx2160a_common.h
+index 91e9a2470f..f0c44a2368 100644
+--- a/include/configs/lx2160a_common.h
++++ b/include/configs/lx2160a_common.h
+@@ -235,6 +235,16 @@ int select_i2c_ch_pca9547_sec(unsigned char ch);
+ "esbc_validate 0x80680000 ;" \
+ "fsl_mc start mc 0x80a00000 0x80e00000\0"
+
++#define SD2_MC_INIT_CMD \
++ "mmc dev 1; mmc read 0x80a00000 0x5000 0x1200;" \
++ "mmc read 0x80e00000 0x7000 0x800;" \
++ "env exists secureboot && " \
++ "mmc read 0x80640000 0x3200 0x20 && " \
++ "mmc read 0x80680000 0x3400 0x20 && " \
++ "esbc_validate 0x80640000 && " \
++ "esbc_validate 0x80680000 ;" \
++ "fsl_mc start mc 0x80a00000 0x80e00000\0"
++
+ #define EXTRA_ENV_SETTINGS \
+ "hwconfig=fsl_ddr:bank_intlv=auto\0" \
+ "ramdisk_addr=0x800000\0" \
+diff --git a/include/configs/lx2160acex7.h b/include/configs/lx2160acex7.h
+index 7116e038a1..310168db47 100644
+--- a/include/configs/lx2160acex7.h
++++ b/include/configs/lx2160acex7.h
+@@ -46,11 +46,6 @@
+
+ #endif
+
+-/* EMC2301 */
+-#define I2C_MUX_CH_EMC2301 0x01
+-#define I2C_EMC2301_ADDR 0x2f
+-#define I2C_EMC2301_CMD 0x40
+-#define I2C_EMC2301_PWM 0x80
+
+ /* EEPROM */
+ #undef CONFIG_ID_EEPROM /* Fixme */
+@@ -73,7 +68,14 @@
+ "$kernelheader_size && esbc_validate ${kernelheader_addr_r}; "\
+ " bootm $load_addr#$BOARD\0" \
+ "sd_bootcmd=echo Trying load from sd card..;" \
+- "mmc dev 0; mmcinfo; mmc read $load_addr " \
++ "mmcinfo; mmc read $load_addr " \
++ "$kernel_addr_sd $kernel_size_sd ;" \
++ "env exists secureboot && mmc read $kernelheader_addr_r "\
++ "$kernelhdr_addr_sd $kernelhdr_size_sd " \
++ " && esbc_validate ${kernelheader_addr_r};" \
++ "bootm $load_addr#$BOARD\0" \
++ "emmc_bootcmd=echo Trying load from emmc card..;" \
++ "mmc dev 1; mmcinfo; mmc read $load_addr " \
+ "$kernel_addr_sd $kernel_size_sd ;" \
+ "env exists secureboot && mmc read $kernelheader_addr_r "\
+ "$kernelhdr_addr_sd $kernelhdr_size_sd " \
+--
+2.17.1
+