aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2023-04-14 10:50:04 -0400
committerTom Rini <trini@konsulko.com>2023-04-14 10:50:04 -0400
commit75f415b3269891984d4bc87ba411173901763613 (patch)
tree1bd76a87d0e61ac9d7012caa9f13c312fc4be772
parent9e804638bfe2693a908abf066ff66c251572afa7 (diff)
parent5fc892e83f34a0b082ff46d3cc411d6813c1f726 (diff)
downloadu-boot-75f415b3269891984d4bc87ba411173901763613.zip
u-boot-75f415b3269891984d4bc87ba411173901763613.tar.gz
u-boot-75f415b3269891984d4bc87ba411173901763613.tar.bz2
Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-sunxi
The biggest change is some refactoring of the H616 DRAM driver, which allows better fine-tuning for each board, and is the base for pending LPDDR3 and LPDDR4 support, needed by new boards. The sun8i-emac Ethernet driver sees some refactoring that enables it for the Allwinner D1 EMAC IP. The sunxi HDMI driver is now using more DT properties. Also the early SPL code now supports some odd H616 SoC variant. There are some more patches pending, that require the final review touches and some testing, I will send a separate PR for them later. The gitlab CI completed successfully, and I boot tested a few boards with different SoCs, via FEL and SD card, into Linux.
-rw-r--r--arch/arm/dts/sun6i-a31-mixtile-loftq.dts17
-rw-r--r--arch/arm/include/asm/arch-sunxi/boot0.h21
-rw-r--r--arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h17
-rw-r--r--arch/arm/mach-sunxi/Kconfig99
-rw-r--r--arch/arm/mach-sunxi/dram_sun50i_h616.c508
-rw-r--r--arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c20
-rw-r--r--configs/a64-olinuxino-emmc_defconfig1
-rw-r--r--configs/a64-olinuxino_defconfig1
-rw-r--r--configs/amarula_a64_relic_defconfig1
-rw-r--r--configs/bananapi_m64_defconfig1
-rw-r--r--configs/nanopi_a64_defconfig1
-rw-r--r--configs/oceanic_5205_5inmfd_defconfig1
-rw-r--r--configs/orangepi_win_defconfig1
-rw-r--r--configs/orangepi_zero2_defconfig8
-rw-r--r--configs/pine64_plus_defconfig1
-rw-r--r--configs/sopine_baseboard_defconfig1
-rw-r--r--configs/x96_mate_defconfig7
-rw-r--r--drivers/net/sun8i_emac.c96
-rw-r--r--drivers/video/sunxi/sunxi_dw_hdmi.c36
19 files changed, 564 insertions, 274 deletions
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 @@ check_member(sunxi_mctl_ctl_reg, unk_0x4240, 0x4240);
#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 @@ struct dram_para {
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 @@ config DRAM_SUN50I_H616
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 @@ config SUNXI_SRAM_ADDRESS
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_ZQ
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 @@ static const u8 phy_init[] = {
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 @@ static bool mctl_phy_write_leveling(struct dram_para *para)
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 @@ static bool mctl_phy_write_leveling(struct dram_para *para)
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 @@ static bool mctl_phy_read_training(struct dram_para *para)
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 @@ static bool mctl_phy_read_training(struct dram_para *para)
}
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 @@ static bool mctl_phy_read_training(struct dram_para *para)
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 @@ static bool mctl_phy_read_training(struct dram_para *para)
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 @@ static bool mctl_phy_write_training(struct dram_para *para)
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 @@ static bool mctl_phy_write_training(struct dram_para *para)
}
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 @@ static bool mctl_phy_write_training(struct dram_para *para)
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 @@ static bool mctl_phy_write_training(struct dram_para *para)
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;
- }
- 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 + 0x604);
+ for (i = 0; i < 9; i++) {
+ writel_relaxed(val, ptr);
+ writel_relaxed(val, ptr + 0x30);
+ ptr += 2;
+ }
- 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 & 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(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();
+ 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;
+ }
- setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
+ if (para->tpr10 & BIT(30))
+ val = (para->odt_en << 1) & 0x1e;
+ else
+ val = (para->tpr12 >> 15) & 0x1e;
- return true;
+ 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);
+ }
+}
+
+static void mctl_phy_ca_bit_delay_compensation(struct dram_para *para)
+{
+ u32 val, *ptr;
+ int i;
+
+ if (para->tpr0 & BIT(30))
+ val = (para->tpr0 >> 7) & 0x3e;
+ else
+ val = (para->tpr10 >> 3) & 0x1e;
+
+ 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 @@ static bool mctl_phy_init(struct dram_para *para)
(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 @@ static bool mctl_phy_init(struct dram_para *para)
val = 3;
clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x3c, 0xf, val);
- 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);
+ if (para->tpr2 & 0x100) {
+ val = 9;
+ val2 = 7;
+ } else {
+ val = 13;
+ val2 = 9;
+ }
+
+ 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 @@ static bool mctl_phy_init(struct dram_para *para)
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 @@ static bool mctl_phy_init(struct dram_para *para)
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 @@ static bool mctl_phy_init(struct dram_para *para)
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 @@ static bool mctl_phy_init(struct dram_para *para)
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 @@ static bool mctl_phy_init(struct dram_para *para)
}
}
- 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 @@ static bool mctl_phy_init(struct dram_para *para)
}
}
- 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 @@ static bool mctl_phy_init(struct dram_para *para)
}
}
- 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 @@ static bool mctl_phy_init(struct dram_para *para)
}
}
- 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 @@ static bool mctl_ctrl_init(struct dram_para *para)
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 @@ unsigned long sunxi_dram_init(void)
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 @@ void mctl_set_timing_params(struct dram_para *para)
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 @@ void mctl_set_timing_params(struct dram_para *para)
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_ARCH_SUNXI=y
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_ARCH_SUNXI=y
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_ARCH_SUNXI=y
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_ARCH_SUNXI=y
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_ARCH_SUNXI=y
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_ARCH_SUNXI=y
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_ARCH_SUNXI=y
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_ARM=y
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_ARCH_SUNXI=y
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_ARCH_SUNXI=y
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_ARCH_SUNXI=y
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 @@ struct emac_eth_dev {
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 @@ static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata,
{
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 @@ static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata,
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 @@ static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata,
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 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
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 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
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 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
__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 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
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 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
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 @@ static int sunxi_dw_hdmi_probe(struct udevice *dev)
(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 @@ static int sunxi_dw_hdmi_probe(struct udevice *dev)
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);
- /* Clock on */
- setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
+ ret = reset_deassert_bulk(&priv->resets);
+ if (ret)
+ return ret;
+
+ ret = clk_enable_bulk(&priv->clocks);
+ if (ret)
+ return ret;
sunxi_dw_hdmi_phy_init(&priv->hdmi);
@@ -362,6 +373,7 @@ static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
{
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 @@ static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
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;
}