Merge branch 'staging' of https://source.denx.de/u-boot/custodians/u-boot-tegra

Assorted Tegra enhancements. Merged with the recent XPL_BUILD changes,
resolve some whitespace issues and fix the name of the new apalis-tk1
env file by Tom.

Signed-off-by: Tom Rini <trini@konsulko.com>
diff --git a/arch/arm/dts/tegra-u-boot.dtsi b/arch/arm/dts/tegra-u-boot.dtsi
index b3d0dec..c200f2d 100644
--- a/arch/arm/dts/tegra-u-boot.dtsi
+++ b/arch/arm/dts/tegra-u-boot.dtsi
@@ -19,6 +19,27 @@
 			};
 		};
 
+#ifdef CONFIG_MULTI_DTB_FIT
+		image2 {
+			filename = "u-boot-dtb-tegra.bin";
+			pad-byte = <0xff>;
+			u-boot-spl {
+			};
+			u-boot-nodtb {
+				offset = <(U_BOOT_OFFSET)>;
+			};
+			fit-dtb {
+#ifdef CONFIG_MULTI_DTB_FIT_LZO
+				filename = "fit-dtb.blob.lzo";
+#elif CONFIG_MULTI_DTB_FIT_GZIP
+				filename = "fit-dtb.blob.gz";
+#else
+				filename = "fit-dtb.blob";
+#endif
+				type = "blob";
+			};
+		};
+#else
 		/* Same as image1 - some tools still expect the -dtb suffix */
 		image2 {
 			filename = "u-boot-dtb-tegra.bin";
@@ -29,6 +50,7 @@
 				offset = <(U_BOOT_OFFSET)>;
 			};
 		};
+#endif
 
 		image3 {
 			filename = "u-boot-nodtb-tegra.bin";
diff --git a/arch/arm/include/asm/arch-tegra/tegra.h b/arch/arm/include/asm/arch-tegra/tegra.h
index 7a4e097..a399c94 100644
--- a/arch/arm/include/asm/arch-tegra/tegra.h
+++ b/arch/arm/include/asm/arch-tegra/tegra.h
@@ -68,8 +68,9 @@
 
 /* These are the available SKUs (product types) for Tegra */
 enum {
-	SKU_ID_T20_7		= 0x7,
+	SKU_ID_AP20		= 0x7,
 	SKU_ID_T20		= 0x8,
+	SKU_ID_AP20H		= 0xf,
 	SKU_ID_T25SE		= 0x14,
 	SKU_ID_AP25		= 0x17,
 	SKU_ID_T25		= 0x18,
diff --git a/arch/arm/include/asm/arch-tegra/usb.h b/arch/arm/include/asm/arch-tegra/usb.h
index 6e6ea14..2ae109a 100644
--- a/arch/arm/include/asm/arch-tegra/usb.h
+++ b/arch/arm/include/asm/arch-tegra/usb.h
@@ -336,10 +336,13 @@
 #define UTMIP_XCVR_HSSLEW_MSB_SHIFT		25
 #define UTMIP_XCVR_HSSLEW_MSB_MASK		\
 			(0x7f << UTMIP_XCVR_HSSLEW_MSB_SHIFT)
-#define UTMIP_XCVR_SETUP_MSB_SHIFT	22
-#define UTMIP_XCVR_SETUP_MSB_MASK	(0x7 << UTMIP_XCVR_SETUP_MSB_SHIFT)
-#define UTMIP_XCVR_SETUP_SHIFT		0
-#define UTMIP_XCVR_SETUP_MASK		(0xf << UTMIP_XCVR_SETUP_SHIFT)
+
+#define UTMIP_XCVR_SETUP(x)			(((x) & 0xf) << 0)
+#define UTMIP_XCVR_SETUP_MSB(x)			((((x) & 0x70) >> 4) << 22)
+#define UTMIP_XCVR_LSRSLEW(x)			(((x) & 0x3) << 8)
+#define UTMIP_XCVR_LSFSLEW(x)			(((x) & 0x3) << 10)
+#define UTMIP_XCVR_HSSLEW(x)			(((x) & 0x3) << 4)
+#define UTMIP_XCVR_HSSLEW_MSB(x)		((((x) & 0x1fc) >> 2) << 25)
 
 /* USBx_UTMIP_XCVR_CFG1_0 */
 #define UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT		18
diff --git a/arch/arm/include/asm/arch-tegra30/funcmux.h b/arch/arm/include/asm/arch-tegra30/funcmux.h
index 2e8b335..0541406 100644
--- a/arch/arm/include/asm/arch-tegra30/funcmux.h
+++ b/arch/arm/include/asm/arch-tegra30/funcmux.h
@@ -16,5 +16,6 @@
 
 	/* UART configs */
 	FUNCMUX_UART1_ULPI = 0,
+	FUNCMUX_UART5_SDMMC1 = 1,
 };
 #endif	/* _TEGRA30_FUNCMUX_H_ */
diff --git a/arch/arm/mach-tegra/ap.c b/arch/arm/mach-tegra/ap.c
index 1ea620e..f35bdba 100644
--- a/arch/arm/mach-tegra/ap.c
+++ b/arch/arm/mach-tegra/ap.c
@@ -32,7 +32,7 @@
 	 * Tegra30, 0x35 for T114, and 0x40 for Tegra124.
 	 */
 	rev = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT;
-	debug("%s: CHIPID is 0x%02X\n", __func__, rev);
+	debug("%s: CHIPID is 0x%02x\n", __func__, rev);
 
 	return rev;
 }
@@ -43,7 +43,7 @@
 	struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE;
 
 	sku_id = readl(&fuse->sku_info) & 0xff;
-	debug("%s: SKU info byte is 0x%02X\n", __func__, sku_id);
+	debug("%s: SKU info byte is 0x%02x\n", __func__, sku_id);
 
 	return sku_id;
 }
@@ -58,8 +58,9 @@
 	switch (chip_id) {
 	case CHIPID_TEGRA20:
 		switch (sku_id) {
-		case SKU_ID_T20_7:
+		case SKU_ID_AP20:
 		case SKU_ID_T20:
+		case SKU_ID_AP20H:
 			return TEGRA_SOC_T20;
 		case SKU_ID_T25SE:
 		case SKU_ID_AP25:
@@ -103,8 +104,8 @@
 	}
 
 	/* unknown chip/sku id */
-	printf("%s: ERROR: UNKNOWN CHIP/SKU ID COMBO (0x%02X/0x%02X)\n",
-		__func__, chip_id, sku_id);
+	printf("%s: ERROR: UNKNOWN CHIP/SKU ID COMBO (0x%02x/0x%02x)\n",
+	       __func__, chip_id, sku_id);
 	return TEGRA_SOC_UNKNOWN;
 }
 
diff --git a/arch/arm/mach-tegra/board.c b/arch/arm/mach-tegra/board.c
index cc37878..7ca56a3 100644
--- a/arch/arm/mach-tegra/board.c
+++ b/arch/arm/mach-tegra/board.c
@@ -181,7 +181,7 @@
 	-1,
 	-1,
 	-1,
-	-1,
+	FUNCMUX_UART5_SDMMC1,  /* UARTE */
 #elif defined(CONFIG_TEGRA114)
 	-1,
 	-1,
diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c
index 8e7fd7e..6e9ef68 100644
--- a/arch/arm/mach-tegra/board2.c
+++ b/arch/arm/mach-tegra/board2.c
@@ -6,6 +6,7 @@
 
 #include <config.h>
 #include <dm.h>
+#include <dm/root.h>
 #include <env.h>
 #include <errno.h>
 #include <init.h>
@@ -457,3 +458,18 @@
 
 	return CFG_SYS_SDRAM_BASE + usable_ram_size_below_4g();
 }
+
+#if IS_ENABLED(CONFIG_DTB_RESELECT)
+int embedded_dtb_select(void)
+{
+	int ret, rescan;
+
+	ret = fdtdec_resetup(&rescan);
+	if (!ret && rescan) {
+		dm_uninit();
+		dm_init_and_scan(true);
+	}
+
+	return 0;
+}
+#endif
diff --git a/board/asus/grouper/MAINTAINERS b/board/asus/grouper/MAINTAINERS
index f4068d8..3c59632 100644
--- a/board/asus/grouper/MAINTAINERS
+++ b/board/asus/grouper/MAINTAINERS
@@ -2,6 +2,6 @@
 M:	Svyatoslav Ryhel <clamor95@gmail.com>
 S:	Maintained
 F:	board/asus/grouper/
-F:	configs/grouper_common_defconfig
-F:	doc/board/asus/grouper_common.rst
+F:	configs/grouper_defconfig
+F:	doc/board/asus/grouper.rst
 F:	include/configs/grouper.h
diff --git a/board/asus/grouper/Makefile b/board/asus/grouper/Makefile
index 05c6ffb..8a8e653 100644
--- a/board/asus/grouper/Makefile
+++ b/board/asus/grouper/Makefile
@@ -6,9 +6,7 @@
 #  (C) Copyright 2021
 #  Svyatoslav Ryhel <clamor95@gmail.com>
 
-ifdef CONFIG_XPL_BUILD
-obj-$(CONFIG_DM_PMIC_MAX77663) += grouper-spl-max.o
-obj-$(CONFIG_DM_PMIC_TPS65910) += grouper-spl-ti.o
-endif
+obj-$(CONFIG_SPL_BUILD) += grouper-spl.o
+obj-$(CONFIG_MULTI_DTB_FIT) += board-info.o
 
 obj-y += grouper.o
diff --git a/board/asus/grouper/board-info.c b/board/asus/grouper/board-info.c
new file mode 100644
index 0000000..4892acc
--- /dev/null
+++ b/board/asus/grouper/board-info.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  (C) Copyright 2024
+ *  Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#include <env.h>
+#include <spl_gpio.h>
+
+#include <asm/gpio.h>
+#include <asm/arch/pinmux.h>
+
+/*
+ *	PMIC_ID is GMI_CS2_N_PK3
+ *	MODEM_ID is GMI_CS4_N_PK2
+ *
+ *		Extended Project ID
+ *	====================================
+ *	MODEM_ID  PMIC_ID	project name
+ *	0	  0		grouper-E1565
+ *	0	  1		grouper-PM269
+ *	1	  0		tilapia
+ */
+enum project_rev {
+	E1565, PM269, TILAPIA, COUNT,
+};
+
+static const char * const project_id_to_fdt[] = {
+	[E1565] = "tegra30-asus-nexus7-grouper-E1565",
+	[PM269] = "tegra30-asus-nexus7-grouper-PM269",
+	[TILAPIA] = "tegra30-asus-nexus7-tilapia-E1565",
+};
+
+static int id_gpio_get_value(u32 pingrp, u32 pin)
+{
+	/* Configure pinmux */
+	pinmux_set_func(pingrp, PMUX_FUNC_GMI);
+	pinmux_set_pullupdown(pingrp, PMUX_PULL_DOWN);
+	pinmux_tristate_enable(pingrp);
+	pinmux_set_io(pingrp, PMUX_PIN_INPUT);
+
+	/*
+	 * Since this function may be called
+	 * during DM reload we should use SPL
+	 * GPIO functions which do not depend
+	 * on DM.
+	 */
+	spl_gpio_input(NULL, pin);
+	return spl_gpio_get_value(NULL, pin);
+}
+
+static int get_project_id(void)
+{
+	u32 pmic_id, modem_id, proj_id;
+
+	modem_id = id_gpio_get_value(PMUX_PINGRP_GMI_CS4_N_PK2,
+				     TEGRA_GPIO(K, 2));
+	pmic_id = id_gpio_get_value(PMUX_PINGRP_GMI_CS2_N_PK3,
+				    TEGRA_GPIO(K, 3));
+
+	proj_id = (modem_id << 1 | pmic_id) & COUNT;
+
+	log_debug("[GROUPER]: project id %d (%s)\n", proj_id,
+		  project_id_to_fdt[proj_id]);
+
+	return proj_id;
+}
+
+int board_fit_config_name_match(const char *name)
+{
+	if (!strcmp(name, project_id_to_fdt[get_project_id()]))
+		return 0;
+
+	return -1;
+}
+
+void nvidia_board_late_init(void)
+{
+	char dt_path[64] = { 0 };
+
+	snprintf(dt_path, sizeof(dt_path), "%s.dtb",
+		 project_id_to_fdt[get_project_id()]);
+	env_set("fdtfile", dt_path);
+}
diff --git a/board/asus/grouper/configs/grouper_E1565.config b/board/asus/grouper/configs/grouper_E1565.config
deleted file mode 100644
index 265295c..0000000
--- a/board/asus/grouper/configs/grouper_E1565.config
+++ /dev/null
@@ -1,6 +0,0 @@
-CONFIG_DEFAULT_DEVICE_TREE="tegra30-asus-nexus7-grouper-E1565"
-CONFIG_CMD_POWEROFF=y
-# CONFIG_MAX77663_GPIO is not set
-CONFIG_DM_PMIC_MAX77663=y
-CONFIG_DM_REGULATOR_MAX77663=y
-CONFIG_SYSRESET_MAX77663=y
diff --git a/board/asus/grouper/configs/grouper_PM269.config b/board/asus/grouper/configs/grouper_PM269.config
deleted file mode 100644
index a7ee358..0000000
--- a/board/asus/grouper/configs/grouper_PM269.config
+++ /dev/null
@@ -1,6 +0,0 @@
-CONFIG_DEFAULT_DEVICE_TREE="tegra30-asus-nexus7-grouper-PM269"
-CONFIG_CMD_POWEROFF=y
-CONFIG_DM_PMIC_TPS65910=y
-# CONFIG_DM_REGULATOR_TPS65910 is not set
-CONFIG_DM_REGULATOR_TPS65911=y
-CONFIG_SYSRESET_TPS65910=y
diff --git a/board/asus/grouper/configs/tilapia.config b/board/asus/grouper/configs/tilapia.config
deleted file mode 100644
index d461b47..0000000
--- a/board/asus/grouper/configs/tilapia.config
+++ /dev/null
@@ -1,7 +0,0 @@
-CONFIG_DEFAULT_DEVICE_TREE="tegra30-asus-nexus7-tilapia-E1565"
-CONFIG_SYS_PROMPT="Tegra30 (Tilapia) # "
-CONFIG_CMD_POWEROFF=y
-# CONFIG_MAX77663_GPIO is not set
-CONFIG_DM_PMIC_MAX77663=y
-CONFIG_DM_REGULATOR_MAX77663=y
-CONFIG_SYSRESET_MAX77663=y
diff --git a/board/asus/grouper/grouper-spl-max.c b/board/asus/grouper/grouper-spl-max.c
deleted file mode 100644
index 3e58bf9..0000000
--- a/board/asus/grouper/grouper-spl-max.c
+++ /dev/null
@@ -1,45 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- *  T30 Grouper MAX SPL stage configuration
- *
- *  (C) Copyright 2010-2013
- *  NVIDIA Corporation <www.nvidia.com>
- *
- *  (C) Copyright 2022
- *  Svyatoslav Ryhel <clamor95@gmail.com>
- */
-
-#include <asm/arch/tegra.h>
-#include <asm/arch-tegra/tegra_i2c.h>
-#include <linux/delay.h>
-
-#define MAX77663_I2C_ADDR		(0x3C << 1)
-
-#define MAX77663_REG_SD0		0x16
-#define MAX77663_REG_SD0_DATA		(0x2100 | MAX77663_REG_SD0)
-#define MAX77663_REG_SD1		0x17
-#define MAX77663_REG_SD1_DATA		(0x3000 | MAX77663_REG_SD1)
-#define MAX77663_REG_LDO4		0x2B
-#define MAX77663_REG_LDO4_DATA		(0xE000 | MAX77663_REG_LDO4)
-
-#define MAX77663_REG_GPIO4		0x3A
-#define MAX77663_REG_GPIO4_DATA		(0x0100 | MAX77663_REG_GPIO4)
-
-void pmic_enable_cpu_vdd(void)
-{
-	/* Set VDD_CORE to 1.200V. */
-	tegra_i2c_ll_write(MAX77663_I2C_ADDR, MAX77663_REG_SD1_DATA);
-
-	udelay(1000);
-
-	/* Bring up VDD_CPU to 1.0125V. */
-	tegra_i2c_ll_write(MAX77663_I2C_ADDR, MAX77663_REG_SD0_DATA);
-	udelay(1000);
-
-	/* Bring up VDD_RTC to 1.200V. */
-	tegra_i2c_ll_write(MAX77663_I2C_ADDR, MAX77663_REG_LDO4_DATA);
-	udelay(10 * 1000);
-
-	/* Set 32k-out gpio state */
-	tegra_i2c_ll_write(MAX77663_I2C_ADDR, MAX77663_REG_GPIO4_DATA);
-}
diff --git a/board/asus/grouper/grouper-spl-ti.c b/board/asus/grouper/grouper-spl-ti.c
deleted file mode 100644
index 1dcce80..0000000
--- a/board/asus/grouper/grouper-spl-ti.c
+++ /dev/null
@@ -1,41 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- *  T30 Grouper TI SPL stage configuration
- *
- *  (C) Copyright 2010-2013
- *  NVIDIA Corporation <www.nvidia.com>
- *
- *  (C) Copyright 2022
- *  Svyatoslav Ryhel <clamor95@gmail.com>
- */
-
-#include <asm/arch/tegra.h>
-#include <asm/arch-tegra/tegra_i2c.h>
-#include <linux/delay.h>
-
-#define TPS65911_I2C_ADDR		(0x2D << 1)
-#define TPS65911_VDDCTRL_OP_REG		0x28
-#define TPS65911_VDDCTRL_SR_REG		0x27
-#define TPS65911_VDDCTRL_OP_DATA	(0x2400 | TPS65911_VDDCTRL_OP_REG)
-#define TPS65911_VDDCTRL_SR_DATA	(0x0100 | TPS65911_VDDCTRL_SR_REG)
-
-#define TPS62361B_I2C_ADDR		(0x60 << 1)
-#define TPS62361B_SET3_REG		0x03
-#define TPS62361B_SET3_DATA		(0x4600 | TPS62361B_SET3_REG)
-
-void pmic_enable_cpu_vdd(void)
-{
-	/* Set VDD_CORE to 1.200V. */
-	tegra_i2c_ll_write(TPS62361B_I2C_ADDR, TPS62361B_SET3_DATA);
-
-	udelay(1000);
-
-	/*
-	 * Bring up CPU VDD via the TPS65911x PMIC on the DVC I2C bus.
-	 * First set VDD to 1.0125V, then enable the VDD regulator.
-	 */
-	tegra_i2c_ll_write(TPS65911_I2C_ADDR, TPS65911_VDDCTRL_OP_DATA);
-	udelay(1000);
-	tegra_i2c_ll_write(TPS65911_I2C_ADDR, TPS65911_VDDCTRL_SR_DATA);
-	udelay(10 * 1000);
-}
diff --git a/board/asus/grouper/grouper-spl.c b/board/asus/grouper/grouper-spl.c
new file mode 100644
index 0000000..a8d4e54
--- /dev/null
+++ b/board/asus/grouper/grouper-spl.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  T30 Grouper SPL stage configuration
+ *
+ *  (C) Copyright 2010-2013
+ *  NVIDIA Corporation <www.nvidia.com>
+ *
+ *  (C) Copyright 2022
+ *  Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#include <asm/gpio.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/tegra.h>
+#include <asm/arch-tegra/tegra_i2c.h>
+#include <spl_gpio.h>
+#include <linux/delay.h>
+
+#define MAX77663_I2C_ADDR		(0x3C << 1)
+
+#define MAX77663_REG_SD0		0x16
+#define MAX77663_REG_SD0_DATA		(0x2100 | MAX77663_REG_SD0)
+#define MAX77663_REG_SD1		0x17
+#define MAX77663_REG_SD1_DATA		(0x3000 | MAX77663_REG_SD1)
+#define MAX77663_REG_LDO4		0x2B
+#define MAX77663_REG_LDO4_DATA		(0xE000 | MAX77663_REG_LDO4)
+
+#define MAX77663_REG_GPIO4		0x3A
+#define MAX77663_REG_GPIO4_DATA		(0x0100 | MAX77663_REG_GPIO4)
+
+#define TPS65911_I2C_ADDR		(0x2D << 1)
+
+#define TPS65911_VDDCTRL_OP_REG		0x28
+#define TPS65911_VDDCTRL_SR_REG		0x27
+#define TPS65911_VDDCTRL_OP_DATA	(0x2400 | TPS65911_VDDCTRL_OP_REG)
+#define TPS65911_VDDCTRL_SR_DATA	(0x0100 | TPS65911_VDDCTRL_SR_REG)
+
+#define TPS62361B_I2C_ADDR		(0x60 << 1)
+
+#define TPS62361B_SET3_REG		0x03
+#define TPS62361B_SET3_DATA		(0x4600 | TPS62361B_SET3_REG)
+
+/*
+ *	PCB_ID[8] is GMI_CS2_N_PK3
+ *
+ *	    PMIC module detection
+ *	==============================
+ *	PCB_ID[8]	0	1
+ *	PMIC		Maxim	TI
+ */
+static bool ti_pmic_detected(void)
+{
+	/* Configure pinmux */
+	pinmux_set_func(PMUX_PINGRP_GMI_CS2_N_PK3, PMUX_FUNC_GMI);
+	pinmux_set_pullupdown(PMUX_PINGRP_GMI_CS2_N_PK3, PMUX_PULL_DOWN);
+	pinmux_tristate_enable(PMUX_PINGRP_GMI_CS2_N_PK3);
+	pinmux_set_io(PMUX_PINGRP_GMI_CS2_N_PK3, PMUX_PIN_INPUT);
+
+	spl_gpio_input(NULL, TEGRA_GPIO(K, 3));
+	return spl_gpio_get_value(NULL, TEGRA_GPIO(K, 3));
+}
+
+static void max_enable_cpu_vdd(void)
+{
+	/* Set VDD_CORE to 1.200V. */
+	tegra_i2c_ll_write(MAX77663_I2C_ADDR, MAX77663_REG_SD1_DATA);
+
+	udelay(1000);
+
+	/* Bring up VDD_CPU to 1.0125V. */
+	tegra_i2c_ll_write(MAX77663_I2C_ADDR, MAX77663_REG_SD0_DATA);
+	udelay(1000);
+
+	/* Bring up VDD_RTC to 1.200V. */
+	tegra_i2c_ll_write(MAX77663_I2C_ADDR, MAX77663_REG_LDO4_DATA);
+	udelay(10 * 1000);
+
+	/* Set 32k-out gpio state */
+	tegra_i2c_ll_write(MAX77663_I2C_ADDR, MAX77663_REG_GPIO4_DATA);
+}
+
+static void ti_enable_cpu_vdd(void)
+{
+	/* Set VDD_CORE to 1.200V. */
+	tegra_i2c_ll_write(TPS62361B_I2C_ADDR, TPS62361B_SET3_DATA);
+
+	udelay(1000);
+
+	/*
+	 * Bring up CPU VDD via the TPS65911x PMIC on the DVC I2C bus.
+	 * First set VDD to 1.0125V, then enable the VDD regulator.
+	 */
+	tegra_i2c_ll_write(TPS65911_I2C_ADDR, TPS65911_VDDCTRL_OP_DATA);
+	udelay(1000);
+	tegra_i2c_ll_write(TPS65911_I2C_ADDR, TPS65911_VDDCTRL_SR_DATA);
+	udelay(10 * 1000);
+}
+
+void pmic_enable_cpu_vdd(void)
+{
+	if (ti_pmic_detected())
+		ti_enable_cpu_vdd();
+	else
+		max_enable_cpu_vdd();
+}
diff --git a/board/asus/grouper/grouper.env b/board/asus/grouper/grouper.env
new file mode 100644
index 0000000..b1f4aeb
--- /dev/null
+++ b/board/asus/grouper/grouper.env
@@ -0,0 +1,15 @@
+#include <env/nvidia/prod_upd.env>
+
+button_cmd_0_name=Volume Down
+button_cmd_0=bootmenu
+button_cmd_1_name=Lid
+button_cmd_1=poweroff
+partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}
+
+bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu
+bootmenu_1=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu
+bootmenu_2=update bootloader=run flash_uboot
+bootmenu_3=reboot RCM=enterrcm
+bootmenu_4=reboot=reset
+bootmenu_5=power off=poweroff
+bootmenu_delay=-1
diff --git a/board/asus/transformer-t20/transformer-t20.env b/board/asus/transformer-t20/transformer-t20.env
new file mode 100644
index 0000000..2f7e820
--- /dev/null
+++ b/board/asus/transformer-t20/transformer-t20.env
@@ -0,0 +1,17 @@
+#include <env/nvidia/prod_upd.env>
+
+button_cmd_0_name=Volume Down
+button_cmd_0=bootmenu
+button_cmd_1_name=Lid sensor
+button_cmd_1=poweroff
+partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}
+boot_dev=1
+
+bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu
+bootmenu_1=mount external storage=usb start && ums 0 mmc 1; bootmenu
+bootmenu_2=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu
+bootmenu_3=update bootloader=run flash_uboot
+bootmenu_4=reboot RCM=enterrcm
+bootmenu_5=reboot=reset
+bootmenu_6=power off=poweroff
+bootmenu_delay=-1
diff --git a/board/asus/transformer-t30/MAINTAINERS b/board/asus/transformer-t30/MAINTAINERS
index 071a9c0..869cc5a 100644
--- a/board/asus/transformer-t30/MAINTAINERS
+++ b/board/asus/transformer-t30/MAINTAINERS
@@ -4,5 +4,4 @@
 F:	board/asus/transformer-t30/
 F:	configs/transformer_t30_defconfig
 F:	doc/board/asus/transformer_t30.rst
-F:	include/configs/transformer-common.h
 F:	include/configs/transformer-t30.h
diff --git a/board/asus/transformer-t30/Makefile b/board/asus/transformer-t30/Makefile
index ad70078..22b6160 100644
--- a/board/asus/transformer-t30/Makefile
+++ b/board/asus/transformer-t30/Makefile
@@ -6,6 +6,7 @@
 #  (C) Copyright 2021
 #  Svyatoslav Ryhel <clamor95@gmail.com>
 
-obj-$(CONFIG_XPL_BUILD) += transformer-t30-spl.o
+obj-$(CONFIG_SPL_BUILD) += transformer-t30-spl.o
+obj-$(CONFIG_MULTI_DTB_FIT) += board-info.o
 
 obj-y += transformer-t30.o
diff --git a/board/asus/transformer-t30/board-info.c b/board/asus/transformer-t30/board-info.c
new file mode 100644
index 0000000..a2b540c
--- /dev/null
+++ b/board/asus/transformer-t30/board-info.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  (C) Copyright 2024
+ *  Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#include <env.h>
+#include <spl_gpio.h>
+
+#include <asm/gpio.h>
+#include <asm/arch/pinmux.h>
+
+/*
+ *	PCB_ID[1] is kb_row5_pr5
+ *	PCB_ID[3] is kb_col7_pq7
+ *	PCB_ID[4] is kb_row2_pr2
+ *	PCB_ID[5] is kb_col5_pq5
+ *
+ *			  Project ID
+ *	=====================================================
+ *	PCB_ID[1] PCB_ID[5] PCB_ID[4] PCB_ID[3]	Project
+ *	0	  0	    0	      0		TF201
+ *	0	  0	    0	      1		P1801
+ *	0	  0	    1	      0		TF300T
+ *	0	  0	    1	      1		TF300TG
+ *	0	  1	    0	      0		TF700T
+ *	0	  1	    0	      1		TF300TL
+ *	0	  1	    1	      0		Extension
+ *	0	  1	    1	      1		TF500T
+ *	1	  0	    0	      0		TF502T/TF600T
+ *	=====================================================
+ */
+enum project_rev {
+	TF201, P1801, TF300T, TF300TG, TF700T,
+	TF300TL, EXT, TF500T, TF600T
+};
+
+static const char * const project_id_to_fdt[] = {
+	[TF201] = "tegra30-asus-tf201",
+	[P1801] = "tegra30-asus-p1801-t",
+	[TF300T] = "tegra30-asus-tf300t",
+	[TF300TG] = "tegra30-asus-tf300tg",
+	[TF700T] = "tegra30-asus-tf700t",
+	[TF300TL] = "tegra30-asus-tf300tl",
+	[TF600T] = "tegra30-asus-tf600t",
+};
+
+static int id_gpio_get_value(u32 pingrp, u32 pin)
+{
+	/* Configure pinmux */
+	pinmux_set_func(pingrp, PMUX_FUNC_KBC);
+	pinmux_set_pullupdown(pingrp, PMUX_PULL_DOWN);
+	pinmux_tristate_enable(pingrp);
+	pinmux_set_io(pingrp, PMUX_PIN_INPUT);
+
+	/*
+	 * Since this function may be called
+	 * during DM reload we should use SPL
+	 * GPIO functions which do not depend
+	 * on DM.
+	 */
+	spl_gpio_input(NULL, pin);
+	return spl_gpio_get_value(NULL, pin);
+}
+
+static int get_project_id(void)
+{
+	u32 pcb_id1, pcb_id3, pcb_id4, pcb_id5;
+
+	pcb_id1 = id_gpio_get_value(PMUX_PINGRP_KB_ROW5_PR5,
+				    TEGRA_GPIO(R, 5));
+	pcb_id3 = id_gpio_get_value(PMUX_PINGRP_KB_COL7_PQ7,
+				    TEGRA_GPIO(Q, 7));
+	pcb_id4 = id_gpio_get_value(PMUX_PINGRP_KB_ROW2_PR2,
+				    TEGRA_GPIO(R, 2));
+	pcb_id5 = id_gpio_get_value(PMUX_PINGRP_KB_COL5_PQ5,
+				    TEGRA_GPIO(Q, 5));
+
+	/* Construct board ID */
+	int proj_id = pcb_id1 << 3 | pcb_id5 << 2 |
+		      pcb_id4 << 1 | pcb_id3;
+
+	log_debug("[TRANSFORMER]: project id %d (%s)\n", proj_id,
+		  project_id_to_fdt[proj_id]);
+
+	/* Mark tablet with SPI flash */
+	if (proj_id == TF600T)
+		env_set_hex("spiflash", true);
+	else
+		env_set_hex("spiflash", false);
+
+	return proj_id & 0xf;
+}
+
+int board_fit_config_name_match(const char *name)
+{
+	if (!strcmp(name, project_id_to_fdt[get_project_id()]))
+		return 0;
+
+	return -1;
+}
+
+void nvidia_board_late_init(void)
+{
+	char dt_path[64] = { 0 };
+
+	snprintf(dt_path, sizeof(dt_path), "%s.dtb",
+		 project_id_to_fdt[get_project_id()]);
+	env_set("fdtfile", dt_path);
+}
diff --git a/board/asus/transformer-t30/configs/p1801-t.config b/board/asus/transformer-t30/configs/p1801-t.config
deleted file mode 100644
index f378f54..0000000
--- a/board/asus/transformer-t30/configs/p1801-t.config
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG_DEFAULT_DEVICE_TREE="tegra30-asus-p1801-t"
-# CONFIG_I2C_MUX is not set
-CONFIG_USB_GADGET_PRODUCT_NUM=0x4cb0
diff --git a/board/asus/transformer-t30/configs/tf201.config b/board/asus/transformer-t30/configs/tf201.config
deleted file mode 100644
index e4fd303..0000000
--- a/board/asus/transformer-t30/configs/tf201.config
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG_DEFAULT_DEVICE_TREE="tegra30-asus-tf201"
-# CONFIG_I2C_MUX is not set
-CONFIG_USB_GADGET_PRODUCT_NUM=0x4d00
diff --git a/board/asus/transformer-t30/configs/tf300t.config b/board/asus/transformer-t30/configs/tf300t.config
deleted file mode 100644
index 9ad2ebd..0000000
--- a/board/asus/transformer-t30/configs/tf300t.config
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG_DEFAULT_DEVICE_TREE="tegra30-asus-tf300t"
-# CONFIG_I2C_MUX is not set
-CONFIG_USB_GADGET_PRODUCT_NUM=0x4d00
diff --git a/board/asus/transformer-t30/configs/tf300tg.config b/board/asus/transformer-t30/configs/tf300tg.config
deleted file mode 100644
index 7b44a91..0000000
--- a/board/asus/transformer-t30/configs/tf300tg.config
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG_DEFAULT_DEVICE_TREE="tegra30-asus-tf300tg"
-# CONFIG_I2C_MUX is not set
-CONFIG_USB_GADGET_PRODUCT_NUM=0x4c80
diff --git a/board/asus/transformer-t30/configs/tf300tl.config b/board/asus/transformer-t30/configs/tf300tl.config
deleted file mode 100644
index 81e96d5..0000000
--- a/board/asus/transformer-t30/configs/tf300tl.config
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG_DEFAULT_DEVICE_TREE="tegra30-asus-tf300tl"
-# CONFIG_I2C_MUX is not set
-CONFIG_USB_GADGET_PRODUCT_NUM=0x4d00
diff --git a/board/asus/transformer-t30/configs/tf600t.config b/board/asus/transformer-t30/configs/tf600t.config
deleted file mode 100644
index b373486..0000000
--- a/board/asus/transformer-t30/configs/tf600t.config
+++ /dev/null
@@ -1,6 +0,0 @@
-CONFIG_DEFAULT_DEVICE_TREE="tegra30-asus-tf600t"
-CONFIG_BOOTCOMMAND="setenv gpio_button 222; if run check_button; then poweroff; fi; setenv gpio_button 132; if run check_button; then echo Starting SPI flash update ...; run update_spi; fi; run bootcmd_usb0; run bootcmd_mmc1; run bootcmd_mmc0; poweroff;"
-# CONFIG_I2C_MUX is not set
-CONFIG_TEGRA20_SLINK=y
-CONFIG_SPI_FLASH_WINBOND=y
-CONFIG_USB_GADGET_PRODUCT_NUM=0x4d00
diff --git a/board/asus/transformer-t30/configs/tf700t.config b/board/asus/transformer-t30/configs/tf700t.config
deleted file mode 100644
index 887c25f..0000000
--- a/board/asus/transformer-t30/configs/tf700t.config
+++ /dev/null
@@ -1,4 +0,0 @@
-CONFIG_DEFAULT_DEVICE_TREE="tegra30-asus-tf700t"
-CONFIG_CLK_GPIO=y
-CONFIG_USB_GADGET_PRODUCT_NUM=0x4c90
-CONFIG_VIDEO_BRIDGE_TOSHIBA_TC358768=y
diff --git a/board/asus/transformer-t30/transformer-t30.env b/board/asus/transformer-t30/transformer-t30.env
new file mode 100644
index 0000000..9b6f407
--- /dev/null
+++ b/board/asus/transformer-t30/transformer-t30.env
@@ -0,0 +1,17 @@
+#include <env/nvidia/prod_upd.env>
+
+button_cmd_0_name=Volume Down
+button_cmd_0=if spiflash; then run update_spi; else bootmenu; fi
+button_cmd_1_name=Lid sensor
+button_cmd_1=poweroff
+partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}
+boot_dev=1
+
+bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu
+bootmenu_1=mount external storage=usb start && ums 0 mmc 1; bootmenu
+bootmenu_2=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu
+bootmenu_3=update bootloader=run flash_uboot
+bootmenu_4=reboot RCM=enterrcm
+bootmenu_5=reboot=reset
+bootmenu_6=power off=poweroff
+bootmenu_delay=-1
diff --git a/board/htc/endeavoru/endeavoru-spl.c b/board/htc/endeavoru/endeavoru-spl.c
index 3c4caff..33ff72b 100644
--- a/board/htc/endeavoru/endeavoru-spl.c
+++ b/board/htc/endeavoru/endeavoru-spl.c
@@ -9,13 +9,12 @@
  *  Svyatoslav Ryhel <clamor95@gmail.com>
  */
 
-#include <asm/io.h>
 #include <asm/gpio.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/tegra.h>
-#include <asm/arch-tegra/board.h>
 #include <asm/arch-tegra/pmc.h>
 #include <asm/arch-tegra/tegra_i2c.h>
+#include <spl_gpio.h>
 #include <linux/delay.h>
 
 /*
@@ -35,24 +34,6 @@
 #define TPS80032_SMPS1_CFG_STATE_DATA		(0x0100 | TPS80032_SMPS1_CFG_STATE_REG)
 #define TPS80032_SMPS2_CFG_STATE_DATA		(0x0100 | TPS80032_SMPS2_CFG_STATE_REG)
 
-#define TEGRA_GPIO_PS0				144
-
-void pmic_enable_cpu_vdd(void)
-{
-	/* Set VDD_CORE to 1.200V. */
-	tegra_i2c_ll_write(TPS80032_DVS_I2C_ADDR, TPS80032_SMPS2_CFG_VOLTAGE_DATA);
-	udelay(1000);
-	tegra_i2c_ll_write(TPS80032_CTL1_I2C_ADDR, TPS80032_SMPS2_CFG_STATE_DATA);
-
-	udelay(1000);
-
-	/* Bring up VDD_CPU to 1.0125V. */
-	tegra_i2c_ll_write(TPS80032_DVS_I2C_ADDR, TPS80032_SMPS1_CFG_VOLTAGE_DATA);
-	udelay(1000);
-	tegra_i2c_ll_write(TPS80032_CTL1_I2C_ADDR, TPS80032_SMPS1_CFG_STATE_DATA);
-	udelay(10 * 1000);
-}
-
 /*
  * Unlike all other supported Tegra devices and most known Tegra devices, the
  * HTC One X has no hardware way to enter APX/RCM mode, which may lead to a
@@ -65,15 +46,13 @@
  * proposed to add the RCM rebooting hook as early into SPL as possible since
  * SPL is much more robust and has minimal changes that can break bootflow.
  *
- * gpio_early_init_uart() function was chosen as it is the earliest function
+ * pmic_enable_cpu_vdd() function was chosen as it is the earliest function
  * exposed for setup by the device. Hook performs a check for volume up
  * button state and triggers RCM if it is pressed.
  */
-void gpio_early_init_uart(void)
+void apx_hook(void)
 {
-	struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
-	struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(TEGRA_GPIO_PS0)];
-	u32 value;
+	int value;
 
 	/* Configure pinmux */
 	pinmux_set_func(PMUX_PINGRP_KB_ROW8_PS0, PMUX_FUNC_KBC);
@@ -81,19 +60,8 @@
 	pinmux_tristate_disable(PMUX_PINGRP_KB_ROW8_PS0);
 	pinmux_set_io(PMUX_PINGRP_KB_ROW8_PS0, PMUX_PIN_INPUT);
 
-	/* Configure GPIO direction as input. */
-	value = readl(&bank->gpio_dir_out[GPIO_PORT(TEGRA_GPIO_PS0)]);
-	value &= ~(1 << GPIO_BIT(TEGRA_GPIO_PS0));
-	writel(value, &bank->gpio_dir_out[GPIO_PORT(TEGRA_GPIO_PS0)]);
-
-	/* Enable the pin as a GPIO */
-	value = readl(&bank->gpio_config[GPIO_PORT(TEGRA_GPIO_PS0)]);
-	value |= 1 << GPIO_BIT(TEGRA_GPIO_PS0);
-	writel(value, &bank->gpio_config[GPIO_PORT(TEGRA_GPIO_PS0)]);
-
-	/* Get GPIO value */
-	value = readl(&bank->gpio_in[GPIO_PORT(TEGRA_GPIO_PS0)]);
-	value = (value >> GPIO_BIT(TEGRA_GPIO_PS0)) & 1;
+	spl_gpio_input(NULL, TEGRA_GPIO(S, 0));
+	value = spl_gpio_get_value(NULL, TEGRA_GPIO(S, 0));
 
 	/* Enter RCM if button is pressed */
 	if (!value) {
@@ -101,3 +69,22 @@
 		tegra_pmc_writel(PMC_CNTRL_MAIN_RST, PMC_CNTRL);
 	}
 }
+
+void pmic_enable_cpu_vdd(void)
+{
+	/* Check if RCM request is active */
+	apx_hook();
+
+	/* Set VDD_CORE to 1.200V. */
+	tegra_i2c_ll_write(TPS80032_DVS_I2C_ADDR, TPS80032_SMPS2_CFG_VOLTAGE_DATA);
+	udelay(1000);
+	tegra_i2c_ll_write(TPS80032_CTL1_I2C_ADDR, TPS80032_SMPS2_CFG_STATE_DATA);
+
+	udelay(1000);
+
+	/* Bring up VDD_CPU to 1.0125V. */
+	tegra_i2c_ll_write(TPS80032_DVS_I2C_ADDR, TPS80032_SMPS1_CFG_VOLTAGE_DATA);
+	udelay(1000);
+	tegra_i2c_ll_write(TPS80032_CTL1_I2C_ADDR, TPS80032_SMPS1_CFG_STATE_DATA);
+	udelay(10 * 1000);
+}
diff --git a/board/htc/endeavoru/endeavoru.env b/board/htc/endeavoru/endeavoru.env
new file mode 100644
index 0000000..53e9b56
--- /dev/null
+++ b/board/htc/endeavoru/endeavoru.env
@@ -0,0 +1,13 @@
+#include <env/nvidia/prod_upd.env>
+
+button_cmd_0_name=Volume Down
+button_cmd_0=bootmenu
+partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}
+
+bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu
+bootmenu_1=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu
+bootmenu_2=update bootloader=run flash_uboot
+bootmenu_3=reboot RCM=enterrcm
+bootmenu_4=reboot=reset
+bootmenu_5=power off=poweroff
+bootmenu_delay=-1
diff --git a/board/lenovo/ideapad-yoga-11/ideapad-yoga-11.env b/board/lenovo/ideapad-yoga-11/ideapad-yoga-11.env
new file mode 100644
index 0000000..7bc2b80
--- /dev/null
+++ b/board/lenovo/ideapad-yoga-11/ideapad-yoga-11.env
@@ -0,0 +1,16 @@
+#include <env/nvidia/prod_upd.env>
+
+button_cmd_0_name=Volume Down
+button_cmd_0=bootmenu
+button_cmd_1_name=Lid sensor
+button_cmd_1=poweroff
+partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}
+
+bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu
+bootmenu_1=mount external storage=usb start && ums 0 mmc 1; bootmenu
+bootmenu_2=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu
+bootmenu_3=update bootloader=run update_spi
+bootmenu_4=reboot RCM=enterrcm
+bootmenu_5=reboot=reset
+bootmenu_6=power off=poweroff
+bootmenu_delay=-1
diff --git a/board/lg/x3-t30/configs/p880.config b/board/lg/x3-t30/configs/p880.config
index 57c2885..44e0fa7 100644
--- a/board/lg/x3-t30/configs/p880.config
+++ b/board/lg/x3-t30/configs/p880.config
@@ -1,3 +1,4 @@
+CONFIG_ENV_SOURCE_FILE="p880"
 CONFIG_DEFAULT_DEVICE_TREE="tegra30-lg-p880"
 CONFIG_SYS_PROMPT="Tegra30 (P880) # "
 CONFIG_VIDEO_LCD_RENESAS_R69328=y
diff --git a/board/lg/x3-t30/configs/p895.config b/board/lg/x3-t30/configs/p895.config
index 2eba925..267ae3a 100644
--- a/board/lg/x3-t30/configs/p895.config
+++ b/board/lg/x3-t30/configs/p895.config
@@ -1,3 +1,4 @@
+CONFIG_ENV_SOURCE_FILE="p895"
 CONFIG_DEFAULT_DEVICE_TREE="tegra30-lg-p895"
 CONFIG_SYS_PROMPT="Tegra30 (P895) # "
 CONFIG_VIDEO_LCD_RENESAS_R61307=y
diff --git a/board/lg/x3-t30/p880.env b/board/lg/x3-t30/p880.env
new file mode 100644
index 0000000..f2bf298
--- /dev/null
+++ b/board/lg/x3-t30/p880.env
@@ -0,0 +1,15 @@
+#include <env/nvidia/prod_upd.env>
+
+button_cmd_0_name=Volume Down
+button_cmd_0=bootmenu
+partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}
+boot_dev=1
+
+bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu
+bootmenu_1=mount external storage=usb start && ums 0 mmc 1; bootmenu
+bootmenu_2=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu
+bootmenu_3=update bootloader=run flash_uboot
+bootmenu_4=reboot RCM=enterrcm
+bootmenu_5=reboot=reset
+bootmenu_6=power off=poweroff
+bootmenu_delay=-1
diff --git a/board/lg/x3-t30/p895.env b/board/lg/x3-t30/p895.env
new file mode 100644
index 0000000..53e9b56
--- /dev/null
+++ b/board/lg/x3-t30/p895.env
@@ -0,0 +1,13 @@
+#include <env/nvidia/prod_upd.env>
+
+button_cmd_0_name=Volume Down
+button_cmd_0=bootmenu
+partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}
+
+bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu
+bootmenu_1=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu
+bootmenu_2=update bootloader=run flash_uboot
+bootmenu_3=reboot RCM=enterrcm
+bootmenu_4=reboot=reset
+bootmenu_5=power off=poweroff
+bootmenu_delay=-1
diff --git a/board/microsoft/surface-rt/surface-rt.env b/board/microsoft/surface-rt/surface-rt.env
new file mode 100644
index 0000000..6829290
--- /dev/null
+++ b/board/microsoft/surface-rt/surface-rt.env
@@ -0,0 +1,14 @@
+button_cmd_0_name=Volume Down
+button_cmd_0=bootmenu
+button_cmd_1_name=Hall Sensor
+button_cmd_1=poweroff
+partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}
+
+bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu
+bootmenu_1=mount external storage=usb start && ums 0 mmc 1; bootmenu
+bootmenu_2=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu
+bootmenu_3=boot from USB=usb reset; usb start; bootflow scan
+bootmenu_4=reboot RCM=enterrcm
+bootmenu_5=reboot=reset
+bootmenu_6=power off=poweroff
+bootmenu_delay=-1
diff --git a/board/nvidia/cardhu/cardhu.env b/board/nvidia/cardhu/cardhu.env
new file mode 100644
index 0000000..9d1e3e1
--- /dev/null
+++ b/board/nvidia/cardhu/cardhu.env
@@ -0,0 +1,2 @@
+board_name=cardhu-a04
+fdtfile=tegra30-cardhu-a04.dtb
diff --git a/board/nvidia/p2771-0000/p2771-0000.env b/board/nvidia/p2771-0000/p2771-0000.env
new file mode 100644
index 0000000..6789cc1
--- /dev/null
+++ b/board/nvidia/p2771-0000/p2771-0000.env
@@ -0,0 +1,22 @@
+calculated_vars=kernel_addr_r fdt_addr_r scriptaddr pxefile_addr_r ramdisk_addr_r
+
+kernel_addr_r_align=00200000
+kernel_addr_r_offset=00080000
+kernel_addr_r_size=02000000
+kernel_addr_r_aliases=loadaddr
+
+fdt_addr_r_align=00200000
+fdt_addr_r_offset=00000000
+fdt_addr_r_size=00200000
+
+scriptaddr_align=00200000
+scriptaddr_offset=00000000
+scriptaddr_size=00200000
+
+pxefile_addr_r_align=00200000
+pxefile_addr_r_offset=00000000
+pxefile_addr_r_size=00200000
+
+ramdisk_addr_r_align=00200000
+ramdisk_addr_r_offset=00000000
+ramdisk_addr_r_size=02000000
diff --git a/board/nvidia/p3450-0000/p3450-0000.env b/board/nvidia/p3450-0000/p3450-0000.env
new file mode 100644
index 0000000..f21d2fc
--- /dev/null
+++ b/board/nvidia/p3450-0000/p3450-0000.env
@@ -0,0 +1,7 @@
+/* Only MMC/PXE/DHCP for now, add USB back in later when supported */
+boot_targets=mmc1 mmc0 pxe dhcp
+
+preboot=if test -e mmc 1:1 /u-boot-preboot.scr; then
+	load mmc 1:1 ${scriptaddr} /u-boot-preboot.scr;
+		source ${scriptaddr};
+	fi
diff --git a/board/toradex/apalis-tk1/apalis-tk1.env b/board/toradex/apalis-tk1/apalis-tk1.env
new file mode 100644
index 0000000..9c2d9a9
--- /dev/null
+++ b/board/toradex/apalis-tk1/apalis-tk1.env
@@ -0,0 +1,45 @@
+/*
+ * Custom Boot configuration:
+ * 1. 8bit SD port (MMC1)
+ * 2. 4bit SD port (MMC2)
+ * 3. eMMC (MMC0)
+ */
+boot_targets=mmc1 mmc2 mmc0 usb pxe dhcp
+
+boot_file=zImage
+boot_script_dhcp=boot.scr
+console=ttyS0
+defargs=lp0_vec=2064@0xf46ff000 core_edp_mv=1150 core_edp_ma=4000
+	usb_port_owner_info=2 lane_owner_info=6 emc_max_dvfs=0
+	user_debug=30 pcie_aspm=off
+dfu_alt_info=apalis-tk1.img raw 0x0 0x500 mmcpart 1;
+	boot part 0 1 mmcpart 0;
+	rootfs part 0 2 mmcpart 0;
+	zImage fat 0 1 mmcpart 0;
+	tegra124-apalis-eval.dtb fat 0 1 mmcpart 0
+fdt_board=eval
+fdt_fixup=;
+fdt_module=apalis-v1.2
+uboot_hwpart=1
+uboot_blk=0
+set_blkcnt=setexpr blkcnt ${filesize} + 0x1ff &&
+	setexpr blkcnt ${blkcnt} / 0x200
+update_uboot=run set_blkcnt && mmc dev 0 ${uboot_hwpart} &&
+	mmc write ${loadaddr} ${uboot_blk} ${blkcnt}
+setethupdate=if env exists ethaddr; then; else setenv ethaddr
+	00:14:2d:00:00:00; fi; pci enum && tftpboot ${loadaddr}
+	flash_eth.img && source ${loadaddr}
+setsdupdate=setenv interface mmc; setenv drive 1; mmc rescan;
+	load ${interface} ${drive}:1 ${loadaddr} flash_blk.img
+	|| setenv drive 2; mmc rescan; load ${interface} ${drive}:1
+	${loadaddr} flash_blk.img &&
+	source ${loadaddr}
+setup=setenv setupargs igb_mac=${ethaddr}
+	consoleblank=0 no_console_suspend=1 console=tty1
+	console=${console},${baudrate}n8 debug_uartport=lsport,0
+	${memargs}
+setupdate=run setsdupdate || run setusbupdate || run setethupdate
+setusbupdate=usb start && setenv interface usb; setenv drive 0;
+	load ${interface} ${drive}:1 ${loadaddr} flash_blk.img &&
+	source ${loadaddr}
+vidargs=fbcon=map:1
diff --git a/board/toradex/apalis_t30/apalis_t30.env b/board/toradex/apalis_t30/apalis_t30.env
new file mode 100644
index 0000000..a8f2904
--- /dev/null
+++ b/board/toradex/apalis_t30/apalis_t30.env
@@ -0,0 +1,9 @@
+uboot_hwpart=1
+uboot_blk=0
+
+set_blkcnt=setexpr blkcnt ${filesize} + 0x1ff &&
+	setexpr blkcnt ${blkcnt} / 0x200
+update_uboot=run set_blkcnt && mmc dev 0 ${uboot_hwpart} &&
+	mmc write ${loadaddr} ${uboot_blk} ${blkcnt}
+
+boot_script_dhcp=boot.scr
diff --git a/board/toradex/colibri_t20/colibri_t20.env b/board/toradex/colibri_t20/colibri_t20.env
new file mode 100644
index 0000000..5e9f063
--- /dev/null
+++ b/board/toradex/colibri_t20/colibri_t20.env
@@ -0,0 +1,3 @@
+/* Environment in NAND, 64K is a bit excessive but erase block is 512K anyway */
+boot_script_dhcp=boot.scr
+update_uboot=nand erase.part u-boot && nand write ${loadaddr} u-boot ${filesize}
diff --git a/board/toradex/colibri_t30/colibri_t30.env b/board/toradex/colibri_t30/colibri_t30.env
new file mode 100644
index 0000000..a8f2904
--- /dev/null
+++ b/board/toradex/colibri_t30/colibri_t30.env
@@ -0,0 +1,9 @@
+uboot_hwpart=1
+uboot_blk=0
+
+set_blkcnt=setexpr blkcnt ${filesize} + 0x1ff &&
+	setexpr blkcnt ${blkcnt} / 0x200
+update_uboot=run set_blkcnt && mmc dev 0 ${uboot_hwpart} &&
+	mmc write ${loadaddr} ${uboot_blk} ${blkcnt}
+
+boot_script_dhcp=boot.scr
diff --git a/board/wexler/qc750/qc750.env b/board/wexler/qc750/qc750.env
new file mode 100644
index 0000000..f2bf298
--- /dev/null
+++ b/board/wexler/qc750/qc750.env
@@ -0,0 +1,15 @@
+#include <env/nvidia/prod_upd.env>
+
+button_cmd_0_name=Volume Down
+button_cmd_0=bootmenu
+partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}
+boot_dev=1
+
+bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu
+bootmenu_1=mount external storage=usb start && ums 0 mmc 1; bootmenu
+bootmenu_2=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu
+bootmenu_3=update bootloader=run flash_uboot
+bootmenu_4=reboot RCM=enterrcm
+bootmenu_5=reboot=reset
+bootmenu_6=power off=poweroff
+bootmenu_delay=-1
diff --git a/configs/apalis-tk1_defconfig b/configs/apalis-tk1_defconfig
index 7fa6161..baab3bf 100644
--- a/configs/apalis-tk1_defconfig
+++ b/configs/apalis-tk1_defconfig
@@ -4,6 +4,7 @@
 CONFIG_TEXT_BASE=0x80110000
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_NR_DRAM_BANKS=2
+CONFIG_ENV_SOURCE_FILE="apalis-tk1"
 CONFIG_ENV_SIZE=0x2000
 CONFIG_ENV_OFFSET=0xFFFFDE00
 CONFIG_DEFAULT_DEVICE_TREE="tegra124-apalis"
@@ -19,7 +20,7 @@
 CONFIG_FIT_VERBOSE=y
 CONFIG_BOOTDELAY=1
 CONFIG_OF_SYSTEM_SETUP=y
-CONFIG_BOOTCOMMAND="setenv fdtfile ${soc}-${fdt_module}-${fdt_board}.dtb && run distro_bootcmd"
+CONFIG_BOOTCOMMAND="setenv fdtfile ${soc}-${fdt_module}-${fdt_board}.dtb && bootflow scan"
 CONFIG_SYS_CBSIZE=1024
 CONFIG_SYS_PBSIZE=1054
 CONFIG_CONSOLE_MUX=y
diff --git a/configs/apalis_t30_defconfig b/configs/apalis_t30_defconfig
index d7da23e..963b280 100644
--- a/configs/apalis_t30_defconfig
+++ b/configs/apalis_t30_defconfig
@@ -4,6 +4,7 @@
 CONFIG_TEXT_BASE=0x80110000
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_NR_DRAM_BANKS=2
+CONFIG_ENV_SOURCE_FILE="apalis_t30"
 CONFIG_ENV_SIZE=0x2000
 CONFIG_ENV_OFFSET=0xFFFFDE00
 CONFIG_DEFAULT_DEVICE_TREE="tegra30-apalis"
diff --git a/configs/cardhu_defconfig b/configs/cardhu_defconfig
index 7d88a25..3fca1ae 100644
--- a/configs/cardhu_defconfig
+++ b/configs/cardhu_defconfig
@@ -4,6 +4,7 @@
 CONFIG_ARCH_TEGRA=y
 CONFIG_TEXT_BASE=0x80110000
 CONFIG_NR_DRAM_BANKS=2
+CONFIG_ENV_SOURCE_FILE="cardhu"
 CONFIG_SF_DEFAULT_SPEED=24000000
 CONFIG_ENV_SIZE=0x2000
 CONFIG_ENV_OFFSET=0xFFFFE000
diff --git a/configs/colibri_t20_defconfig b/configs/colibri_t20_defconfig
index 67456c8..a1a12e2 100644
--- a/configs/colibri_t20_defconfig
+++ b/configs/colibri_t20_defconfig
@@ -4,6 +4,7 @@
 CONFIG_TEXT_BASE=0x00110000
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_NR_DRAM_BANKS=2
+CONFIG_ENV_SOURCE_FILE="colibri_t20"
 CONFIG_ENV_SIZE=0x10000
 CONFIG_ENV_OFFSET=0x200000
 CONFIG_DEFAULT_DEVICE_TREE="tegra20-colibri"
diff --git a/configs/colibri_t30_defconfig b/configs/colibri_t30_defconfig
index 5044feb..3be175b 100644
--- a/configs/colibri_t30_defconfig
+++ b/configs/colibri_t30_defconfig
@@ -4,6 +4,7 @@
 CONFIG_TEXT_BASE=0x80110000
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_NR_DRAM_BANKS=2
+CONFIG_ENV_SOURCE_FILE="colibri_t30"
 CONFIG_ENV_SIZE=0x2000
 CONFIG_ENV_OFFSET=0xFFFFDE00
 CONFIG_DEFAULT_DEVICE_TREE="tegra30-colibri"
diff --git a/configs/endeavoru_defconfig b/configs/endeavoru_defconfig
index fddc3d8..f0c8ce1 100644
--- a/configs/endeavoru_defconfig
+++ b/configs/endeavoru_defconfig
@@ -5,6 +5,7 @@
 CONFIG_INITRD_TAG=y
 CONFIG_TEXT_BASE=0x80110000
 CONFIG_NR_DRAM_BANKS=2
+CONFIG_ENV_SOURCE_FILE="endeavoru"
 CONFIG_ENV_SIZE=0x3000
 CONFIG_ENV_OFFSET=0xFFFFD000
 CONFIG_DEFAULT_DEVICE_TREE="tegra30-htc-endeavoru"
diff --git a/configs/grouper_common_defconfig b/configs/grouper_defconfig
similarity index 84%
rename from configs/grouper_common_defconfig
rename to configs/grouper_defconfig
index 7d8cb61..d07d740 100644
--- a/configs/grouper_common_defconfig
+++ b/configs/grouper_defconfig
@@ -5,6 +5,7 @@
 CONFIG_INITRD_TAG=y
 CONFIG_TEXT_BASE=0x80110000
 CONFIG_NR_DRAM_BANKS=2
+CONFIG_ENV_SOURCE_FILE="grouper"
 CONFIG_ENV_SIZE=0x3000
 CONFIG_ENV_OFFSET=0xFFFFD000
 CONFIG_DEFAULT_DEVICE_TREE="tegra30-asus-nexus7-grouper-E1565"
@@ -38,6 +39,7 @@
 CONFIG_CMD_GPT_RENAME=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_POWEROFF=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_USB_MASS_STORAGE=y
 CONFIG_CMD_UMS_ABORT_KEYED=y
@@ -47,6 +49,9 @@
 CONFIG_CMD_EXT4_WRITE=y
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_OF_LIST="tegra30-asus-nexus7-grouper-E1565 tegra30-asus-nexus7-grouper-PM269 tegra30-asus-nexus7-tilapia-E1565"
+CONFIG_DTB_RESELECT=y
+CONFIG_MULTI_DTB_FIT=y
 CONFIG_ENV_OVERWRITE=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SYS_MMC_ENV_PART=2
@@ -61,10 +66,16 @@
 CONFIG_SYS_I2C_TEGRA=y
 CONFIG_BUTTON_KEYBOARD=y
 CONFIG_DM_PMIC=y
+CONFIG_DM_PMIC_MAX77663=y
+CONFIG_DM_PMIC_TPS65910=y
 CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_MAX77663=y
 CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_TPS65911=y
 CONFIG_PWM_TEGRA=y
 CONFIG_SYS_NS16550=y
+CONFIG_SYSRESET_MAX77663=y
+CONFIG_SYSRESET_TPS65910=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_TEGRA=y
diff --git a/configs/ideapad-yoga-11_defconfig b/configs/ideapad-yoga-11_defconfig
index 4618c52..a9dd521 100644
--- a/configs/ideapad-yoga-11_defconfig
+++ b/configs/ideapad-yoga-11_defconfig
@@ -5,6 +5,7 @@
 CONFIG_INITRD_TAG=y
 CONFIG_TEXT_BASE=0x80110000
 CONFIG_NR_DRAM_BANKS=2
+CONFIG_ENV_SOURCE_FILE="ideapad-yoga-11"
 CONFIG_ENV_SIZE=0x3000
 CONFIG_ENV_OFFSET=0xFFFFD000
 CONFIG_DEFAULT_DEVICE_TREE="tegra30-lenovo-ideapad-yoga-11"
diff --git a/configs/p2771-0000-000_defconfig b/configs/p2771-0000-000_defconfig
index 3554ba6..a125865 100644
--- a/configs/p2771-0000-000_defconfig
+++ b/configs/p2771-0000-000_defconfig
@@ -5,6 +5,7 @@
 CONFIG_ARCH_TEGRA=y
 CONFIG_TEXT_BASE=0x80080000
 CONFIG_NR_DRAM_BANKS=1026
+CONFIG_ENV_SOURCE_FILE="p2771-0000"
 CONFIG_ENV_SIZE=0x2000
 CONFIG_ENV_OFFSET=0xFFFFE000
 CONFIG_DEFAULT_DEVICE_TREE="tegra186-p2771-0000-000"
diff --git a/configs/p3450-0000_defconfig b/configs/p3450-0000_defconfig
index ac7ed8e..a002178 100644
--- a/configs/p3450-0000_defconfig
+++ b/configs/p3450-0000_defconfig
@@ -6,6 +6,7 @@
 CONFIG_TEXT_BASE=0x80080000
 CONFIG_SYS_MALLOC_LEN=0x2500000
 CONFIG_NR_DRAM_BANKS=2
+CONFIG_ENV_SOURCE_FILE="p3450-0000"
 CONFIG_SF_DEFAULT_SPEED=24000000
 CONFIG_ENV_SIZE=0x2000
 CONFIG_ENV_OFFSET=0xFFFFE000
diff --git a/configs/qc750_defconfig b/configs/qc750_defconfig
index d0b07ee..58a3c83 100644
--- a/configs/qc750_defconfig
+++ b/configs/qc750_defconfig
@@ -5,6 +5,7 @@
 CONFIG_INITRD_TAG=y
 CONFIG_TEXT_BASE=0x80110000
 CONFIG_NR_DRAM_BANKS=2
+CONFIG_ENV_SOURCE_FILE="qc750"
 CONFIG_ENV_SIZE=0x3000
 CONFIG_ENV_OFFSET=0xFFFFD000
 CONFIG_DEFAULT_DEVICE_TREE="tegra30-wexler-qc750"
diff --git a/configs/surface-rt_defconfig b/configs/surface-rt_defconfig
index dbb08ab..c1fd4a5 100644
--- a/configs/surface-rt_defconfig
+++ b/configs/surface-rt_defconfig
@@ -5,6 +5,7 @@
 CONFIG_INITRD_TAG=y
 CONFIG_TEXT_BASE=0x80110000
 CONFIG_NR_DRAM_BANKS=2
+CONFIG_ENV_SOURCE_FILE="surface-rt"
 CONFIG_ENV_SIZE=0x3000
 CONFIG_ENV_OFFSET=0xFFFFD000
 CONFIG_DEFAULT_DEVICE_TREE="tegra30-microsoft-surface-rt"
diff --git a/configs/transformer_t20_defconfig b/configs/transformer_t20_defconfig
index f424ce8..df993c3 100644
--- a/configs/transformer_t20_defconfig
+++ b/configs/transformer_t20_defconfig
@@ -5,6 +5,7 @@
 CONFIG_INITRD_TAG=y
 CONFIG_TEXT_BASE=0x00110000
 CONFIG_NR_DRAM_BANKS=2
+CONFIG_ENV_SOURCE_FILE="transformer-t20"
 CONFIG_ENV_SIZE=0x3000
 CONFIG_ENV_OFFSET=0xFFFFD000
 CONFIG_DEFAULT_DEVICE_TREE="tegra20-asus-tf101"
diff --git a/configs/transformer_t30_defconfig b/configs/transformer_t30_defconfig
index 1078403..9102dcc 100644
--- a/configs/transformer_t30_defconfig
+++ b/configs/transformer_t30_defconfig
@@ -5,6 +5,7 @@
 CONFIG_INITRD_TAG=y
 CONFIG_TEXT_BASE=0x80110000
 CONFIG_NR_DRAM_BANKS=2
+CONFIG_ENV_SOURCE_FILE="transformer-t30"
 CONFIG_ENV_SIZE=0x3000
 CONFIG_ENV_OFFSET=0xFFFFD000
 CONFIG_DEFAULT_DEVICE_TREE="tegra30-asus-tf201"
@@ -49,10 +50,14 @@
 CONFIG_CMD_EXT4_WRITE=y
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_OF_LIST="tegra30-asus-p1801-t tegra30-asus-tf201 tegra30-asus-tf300t tegra30-asus-tf300tg tegra30-asus-tf300tl tegra30-asus-tf600t tegra30-asus-tf700t"
+CONFIG_DTB_RESELECT=y
+CONFIG_MULTI_DTB_FIT=y
 CONFIG_ENV_OVERWRITE=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SYS_MMC_ENV_PART=2
 CONFIG_BUTTON=y
+CONFIG_CLK_GPIO=y
 CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x91000000
 CONFIG_FASTBOOT_BUF_SIZE=0x10000000
@@ -64,6 +69,7 @@
 CONFIG_I2C_MUX=y
 CONFIG_I2C_MUX_GPIO=y
 CONFIG_BUTTON_KEYBOARD=y
+CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_DM_PMIC=y
 CONFIG_DM_PMIC_TPS65910=y
 CONFIG_DM_REGULATOR=y
@@ -71,6 +77,7 @@
 CONFIG_DM_REGULATOR_TPS65911=y
 CONFIG_PWM_TEGRA=y
 CONFIG_SYS_NS16550=y
+CONFIG_TEGRA20_SLINK=y
 CONFIG_SYSRESET_TPS65910=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
@@ -79,7 +86,9 @@
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="ASUS"
 CONFIG_USB_GADGET_VENDOR_NUM=0x0b05
+CONFIG_USB_GADGET_PRODUCT_NUM=0x4daf
 CONFIG_CI_UDC=y
 CONFIG_VIDEO=y
 # CONFIG_VIDEO_LOGO is not set
+CONFIG_VIDEO_BRIDGE_TOSHIBA_TC358768=y
 CONFIG_VIDEO_TEGRA20=y
diff --git a/disk/Kconfig b/disk/Kconfig
index ffa835e..b0bd025 100644
--- a/disk/Kconfig
+++ b/disk/Kconfig
@@ -49,6 +49,16 @@
 	default y if MAC_PARTITION
 	select SPL_PARTITIONS
 
+config TEGRA_PARTITION
+	bool "Enable Nvidia Tegra partition table"
+	select PARTITIONS
+	select EFI_PARTITION
+	help
+	  Say Y here if you would like to use U-Boot on a device that
+	  is using the Nvidia Tegra partition table and cannot alter it.
+
+	  If unsure, say N.
+
 config DOS_PARTITION
 	bool "Enable MS Dos partition table"
 	default y if BOOT_DEFAULTS
diff --git a/disk/part_efi.c b/disk/part_efi.c
index 580821a..7f04c6e 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -318,6 +318,17 @@
 	/* Read legacy MBR from block 0 and validate it */
 	if ((blk_dread(desc, 0, 1, (ulong *)legacymbr) != 1)
 		|| (is_pmbr_valid(legacymbr) != 1)) {
+		/*
+		 * TegraPT is compatible with EFI part, but it
+		 * cannot pass the Protective MBR check. Skip it
+		 * if CONFIG_TEGRA_PARTITION is enabled and the
+		 * device in question is eMMC.
+		 */
+		if (IS_ENABLED(CONFIG_TEGRA_PARTITION))
+			if (!is_pmbr_valid(legacymbr) &&
+			    desc->uclass_id == UCLASS_MMC &&
+			    !desc->devnum)
+				return 0;
 		return -1;
 	}
 	return 0;
diff --git a/doc/board/asus/grouper_common.rst b/doc/board/asus/grouper.rst
similarity index 93%
rename from doc/board/asus/grouper_common.rst
rename to doc/board/asus/grouper.rst
index 47a854e..d56a9ca 100644
--- a/doc/board/asus/grouper_common.rst
+++ b/doc/board/asus/grouper.rst
@@ -19,14 +19,14 @@
 Build U-Boot
 ------------
 
-Device support is implemented by applying config fragment to a generic board
-defconfig. Valid fragments are ``tilapia.config``, ``grouper_E1565.config``
-and ``grouper_PM269.config``.
+U-Boot features ability to detect grouper board revision on which it is
+loaded. Currently are supported both TI and MAXIM based WiFi-only models
+along with cellular one.
 
 .. code-block:: bash
 
     $ export CROSS_COMPILE=arm-linux-gnueabi-
-    $ make grouper_common_defconfig grouper_E1565.config # For maxim based grouper
+    $ make grouper_defconfig # For all grouper versions and tilapia
     $ make
 
 After the build succeeds, you will obtain the final ``u-boot-dtb-tegra.bin``
diff --git a/doc/board/asus/index.rst b/doc/board/asus/index.rst
index 2b10328..2cac04c 100644
--- a/doc/board/asus/index.rst
+++ b/doc/board/asus/index.rst
@@ -6,6 +6,6 @@
 .. toctree::
    :maxdepth: 2
 
-   grouper_common
+   grouper
    transformer_t20
    transformer_t30
diff --git a/doc/board/asus/transformer_t30.rst b/doc/board/asus/transformer_t30.rst
index ff9792d..bebc4b9 100644
--- a/doc/board/asus/transformer_t30.rst
+++ b/doc/board/asus/transformer_t30.rst
@@ -20,15 +20,18 @@
 Build U-Boot
 ------------
 
-Device support is implemented by applying a config fragment to a generic board
-defconfig. Valid fragments are ``tf201.config``, ``tf300t.config``,
-``tf300tg.config``, ``tf300tl.config``, ``tf700t.config``, ``tf600t.config`` and
-``p1801-t.config``.
+U-Boot features ability to detect transformer device model on which it is
+loaded. The list of supported devices include:
+- ASUS Transformer Prime TF201
+- ASUS Transformer Pad (3G/LTE) TF300T/TG/TL
+- ASUS Transformer Infinity TF700T
+- ASUS Portable AiO P1801-T
+- ASUS VivoTab RT TF600T
 
 .. code-block:: bash
 
     $ export CROSS_COMPILE=arm-linux-gnueabi-
-    $ make transformer_t30_defconfig tf201.config # For TF201
+    $ make transformer_t30_defconfig
     $ make
 
 After the build succeeds, you will obtain the final ``u-boot-dtb-tegra.bin``
diff --git a/drivers/gpio/tegra_gpio.c b/drivers/gpio/tegra_gpio.c
index 6cafffa..b83df35 100644
--- a/drivers/gpio/tegra_gpio.c
+++ b/drivers/gpio/tegra_gpio.c
@@ -257,6 +257,56 @@
 	.xlate			= tegra_gpio_xlate,
 };
 
+/*
+ * SPL GPIO functions.
+ */
+int spl_gpio_output(void *regs, uint gpio, int value)
+{
+	/* Configure GPIO output value. */
+	set_level(gpio, value);
+
+	/* Configure GPIO direction as output. */
+	set_direction(gpio, DIRECTION_OUTPUT);
+
+	/* Enable the pin as a GPIO */
+	set_config(gpio, 1);
+
+	return 0;
+}
+
+int spl_gpio_input(void *regs, uint gpio)
+{
+	/* Configure GPIO direction as input. */
+	set_direction(gpio, DIRECTION_INPUT);
+
+	/* Enable the pin as a GPIO */
+	set_config(gpio, 1);
+
+	return 0;
+}
+
+int spl_gpio_get_value(void *regs, uint gpio)
+{
+	struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
+	struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
+	int val;
+
+	if (get_direction(gpio) == DIRECTION_INPUT)
+		val = readl(&bank->gpio_in[GPIO_PORT(gpio)]);
+	else
+		val = readl(&bank->gpio_out[GPIO_PORT(gpio)]);
+
+	return (val >> GPIO_BIT(gpio)) & 1;
+}
+
+int spl_gpio_set_value(void *regs, uint gpio, int value)
+{
+	/* Configure GPIO output value. */
+	set_level(gpio, value);
+
+	return 0;
+}
+
 /**
  * Returns the name of a GPIO port
  *
diff --git a/drivers/pinctrl/tegra/funcmux-tegra30.c b/drivers/pinctrl/tegra/funcmux-tegra30.c
index e31b859..5d3403a 100644
--- a/drivers/pinctrl/tegra/funcmux-tegra30.c
+++ b/drivers/pinctrl/tegra/funcmux-tegra30.c
@@ -33,6 +33,22 @@
 			break;
 		}
 		break;
+	case PERIPH_ID_UART5:
+		switch (config) {
+		case FUNCMUX_UART5_SDMMC1:
+			pinmux_set_func(PMUX_PINGRP_SDMMC1_DAT3_PY4,
+					PMUX_FUNC_UARTE);
+			pinmux_set_func(PMUX_PINGRP_SDMMC1_DAT2_PY5,
+					PMUX_FUNC_UARTE);
+
+			pinmux_set_io(PMUX_PINGRP_SDMMC1_DAT3_PY4, PMUX_PIN_OUTPUT);
+			pinmux_set_io(PMUX_PINGRP_SDMMC1_DAT2_PY5, PMUX_PIN_INPUT);
+
+			pinmux_tristate_disable(PMUX_PINGRP_SDMMC1_DAT3_PY4);
+			pinmux_tristate_disable(PMUX_PINGRP_SDMMC1_DAT2_PY5);
+			break;
+		}
+		break;
 
 	/* Add other periph IDs here as needed */
 
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 343893b..7c73eb6 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -66,9 +66,24 @@
 	USB_CTRL_COUNT,
 };
 
+struct tegra_utmip_config {
+	u32 hssync_start_delay;
+	u32 elastic_limit;
+	u32 idle_wait_delay;
+	u32 term_range_adj;
+	bool xcvr_setup_use_fuses;
+	u32 xcvr_setup;
+	u32 xcvr_lsfslew;
+	u32 xcvr_lsrslew;
+	u32 xcvr_hsslew;
+	u32 hssquelch_level;
+	u32 hsdiscon_level;
+};
+
 /* Information about a USB port */
 struct fdt_usb {
 	struct ehci_ctrl ehci;
+	struct tegra_utmip_config utmip_config;
 	struct usb_ctlr *reg;	/* address of registers in physical memory */
 	unsigned utmi:1;	/* 1 if port has external tranceiver, else 0 */
 	unsigned ulpi:1;	/* 1 if port has external ULPI transceiver */
@@ -192,15 +207,6 @@
 	{ 0x028, 0x01, 0x01, 0x0,   0,  0x02, 0x2F, 0x08, 0x76,  65000,  5 }
 };
 
-/* UTMIP Idle Wait Delay */
-static const u8 utmip_idle_wait_delay = 17;
-
-/* UTMIP Elastic limit */
-static const u8 utmip_elastic_limit = 16;
-
-/* UTMIP High Speed Sync Start Delay */
-static const u8 utmip_hs_sync_start_delay = 9;
-
 struct fdt_usb_controller {
 	/* flag to determine whether controller supports hostpc register */
 	u32 has_hostpc:1;
@@ -377,6 +383,7 @@
 	u32 b_sess_valid_mask, val;
 	int loop_count;
 	const unsigned *timing;
+	struct tegra_utmip_config *utmip_config = &config->utmip_config;
 	struct usb_ctlr *usbctlr = config->reg;
 	struct clk_rst_ctlr *clkrst;
 	struct usb_ctlr *usb1ctlr;
@@ -463,16 +470,29 @@
 
 		/* Recommended PHY settings for EYE diagram */
 		val = readl(&usbctlr->utmip_xcvr_cfg0);
-		clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MASK,
-				0x4 << UTMIP_XCVR_SETUP_SHIFT);
-		clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MSB_MASK,
-				0x3 << UTMIP_XCVR_SETUP_MSB_SHIFT);
-		clrsetbits_le32(&val, UTMIP_XCVR_HSSLEW_MSB_MASK,
-				0x8 << UTMIP_XCVR_HSSLEW_MSB_SHIFT);
+
+		if (!utmip_config->xcvr_setup_use_fuses) {
+			clrsetbits_le32(&val, UTMIP_XCVR_SETUP(~0),
+					UTMIP_XCVR_SETUP(utmip_config->xcvr_setup));
+			clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MSB(~0),
+					UTMIP_XCVR_SETUP_MSB(utmip_config->xcvr_setup));
+		}
+
+		clrsetbits_le32(&val, UTMIP_XCVR_LSFSLEW(~0),
+				UTMIP_XCVR_LSFSLEW(utmip_config->xcvr_lsfslew));
+		clrsetbits_le32(&val, UTMIP_XCVR_LSRSLEW(~0),
+				UTMIP_XCVR_LSRSLEW(utmip_config->xcvr_lsrslew));
+
+		clrsetbits_le32(&val, UTMIP_XCVR_HSSLEW(~0),
+				UTMIP_XCVR_HSSLEW(utmip_config->xcvr_hsslew));
+		clrsetbits_le32(&val, UTMIP_XCVR_HSSLEW_MSB(~0),
+				UTMIP_XCVR_HSSLEW_MSB(utmip_config->xcvr_hsslew));
 		writel(val, &usbctlr->utmip_xcvr_cfg0);
+
 		clrsetbits_le32(&usbctlr->utmip_xcvr_cfg1,
 				UTMIP_XCVR_TERM_RANGE_ADJ_MASK,
-				0x7 << UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT);
+				utmip_config->term_range_adj <<
+				UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT);
 
 		/* Some registers can be controlled from USB1 only. */
 		if (config->periph_id != PERIPH_ID_USBD) {
@@ -485,9 +505,11 @@
 		val = readl(&usb1ctlr->utmip_bias_cfg0);
 		setbits_le32(&val, UTMIP_HSDISCON_LEVEL_MSB);
 		clrsetbits_le32(&val, UTMIP_HSDISCON_LEVEL_MASK,
-				0x1 << UTMIP_HSDISCON_LEVEL_SHIFT);
+				utmip_config->hsdiscon_level <<
+				UTMIP_HSDISCON_LEVEL_SHIFT);
 		clrsetbits_le32(&val, UTMIP_HSSQUELCH_LEVEL_MASK,
-				0x2 << UTMIP_HSSQUELCH_LEVEL_SHIFT);
+				utmip_config->hssquelch_level <<
+				UTMIP_HSSQUELCH_LEVEL_SHIFT);
 		writel(val, &usb1ctlr->utmip_bias_cfg0);
 
 		/* Miscellaneous setting mentioned in Programming Guide */
@@ -521,7 +543,11 @@
 	setbits_le32(&usbctlr->utmip_bat_chrg_cfg0, UTMIP_PD_CHRG);
 
 	clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_XCVR_LSBIAS_SE);
-	setbits_le32(&usbctlr->utmip_spare_cfg0, FUSE_SETUP_SEL);
+
+	if (utmip_config->xcvr_setup_use_fuses)
+		setbits_le32(&usbctlr->utmip_spare_cfg0, FUSE_SETUP_SEL);
+	else
+		clrbits_le32(&usbctlr->utmip_spare_cfg0, FUSE_SETUP_SEL);
 
 	/*
 	 * Configure the UTMIP_IDLE_WAIT and UTMIP_ELASTIC_LIMIT
@@ -535,15 +561,16 @@
 	/* Set PLL enable delay count and Crystal frequency count */
 	val = readl(&usbctlr->utmip_hsrx_cfg0);
 	clrsetbits_le32(&val, UTMIP_IDLE_WAIT_MASK,
-		utmip_idle_wait_delay << UTMIP_IDLE_WAIT_SHIFT);
+		utmip_config->idle_wait_delay << UTMIP_IDLE_WAIT_SHIFT);
 	clrsetbits_le32(&val, UTMIP_ELASTIC_LIMIT_MASK,
-		utmip_elastic_limit << UTMIP_ELASTIC_LIMIT_SHIFT);
+		utmip_config->elastic_limit << UTMIP_ELASTIC_LIMIT_SHIFT);
 	writel(val, &usbctlr->utmip_hsrx_cfg0);
 
 	/* Configure the UTMIP_HS_SYNC_START_DLY */
 	clrsetbits_le32(&usbctlr->utmip_hsrx_cfg1,
 		UTMIP_HS_SYNC_START_DLY_MASK,
-		utmip_hs_sync_start_delay << UTMIP_HS_SYNC_START_DLY_SHIFT);
+		utmip_config->hssync_start_delay <<
+		UTMIP_HS_SYNC_START_DLY_SHIFT);
 
 	/* Preceed the crystal clock disable by >100ns delay. */
 	udelay(1);
@@ -763,6 +790,69 @@
 	return 0;
 }
 
+static void fdt_decode_usb_phy(struct udevice *dev)
+{
+	struct fdt_usb *priv = dev_get_priv(dev);
+	struct tegra_utmip_config *utmip_config = &priv->utmip_config;
+	u32 usb_phy_phandle;
+	ofnode usb_phy_node;
+	int ret;
+
+	ret = ofnode_read_u32(dev_ofnode(dev), "nvidia,phy", &usb_phy_phandle);
+	if (ret)
+		log_debug("%s: required usb phy node isn't provided\n", __func__);
+
+	usb_phy_node = ofnode_get_by_phandle(usb_phy_phandle);
+	if (!ofnode_valid(usb_phy_node) || !ofnode_is_enabled(usb_phy_node)) {
+		log_debug("%s: failed to find usb phy node or it is disabled\n", __func__);
+		utmip_config->xcvr_setup_use_fuses = true;
+	} else {
+		utmip_config->xcvr_setup_use_fuses =
+			ofnode_read_bool(usb_phy_node, "nvidia,xcvr-setup-use-fuses");
+	}
+
+	utmip_config->hssync_start_delay =
+		ofnode_read_u32_default(usb_phy_node,
+					"nvidia,hssync-start-delay", 0x9);
+
+	utmip_config->elastic_limit =
+		ofnode_read_u32_default(usb_phy_node,
+					"nvidia,elastic-limit", 0x10);
+
+	utmip_config->idle_wait_delay =
+		ofnode_read_u32_default(usb_phy_node,
+					"nvidia,idle-wait-delay", 0x11);
+
+	utmip_config->term_range_adj =
+		ofnode_read_u32_default(usb_phy_node,
+					"nvidia,term-range-adj", 0x7);
+
+	utmip_config->xcvr_lsfslew =
+		ofnode_read_u32_default(usb_phy_node,
+					"nvidia,xcvr-lsfslew", 0x0);
+
+	utmip_config->xcvr_lsrslew =
+		ofnode_read_u32_default(usb_phy_node,
+					"nvidia,xcvr-lsrslew", 0x3);
+
+	utmip_config->xcvr_hsslew =
+		ofnode_read_u32_default(usb_phy_node,
+					"nvidia,xcvr-hsslew", 0x8);
+
+	utmip_config->hssquelch_level =
+		ofnode_read_u32_default(usb_phy_node,
+					"nvidia,hssquelch-level", 0x2);
+
+	utmip_config->hsdiscon_level =
+		ofnode_read_u32_default(usb_phy_node,
+					"nvidia,hsdiscon-level", 0x1);
+
+	if (!utmip_config->xcvr_setup_use_fuses) {
+		ofnode_read_u32(usb_phy_node, "nvidia,xcvr-setup",
+				&utmip_config->xcvr_setup);
+	}
+}
+
 int usb_common_init(struct fdt_usb *config, enum usb_init_type init)
 {
 	int ret = 0;
@@ -850,6 +940,8 @@
 
 	priv->type = dev_get_driver_data(dev);
 
+	fdt_decode_usb_phy(dev);
+
 	return 0;
 }
 
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 6e79694..3c3ceba 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -599,6 +599,15 @@
 	  LCD module found in Microsoft Surface 2. The panel has a FullHD
 	  resolution (1920x1080).
 
+config VIDEO_LCD_SHARP_LQ101R1SX01
+	tristate "Sharp LQ101R1SX01 2560x1600 DSI video mode panel"
+	depends on PANEL && BACKLIGHT
+	select VIDEO_MIPI_DSI
+	help
+	  Say Y here if you want to enable support for Sharp LQ101R1SX01
+	  LCD module found in ASUS Transformer TF701T. The panel has a
+	  WQXGA resolution (2560x1600).
+
 config VIDEO_LCD_SSD2828
 	bool "SSD2828 bridge chip"
 	---help---
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index af8b2b2..5a00438 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -64,6 +64,7 @@
 obj-$(CONFIG_VIDEO_LCD_RENESAS_R61307) += renesas-r61307.o
 obj-$(CONFIG_VIDEO_LCD_RENESAS_R69328) += renesas-r69328.o
 obj-$(CONFIG_VIDEO_LCD_SAMSUNG_LTL106HL02) += samsung-ltl106hl02.o
+obj-$(CONFIG_VIDEO_LCD_SHARP_LQ101R1SX01) += sharp-lq101r1sx01.o
 obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o
 obj-$(CONFIG_VIDEO_LCD_TDO_TL070WSH30) += tdo-tl070wsh30.o
 obj-$(CONFIG_VIDEO_MCDE_SIMPLE) += mcde_simple.o
diff --git a/drivers/video/sharp-lq101r1sx01.c b/drivers/video/sharp-lq101r1sx01.c
new file mode 100644
index 0000000..5d8453f
--- /dev/null
+++ b/drivers/video/sharp-lq101r1sx01.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Sharp LQ101R1SX01 DSI panel driver
+ *
+ * Copyright (C) 2014 NVIDIA Corporation
+ * Copyright (c) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#include <backlight.h>
+#include <dm.h>
+#include <panel.h>
+#include <log.h>
+#include <mipi_dsi.h>
+#include <linux/delay.h>
+#include <power/regulator.h>
+
+struct sharp_lq101r1sx01_priv {
+	struct udevice *backlight;
+	struct udevice *panel_sec;
+	struct udevice *vcc;
+};
+
+static struct display_timing default_timing = {
+	.pixelclock.typ		= 278000000,
+	.hactive.typ		= 2560,
+	.hfront_porch.typ	= 128,
+	.hback_porch.typ	= 64,
+	.hsync_len.typ		= 64,
+	.vactive.typ		= 1600,
+	.vfront_porch.typ	= 4,
+	.vback_porch.typ	= 8,
+	.vsync_len.typ		= 32,
+};
+
+static int sharp_lq101r1sx01_write(struct mipi_dsi_device *dsi,
+				   u16 offset, u8 value)
+{
+	u8 payload[3] = { offset >> 8, offset & 0xff, value };
+	int ret;
+
+	ret = mipi_dsi_generic_write(dsi, payload, sizeof(payload));
+	if (ret < 0) {
+		log_debug("%s: failed to write %02x to %04x: %zd\n",
+			  __func__, value, offset, ret);
+		return ret;
+	}
+
+	ret = mipi_dsi_dcs_nop(dsi);
+	if (ret < 0) {
+		log_debug("%s: failed to send DCS nop: %zd\n",
+			  __func__, ret);
+		return ret;
+	}
+
+	udelay(20);
+
+	return 0;
+}
+
+static int sharp_setup_symmetrical_split(struct mipi_dsi_device *left,
+					 struct mipi_dsi_device *right,
+					 struct display_timing *timing)
+{
+	int ret;
+
+	ret = mipi_dsi_dcs_set_column_address(left, 0,
+					      timing->hactive.typ / 2 - 1);
+	if (ret < 0) {
+		log_debug("%s: failed to set column address: %d\n",
+			  __func__, ret);
+		return ret;
+	}
+
+	ret = mipi_dsi_dcs_set_page_address(left, 0, timing->vactive.typ - 1);
+	if (ret < 0) {
+		log_debug("%s: failed to set page address: %d\n",
+			  __func__, ret);
+		return ret;
+	}
+
+	ret = mipi_dsi_dcs_set_column_address(right, timing->hactive.typ / 2,
+					      timing->hactive.typ - 1);
+	if (ret < 0) {
+		log_debug("%s: failed to set column address: %d\n",
+			  __func__, ret);
+		return ret;
+	}
+
+	ret = mipi_dsi_dcs_set_page_address(right, 0, timing->vactive.typ - 1);
+	if (ret < 0) {
+		log_debug("%s: failed to set page address: %d\n",
+			  __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int sharp_lq101r1sx01_enable_backlight(struct udevice *dev)
+{
+	struct sharp_lq101r1sx01_priv *priv = dev_get_priv(dev);
+
+	if (!priv->panel_sec)
+		return 0;
+
+	struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+	struct mipi_dsi_panel_plat *plat_sec = dev_get_plat(priv->panel_sec);
+	struct mipi_dsi_device *link1 = plat->device;
+	struct mipi_dsi_device *link2 = plat_sec->device;
+	int ret;
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(link1);
+	if (ret < 0) {
+		log_debug("%s: failed to exit sleep mode: %d\n",
+			  __func__, ret);
+		return ret;
+	}
+
+	/* set left-right mode */
+	ret = sharp_lq101r1sx01_write(link1, 0x1000, 0x2a);
+	if (ret < 0) {
+		log_debug("%s: failed to set left-right mode: %d\n",
+			  __func__, ret);
+		return ret;
+	}
+
+	/* enable command mode */
+	ret = sharp_lq101r1sx01_write(link1, 0x1001, 0x01);
+	if (ret < 0) {
+		log_debug("%s: failed to enable command mode: %d\n",
+			  __func__, ret);
+		return ret;
+	}
+
+	ret = mipi_dsi_dcs_set_pixel_format(link1, MIPI_DCS_PIXEL_FMT_24BIT);
+	if (ret < 0) {
+		log_debug("%s: failed to set pixel format: %d\n",
+			  __func__, ret);
+		return ret;
+	}
+
+	/*
+	 * TODO: The device supports both left-right and even-odd split
+	 * configurations, but this driver currently supports only the left-
+	 * right split. To support a different mode a mechanism needs to be
+	 * put in place to communicate the configuration back to the DSI host
+	 * controller.
+	 */
+	ret = sharp_setup_symmetrical_split(link1, link2, &default_timing);
+	if (ret < 0) {
+		log_debug("%s: failed to set up symmetrical split: %d\n",
+			  __func__, ret);
+		return ret;
+	}
+
+	ret = mipi_dsi_dcs_set_display_on(link1);
+	if (ret < 0) {
+		log_debug("%s: failed to set panel on: %d\n",
+			  __func__, ret);
+		return ret;
+	}
+	mdelay(20);
+
+	return 0;
+}
+
+static int sharp_lq101r1sx01_set_backlight(struct udevice *dev, int percent)
+{
+	struct sharp_lq101r1sx01_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	if (!priv->panel_sec)
+		return 0;
+
+	ret = backlight_enable(priv->backlight);
+	if (ret)
+		return ret;
+
+	return backlight_set_brightness(priv->backlight, percent);
+}
+
+static int sharp_lq101r1sx01_timings(struct udevice *dev,
+				     struct display_timing *timing)
+{
+	memcpy(timing, &default_timing, sizeof(*timing));
+	return 0;
+}
+
+static int sharp_lq101r1sx01_of_to_plat(struct udevice *dev)
+{
+	struct sharp_lq101r1sx01_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	/* If node has no link2 it is secondary panel */
+	if (!dev_read_bool(dev, "link2"))
+		return 0;
+
+	ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev,
+					   "link2", &priv->panel_sec);
+	if (ret) {
+		log_debug("%s: cannot get secondary panel: ret = %d\n",
+			  __func__, ret);
+		return ret;
+	}
+
+	ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
+					   "backlight", &priv->backlight);
+	if (ret) {
+		log_debug("%s: cannot get backlight: ret = %d\n",
+			  __func__, ret);
+		return ret;
+	}
+
+	ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
+					   "power-supply", &priv->vcc);
+	if (ret) {
+		log_debug("%s: cannot get power-supply: ret = %d\n",
+			  __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int sharp_lq101r1sx01_hw_init(struct udevice *dev)
+{
+	struct sharp_lq101r1sx01_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	if (!priv->panel_sec)
+		return 0;
+
+	ret = regulator_set_enable_if_allowed(priv->vcc, 1);
+	if (ret) {
+		log_debug("%s: enabling power-supply failed (%d)\n",
+			  __func__, ret);
+		return ret;
+	}
+
+	/*
+	 * According to the datasheet, the panel needs around 10 ms to fully
+	 * power up. At least another 120 ms is required before exiting sleep
+	 * mode to make sure the panel is ready. Throw in another 20 ms for
+	 * good measure.
+	 */
+	mdelay(150);
+
+	return 0;
+}
+
+static int sharp_lq101r1sx01_probe(struct udevice *dev)
+{
+	struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+
+	/* fill characteristics of DSI data link */
+	plat->lanes = 4;
+	plat->format = MIPI_DSI_FMT_RGB888;
+
+	return sharp_lq101r1sx01_hw_init(dev);
+}
+
+static const struct panel_ops sharp_lq101r1sx01_ops = {
+	.enable_backlight	= sharp_lq101r1sx01_enable_backlight,
+	.set_backlight		= sharp_lq101r1sx01_set_backlight,
+	.get_display_timing	= sharp_lq101r1sx01_timings,
+};
+
+static const struct udevice_id sharp_lq101r1sx01_ids[] = {
+	{ .compatible = "sharp,lq101r1sx01" },
+	{ }
+};
+
+U_BOOT_DRIVER(sharp_lq101r1sx01) = {
+	.name		= "sharp_lq101r1sx01",
+	.id		= UCLASS_PANEL,
+	.of_match	= sharp_lq101r1sx01_ids,
+	.ops		= &sharp_lq101r1sx01_ops,
+	.of_to_plat	= sharp_lq101r1sx01_of_to_plat,
+	.probe		= sharp_lq101r1sx01_probe,
+	.plat_auto	= sizeof(struct mipi_dsi_panel_plat),
+	.priv_auto	= sizeof(struct sharp_lq101r1sx01_priv),
+};
diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c
index accabbf..d24aa37 100644
--- a/drivers/video/tegra20/tegra-dc.c
+++ b/drivers/video/tegra20/tegra-dc.c
@@ -26,8 +26,6 @@
 
 #include "tegra-dc.h"
 
-DECLARE_GLOBAL_DATA_PTR;
-
 /* Holder of Tegra per-SOC DC differences */
 struct tegra_dc_soc_info {
 	bool has_timer;
diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c
index 35a8e6c..6327266 100644
--- a/drivers/video/tegra20/tegra-dsi.c
+++ b/drivers/video/tegra20/tegra-dsi.c
@@ -20,6 +20,7 @@
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
+#include <asm/arch-tegra/clk_rst.h>
 
 #include "tegra-dc.h"
 #include "tegra-dsi.h"
@@ -50,6 +51,10 @@
 	int host_fifo_depth;
 
 	u32 version;
+
+	/* for ganged-mode support */
+	struct udevice *master;
+	struct udevice *slave;
 };
 
 static void tegra_dc_enable_controller(struct udevice *dev)
@@ -595,6 +600,17 @@
 	writel(value, &ptiming->dsi_bta_timing);
 }
 
+static void tegra_dsi_ganged_enable(struct udevice *dev, unsigned int start,
+				    unsigned int size)
+{
+	struct tegra_dsi_priv *priv = dev_get_priv(dev);
+	struct dsi_ganged_mode_reg *ganged = &priv->dsi->ganged;
+
+	writel(start, &ganged->ganged_mode_start);
+	writel(size << 16 | size, &ganged->ganged_mode_size);
+	writel(DSI_GANGED_MODE_CONTROL_ENABLE, &ganged->ganged_mode_ctrl);
+}
+
 static void tegra_dsi_configure(struct udevice *dev,
 				unsigned long mode_flags)
 {
@@ -679,9 +695,19 @@
 		writel(hact << 16 | hbp, &len->dsi_pkt_len_2_3);
 		writel(hfp, &len->dsi_pkt_len_4_5);
 		writel(0x0f0f << 16, &len->dsi_pkt_len_6_7);
+
+		/* set SOL delay (for non-burst mode only) */
+		writel(8 * mul / div, &misc->dsi_sol_delay);
 	} else {
-		/* 1 byte (DCS command) + pixel data */
-		value = 1 + timing->hactive.typ * mul / div;
+		if (priv->master || priv->slave) {
+			/*
+			 * For ganged mode, assume symmetric left-right mode.
+			 */
+			value = 1 + (timing->hactive.typ / 2) * mul / div;
+		} else {
+			/* 1 byte (DCS command) + pixel data */
+			value = 1 + timing->hactive.typ * mul / div;
+		}
 
 		writel(0, &len->dsi_pkt_len_0_1);
 		writel(value << 16, &len->dsi_pkt_len_2_3);
@@ -691,10 +717,40 @@
 		value = MIPI_DCS_WRITE_MEMORY_START << 8 |
 			MIPI_DCS_WRITE_MEMORY_CONTINUE;
 		writel(value, &len->dsi_dcs_cmds);
+
+		/* set SOL delay */
+		if (priv->master || priv->slave) {
+			unsigned long delay, bclk, bclk_ganged;
+			unsigned int lanes = device->lanes;
+			unsigned long htotal = timing->hactive.typ + timing->hfront_porch.typ +
+					       timing->hback_porch.typ + timing->hsync_len.typ;
+
+			/* SOL to valid, valid to FIFO and FIFO write delay */
+			delay = 4 + 4 + 2;
+			delay = DIV_ROUND_UP(delay * mul, div * lanes);
+			/* FIFO read delay */
+			delay = delay + 6;
+
+			bclk = DIV_ROUND_UP(htotal * mul, div * lanes);
+			bclk_ganged = DIV_ROUND_UP(bclk * lanes / 2, lanes);
+			value = bclk - bclk_ganged + delay + 20;
+		} else {
+			/* TODO: revisit for non-ganged mode */
+			value = 8 * mul / div;
+		}
+
+		writel(value, &misc->dsi_sol_delay);
 	}
 
-	/* set SOL delay (for non-burst mode only) */
-	writel(8 * mul / div, &misc->dsi_sol_delay);
+	if (priv->slave) {
+		/*
+		 * TODO: Support modes other than symmetrical left-right
+		 * split.
+		 */
+		tegra_dsi_ganged_enable(dev, 0, timing->hactive.typ / 2);
+		tegra_dsi_ganged_enable(priv->slave, timing->hactive.typ / 2,
+					timing->hactive.typ / 2);
+	}
 }
 
 static int tegra_dsi_encoder_enable(struct udevice *dev)
@@ -774,6 +830,9 @@
 	value |= DSI_POWER_CONTROL_ENABLE;
 	writel(value, &misc->dsi_pwr_ctrl);
 
+	if (priv->slave)
+		tegra_dsi_encoder_enable(priv->slave);
+
 	return 0;
 }
 
@@ -803,6 +862,14 @@
 	unsigned int mul, div;
 	unsigned long bclk, plld;
 
+	if (!priv->slave) {
+		/* Change DSIB clock parent to match DSIA */
+		struct clk_rst_ctlr *clkrst =
+			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+
+		clrbits_le32(&clkrst->plld2.pll_base, BIT(25)); /* DSIB_CLK_SRC */
+	}
+
 	tegra_dsi_get_muldiv(device->format, &mul, &div);
 
 	bclk = (priv->timing.pixelclock.typ * mul) /
@@ -854,6 +921,24 @@
 	reset_set_enable(priv->dsi_clk, 0);
 }
 
+static int tegra_dsi_ganged_probe(struct udevice *dev)
+{
+	struct tegra_dsi_priv *mpriv = dev_get_priv(dev);
+	struct udevice *gangster;
+
+	uclass_get_device_by_phandle(UCLASS_PANEL, dev,
+				     "nvidia,ganged-mode", &gangster);
+	if (gangster) {
+		/* Ganged mode is set */
+		struct tegra_dsi_priv *spriv = dev_get_priv(gangster);
+
+		mpriv->slave = gangster;
+		spriv->master = dev;
+	}
+
+	return 0;
+}
+
 static int tegra_dsi_bridge_probe(struct udevice *dev)
 {
 	struct tegra_dsi_priv *priv = dev_get_priv(dev);
@@ -873,6 +958,8 @@
 	priv->video_fifo_depth = 1920;
 	priv->host_fifo_depth = 64;
 
+	tegra_dsi_ganged_probe(dev);
+
 	ret = reset_get_by_name(dev, "dsi", &reset_ctl);
 	if (ret) {
 		log_debug("%s: reset_get_by_name() failed: %d\n",
diff --git a/drivers/video/tegra20/tegra-dsi.h b/drivers/video/tegra20/tegra-dsi.h
index 69dac4b..683c5e3 100644
--- a/drivers/video/tegra20/tegra-dsi.h
+++ b/drivers/video/tegra20/tegra-dsi.h
@@ -98,9 +98,9 @@
 	uint dsi_to_tally;		/* _DSI_TO_TALLY_0 */
 };
 
-/* DSI PAD control register 0x04b ~ 0x04e */
+/* DSI PAD control register 0x04b ~ 0x052 */
 struct dsi_pad_ctrl_reg {
-	/* Address 0x04b ~ 0x04e */
+	/* Address 0x04b ~ 0x052 */
 	uint pad_ctrl;			/* _PAD_CONTROL_0 */
 	uint pad_ctrl_cd;		/* _PAD_CONTROL_CD_0 */
 	uint pad_cd_status;		/* _PAD_CD_STATUS_0 */
@@ -111,6 +111,14 @@
 	uint pad_ctrl_4;		/* _PAD_CONTROL_4 */
 };
 
+/* DSI ganged mode register 0x053 ~ 0x04e */
+struct dsi_ganged_mode_reg {
+	/* Address 0x053 ~ 0x055 */
+	uint ganged_mode_ctrl;		/* _DSI_GANGED_MODE_CONTROL_0 */
+	uint ganged_mode_start;		/* _DSI_GANGED_MODE_START_0 */
+	uint ganged_mode_size;		/* _DSI_GANGED_MODE_SIZE_0 */
+};
+
 /* Display Serial Interface (DSI_) regs */
 struct dsi_ctlr {
 	struct dsi_syncpt_reg syncpt;	/* SYNCPT register 0x000 ~ 0x002 */
@@ -133,6 +141,7 @@
 	uint reserved5[4];		/* reserved_5[4] */
 
 	struct dsi_pad_ctrl_reg pad;	/* PAD registers 0x04b ~ 0x04e */
+	struct dsi_ganged_mode_reg ganged; /* GANGED registers 0x053 ~ 0x055 */
 };
 
 #define DSI_POWER_CONTROL_ENABLE	BIT(0)
@@ -202,6 +211,8 @@
 #define DSI_PAD_PREEMP_PD(x)		(((x) & 0x3) << 4)
 #define DSI_PAD_PREEMP_PU(x)		(((x) & 0x3) << 0)
 
+#define DSI_GANGED_MODE_CONTROL_ENABLE	BIT(0)
+
 /*
  * pixel format as used in the DSI_CONTROL_FORMAT field
  */
diff --git a/include/configs/apalis-tk1.h b/include/configs/apalis-tk1.h
index 71d4727..4c690a1 100644
--- a/include/configs/apalis-tk1.h
+++ b/include/configs/apalis-tk1.h
@@ -18,64 +18,6 @@
 #define FDT_MODULE			"apalis-v1.2"
 #define FDT_MODULE_V1_0			"apalis"
 
-/*
- * Custom Distro Boot configuration:
- * 1. 8bit SD port (MMC1)
- * 2. 4bit SD port (MMC2)
- * 3. eMMC (MMC0)
- */
-#define BOOT_TARGET_DEVICES(func) \
-	func(MMC, mmc, 1) \
-	func(MMC, mmc, 2) \
-	func(MMC, mmc, 0) \
-	func(USB, usb, 0) \
-	func(PXE, pxe, na) \
-	func(DHCP, dhcp, na)
-
-#define DFU_ALT_EMMC_INFO	"apalis-tk1.img raw 0x0 0x500 mmcpart 1; " \
-				"boot part 0 1 mmcpart 0; " \
-				"rootfs part 0 2 mmcpart 0; " \
-				"zImage fat 0 1 mmcpart 0; " \
-				"tegra124-apalis-eval.dtb fat 0 1 mmcpart 0"
-
-#define UBOOT_UPDATE \
-	"uboot_hwpart=1\0" \
-	"uboot_blk=0\0" \
-	"set_blkcnt=setexpr blkcnt ${filesize} + 0x1ff && " \
-		"setexpr blkcnt ${blkcnt} / 0x200\0" \
-	"update_uboot=run set_blkcnt && mmc dev 0 ${uboot_hwpart} && " \
-		"mmc write ${loadaddr} ${uboot_blk} ${blkcnt}\0" \
-
-#define BOARD_EXTRA_ENV_SETTINGS \
-	"boot_file=zImage\0" \
-	"boot_script_dhcp=boot.scr\0" \
-	"console=ttyS0\0" \
-	"defargs=lp0_vec=2064@0xf46ff000 core_edp_mv=1150 core_edp_ma=4000 " \
-		"usb_port_owner_info=2 lane_owner_info=6 emc_max_dvfs=0 " \
-		"user_debug=30 pcie_aspm=off\0" \
-	"dfu_alt_info=" DFU_ALT_EMMC_INFO "\0" \
-	"fdt_board=eval\0" \
-	"fdt_fixup=;\0" \
-	"fdt_module=" FDT_MODULE "\0" \
-	UBOOT_UPDATE \
-	"setethupdate=if env exists ethaddr; then; else setenv ethaddr " \
-		"00:14:2d:00:00:00; fi; pci enum && tftpboot ${loadaddr} " \
-		"flash_eth.img && source ${loadaddr}\0" \
-	"setsdupdate=setenv interface mmc; setenv drive 1; mmc rescan; " \
-		"load ${interface} ${drive}:1 ${loadaddr} flash_blk.img " \
-		"|| setenv drive 2; mmc rescan; load ${interface} ${drive}:1 " \
-		"${loadaddr} flash_blk.img && " \
-		"source ${loadaddr}\0" \
-	"setup=setenv setupargs igb_mac=${ethaddr} " \
-		"consoleblank=0 no_console_suspend=1 console=tty1 " \
-		"console=${console},${baudrate}n8 debug_uartport=lsport,0 " \
-		"${memargs}\0" \
-	"setupdate=run setsdupdate || run setusbupdate || run setethupdate\0" \
-	"setusbupdate=usb start && setenv interface usb; setenv drive 0; " \
-		"load ${interface} ${drive}:1 ${loadaddr} flash_blk.img && " \
-		"source ${loadaddr}\0" \
-	"vidargs=fbcon=map:1\0"
-
 #include "tegra-common-post.h"
 
 #endif /* __CONFIG_H */
diff --git a/include/configs/apalis_t30.h b/include/configs/apalis_t30.h
index 80204d7..87a679e 100644
--- a/include/configs/apalis_t30.h
+++ b/include/configs/apalis_t30.h
@@ -22,18 +22,6 @@
  */
 #define CFG_SYS_NS16550_COM1		NV_PA_APB_UARTA_BASE
 
-#define UBOOT_UPDATE \
-	"uboot_hwpart=1\0" \
-	"uboot_blk=0\0" \
-	"set_blkcnt=setexpr blkcnt ${filesize} + 0x1ff && " \
-		"setexpr blkcnt ${blkcnt} / 0x200\0" \
-	"update_uboot=run set_blkcnt && mmc dev 0 ${uboot_hwpart} && " \
-		"mmc write ${loadaddr} ${uboot_blk} ${blkcnt}\0" \
-
-#define BOARD_EXTRA_ENV_SETTINGS \
-	UBOOT_UPDATE \
-	"boot_script_dhcp=boot.scr\0"
-
 #include "tegra-common-post.h"
 
 #endif /* __CONFIG_H */
diff --git a/include/configs/cardhu.h b/include/configs/cardhu.h
index 82729eb..3412b88 100644
--- a/include/configs/cardhu.h
+++ b/include/configs/cardhu.h
@@ -13,10 +13,6 @@
 /* High-level configuration options */
 #define CFG_TEGRA_BOARD_STRING	"NVIDIA Cardhu"
 
-#define BOARD_EXTRA_ENV_SETTINGS \
-	"board_name=cardhu-a04\0" \
-	"fdtfile=tegra30-cardhu-a04.dtb\0"
-
 /* Board-specific serial config */
 #define CFG_SYS_NS16550_COM1		NV_PA_APB_UARTA_BASE
 
diff --git a/include/configs/colibri_t20.h b/include/configs/colibri_t20.h
index ea7d648..bc616d1 100644
--- a/include/configs/colibri_t20.h
+++ b/include/configs/colibri_t20.h
@@ -13,17 +13,6 @@
 /* Board-specific serial config */
 #define CFG_SYS_NS16550_COM1		NV_PA_APB_UARTA_BASE
 
-/* NAND support */
-
-#define UBOOT_UPDATE \
-	"update_uboot=nand erase.part u-boot && " \
-		"nand write ${loadaddr} u-boot ${filesize}\0" \
-
-/* Environment in NAND, 64K is a bit excessive but erase block is 512K anyway */
-#define BOARD_EXTRA_ENV_SETTINGS \
-	"boot_script_dhcp=boot.scr\0" \
-	UBOOT_UPDATE
-
 #include "tegra-common-post.h"
 
 #endif /* __CONFIG_H */
diff --git a/include/configs/colibri_t30.h b/include/configs/colibri_t30.h
index 7edb2c0..1f47466 100644
--- a/include/configs/colibri_t30.h
+++ b/include/configs/colibri_t30.h
@@ -23,18 +23,6 @@
  */
 #define CFG_SYS_NS16550_COM1		NV_PA_APB_UARTA_BASE
 
-#define UBOOT_UPDATE \
-	"uboot_hwpart=1\0" \
-	"uboot_blk=0\0" \
-	"set_blkcnt=setexpr blkcnt ${filesize} + 0x1ff && " \
-		"setexpr blkcnt ${blkcnt} / 0x200\0" \
-	"update_uboot=run set_blkcnt && mmc dev 0 ${uboot_hwpart} && " \
-		"mmc write ${loadaddr} ${uboot_blk} ${blkcnt}\0" \
-
-#define BOARD_EXTRA_ENV_SETTINGS \
-	UBOOT_UPDATE \
-	"boot_script_dhcp=boot.scr\0"
-
 #include "tegra-common-post.h"
 
 #endif /* __CONFIG_H */
diff --git a/include/configs/endeavoru.h b/include/configs/endeavoru.h
index 348078f..33d0021 100644
--- a/include/configs/endeavoru.h
+++ b/include/configs/endeavoru.h
@@ -10,54 +10,11 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
-#include <linux/sizes.h>
-
 #include "tegra30-common.h"
 
 /* High-level configuration options */
 #define CFG_TEGRA_BOARD_STRING		"HTC One X"
 
-#define ENDEAVORU_FLASH_UBOOT \
-	"flash_uboot=echo Preparing RAM;" \
-		"mw ${kernel_addr_r} 0 ${boot_block_size_r};" \
-		"mw ${ramdisk_addr_r} 0 ${boot_block_size_r};" \
-		"echo Reading BCT;" \
-		"mmc dev 0 1;" \
-		"mmc read ${kernel_addr_r} 0 ${boot_block_size};" \
-		"echo Reading bootloader;" \
-		"if load mmc 0:1 ${ramdisk_addr_r} ${bootloader_file};" \
-		"then echo Calculating bootloader size;" \
-			"size mmc 0:1 ${bootloader_file};" \
-			"ebtupdate ${kernel_addr_r} ${ramdisk_addr_r} ${filesize};" \
-			"echo Writing bootloader to eMMC;" \
-			"mmc dev 0 1;" \
-			"mmc write ${kernel_addr_r} 0 ${boot_block_size};" \
-			"mmc dev 0 2;" \
-			"mmc write ${ramdisk_addr_r} 0 ${boot_block_size};" \
-			"echo Bootloader written successfully;" \
-			"pause 'Press ANY key to reboot device...'; reset;" \
-		"else echo Reading bootloader failed;" \
-			"pause 'Press ANY key to return to bootmenu...'; bootmenu; fi\0"
-
-#define ENDEAVORU_BOOTMENU \
-	ENDEAVORU_FLASH_UBOOT \
-	"bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu\0" \
-	"bootmenu_1=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu\0" \
-	"bootmenu_2=update bootloader=run flash_uboot\0" \
-	"bootmenu_3=reboot RCM=enterrcm\0" \
-	"bootmenu_4=reboot=reset\0" \
-	"bootmenu_5=power off=poweroff\0" \
-	"bootmenu_delay=-1\0"
-
-#define BOARD_EXTRA_ENV_SETTINGS \
-	"boot_block_size_r=0x200000\0" \
-	"boot_block_size=0x1000\0" \
-	"bootloader_file=u-boot-dtb-tegra.bin\0" \
-	"button_cmd_0_name=Volume Down\0" \
-	"button_cmd_0=bootmenu\0" \
-	"partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}\0" \
-	ENDEAVORU_BOOTMENU
-
 /* Board-specific serial config */
 #define CFG_SYS_NS16550_COM1		NV_PA_APB_UARTA_BASE
 
diff --git a/include/configs/grouper.h b/include/configs/grouper.h
index 8064b88..b6ef6ff 100644
--- a/include/configs/grouper.h
+++ b/include/configs/grouper.h
@@ -6,56 +6,11 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
-#include <linux/sizes.h>
-
 #include "tegra30-common.h"
 
 /* High-level configuration options */
 #define CFG_TEGRA_BOARD_STRING		"ASUS Google Nexus 7 (2012)"
 
-#define GROUPER_FLASH_UBOOT \
-	"flash_uboot=echo Preparing RAM;" \
-		"mw ${kernel_addr_r} 0 ${boot_block_size_r};" \
-		"mw ${ramdisk_addr_r} 0 ${boot_block_size_r};" \
-		"echo Reading BCT;" \
-		"mmc dev 0 1;" \
-		"mmc read ${kernel_addr_r} 0 ${boot_block_size};" \
-		"echo Reading bootloader;" \
-		"if load mmc 0:1 ${ramdisk_addr_r} ${bootloader_file};" \
-		"then echo Calculating bootloader size;" \
-			"size mmc 0:1 ${bootloader_file};" \
-			"ebtupdate ${kernel_addr_r} ${ramdisk_addr_r} ${filesize};" \
-			"echo Writing bootloader to eMMC;" \
-			"mmc dev 0 1;" \
-			"mmc write ${kernel_addr_r} 0 ${boot_block_size};" \
-			"mmc dev 0 2;" \
-			"mmc write ${ramdisk_addr_r} 0 ${boot_block_size};" \
-			"echo Bootloader written successfully;" \
-			"pause 'Press ANY key to reboot device...'; reset;" \
-		"else echo Reading bootloader failed;" \
-			"pause 'Press ANY key to return to bootmenu...'; bootmenu; fi\0"
-
-#define GROUPER_BOOTMENU \
-	GROUPER_FLASH_UBOOT \
-	"bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu\0" \
-	"bootmenu_1=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu\0" \
-	"bootmenu_2=update bootloader=run flash_uboot\0" \
-	"bootmenu_3=reboot RCM=enterrcm\0" \
-	"bootmenu_4=reboot=reset\0" \
-	"bootmenu_5=power off=poweroff\0" \
-	"bootmenu_delay=-1\0"
-
-#define BOARD_EXTRA_ENV_SETTINGS \
-	"boot_block_size_r=0x200000\0" \
-	"boot_block_size=0x1000\0" \
-	"bootloader_file=u-boot-dtb-tegra.bin\0" \
-	"button_cmd_0_name=Volume Down\0" \
-	"button_cmd_0=bootmenu\0" \
-	"button_cmd_1_name=Lid\0" \
-	"button_cmd_1=poweroff\0" \
-	"partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}\0" \
-	GROUPER_BOOTMENU
-
 /* Board-specific serial config */
 #define CFG_SYS_NS16550_COM1		NV_PA_APB_UARTA_BASE
 
diff --git a/include/configs/ideapad-yoga-11.h b/include/configs/ideapad-yoga-11.h
index 12c7649..c4e6b2a 100644
--- a/include/configs/ideapad-yoga-11.h
+++ b/include/configs/ideapad-yoga-11.h
@@ -11,64 +11,6 @@
 /* High-level configuration options */
 #define CFG_TEGRA_BOARD_STRING		"Lenovo Ideapad Yoga 11"
 
-#define IDEAPAD_FLASH_UBOOT \
-	"flash_uboot=sf probe 0:1;" \
-		"echo Dumping current SPI flash content ...;" \
-		"sf read ${kernel_addr_r} 0x0 ${spi_size};" \
-		"if fatwrite mmc 1:1 ${kernel_addr_r} spi-flash-backup.bin ${spi_size};" \
-		"then echo SPI flash content was successfully written into spi-flash-backup.bin;" \
-			"echo Reading SPI flash binary;" \
-			"if load mmc 1:1 ${kernel_addr_r} repart-block.bin;" \
-			"then echo Writing bootloader into SPI flash;" \
-				"sf probe 0:1;" \
-				"sf update ${kernel_addr_r} 0x0 ${spi_size};" \
-				"echo Bootloader SUCCESSFULLY written into SPI flash;" \
-				"pause 'Press ANY key to reboot...'; reset;" \
-			"else echo Preparing RAM;" \
-				"mw ${kernel_addr_r} 0 ${boot_block_size_r};" \
-				"mw ${ramdisk_addr_r} 0 ${boot_block_size_r};" \
-				"echo Reading BCT;" \
-				"sf read ${kernel_addr_r} 0x0 ${boot_block_size_r};" \
-				"echo Reading bootloader;" \
-				"if load mmc 1:1 ${ramdisk_addr_r} ${bootloader_file};" \
-				"then echo Calculating bootloader size;" \
-					"size mmc 1:1 ${bootloader_file};" \
-					"ebtupdate ${kernel_addr_r} ${ramdisk_addr_r} ${filesize};" \
-					"echo Writing bootloader into SPI flash;" \
-					"sf probe 0:1;" \
-					"sf update ${kernel_addr_r} 0x0 ${boot_block_size_r};" \
-					"sf update ${ramdisk_addr_r} ${boot_block_size_r} ${boot_block_size_r};" \
-					"echo Bootloader written SUCCESSFULLY;" \
-					"pause 'Press ANY key to reboot...'; reset;" \
-				"else echo Reading bootloader failed;" \
-					"pause 'Press ANY key to reboot...'; reset; fi;" \
-			"fi;" \
-		"else echo SPI flash backup FAILED! Aborting ...;" \
-			"pause 'Press ANY key to reboot...'; reset; fi\0"
-
-#define IDEAPAD_BOOTMENU \
-	IDEAPAD_FLASH_UBOOT \
-	"bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu\0" \
-	"bootmenu_1=mount external storage=usb start && ums 0 mmc 1; bootmenu\0" \
-	"bootmenu_2=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu\0" \
-	"bootmenu_3=update bootloader=run flash_uboot\0" \
-	"bootmenu_4=reboot RCM=enterrcm\0" \
-	"bootmenu_5=reboot=reset\0" \
-	"bootmenu_6=power off=poweroff\0" \
-	"bootmenu_delay=-1\0"
-
-#define BOARD_EXTRA_ENV_SETTINGS \
-	"spi_size=0x400000\0" \
-	"boot_block_size_r=0x200000\0" \
-	"boot_block_size=0x1000\0" \
-	"bootloader_file=u-boot-dtb-tegra.bin\0" \
-	"button_cmd_0_name=Volume Down\0" \
-	"button_cmd_0=bootmenu\0" \
-	"button_cmd_1_name=Lid sensor\0" \
-	"button_cmd_1=poweroff\0" \
-	"partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}\0" \
-	IDEAPAD_BOOTMENU
-
 /* Board-specific serial config */
 #define CFG_SYS_NS16550_COM1		NV_PA_APB_UARTA_BASE
 
diff --git a/include/configs/p2771-0000.h b/include/configs/p2771-0000.h
index e409cc3..fc1b7c0 100644
--- a/include/configs/p2771-0000.h
+++ b/include/configs/p2771-0000.h
@@ -15,26 +15,6 @@
 
 /* Environment in eMMC, at the end of 2nd "boot sector" */
 
-#define BOARD_EXTRA_ENV_SETTINGS \
-	"calculated_vars=kernel_addr_r fdt_addr_r scriptaddr pxefile_addr_r " \
-		"ramdisk_addr_r\0" \
-	"kernel_addr_r_align=00200000\0" \
-	"kernel_addr_r_offset=00080000\0" \
-	"kernel_addr_r_size=02000000\0" \
-	"kernel_addr_r_aliases=loadaddr\0" \
-	"fdt_addr_r_align=00200000\0" \
-	"fdt_addr_r_offset=00000000\0" \
-	"fdt_addr_r_size=00200000\0" \
-	"scriptaddr_align=00200000\0" \
-	"scriptaddr_offset=00000000\0" \
-	"scriptaddr_size=00200000\0" \
-	"pxefile_addr_r_align=00200000\0" \
-	"pxefile_addr_r_offset=00000000\0" \
-	"pxefile_addr_r_size=00200000\0" \
-	"ramdisk_addr_r_align=00200000\0" \
-	"ramdisk_addr_r_offset=00000000\0" \
-	"ramdisk_addr_r_size=02000000\0"
-
 #include "tegra-common-post.h"
 
 #endif
diff --git a/include/configs/p3450-0000.h b/include/configs/p3450-0000.h
index e60f42e..1138c1d 100644
--- a/include/configs/p3450-0000.h
+++ b/include/configs/p3450-0000.h
@@ -15,19 +15,6 @@
 
 /* Board-specific serial config */
 
-/* Only MMC/PXE/DHCP for now, add USB back in later when supported */
-#define BOOT_TARGET_DEVICES(func) \
-	func(MMC, mmc, 1) \
-	func(MMC, mmc, 0) \
-	func(PXE, pxe, na) \
-	func(DHCP, dhcp, na)
-
-#define BOARD_EXTRA_ENV_SETTINGS \
-	"preboot=if test -e mmc 1:1 /u-boot-preboot.scr; then " \
-		"load mmc 1:1 ${scriptaddr} /u-boot-preboot.scr; " \
-		"source ${scriptaddr}; " \
-	"fi\0"
-
 /* General networking support */
 #include "tegra-common-post.h"
 
diff --git a/include/configs/qc750.h b/include/configs/qc750.h
index ce6665d..ad9f914 100644
--- a/include/configs/qc750.h
+++ b/include/configs/qc750.h
@@ -15,48 +15,6 @@
 /* High-level configuration options */
 #define CFG_TEGRA_BOARD_STRING		"Wexler QC750"
 
-#define QC750_FLASH_UBOOT \
-	"flash_uboot=echo Preparing RAM;" \
-		"mw ${kernel_addr_r} 0 ${boot_block_size_r};" \
-		"mw ${ramdisk_addr_r} 0 ${boot_block_size_r};" \
-		"echo Reading BCT;" \
-		"mmc dev 0 1;" \
-		"mmc read ${kernel_addr_r} 0 ${boot_block_size};" \
-		"echo Reading bootloader;" \
-		"if load mmc 1:1 ${ramdisk_addr_r} ${bootloader_file};" \
-		"then echo Calculating bootloader size;" \
-			"size mmc 1:1 ${bootloader_file};" \
-			"ebtupdate ${kernel_addr_r} ${ramdisk_addr_r} ${filesize};" \
-			"echo Writing bootloader to eMMC;" \
-			"mmc dev 0 1;" \
-			"mmc write ${kernel_addr_r} 0 ${boot_block_size};" \
-			"mmc dev 0 2;" \
-			"mmc write ${ramdisk_addr_r} 0 ${boot_block_size};" \
-			"echo Bootloader written successfully;" \
-			"pause 'Press ANY key to reboot device...'; reset;" \
-		"else echo Reading bootloader failed;" \
-			"pause 'Press ANY key to return to bootmenu...'; bootmenu; fi\0"
-
-#define QC750_BOOTMENU \
-	QC750_FLASH_UBOOT \
-	"bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu\0" \
-	"bootmenu_1=mount external storage=usb start && ums 0 mmc 1; bootmenu\0" \
-	"bootmenu_2=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu\0" \
-	"bootmenu_3=update bootloader=run flash_uboot\0" \
-	"bootmenu_4=reboot RCM=enterrcm\0" \
-	"bootmenu_5=reboot=reset\0" \
-	"bootmenu_6=power off=poweroff\0" \
-	"bootmenu_delay=-1\0"
-
-#define BOARD_EXTRA_ENV_SETTINGS \
-	"boot_block_size_r=0x200000\0" \
-	"boot_block_size=0x1000\0" \
-	"bootloader_file=u-boot-dtb-tegra.bin\0" \
-	"button_cmd_0_name=Volume Down\0" \
-	"button_cmd_0=bootmenu\0" \
-	"partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}\0" \
-	QC750_BOOTMENU
-
 /* Board-specific serial config */
 #define CFG_SYS_NS16550_COM1		NV_PA_APB_UARTD_BASE
 
diff --git a/include/configs/surface-rt.h b/include/configs/surface-rt.h
index 30f6450..1f0837e 100644
--- a/include/configs/surface-rt.h
+++ b/include/configs/surface-rt.h
@@ -13,24 +13,6 @@
 /* High-level configuration options */
 #define CFG_TEGRA_BOARD_STRING		"Microsoft Surface RT"
 
-#define SURFACE_RT_BOOTMENU \
-	"bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu\0" \
-	"bootmenu_1=mount external storage=usb start && ums 0 mmc 1; bootmenu\0" \
-	"bootmenu_2=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu\0" \
-	"bootmenu_3=boot from USB=usb reset; usb start; bootflow scan\0" \
-	"bootmenu_4=reboot RCM=enterrcm\0" \
-	"bootmenu_5=reboot=reset\0" \
-	"bootmenu_6=power off=poweroff\0" \
-	"bootmenu_delay=-1\0"
-
-#define BOARD_EXTRA_ENV_SETTINGS \
-	"button_cmd_0_name=Volume Down\0" \
-	"button_cmd_0=bootmenu\0" \
-	"button_cmd_1_name=Hall Sensor\0" \
-	"button_cmd_1=poweroff\0" \
-	"partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}\0" \
-	SURFACE_RT_BOOTMENU
-
 /* Board-specific serial config */
 #define CFG_SYS_NS16550_COM1		NV_PA_APB_UARTA_BASE
 
diff --git a/include/configs/transformer-common.h b/include/configs/transformer-common.h
deleted file mode 100644
index bb6817c..0000000
--- a/include/configs/transformer-common.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) 2022, Svyatoslav Ryhel <clamor95@gmail.com>.
- */
-
-#ifndef __TRANSFORMER_COMMON_H
-#define __TRANSFORMER_COMMON_H
-
-/* High-level configuration options */
-#define CFG_TEGRA_BOARD_STRING		"ASUS Transformer"
-
-#define TRANSFORMER_FLASH_UBOOT \
-	"flash_uboot=echo Preparing RAM;" \
-		"mw ${kernel_addr_r} 0 ${boot_block_size_r};" \
-		"mw ${ramdisk_addr_r} 0 ${boot_block_size_r};" \
-		"echo Reading BCT;" \
-		"mmc dev 0 1;" \
-		"mmc read ${kernel_addr_r} 0 ${boot_block_size};" \
-		"echo Reading bootloader;" \
-		"if load mmc 1:1 ${ramdisk_addr_r} ${bootloader_file};" \
-		"then echo Calculating bootloader size;" \
-			"size mmc 1:1 ${bootloader_file};" \
-			"ebtupdate ${kernel_addr_r} ${ramdisk_addr_r} ${filesize};" \
-			"echo Writing bootloader to eMMC;" \
-			"mmc dev 0 1;" \
-			"mmc write ${kernel_addr_r} 0 ${boot_block_size};" \
-			"mmc dev 0 2;" \
-			"mmc write ${ramdisk_addr_r} 0 ${boot_block_size};" \
-			"echo Bootloader written successfully;" \
-			"pause 'Press ANY key to reboot device...'; reset;" \
-		"else echo Reading bootloader failed;" \
-			"pause 'Press ANY key to return to bootmenu...'; bootmenu; fi\0"
-
-#define TRANSFORMER_FLASH_SPI \
-	"update_spi=sf probe 0:1;" \
-		"echo Dumping current SPI flash content ...;" \
-		"sf read ${kernel_addr_r} 0x0 ${spi_size};" \
-		"if fatwrite mmc 1:1 ${kernel_addr_r} spi-flash-backup.bin ${spi_size};" \
-		"then echo SPI flash content was successfully written into spi-flash-backup.bin;" \
-			"echo Reading SPI flash binary;" \
-			"if load mmc 1:1 ${kernel_addr_r} repart-block.bin;" \
-			"then echo Writing bootloader into SPI flash;" \
-				"sf probe 0:1;" \
-				"sf update ${kernel_addr_r} 0x0 ${spi_size};" \
-				"poweroff;" \
-			"else echo Preparing RAM;" \
-				"mw ${kernel_addr_r} 0 ${boot_block_size_r};" \
-				"mw ${ramdisk_addr_r} 0 ${boot_block_size_r};" \
-				"echo Reading BCT;" \
-				"sf read ${kernel_addr_r} 0x0 ${boot_block_size_r};" \
-				"echo Reading bootloader;" \
-				"if load mmc 1:1 ${ramdisk_addr_r} ${bootloader_file};" \
-				"then echo Calculating bootloader size;" \
-					"size mmc 1:1 ${bootloader_file};" \
-					"ebtupdate ${kernel_addr_r} ${ramdisk_addr_r} ${filesize};" \
-					"echo Writing bootloader into SPI flash;" \
-					"sf probe 0:1;" \
-					"sf update ${kernel_addr_r} 0x0 ${boot_block_size_r};" \
-					"sf update ${ramdisk_addr_r} ${boot_block_size_r} ${boot_block_size_r};" \
-					"echo Bootloader written successfully; poweroff;" \
-				"else echo Reading bootloader failed;" \
-					"poweroff; fi;" \
-			"fi;" \
-		"else echo SPI flash backup FAILED! Aborting ...;" \
-			"poweroff; fi\0"
-
-#define TRANSFORMER_BOOTMENU \
-	TRANSFORMER_FLASH_UBOOT \
-	TRANSFORMER_FLASH_SPI \
-	"bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu\0" \
-	"bootmenu_1=mount external storage=usb start && ums 0 mmc 1; bootmenu\0" \
-	"bootmenu_2=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu\0" \
-	"bootmenu_3=update bootloader=run flash_uboot\0" \
-	"bootmenu_4=reboot RCM=enterrcm\0" \
-	"bootmenu_5=reboot=reset\0" \
-	"bootmenu_6=power off=poweroff\0" \
-	"bootmenu_delay=-1\0"
-
-#define BOARD_EXTRA_ENV_SETTINGS \
-	"spi_size=0x400000\0" \
-	"boot_block_size_r=0x200000\0" \
-	"boot_block_size=0x1000\0" \
-	"bootloader_file=u-boot-dtb-tegra.bin\0" \
-	"button_cmd_0_name=Volume Down\0" \
-	"button_cmd_0=bootmenu\0" \
-	"button_cmd_1_name=Lid sensor\0" \
-	"button_cmd_1=poweroff\0" \
-	"partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}\0" \
-	TRANSFORMER_BOOTMENU
-
-#endif /* __CONFIG_H */
diff --git a/include/configs/transformer-t20.h b/include/configs/transformer-t20.h
index ca1e70c..6a3d9b2 100644
--- a/include/configs/transformer-t20.h
+++ b/include/configs/transformer-t20.h
@@ -11,7 +11,9 @@
 #define __CONFIG_H
 
 #include "tegra20-common.h"
-#include "transformer-common.h"
+
+/* High-level configuration options */
+#define CFG_TEGRA_BOARD_STRING		"ASUS Transformer"
 
 /* Board-specific serial config */
 #define CFG_SYS_NS16550_COM1		NV_PA_APB_UARTD_BASE
diff --git a/include/configs/transformer-t30.h b/include/configs/transformer-t30.h
index d2a16f12..792b958 100644
--- a/include/configs/transformer-t30.h
+++ b/include/configs/transformer-t30.h
@@ -10,10 +10,10 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
-#include <linux/sizes.h>
-
 #include "tegra30-common.h"
-#include "transformer-common.h"
+
+/* High-level configuration options */
+#define CFG_TEGRA_BOARD_STRING		"ASUS Transformer"
 
 /* Board-specific serial config */
 #define CFG_SYS_NS16550_COM1		NV_PA_APB_UARTA_BASE
diff --git a/include/configs/x3-t30.h b/include/configs/x3-t30.h
index 78a2012..c152af9 100644
--- a/include/configs/x3-t30.h
+++ b/include/configs/x3-t30.h
@@ -10,55 +10,11 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
-#include <linux/sizes.h>
-
 #include "tegra30-common.h"
 
 /* High-level configuration options */
 #define CFG_TEGRA_BOARD_STRING		"LG X3 Board"
 
-#define X3_FLASH_UBOOT \
-	"flash_uboot=echo Preparing RAM;" \
-		"mw ${kernel_addr_r} 0 ${boot_block_size_r};" \
-		"mw ${ramdisk_addr_r} 0 ${boot_block_size_r};" \
-		"echo Reading BCT;" \
-		"mmc dev 0 1;" \
-		"mmc read ${kernel_addr_r} 0 ${boot_block_size};" \
-		"echo Reading bootloader;" \
-		"if load mmc 0:1 ${ramdisk_addr_r} ${bootloader_file};" \
-		"then echo Calculating bootloader size;" \
-			"size mmc 0:1 ${bootloader_file};" \
-			"ebtupdate ${kernel_addr_r} ${ramdisk_addr_r} ${filesize};" \
-			"echo Writing bootloader to eMMC;" \
-			"mmc dev 0 1;" \
-			"mmc write ${kernel_addr_r} 0 ${boot_block_size};" \
-			"mmc dev 0 2;" \
-			"mmc write ${ramdisk_addr_r} 0 ${boot_block_size};" \
-			"echo Bootloader written successfully;" \
-			"pause 'Press ANY key to reboot device...'; reset;" \
-		"else echo Reading bootloader failed;" \
-			"pause 'Press ANY key to return to bootmenu...'; bootmenu; fi\0"
-
-#define X3_BOOTMENU \
-	X3_FLASH_UBOOT \
-	"bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu\0" \
-	"bootmenu_1=mount external storage=usb start && ums 0 mmc 1; bootmenu\0" \
-	"bootmenu_2=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu\0" \
-	"bootmenu_3=update bootloader=run flash_uboot\0" \
-	"bootmenu_4=reboot RCM=enterrcm\0" \
-	"bootmenu_5=reboot=reset\0" \
-	"bootmenu_6=power off=poweroff\0" \
-	"bootmenu_delay=-1\0"
-
-#define BOARD_EXTRA_ENV_SETTINGS \
-	"boot_block_size_r=0x200000\0" \
-	"boot_block_size=0x1000\0" \
-	"bootloader_file=u-boot-dtb-tegra.bin\0" \
-	"button_cmd_0_name=Volume Down\0" \
-	"button_cmd_0=bootmenu\0" \
-	"partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}\0" \
-	X3_BOOTMENU
-
 /* Board-specific serial config */
 #define CFG_SYS_NS16550_COM1		NV_PA_APB_UARTD_BASE
 
diff --git a/include/env/nvidia/prod_upd.env b/include/env/nvidia/prod_upd.env
new file mode 100644
index 0000000..f4e3819
--- /dev/null
+++ b/include/env/nvidia/prod_upd.env
@@ -0,0 +1,60 @@
+boot_block_size_r=0x200000
+boot_block_size=0x1000
+bootloader_file=u-boot-dtb-tegra.bin
+spi_size=0x400000
+boot_dev=0
+
+flash_uboot=echo Preparing RAM;
+	mw ${kernel_addr_r} 0 ${boot_block_size_r};
+		mw ${ramdisk_addr_r} 0 ${boot_block_size_r};
+		echo Reading BCT;
+		mmc dev 0 1;
+		mmc read ${kernel_addr_r} 0 ${boot_block_size};
+		echo Reading bootloader;
+		if load mmc ${boot_dev}:1 ${ramdisk_addr_r} ${bootloader_file};
+		then echo Calculating bootloader size;
+			size mmc ${boot_dev}:1 ${bootloader_file};
+			ebtupdate ${kernel_addr_r} ${ramdisk_addr_r} ${filesize};
+			echo Writing bootloader to eMMC;
+			mmc dev 0 1;
+			mmc write ${kernel_addr_r} 0 ${boot_block_size};
+			mmc dev 0 2;
+			mmc write ${ramdisk_addr_r} 0 ${boot_block_size};
+			echo Bootloader written successfully;
+			pause 'Press ANY key to reboot device...'; reset;
+		else echo Reading bootloader failed;
+			pause 'Press ANY key to return to bootmenu...'; bootmenu; fi
+
+update_spi=sf probe 0:1;
+	echo Dumping current SPI flash content ...;
+	sf read ${kernel_addr_r} 0x0 ${spi_size};
+	if fatwrite mmc 1:1 ${kernel_addr_r} spi-flash-backup.bin ${spi_size};
+	then echo SPI flash content was successfully written into spi-flash-backup.bin;
+		echo Reading SPI flash binary;
+		if load mmc 1:1 ${kernel_addr_r} repart-block.bin;
+		then echo Writing bootloader into SPI flash;
+			sf probe 0:1;
+			sf update ${kernel_addr_r} 0x0 ${spi_size};
+			echo Bootloader SUCCESSFULLY written into SPI flash;
+			pause 'Press ANY key to reboot...'; reset;
+		else echo Preparing RAM;
+			mw ${kernel_addr_r} 0 ${boot_block_size_r};
+			mw ${ramdisk_addr_r} 0 ${boot_block_size_r};
+			echo Reading BCT;
+			sf read ${kernel_addr_r} 0x0 ${boot_block_size_r};
+			echo Reading bootloader;
+			if load mmc 1:1 ${ramdisk_addr_r} ${bootloader_file};
+			then echo Calculating bootloader size;
+				size mmc 1:1 ${bootloader_file};
+				ebtupdate ${kernel_addr_r} ${ramdisk_addr_r} ${filesize};
+				echo Writing bootloader into SPI flash;
+				sf probe 0:1;
+				sf update ${kernel_addr_r} 0x0 ${boot_block_size_r};
+				sf update ${ramdisk_addr_r} ${boot_block_size_r} ${boot_block_size_r};
+				echo Bootloader written SUCCESSFULLY;
+				pause 'Press ANY key to reboot...'; reset;
+			else echo Reading bootloader failed;
+				pause 'Press ANY key to reboot...'; reset; fi;
+		fi;
+	else echo SPI flash backup FAILED! Aborting ...;
+		pause 'Press ANY key to reboot...'; reset; fi
diff --git a/include/spl_gpio.h b/include/spl_gpio.h
index e39ac3f..b33261a 100644
--- a/include/spl_gpio.h
+++ b/include/spl_gpio.h
@@ -59,4 +59,23 @@
  */
 int spl_gpio_input(void *regs, uint gpio);
 
+/**
+ * spl_gpio_get_value() - Get GPIO value
+ *
+ * @regs: Pointer to GPIO registers
+ * @gpio: GPIO to adjust (SoC-specific)
+ * Return: return GPIO value if OK, -ve on error
+ */
+int spl_gpio_get_value(void *regs, uint gpio);
+
+/**
+ * spl_gpio_set_value() - Set value on GPIO
+ *
+ * @regs: Pointer to GPIO registers
+ * @gpio: GPIO to adjust (SoC-specific)
+ * @value: 0 to set the output low, 1 to set it high
+ * Return: return 0 if OK, -ve on error
+ */
+int spl_gpio_set_value(void *regs, uint gpio, int value);
+
 #endif /* __SPL_GPIO_H */