diff options
-rw-r--r-- | arch/arm/dts/sun6i-a31-mixtile-loftq.dts | 17 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-sunxi/boot0.h | 21 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h | 17 | ||||
-rw-r--r-- | arch/arm/mach-sunxi/Kconfig | 99 | ||||
-rw-r--r-- | arch/arm/mach-sunxi/dram_sun50i_h616.c | 508 | ||||
-rw-r--r-- | arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c | 20 | ||||
-rw-r--r-- | configs/a64-olinuxino-emmc_defconfig | 1 | ||||
-rw-r--r-- | configs/a64-olinuxino_defconfig | 1 | ||||
-rw-r--r-- | configs/amarula_a64_relic_defconfig | 1 | ||||
-rw-r--r-- | configs/bananapi_m64_defconfig | 1 | ||||
-rw-r--r-- | configs/nanopi_a64_defconfig | 1 | ||||
-rw-r--r-- | configs/oceanic_5205_5inmfd_defconfig | 1 | ||||
-rw-r--r-- | configs/orangepi_win_defconfig | 1 | ||||
-rw-r--r-- | configs/orangepi_zero2_defconfig | 8 | ||||
-rw-r--r-- | configs/pine64_plus_defconfig | 1 | ||||
-rw-r--r-- | configs/sopine_baseboard_defconfig | 1 | ||||
-rw-r--r-- | configs/x96_mate_defconfig | 7 | ||||
-rw-r--r-- | drivers/net/sun8i_emac.c | 96 | ||||
-rw-r--r-- | drivers/video/sunxi/sunxi_dw_hdmi.c | 36 |
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 dde9bdf2f92..bd98fb3e6a6 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 = <®_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 46b7e073b59..30f5680757a 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 134679d5520..6db869c0985 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 6417aee944b..6dcbb096f74 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 454c845a001..1f9416d6eaf 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 8f508344bc1..eea4d6abec8 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 8ec9eb3e9c2..a5989fab1c6 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 16cef18beef..0b469c25d0d 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 ae44b66d109..292af6e372e 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 99dc2f7d209..d957071cb13 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 70fc257eebd..608238757ba 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 2ebca673808..6cdcf782bee 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 3b78ad7e52d..df11ad8c8fd 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 72fc419ca7e..6cb942f511a 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 f42f4e5923a..08c13b58a1e 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 a5e1478c117..d9b0eb37c54 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 38b82c3a3ec..aedb3277022 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 e800a326b81..04c3274fbe1 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 4f5d0989286..0324a050d03 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; } |