Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-marvell

- mvebu: Boot support for 4K Native disks (Pali)
- a38x: Perform DDR training sequence again for 2nd boot (Tony)
diff --git a/arch/arm/dts/sun6i-a31-mixtile-loftq.dts b/arch/arm/dts/sun6i-a31-mixtile-loftq.dts
index dde9bdf..bd98fb3 100644
--- a/arch/arm/dts/sun6i-a31-mixtile-loftq.dts
+++ b/arch/arm/dts/sun6i-a31-mixtile-loftq.dts
@@ -6,6 +6,9 @@
  */
 
 /dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+
 #include "sun6i-a31.dtsi"
 
 / {
@@ -19,6 +22,15 @@
 	chosen {
 		stdout-path = "serial0:115200n8";
 	};
+
+	reg_usb1_vbus: usb1-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb1-vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		enable-active-high;
+		gpio = <&pio 7 24 GPIO_ACTIVE_HIGH>; /* PH24 */
+	};
 };
 
 &ehci0 {
@@ -56,3 +68,8 @@
 	pinctrl-0 = <&uart0_ph_pins>;
 	status = "okay";
 };
+
+&usbphy {
+	usb1_vbus-supply = <&reg_usb1_vbus>;
+	status = "okay";
+};
diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h b/arch/arm/include/asm/arch-sunxi/boot0.h
index 46b7e07..30f5680 100644
--- a/arch/arm/include/asm/arch-sunxi/boot0.h
+++ b/arch/arm/include/asm/arch-sunxi/boot0.h
@@ -16,8 +16,8 @@
 	b       reset
 	.space  0x7c
 
-	.word	0xe28f0058	// add     r0, pc, #88
-	.word	0xe59f1054	// ldr     r1, [pc, #84]
+	.word	0xe28f0070	// add     r0, pc, #112	 // @(fel_stash - .)
+	.word	0xe59f106c	// ldr     r1, [pc, #108] // fel_stash - .
 	.word	0xe0800001	// add     r0, r0, r1
 	.word	0xe580d000	// str     sp, [r0]
 	.word	0xe580e004	// str     lr, [r0, #4]
@@ -28,8 +28,12 @@
 	.word	0xee1cef10	// mrc     15, 0, lr, cr12, cr0, {0}
 	.word	0xe580e010	// str     lr, [r0, #16]
 
-	.word	0xe59f1024	// ldr     r1, [pc, #36] ; 0x170000a0
-	.word	0xe59f0024	// ldr     r0, [pc, #36] ; CONFIG_*_TEXT_BASE
+	.word	0xe59f1034	// ldr     r1, [pc, #52] ; RVBAR_ADDRESS
+	.word	0xe59f0034	// ldr     r0, [pc, #52] ; SUNXI_SRAMC_BASE
+	.word	0xe5900024	// ldr     r0, [r0, #36] ; SRAM_VER_REG
+	.word	0xe21000ff	// ands    r0, r0, #255    ; 0xff
+	.word	0x159f102c	// ldrne   r1, [pc, #44] ; RVBAR_ALTERNATIVE
+	.word	0xe59f002c	// ldr     r0, [pc, #44] ; CONFIG_*TEXT_BASE
 	.word	0xe5810000	// str     r0, [r1]
 	.word	0xf57ff04f	// dsb     sy
 	.word	0xf57ff06f	// isb     sy
@@ -39,11 +43,10 @@
 	.word	0xf57ff06f	// isb     sy
 	.word	0xe320f003	// wfi
 	.word	0xeafffffd	// b       @wfi
-#ifndef CONFIG_SUN50I_GEN_H6
-	.word	0x017000a0	// writeable RVBAR mapping address
-#else
-	.word	0x09010040	// writeable RVBAR mapping address
-#endif
+
+	.word	CONFIG_SUNXI_RVBAR_ADDRESS	// writable RVBAR mapping addr
+	.word	SUNXI_SRAMC_BASE
+	.word	CONFIG_SUNXI_RVBAR_ALTERNATIVE	// address for die variant
 #ifdef CONFIG_SPL_BUILD
 	.word	CONFIG_SPL_TEXT_BASE
 #else
diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
index 134679d..6db869c 100644
--- a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
+++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
@@ -137,6 +137,14 @@
 #define MSTR_ACTIVE_RANKS(x)	(((x == 2) ? 3 : 1) << 24)
 #define MSTR_BURST_LENGTH(x)	(((x) >> 1) << 16)
 
+#define TPR10_CA_BIT_DELAY	BIT(16)
+#define TPR10_DX_BIT_DELAY0	BIT(17)
+#define TPR10_DX_BIT_DELAY1	BIT(18)
+#define TPR10_WRITE_LEVELING	BIT(20)
+#define TPR10_READ_CALIBRATION	BIT(21)
+#define TPR10_READ_TRAINING	BIT(22)
+#define TPR10_WRITE_TRAINING	BIT(23)
+
 struct dram_para {
 	u32 clk;
 	enum sunxi_dram_type type;
@@ -144,6 +152,15 @@
 	u8 rows;
 	u8 ranks;
 	u8 bus_full_width;
+	u32 dx_odt;
+	u32 dx_dri;
+	u32 ca_dri;
+	u32 odt_en;
+	u32 tpr0;
+	u32 tpr2;
+	u32 tpr10;
+	u32 tpr11;
+	u32 tpr12;
 };
 
 
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 6417aee..6dcbb09 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -52,37 +52,56 @@
 	  like H616.
 
 if DRAM_SUN50I_H616
-config DRAM_SUN50I_H616_WRITE_LEVELING
-	bool "H616 DRAM write leveling"
-	---help---
-	  Select this when DRAM on your H616 board needs write leveling.
+config DRAM_SUN50I_H616_DX_ODT
+	hex "H616 DRAM DX ODT parameter"
+	help
+	  DX ODT value from vendor DRAM settings.
 
-config DRAM_SUN50I_H616_READ_CALIBRATION
-	bool "H616 DRAM read calibration"
-	---help---
-	  Select this when DRAM on your H616 board needs read calibration.
+config DRAM_SUN50I_H616_DX_DRI
+	hex "H616 DRAM DX DRI parameter"
+	help
+	  DX DRI value from vendor DRAM settings.
 
-config DRAM_SUN50I_H616_READ_TRAINING
-	bool "H616 DRAM read training"
-	---help---
-	  Select this when DRAM on your H616 board needs read training.
+config DRAM_SUN50I_H616_CA_DRI
+	hex "H616 DRAM CA DRI parameter"
+	help
+	  CA DRI value from vendor DRAM settings.
 
-config DRAM_SUN50I_H616_WRITE_TRAINING
-	bool "H616 DRAM write training"
-	---help---
-	  Select this when DRAM on your H616 board needs write training.
+config DRAM_SUN50I_H616_ODT_EN
+	hex "H616 DRAM ODT EN parameter"
+	default 0x1
+	help
+	  ODT EN value from vendor DRAM settings.
 
-config DRAM_SUN50I_H616_BIT_DELAY_COMPENSATION
-	bool "H616 DRAM bit delay compensation"
-	---help---
-	  Select this when DRAM on your H616 board needs bit delay
-	  compensation.
+config DRAM_SUN50I_H616_TPR0
+	hex "H616 DRAM TPR0 parameter"
+	default 0x0
+	help
+	  TPR0 value from vendor DRAM settings.
 
-config DRAM_SUN50I_H616_UNKNOWN_FEATURE
-	bool "H616 DRAM unknown feature"
-	---help---
-	  Select this when DRAM on your H616 board needs this unknown
-	  feature.
+config DRAM_SUN50I_H616_TPR2
+	hex "H616 DRAM TPR2 parameter"
+	default 0x0
+	help
+	  TPR2 value from vendor DRAM settings.
+
+config DRAM_SUN50I_H616_TPR10
+	hex "H616 DRAM TPR10 parameter"
+	help
+	  TPR10 value from vendor DRAM settings. It tells which features
+	  should be configured, like write leveling, read calibration, etc.
+
+config DRAM_SUN50I_H616_TPR11
+	hex "H616 DRAM TPR11 parameter"
+	default 0x0
+	help
+	  TPR11 value from vendor DRAM settings.
+
+config DRAM_SUN50I_H616_TPR12
+	hex "H616 DRAM TPR12 parameter"
+	default 0x0
+	help
+	  TPR12 value from vendor DRAM settings.
 endif
 
 config SUN6I_PRCM
@@ -110,6 +129,32 @@
 	Some newer SoCs map the boot ROM at address 0 instead and move the
 	SRAM to a different address.
 
+config SUNXI_RVBAR_ADDRESS
+	hex
+	depends on ARM64
+	default 0x09010040 if SUN50I_GEN_H6
+	default 0x017000a0
+	---help---
+	The read-only RVBAR system register holds the address of the first
+	instruction to execute after a reset. Allwinner cores provide a
+	writable MMIO backing store for this register, to allow to set the
+	entry point when switching to AArch64. This store is on different
+	addresses, depending on the SoC.
+
+config SUNXI_RVBAR_ALTERNATIVE
+	hex
+	depends on ARM64
+	default 0x08100040 if MACH_SUN50I_H616
+	default SUNXI_RVBAR_ADDRESS
+	---help---
+	The H616 die exists in at least two variants, with one having the
+	RVBAR registers at a different address. If the SoC variant ID
+	(stored in SRAM_VER_REG[7:0]) is not 0, we need to use the
+	other address.
+	Set this alternative address to the same as the normal address
+	for all other SoCs, so the content of the SRAM_VER_REG becomes
+	irrelevant there, and we can use the same code.
+
 config SUNXI_A64_TIMER_ERRATUM
 	bool
 
@@ -499,12 +544,12 @@
 
 config DRAM_ODT_EN
 	bool "sunxi dram odt enable"
+	depends on !MACH_SUN50I_H616
 	default y if MACH_SUN8I_A23
 	default y if MACH_SUNXI_H3_H5
 	default y if MACH_SUN8I_R40
 	default y if MACH_SUN50I
 	default y if MACH_SUN50I_H6
-	default y if MACH_SUN50I_H616
 	---help---
 	Select this to enable dram odt (on die termination).
 
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c
index 454c845..1f9416d 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h616.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c
@@ -234,37 +234,49 @@
 	0x09, 0x05, 0x18
 };
 
-static void mctl_phy_configure_odt(void)
+static void mctl_phy_configure_odt(struct dram_para *para)
 {
-	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x388);
-	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x38c);
+	unsigned int val;
 
-	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x3c8);
-	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x3cc);
+	val = para->dx_dri & 0x1f;
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x388);
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x38c);
 
-	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x408);
-	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x40c);
+	val = (para->dx_dri >> 8) & 0x1f;
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x3c8);
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x3cc);
 
-	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x448);
-	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x44c);
+	val = (para->dx_dri >> 16) & 0x1f;
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x408);
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x40c);
 
-	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x340);
-	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x344);
+	val = (para->dx_dri >> 24) & 0x1f;
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x448);
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x44c);
 
-	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x348);
-	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x34c);
+	val = para->ca_dri & 0x1f;
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x340);
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x344);
 
-	writel_relaxed(0x8, SUNXI_DRAM_PHY0_BASE + 0x380);
-	writel_relaxed(0x8, SUNXI_DRAM_PHY0_BASE + 0x384);
+	val = (para->ca_dri >> 8) & 0x1f;
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x348);
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x34c);
 
-	writel_relaxed(0x8, SUNXI_DRAM_PHY0_BASE + 0x3c0);
-	writel_relaxed(0x8, SUNXI_DRAM_PHY0_BASE + 0x3c4);
+	val = para->dx_odt & 0x1f;
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x380);
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x384);
 
-	writel_relaxed(0x8, SUNXI_DRAM_PHY0_BASE + 0x400);
-	writel_relaxed(0x8, SUNXI_DRAM_PHY0_BASE + 0x404);
+	val = (para->dx_odt >> 8) & 0x1f;
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x3c0);
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x3c4);
 
-	writel_relaxed(0x8, SUNXI_DRAM_PHY0_BASE + 0x440);
-	writel_relaxed(0x8, SUNXI_DRAM_PHY0_BASE + 0x444);
+	val = (para->dx_odt >> 16) & 0x1f;
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x400);
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x404);
+
+	val = (para->dx_odt >> 24) & 0x1f;
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x440);
+	writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x444);
 
 	dmb();
 }
@@ -285,7 +297,7 @@
 	else
 		val = 3;
 
-	mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
+	mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
 
 	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
 
@@ -314,7 +326,7 @@
 		else
 			val = 3;
 
-		mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
+		mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
 
 		clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
 	}
@@ -398,26 +410,26 @@
 	setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 6);
 	setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 1);
 
-	mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
+	mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
 	if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
 		result = false;
 
 	if (para->bus_full_width) {
-		mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
+		mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
 		if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
 			result = false;
 	}
 
-	ptr1 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x898);
-	ptr2 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x850);
+	ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x898);
+	ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x850);
 	for (i = 0; i < 9; i++) {
 		val1 = readl(&ptr1[i]);
 		val2 = readl(&ptr2[i]);
 		if (val1 - val2 <= 6)
 			result = false;
 	}
-	ptr1 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x8bc);
-	ptr2 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x874);
+	ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8bc);
+	ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x874);
 	for (i = 0; i < 9; i++) {
 		val1 = readl(&ptr1[i]);
 		val2 = readl(&ptr2[i]);
@@ -426,8 +438,8 @@
 	}
 
 	if (para->bus_full_width) {
-		ptr1 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xa98);
-		ptr2 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xa50);
+		ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa98);
+		ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa50);
 		for (i = 0; i < 9; i++) {
 			val1 = readl(&ptr1[i]);
 			val2 = readl(&ptr2[i]);
@@ -435,8 +447,8 @@
 				result = false;
 		}
 
-		ptr1 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xabc);
-		ptr2 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xa74);
+		ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xabc);
+		ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa74);
 		for (i = 0; i < 9; i++) {
 			val1 = readl(&ptr1[i]);
 			val2 = readl(&ptr2[i]);
@@ -454,12 +466,12 @@
 		setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 6);
 		setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 1);
 
-		mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
+		mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
 		if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
 			result = false;
 
 		if (para->bus_full_width) {
-			mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
+			mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
 			if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
 				result = false;
 		}
@@ -488,26 +500,26 @@
 	setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
 	setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x20);
 
-	mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
+	mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
 	if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
 		result = false;
 
 	if (para->bus_full_width) {
-		mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
+		mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
 		if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
 			result = false;
 	}
 
-	ptr1 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x938);
-	ptr2 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x8f0);
+	ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x938);
+	ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8f0);
 	for (i = 0; i < 9; i++) {
 		val1 = readl(&ptr1[i]);
 		val2 = readl(&ptr2[i]);
 		if (val1 - val2 <= 6)
 			result = false;
 	}
-	ptr1 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x95c);
-	ptr2 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x914);
+	ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x95c);
+	ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x914);
 	for (i = 0; i < 9; i++) {
 		val1 = readl(&ptr1[i]);
 		val2 = readl(&ptr2[i]);
@@ -516,16 +528,16 @@
 	}
 
 	if (para->bus_full_width) {
-		ptr1 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xb38);
-		ptr2 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xaf0);
+		ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb38);
+		ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xaf0);
 		for (i = 0; i < 9; i++) {
 			val1 = readl(&ptr1[i]);
 			val2 = readl(&ptr2[i]);
 			if (val1 - val2 <= 6)
 				result = false;
 		}
-		ptr1 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xb5c);
-		ptr2 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xb14);
+		ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb5c);
+		ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb14);
 		for (i = 0; i < 9; i++) {
 			val1 = readl(&ptr1[i]);
 			val2 = readl(&ptr2[i]);
@@ -542,12 +554,12 @@
 		setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
 		setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x20);
 
-		mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
+		mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
 		if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
 			result = false;
 
 		if (para->bus_full_width) {
-			mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
+			mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
 			if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
 				result = false;
 		}
@@ -560,116 +572,254 @@
 	return result;
 }
 
-static bool mctl_phy_bit_delay_compensation(struct dram_para *para)
+static void mctl_phy_bit_delay_compensation(struct dram_para *para)
 {
-	u32 *ptr;
+	u32 *ptr, val;
 	int i;
 
-	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
-	setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 8);
-	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
+	if (para->tpr10 & TPR10_DX_BIT_DELAY1) {
+		clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
+		setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 8);
+		clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
 
-	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x484);
-	for (i = 0; i < 9; i++) {
-		writel_relaxed(0x16, ptr);
-		writel_relaxed(0x16, ptr + 0x30);
-		ptr += 2;
-	}
-	writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x4d0);
-	writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x590);
-	writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x4cc);
-	writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x58c);
+		if (para->tpr10 & BIT(30))
+			val = para->tpr11 & 0x3f;
+		else
+			val = (para->tpr11 & 0xf) << 1;
 
-	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x4d8);
-	for (i = 0; i < 9; i++) {
-		writel_relaxed(0x1a, ptr);
-		writel_relaxed(0x1a, ptr + 0x30);
-		ptr += 2;
-	}
-	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x524);
-	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x5e4);
-	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x520);
-	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x5e0);
+		ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x484);
+		for (i = 0; i < 9; i++) {
+			writel_relaxed(val, ptr);
+			writel_relaxed(val, ptr + 0x30);
+			ptr += 2;
+		}
 
-	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x604);
-	for (i = 0; i < 9; i++) {
-		writel_relaxed(0x1a, ptr);
-		writel_relaxed(0x1a, ptr + 0x30);
-		ptr += 2;
-	}
-	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x650);
-	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x710);
-	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x64c);
-	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x70c);
+		if (para->tpr10 & BIT(30))
+			val = (para->odt_en >> 15) & 0x1e;
+		else
+			val = (para->tpr11 >> 15) & 0x1e;
 
-	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x658);
-	for (i = 0; i < 9; i++) {
-		writel_relaxed(0x1a, ptr);
-		writel_relaxed(0x1a, ptr + 0x30);
-		ptr += 2;
-	}
-	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x6a4);
-	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x764);
-	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x6a0);
-	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x760);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4d0);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x590);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4cc);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x58c);
 
-	dmb();
+		if (para->tpr10 & BIT(30))
+			val = (para->tpr11 >> 8) & 0x3f;
+		else
+			val = (para->tpr11 >> 3) & 0x1e;
 
-	setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
+		ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d8);
+		for (i = 0; i < 9; i++) {
+			writel_relaxed(val, ptr);
+			writel_relaxed(val, ptr + 0x30);
+			ptr += 2;
+		}
 
-	/* second part */
-	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
-	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
+		if (para->tpr10 & BIT(30))
+			val = (para->odt_en >> 19) & 0x1e;
+		else
+			val = (para->tpr11 >> 19) & 0x1e;
 
-	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x480);
-	for (i = 0; i < 9; i++) {
-		writel_relaxed(0x10, ptr);
-		writel_relaxed(0x10, ptr + 0x30);
-		ptr += 2;
-	}
-	writel_relaxed(0x18, SUNXI_DRAM_PHY0_BASE + 0x528);
-	writel_relaxed(0x18, SUNXI_DRAM_PHY0_BASE + 0x5e8);
-	writel_relaxed(0x18, SUNXI_DRAM_PHY0_BASE + 0x4c8);
-	writel_relaxed(0x18, SUNXI_DRAM_PHY0_BASE + 0x588);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x524);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e4);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x520);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e0);
 
-	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x4d4);
-	for (i = 0; i < 9; i++) {
-		writel_relaxed(0x12, ptr);
-		writel_relaxed(0x12, ptr + 0x30);
-		ptr += 2;
-	}
-	writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x52c);
-	writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x5ec);
-	writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x51c);
-	writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x5dc);
+		if (para->tpr10 & BIT(30))
+			val = (para->tpr11 >> 16) & 0x3f;
+		else
+			val = (para->tpr11 >> 7) & 0x1e;
 
-	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x600);
-	for (i = 0; i < 9; i++) {
-		writel_relaxed(0x12, ptr);
-		writel_relaxed(0x12, ptr + 0x30);
-		ptr += 2;
+		ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x604);
+		for (i = 0; i < 9; i++) {
+			writel_relaxed(val, ptr);
+			writel_relaxed(val, ptr + 0x30);
+			ptr += 2;
+		}
+
+		if (para->tpr10 & BIT(30))
+			val = (para->odt_en >> 23) & 0x1e;
+		else
+			val = (para->tpr11 >> 23) & 0x1e;
+
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x650);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x710);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x64c);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x70c);
+
+		if (para->tpr10 & BIT(30))
+			val = (para->tpr11 >> 24) & 0x3f;
+		else
+			val = (para->tpr11 >> 11) & 0x1e;
+
+		ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x658);
+		for (i = 0; i < 9; i++) {
+			writel_relaxed(val, ptr);
+			writel_relaxed(val, ptr + 0x30);
+			ptr += 2;
+		}
+
+		if (para->tpr10 & BIT(30))
+			val = (para->odt_en >> 27) & 0x1e;
+		else
+			val = (para->tpr11 >> 27) & 0x1e;
+
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a4);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x764);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a0);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x760);
+
+		dmb();
+
+		setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
 	}
-	writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x6a8);
-	writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x768);
-	writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x648);
-	writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x708);
 
-	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x654);
-	for (i = 0; i < 9; i++) {
-		writel_relaxed(0x14, ptr);
-		writel_relaxed(0x14, ptr + 0x30);
-		ptr += 2;
+	if (para->tpr10 & TPR10_DX_BIT_DELAY0) {
+		clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
+		clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
+
+		if (para->tpr10 & BIT(30))
+			val = para->tpr12 & 0x3f;
+		else
+			val = (para->tpr12 & 0xf) << 1;
+
+		ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x480);
+		for (i = 0; i < 9; i++) {
+			writel_relaxed(val, ptr);
+			writel_relaxed(val, ptr + 0x30);
+			ptr += 2;
+		}
+
+		if (para->tpr10 & BIT(30))
+			val = (para->odt_en << 1) & 0x1e;
+		else
+			val = (para->tpr12 >> 15) & 0x1e;
+
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x528);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e8);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4c8);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x588);
+
+		if (para->tpr10 & BIT(30))
+			val = (para->tpr12 >> 8) & 0x3f;
+		else
+			val = (para->tpr12 >> 3) & 0x1e;
+
+		ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d4);
+		for (i = 0; i < 9; i++) {
+			writel_relaxed(val, ptr);
+			writel_relaxed(val, ptr + 0x30);
+			ptr += 2;
+		}
+
+		if (para->tpr10 & BIT(30))
+			val = (para->odt_en >> 3) & 0x1e;
+		else
+			val = (para->tpr12 >> 19) & 0x1e;
+
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x52c);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5ec);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x51c);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5dc);
+
+		if (para->tpr10 & BIT(30))
+			val = (para->tpr12 >> 16) & 0x3f;
+		else
+			val = (para->tpr12 >> 7) & 0x1e;
+
+		ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x600);
+		for (i = 0; i < 9; i++) {
+			writel_relaxed(val, ptr);
+			writel_relaxed(val, ptr + 0x30);
+			ptr += 2;
+		}
+
+		if (para->tpr10 & BIT(30))
+			val = (para->odt_en >> 7) & 0x1e;
+		else
+			val = (para->tpr12 >> 23) & 0x1e;
+
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a8);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x768);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x648);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x708);
+
+		if (para->tpr10 & BIT(30))
+			val = (para->tpr12 >> 24) & 0x3f;
+		else
+			val = (para->tpr12 >> 11) & 0x1e;
+
+		ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x654);
+		for (i = 0; i < 9; i++) {
+			writel_relaxed(val, ptr);
+			writel_relaxed(val, ptr + 0x30);
+			ptr += 2;
+		}
+
+		if (para->tpr10 & BIT(30))
+			val = (para->odt_en >> 11) & 0x1e;
+		else
+			val = (para->tpr12 >> 27) & 0x1e;
+
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6ac);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x76c);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x69c);
+		writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x75c);
+
+		dmb();
+
+		setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
 	}
-	writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x6ac);
-	writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x76c);
-	writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x69c);
-	writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x75c);
+}
 
-	dmb();
+static void mctl_phy_ca_bit_delay_compensation(struct dram_para *para)
+{
+	u32 val, *ptr;
+	int i;
 
-	setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
+	if (para->tpr0 & BIT(30))
+		val = (para->tpr0 >> 7) & 0x3e;
+	else
+		val = (para->tpr10 >> 3) & 0x1e;
 
-	return true;
+	ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x780);
+	for (i = 0; i < 32; i++)
+		writel(val, &ptr[i]);
+
+	val = (para->tpr10 << 1) & 0x1e;
+	writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d8);
+	writel(val, SUNXI_DRAM_PHY0_BASE + 0x7dc);
+	writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e0);
+	writel(val, SUNXI_DRAM_PHY0_BASE + 0x7f4);
+
+	/* following configuration is DDR3 specific */
+	val = (para->tpr10 >> 7) & 0x1e;
+	if (para->tpr2 & 1) {
+		writel(val, SUNXI_DRAM_PHY0_BASE + 0x794);
+		if (para->ranks == 2) {
+			val = (para->tpr10 >> 11) & 0x1e;
+			writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e4);
+		}
+		if (para->tpr0 & BIT(31)) {
+			val = (para->tpr0 << 1) & 0x3e;
+			writel(val, SUNXI_DRAM_PHY0_BASE + 0x790);
+			writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8);
+			writel(val, SUNXI_DRAM_PHY0_BASE + 0x7cc);
+		}
+	} else {
+		writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d4);
+		if (para->ranks == 2) {
+			val = (para->tpr10 >> 11) & 0x1e;
+			writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c);
+		}
+		if (para->tpr0 & BIT(31)) {
+			val = (para->tpr0 << 1) & 0x3e;
+			writel(val, SUNXI_DRAM_PHY0_BASE + 0x78c);
+			writel(val, SUNXI_DRAM_PHY0_BASE + 0x7a4);
+			writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8);
+		}
+	}
 }
 
 static bool mctl_phy_init(struct dram_para *para)
@@ -678,7 +828,7 @@
 			(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
 	struct sunxi_mctl_ctl_reg * const mctl_ctl =
 			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
-	u32 val, *ptr;
+	u32 val, val2, *ptr, mr0, mr2;
 	int i;
 
 	if (para->bus_full_width)
@@ -687,42 +837,40 @@
 		val = 3;
 	clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x3c, 0xf, val);
 
+	if (para->tpr2 & 0x100) {
+		val = 9;
+		val2 = 7;
+	} else {
+		val = 13;
+		val2 = 9;
+	}
+
-	writel(0xd, SUNXI_DRAM_PHY0_BASE + 0x14);
-	writel(0xd, SUNXI_DRAM_PHY0_BASE + 0x35c);
-	writel(0xd, SUNXI_DRAM_PHY0_BASE + 0x368);
-	writel(0xd, SUNXI_DRAM_PHY0_BASE + 0x374);
+	writel(val, SUNXI_DRAM_PHY0_BASE + 0x14);
+	writel(val, SUNXI_DRAM_PHY0_BASE + 0x35c);
+	writel(val, SUNXI_DRAM_PHY0_BASE + 0x368);
+	writel(val, SUNXI_DRAM_PHY0_BASE + 0x374);
 
 	writel(0, SUNXI_DRAM_PHY0_BASE + 0x18);
 	writel(0, SUNXI_DRAM_PHY0_BASE + 0x360);
 	writel(0, SUNXI_DRAM_PHY0_BASE + 0x36c);
 	writel(0, SUNXI_DRAM_PHY0_BASE + 0x378);
 
-	writel(9, SUNXI_DRAM_PHY0_BASE + 0x1c);
-	writel(9, SUNXI_DRAM_PHY0_BASE + 0x364);
-	writel(9, SUNXI_DRAM_PHY0_BASE + 0x370);
-	writel(9, SUNXI_DRAM_PHY0_BASE + 0x37c);
+	writel(val2, SUNXI_DRAM_PHY0_BASE + 0x1c);
+	writel(val2, SUNXI_DRAM_PHY0_BASE + 0x364);
+	writel(val2, SUNXI_DRAM_PHY0_BASE + 0x370);
+	writel(val2, SUNXI_DRAM_PHY0_BASE + 0x37c);
 
-	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xc0);
+	ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xc0);
 	for (i = 0; i < ARRAY_SIZE(phy_init); i++)
 		writel(phy_init[i], &ptr[i]);
 
-	if (IS_ENABLED(CONFIG_DRAM_SUN50I_H616_UNKNOWN_FEATURE)) {
-		ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x780);
-		for (i = 0; i < 32; i++)
-			writel(0x16, &ptr[i]);
-		writel(0xe, SUNXI_DRAM_PHY0_BASE + 0x78c);
-		writel(0xe, SUNXI_DRAM_PHY0_BASE + 0x7a4);
-		writel(0xe, SUNXI_DRAM_PHY0_BASE + 0x7b8);
-		writel(0x8, SUNXI_DRAM_PHY0_BASE + 0x7d4);
-		writel(0xe, SUNXI_DRAM_PHY0_BASE + 0x7dc);
-		writel(0xe, SUNXI_DRAM_PHY0_BASE + 0x7e0);
-	}
+	if (para->tpr10 & TPR10_CA_BIT_DELAY)
+		mctl_phy_ca_bit_delay_compensation(para);
 
 	writel(0x80, SUNXI_DRAM_PHY0_BASE + 0x3dc);
 	writel(0x80, SUNXI_DRAM_PHY0_BASE + 0x45c);
 
-	if (IS_ENABLED(CONFIG_DRAM_ODT_EN))
-		mctl_phy_configure_odt();
+	mctl_phy_configure_odt(para);
 
 	clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 7, 0xa);
 
@@ -738,7 +886,7 @@
 
 	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 8);
 
-	mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0x180), 4, 4);
+	mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x180), 4, 4);
 
 	writel(0x37, SUNXI_DRAM_PHY0_BASE + 0x58);
 	clrbits_le32(&mctl_com->unk_0x500, 0x200);
@@ -766,7 +914,15 @@
 	writel(1, &mctl_ctl->swctl);
 	mctl_await_completion(&mctl_ctl->swstat, 1, 1);
 
-	writel(0x1f14, &mctl_ctl->mrctrl1);
+	if (para->tpr2 & 0x100) {
+		mr0 = 0x1b50;
+		mr2 = 0x10;
+	} else {
+		mr0 = 0x1f14;
+		mr2 = 0x20;
+	}
+
+	writel(mr0, &mctl_ctl->mrctrl1);
 	writel(0x80000030, &mctl_ctl->mrctrl0);
 	mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
 
@@ -774,7 +930,7 @@
 	writel(0x80001030, &mctl_ctl->mrctrl0);
 	mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
 
-	writel(0x20, &mctl_ctl->mrctrl1);
+	writel(mr2, &mctl_ctl->mrctrl1);
 	writel(0x80002030, &mctl_ctl->mrctrl0);
 	mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
 
@@ -788,7 +944,7 @@
 	clrbits_le32(&mctl_ctl->rfshctl3, 1);
 	writel(1, &mctl_ctl->swctl);
 
-	if (IS_ENABLED(CONFIG_DRAM_SUN50I_H616_WRITE_LEVELING)) {
+	if (para->tpr10 & TPR10_WRITE_LEVELING) {
 		for (i = 0; i < 5; i++)
 			if (mctl_phy_write_leveling(para))
 				break;
@@ -798,7 +954,7 @@
 		}
 	}
 
-	if (IS_ENABLED(CONFIG_DRAM_SUN50I_H616_READ_CALIBRATION)) {
+	if (para->tpr10 & TPR10_READ_CALIBRATION) {
 		for (i = 0; i < 5; i++)
 			if (mctl_phy_read_calibration(para))
 				break;
@@ -808,7 +964,7 @@
 		}
 	}
 
-	if (IS_ENABLED(CONFIG_DRAM_SUN50I_H616_READ_TRAINING)) {
+	if (para->tpr10 & TPR10_READ_TRAINING) {
 		for (i = 0; i < 5; i++)
 			if (mctl_phy_read_training(para))
 				break;
@@ -818,7 +974,7 @@
 		}
 	}
 
-	if (IS_ENABLED(CONFIG_DRAM_SUN50I_H616_WRITE_TRAINING)) {
+	if (para->tpr10 & TPR10_WRITE_TRAINING) {
 		for (i = 0; i < 5; i++)
 			if (mctl_phy_write_training(para))
 				break;
@@ -828,8 +984,7 @@
 		}
 	}
 
-	if (IS_ENABLED(CONFIG_DRAM_SUN50I_H616_BIT_DELAY_COMPENSATION))
-		mctl_phy_bit_delay_compensation(para);
+	mctl_phy_bit_delay_compensation(para);
 
 	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 4);
 
@@ -873,7 +1028,7 @@
 	writel(0x06000400, &mctl_ctl->unk_0x3240);
 	writel(0x06000400, &mctl_ctl->unk_0x4240);
 
-	setbits_le32(&mctl_com->cr, BIT(31));
+	writel(BIT(31), &mctl_com->cr);
 
 	mctl_set_addrmap(para);
 
@@ -1007,6 +1162,15 @@
 	struct dram_para para = {
 		.clk = CONFIG_DRAM_CLK,
 		.type = SUNXI_DRAM_TYPE_DDR3,
+		.dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT,
+		.dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI,
+		.ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI,
+		.odt_en = CONFIG_DRAM_SUN50I_H616_ODT_EN,
+		.tpr0 = CONFIG_DRAM_SUN50I_H616_TPR0,
+		.tpr2 = CONFIG_DRAM_SUN50I_H616_TPR2,
+		.tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10,
+		.tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11,
+		.tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12,
 	};
 	unsigned long size;
 
diff --git a/arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c b/arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c
index 8f50834..eea4d6a 100644
--- a/arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c
+++ b/arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c
@@ -48,10 +48,22 @@
 	u8 tcl		= 7;			/* JEDEC: CL / 2 => 6 */
 	u8 tcwl		= 5;			/* JEDEC: 8 */
 	u8 t_rdata_en	= 9;			/* ? */
+	u8 t_wr_lat	= 5;			/* ? */
 
-	u8 twtp		= 14;			/* (WL + BL / 2 + tWR) / 2 */
-	u8 twr2rd	= trtp + 7;		/* (WL + BL / 2 + tWTR) / 2 */
-	u8 trd2wr	= 5;			/* (RL + BL / 2 + 2 - WL) / 2 */
+	u8 twtp;				/* (WL + BL / 2 + tWR) / 2 */
+	u8 twr2rd;				/* (WL + BL / 2 + tWTR) / 2 */
+	u8 trd2wr;				/* (RL + BL / 2 + 2 - WL) / 2 */
+
+	if (para->tpr2 & 0x100) {
+		tcl = 5;
+		tcwl = 4;
+		t_rdata_en = 5;
+		t_wr_lat = 3;
+	}
+
+	twtp   = tcl + 2 + tcwl;
+	twr2rd = trtp + 2 + tcwl;
+	trd2wr = tcl + 3 - tcwl;
 
 	/* set DRAM timing */
 	writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | tras,
@@ -85,7 +97,7 @@
 	clrsetbits_le32(&mctl_ctl->rankctl, 0xff0, 0x660);
 
 	/* Configure DFI timing */
-	writel((tcl - 2) | 0x2000000 | (t_rdata_en << 16) | 0x808000,
+	writel(t_wr_lat | 0x2000000 | (t_rdata_en << 16) | 0x808000,
 	       &mctl_ctl->dfitmg0);
 	writel(0x100202, &mctl_ctl->dfitmg1);
 
diff --git a/configs/a64-olinuxino-emmc_defconfig b/configs/a64-olinuxino-emmc_defconfig
index 8ec9eb3..a5989fa 100644
--- a/configs/a64-olinuxino-emmc_defconfig
+++ b/configs/a64-olinuxino-emmc_defconfig
@@ -3,7 +3,6 @@
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-olinuxino-emmc"
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I=y
-CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SUPPORT_EMMC_BOOT=y
diff --git a/configs/a64-olinuxino_defconfig b/configs/a64-olinuxino_defconfig
index 16cef18..0b469c2 100644
--- a/configs/a64-olinuxino_defconfig
+++ b/configs/a64-olinuxino_defconfig
@@ -3,7 +3,6 @@
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-olinuxino"
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I=y
-CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SUN8I_EMAC=y
diff --git a/configs/amarula_a64_relic_defconfig b/configs/amarula_a64_relic_defconfig
index ae44b66..292af6e 100644
--- a/configs/amarula_a64_relic_defconfig
+++ b/configs/amarula_a64_relic_defconfig
@@ -3,7 +3,6 @@
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-amarula-relic"
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I=y
-CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_VIDEO_DE2 is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/bananapi_m64_defconfig b/configs/bananapi_m64_defconfig
index 99dc2f7..d957071 100644
--- a/configs/bananapi_m64_defconfig
+++ b/configs/bananapi_m64_defconfig
@@ -3,7 +3,6 @@
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-bananapi-m64"
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I=y
-CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SUPPORT_EMMC_BOOT=y
diff --git a/configs/nanopi_a64_defconfig b/configs/nanopi_a64_defconfig
index 70fc257..6082387 100644
--- a/configs/nanopi_a64_defconfig
+++ b/configs/nanopi_a64_defconfig
@@ -3,7 +3,6 @@
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-nanopi-a64"
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I=y
-CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SUN8I_EMAC=y
 CONFIG_USB_EHCI_HCD=y
diff --git a/configs/oceanic_5205_5inmfd_defconfig b/configs/oceanic_5205_5inmfd_defconfig
index 2ebca67..6cdcf78 100644
--- a/configs/oceanic_5205_5inmfd_defconfig
+++ b/configs/oceanic_5205_5inmfd_defconfig
@@ -3,7 +3,6 @@
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-oceanic-5205-5inmfd"
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I=y
-CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
 CONFIG_SUNXI_DRAM_LPDDR3_STOCK=y
 CONFIG_DRAM_CLK=552
 CONFIG_DRAM_ZQ=3881949
diff --git a/configs/orangepi_win_defconfig b/configs/orangepi_win_defconfig
index 3b78ad7..df11ad8 100644
--- a/configs/orangepi_win_defconfig
+++ b/configs/orangepi_win_defconfig
@@ -3,7 +3,6 @@
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-orangepi-win"
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I=y
-CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
 CONFIG_MACPWR="PD14"
 CONFIG_SPL_SPI_SUNXI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/orangepi_zero2_defconfig b/configs/orangepi_zero2_defconfig
index 72fc419..6cb942f 100644
--- a/configs/orangepi_zero2_defconfig
+++ b/configs/orangepi_zero2_defconfig
@@ -2,10 +2,10 @@
 CONFIG_ARCH_SUNXI=y
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-h616-orangepi-zero2"
 CONFIG_SPL=y
-CONFIG_DRAM_SUN50I_H616_WRITE_LEVELING=y
-CONFIG_DRAM_SUN50I_H616_READ_CALIBRATION=y
-CONFIG_DRAM_SUN50I_H616_READ_TRAINING=y
-CONFIG_DRAM_SUN50I_H616_WRITE_TRAINING=y
+CONFIG_DRAM_SUN50I_H616_DX_ODT=0x08080808
+CONFIG_DRAM_SUN50I_H616_DX_DRI=0x0e0e0e0e
+CONFIG_DRAM_SUN50I_H616_CA_DRI=0x0e0e
+CONFIG_DRAM_SUN50I_H616_TPR10=0xf83438
 CONFIG_MACH_SUN50I_H616=y
 CONFIG_R_I2C_ENABLE=y
 CONFIG_SPL_SPI_SUNXI=y
diff --git a/configs/pine64_plus_defconfig b/configs/pine64_plus_defconfig
index f42f4e5..08c13b5 100644
--- a/configs/pine64_plus_defconfig
+++ b/configs/pine64_plus_defconfig
@@ -3,7 +3,6 @@
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-pine64-plus"
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I=y
-CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
 CONFIG_PINE64_DT_SELECTION=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_OF_LIST="sun50i-a64-pine64 sun50i-a64-pine64-plus"
diff --git a/configs/sopine_baseboard_defconfig b/configs/sopine_baseboard_defconfig
index a5e1478..d9b0eb3 100644
--- a/configs/sopine_baseboard_defconfig
+++ b/configs/sopine_baseboard_defconfig
@@ -3,7 +3,6 @@
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-sopine-baseboard"
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I=y
-CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
 CONFIG_SUNXI_DRAM_LPDDR3_STOCK=y
 CONFIG_DRAM_CLK=552
 CONFIG_DRAM_ZQ=3881949
diff --git a/configs/x96_mate_defconfig b/configs/x96_mate_defconfig
index 38b82c3..aedb327 100644
--- a/configs/x96_mate_defconfig
+++ b/configs/x96_mate_defconfig
@@ -3,6 +3,13 @@
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-h616-x96-mate"
 CONFIG_SPL=y
 CONFIG_DRAM_SUN50I_H616_READ_CALIBRATION=y
+CONFIG_DRAM_SUN50I_H616_DX_ODT=0x03030303
+CONFIG_DRAM_SUN50I_H616_DX_DRI=0x0e0e0e0e
+CONFIG_DRAM_SUN50I_H616_CA_DRI=0x1c12
+CONFIG_DRAM_SUN50I_H616_TPR0=0xc0000c05
+CONFIG_DRAM_SUN50I_H616_TPR10=0x2f0007
+CONFIG_DRAM_SUN50I_H616_TPR11=0xffffdddd
+CONFIG_DRAM_SUN50I_H616_TPR12=0xfedf7557
 CONFIG_MACH_SUN50I_H616=y
 CONFIG_R_I2C_ENABLE=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
index e800a32..04c3274 100644
--- a/drivers/net/sun8i_emac.c
+++ b/drivers/net/sun8i_emac.c
@@ -127,12 +127,10 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-enum emac_variant {
-	A83T_EMAC = 1,
-	H3_EMAC,
-	A64_EMAC,
-	R40_GMAC,
-	H6_EMAC,
+struct emac_variant {
+	uint			syscon_offset;
+	bool			soc_has_internal_phy;
+	bool			support_rmii;
 };
 
 struct emac_dma_desc {
@@ -160,9 +158,9 @@
 	u32 tx_slot;
 	bool use_internal_phy;
 
-	enum emac_variant variant;
+	const struct emac_variant *variant;
 	void *mac_reg;
-	phys_addr_t sysctl_reg;
+	void *sysctl_reg;
 	struct phy_device *phydev;
 	struct mii_dev *bus;
 	struct clk tx_clk;
@@ -317,25 +315,12 @@
 {
 	u32 reg;
 
-	if (priv->variant == R40_GMAC) {
-		/* Select RGMII for R40 */
-		reg = readl(priv->sysctl_reg + 0x164);
-		reg |= SC_ETCS_INT_GMII |
-		       SC_EPIT |
-		       (CONFIG_GMAC_TX_DELAY << SC_ETXDC_OFFSET);
-
-		writel(reg, priv->sysctl_reg + 0x164);
-		return 0;
-	}
-
-	reg = readl(priv->sysctl_reg + 0x30);
+	reg = readl(priv->sysctl_reg);
 
 	reg = sun8i_emac_set_syscon_ephy(priv, reg);
 
 	reg &= ~(SC_ETCS_MASK | SC_EPIT);
-	if (priv->variant == H3_EMAC ||
-	    priv->variant == A64_EMAC ||
-	    priv->variant == H6_EMAC)
+	if (priv->variant->support_rmii)
 		reg &= ~SC_RMII_EN;
 
 	switch (priv->interface) {
@@ -349,13 +334,10 @@
 		reg |= SC_EPIT | SC_ETCS_INT_GMII;
 		break;
 	case PHY_INTERFACE_MODE_RMII:
-		if (priv->variant == H3_EMAC ||
-		    priv->variant == A64_EMAC ||
-		    priv->variant == H6_EMAC) {
+		if (priv->variant->support_rmii) {
 			reg |= SC_RMII_EN | SC_ETCS_EXT_GMII;
-		break;
+			break;
 		}
-		/* RMII not supported on A83T */
 	default:
 		debug("%s: Invalid PHY interface\n", __func__);
 		return -EINVAL;
@@ -369,7 +351,7 @@
 		reg |= ((pdata->rx_delay_ps / 100) << SC_ERXDC_OFFSET)
 			 & SC_ERXDC_MASK;
 
-	writel(reg, priv->sysctl_reg + 0x30);
+	writel(reg, priv->sysctl_reg);
 
 	return 0;
 }
@@ -792,6 +774,7 @@
 	struct sun8i_eth_pdata *sun8i_pdata = dev_get_plat(dev);
 	struct eth_pdata *pdata = &sun8i_pdata->eth_pdata;
 	struct emac_eth_dev *priv = dev_get_priv(dev);
+	phys_addr_t syscon_base;
 	const fdt32_t *reg;
 	int node = dev_of_offset(dev);
 	int offset = 0;
@@ -806,7 +789,7 @@
 		return -EINVAL;
 	}
 
-	priv->variant = dev_get_driver_data(dev);
+	priv->variant = (const void *)dev_get_driver_data(dev);
 
 	if (!priv->variant) {
 		printf("%s: Missing variant\n", __func__);
@@ -837,13 +820,15 @@
 		      __func__);
 		return -EINVAL;
 	}
-	priv->sysctl_reg = fdt_translate_address((void *)gd->fdt_blob,
-						 offset, reg);
-	if (priv->sysctl_reg == FDT_ADDR_T_NONE) {
+
+	syscon_base = fdt_translate_address((void *)gd->fdt_blob, offset, reg);
+	if (syscon_base == FDT_ADDR_T_NONE) {
 		debug("%s: Cannot find syscon base address\n", __func__);
 		return -EINVAL;
 	}
 
+	priv->sysctl_reg = (void *)syscon_base + priv->variant->syscon_offset;
+
 	pdata->phy_interface = -1;
 	priv->phyaddr = -1;
 	priv->use_internal_phy = false;
@@ -860,7 +845,7 @@
 	if (pdata->phy_interface == PHY_INTERFACE_MODE_NA)
 		return -EINVAL;
 
-	if (priv->variant == H3_EMAC) {
+	if (priv->variant->soc_has_internal_phy) {
 		ret = sun8i_handle_internal_phy(dev, priv);
 		if (ret)
 			return ret;
@@ -900,16 +885,41 @@
 	return 0;
 }
 
+static const struct emac_variant emac_variant_a83t = {
+	.syscon_offset		= 0x30,
+};
+
+static const struct emac_variant emac_variant_h3 = {
+	.syscon_offset		= 0x30,
+	.soc_has_internal_phy	= true,
+	.support_rmii		= true,
+};
+
+static const struct emac_variant emac_variant_r40 = {
+	.syscon_offset		= 0x164,
+};
+
+static const struct emac_variant emac_variant_a64 = {
+	.syscon_offset		= 0x30,
+	.support_rmii		= true,
+};
+
+static const struct emac_variant emac_variant_h6 = {
+	.syscon_offset		= 0x30,
+	.support_rmii		= true,
+};
+
 static const struct udevice_id sun8i_emac_eth_ids[] = {
-	{.compatible = "allwinner,sun8i-h3-emac", .data = (uintptr_t)H3_EMAC },
-	{.compatible = "allwinner,sun50i-a64-emac",
-		.data = (uintptr_t)A64_EMAC },
-	{.compatible = "allwinner,sun8i-a83t-emac",
-		.data = (uintptr_t)A83T_EMAC },
-	{.compatible = "allwinner,sun8i-r40-gmac",
-		.data = (uintptr_t)R40_GMAC },
-	{.compatible = "allwinner,sun50i-h6-emac",
-		.data = (uintptr_t)H6_EMAC },
+	{ .compatible = "allwinner,sun8i-a83t-emac",
+	  .data = (ulong)&emac_variant_a83t },
+	{ .compatible = "allwinner,sun8i-h3-emac",
+	  .data = (ulong)&emac_variant_h3 },
+	{ .compatible = "allwinner,sun8i-r40-gmac",
+	  .data = (ulong)&emac_variant_r40 },
+	{ .compatible = "allwinner,sun50i-a64-emac",
+	  .data = (ulong)&emac_variant_a64 },
+	{ .compatible = "allwinner,sun50i-h6-emac",
+	  .data = (ulong)&emac_variant_h6 },
 	{ }
 };
 
diff --git a/drivers/video/sunxi/sunxi_dw_hdmi.c b/drivers/video/sunxi/sunxi_dw_hdmi.c
index 4f5d098..0324a05 100644
--- a/drivers/video/sunxi/sunxi_dw_hdmi.c
+++ b/drivers/video/sunxi/sunxi_dw_hdmi.c
@@ -5,21 +5,27 @@
  * (C) Copyright 2017 Jernej Skrabec <jernej.skrabec@siol.net>
  */
 
+#include <clk.h>
 #include <common.h>
 #include <display.h>
 #include <dm.h>
 #include <dw_hdmi.h>
 #include <edid.h>
 #include <log.h>
+#include <reset.h>
 #include <time.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/lcdc.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
+#include <power/regulator.h>
 
 struct sunxi_dw_hdmi_priv {
 	struct dw_hdmi hdmi;
+	struct reset_ctl_bulk resets;
+	struct clk_bulk clocks;
+	struct udevice *hvcc;
 };
 
 struct sunxi_hdmi_phy {
@@ -329,6 +335,9 @@
 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 	int ret;
 
+	if (priv->hvcc)
+		regulator_set_enable(priv->hvcc, true);
+
 	/* Set pll3 to 297 MHz */
 	clock_set_pll3(297000000);
 
@@ -336,14 +345,16 @@
 	clrsetbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_PLL_MASK,
 			CCM_HDMI_CTRL_PLL3);
 
-	/* Set ahb gating to pass */
-	setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI);
+	/* This reset is referenced from the PHY devicetree node. */
 	setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI2);
-	setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI);
-	setbits_le32(&ccm->hdmi_slow_clk_cfg, CCM_HDMI_SLOW_CTRL_DDC_GATE);
+
+	ret = reset_deassert_bulk(&priv->resets);
+	if (ret)
+		return ret;
 
-	/* Clock on */
-	setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
+	ret = clk_enable_bulk(&priv->clocks);
+	if (ret)
+		return ret;
 
 	sunxi_dw_hdmi_phy_init(&priv->hdmi);
 
@@ -362,6 +373,7 @@
 {
 	struct sunxi_dw_hdmi_priv *priv = dev_get_priv(dev);
 	struct dw_hdmi *hdmi = &priv->hdmi;
+	int ret;
 
 	hdmi->ioaddr = (ulong)dev_read_addr(dev);
 	hdmi->i2c_clk_high = 0xd8;
@@ -369,6 +381,18 @@
 	hdmi->reg_io_width = 1;
 	hdmi->phy_set = sunxi_dw_hdmi_phy_cfg;
 
+	ret = reset_get_bulk(dev, &priv->resets);
+	if (ret)
+		return ret;
+
+	ret = clk_get_bulk(dev, &priv->clocks);
+	if (ret)
+		return ret;
+
+	ret = device_get_supply_regulator(dev, "hvcc-supply", &priv->hvcc);
+	if (ret)
+		priv->hvcc = NULL;
+
 	return 0;
 }