sunxi: Add TPR2 parameter for H616 DRAM driver
authorJernej Skrabec <jernej.skrabec@gmail.com>
Mon, 10 Apr 2023 08:21:19 +0000 (10:21 +0200)
committerAndre Przywara <andre.przywara@arm.com>
Tue, 11 Apr 2023 23:17:22 +0000 (00:17 +0100)
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.skrabec@gmail.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
arch/arm/mach-sunxi/Kconfig
arch/arm/mach-sunxi/dram_sun50i_h616.c
arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c

index 615532c..6db869c 100644 (file)
@@ -157,6 +157,7 @@ struct dram_para {
        u32 ca_dri;
        u32 odt_en;
        u32 tpr0;
+       u32 tpr2;
        u32 tpr10;
        u32 tpr11;
        u32 tpr12;
index fe34755..6be8a4d 100644 (file)
@@ -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
index 44bb153..1f9416d 100644 (file)
@@ -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,
index f109e92..eea4d6a 100644 (file)
@@ -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,