From deb77f18bf68eef3a94ae9e63498d67ee7be7151 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 10 Apr 2023 10:21:19 +0200 Subject: [PATCH] sunxi: Add TPR2 parameter for H616 DRAM driver It turns out that some H616 and related SoCs (like H313) need TPR2 parameter for proper working. Add it. Signed-off-by: Jernej Skrabec Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- .../include/asm/arch-sunxi/dram_sun50i_h616.h | 1 + arch/arm/mach-sunxi/Kconfig | 6 ++ arch/arm/mach-sunxi/dram_sun50i_h616.c | 75 +++++++++++++------ .../mach-sunxi/dram_timings/h616_ddr3_1333.c | 17 ++++- 4 files changed, 75 insertions(+), 24 deletions(-) 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 615532c6ee..6db869c098 100644 --- a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h +++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h @@ -157,6 +157,7 @@ struct dram_para { 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 fe34755f88..6be8a4de53 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -79,6 +79,12 @@ config DRAM_SUN50I_H616_TPR0 help TPR0 value from vendor DRAM settings. +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 diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 44bb15367b..1f9416d6ea 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -788,21 +788,37 @@ static void mctl_phy_ca_bit_delay_compensation(struct dram_para *para) 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; - 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); + 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); + } } } @@ -812,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) @@ -821,20 +837,28 @@ 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); for (i = 0; i < ARRAY_SIZE(phy_init); i++) @@ -890,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); @@ -898,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); @@ -1135,6 +1167,7 @@ unsigned long sunxi_dram_init(void) .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, 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 f109e92082..eea4d6abec 100644 --- a/arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c +++ b/arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c @@ -50,9 +50,20 @@ void mctl_set_timing_params(struct dram_para *para) u8 t_rdata_en = 9; /* ? */ u8 t_wr_lat = 5; /* ? */ - u8 twtp = tcl + 2 + tcwl; /* (WL + BL / 2 + tWR) / 2 */ - u8 twr2rd = trtp + 2 + tcwl; /* (WL + BL / 2 + tWTR) / 2 */ - u8 trd2wr = tcl + 3 - tcwl; /* (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, -- 2.39.5