On Mon, 10 Apr 2023 10:21:19 +0200 Jernej Skrabec <jernej.skra...@gmail.com> wrote:
Hi, > It turns out that some H616 and related SoCs (like H313) need TPR2 > parameter for proper working. Add it. > > Signed-off-by: Jernej Skrabec <jernej.skra...@gmail.com> I don't have any boards that don't use a TPR2 value of 0, so cannot test the new case, but for TPR2==0 the same values will be written into the registers as before. So: Reviewed-by: Andre Przywara <andre.przyw...@arm.com> Thanks, Andre > --- > .../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 615532c6eebb..6db869c0985b 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 fe34755f88ec..6be8a4de53fe 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 44bb15367beb..1f9416d6eaf5 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 f109e920820b..eea4d6abec81 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,