[PATCH 0/8] sunxi: Update H616 DRAM driver

Current H616 DRAM driver is completely customized to Orange Pi Zero2 board, which is currently the only H616 board supported by U-Boot. Needless to say, this is not ideal for adding new boards. With changes in this series, all DDR3 boards are supported and all that is needed is just vendor DRAM values extracted from Android image. New DRAM types should also be easier to support, since a lot of constants used before are not really DRAM type dependent.
Changes were verified by decompiling driver and generated values were compared to previous, hard coded ones. This was done without dram_para structures, so compiler was able to heavily optimize code and produce constants.
Please take a look.
Best regards, Jernej
Jernej Skrabec (8): sunxi: Fix write to H616 DRAM CR register sunxi: cosmetic: Fix H616 DRAM driver code style sunxi: parameterize H616 DRAM ODT values sunxi: Convert H616 DRAM options to single setting sunxi: Always configure ODT on H616 DRAM sunxi: Make bit delay function in H616 DRAM code void sunxi: Parameterize bit delay code in H616 DRAM driver sunxi: Parameterize H616 DRAM code some more
.../include/asm/arch-sunxi/dram_sun50i_h616.h | 18 + arch/arm/mach-sunxi/Kconfig | 67 +-- arch/arm/mach-sunxi/dram_sun50i_h616.c | 445 +++++++++++------- configs/orangepi_zero2_defconfig | 8 +- 4 files changed, 348 insertions(+), 190 deletions(-)

Vendor DRAM code actually writes to whole CR register and not just sets bit 31 in mctl_ctrl_init().
Just to be safe, do that here too.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com --- arch/arm/mach-sunxi/dram_sun50i_h616.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 454c845a0010..039e76224367 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -873,7 +873,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);

On Sun, 11 Dec 2022 17:32:06 +0100 Jernej Skrabec jernej.skrabec@gmail.com wrote:
Vendor DRAM code actually writes to whole CR register and not just sets bit 31 in mctl_ctrl_init().
Just to be safe, do that here too.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com
Can't really verify this, but it seems to work (TM):
Acked-by: Andre Przywara andre.przywara@arm.com
Cheers, Andre
arch/arm/mach-sunxi/dram_sun50i_h616.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 454c845a0010..039e76224367 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -873,7 +873,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);

Fix code style for pointer declaration. This is just cosmetic change to avoid checkpatch errors in later commits.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com --- arch/arm/mach-sunxi/dram_sun50i_h616.c | 74 +++++++++++++------------- 1 file changed, 37 insertions(+), 37 deletions(-)
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 039e76224367..49983bf7a1b8 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -285,7 +285,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 +314,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 +398,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 +426,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 +435,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 +454,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 +488,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 +516,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 +542,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; } @@ -569,7 +569,7 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 8); clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
- ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x484); + ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x484); for (i = 0; i < 9; i++) { writel_relaxed(0x16, ptr); writel_relaxed(0x16, ptr + 0x30); @@ -580,7 +580,7 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x4cc); writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x58c);
- ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x4d8); + ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d8); for (i = 0; i < 9; i++) { writel_relaxed(0x1a, ptr); writel_relaxed(0x1a, ptr + 0x30); @@ -591,7 +591,7 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x520); writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x5e0);
- ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x604); + ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x604); for (i = 0; i < 9; i++) { writel_relaxed(0x1a, ptr); writel_relaxed(0x1a, ptr + 0x30); @@ -602,7 +602,7 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x64c); writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x70c);
- ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x658); + ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x658); for (i = 0; i < 9; i++) { writel_relaxed(0x1a, ptr); writel_relaxed(0x1a, ptr + 0x30); @@ -621,7 +621,7 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80); clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
- ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x480); + ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x480); for (i = 0; i < 9; i++) { writel_relaxed(0x10, ptr); writel_relaxed(0x10, ptr + 0x30); @@ -632,7 +632,7 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) writel_relaxed(0x18, SUNXI_DRAM_PHY0_BASE + 0x4c8); writel_relaxed(0x18, SUNXI_DRAM_PHY0_BASE + 0x588);
- ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x4d4); + ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d4); for (i = 0; i < 9; i++) { writel_relaxed(0x12, ptr); writel_relaxed(0x12, ptr + 0x30); @@ -643,7 +643,7 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x51c); writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x5dc);
- ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x600); + ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x600); for (i = 0; i < 9; i++) { writel_relaxed(0x12, ptr); writel_relaxed(0x12, ptr + 0x30); @@ -654,7 +654,7 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x648); writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x708);
- ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x654); + ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x654); for (i = 0; i < 9; i++) { writel_relaxed(0x14, ptr); writel_relaxed(0x14, ptr + 0x30); @@ -702,12 +702,12 @@ static bool mctl_phy_init(struct dram_para *para) writel(9, SUNXI_DRAM_PHY0_BASE + 0x370); writel(9, 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); + ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x780); for (i = 0; i < 32; i++) writel(0x16, &ptr[i]); writel(0xe, SUNXI_DRAM_PHY0_BASE + 0x78c); @@ -738,7 +738,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);

On Sun, 11 Dec 2022 17:32:07 +0100 Jernej Skrabec jernej.skrabec@gmail.com wrote:
Hi,
Fix code style for pointer declaration. This is just cosmetic change to avoid checkpatch errors in later commits.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com
confirmed to be just s/(u32*)/(u32 *)/:
Reviewed-by: Andre Przywara andre.przywara@arm.com
Cheers, Andre
arch/arm/mach-sunxi/dram_sun50i_h616.c | 74 +++++++++++++------------- 1 file changed, 37 insertions(+), 37 deletions(-)
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 039e76224367..49983bf7a1b8 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -285,7 +285,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 +314,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 +398,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);
if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3) result = false; }mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
- 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 +426,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);
for (i = 0; i < 9; i++) { val1 = readl(&ptr1[i]); val2 = readl(&ptr2[i]);ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa50);
@@ -435,8 +435,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);
for (i = 0; i < 9; i++) { val1 = readl(&ptr1[i]); val2 = readl(&ptr2[i]);ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa74);
@@ -454,12 +454,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 +488,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);
if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc) result = false; }mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
- 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 +516,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);
for (i = 0; i < 9; i++) { val1 = readl(&ptr1[i]); val2 = readl(&ptr2[i]); if (val1 - val2 <= 6) result = false; }ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xaf0);
ptr1 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xb5c);
ptr2 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xb14);
ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb5c);
for (i = 0; i < 9; i++) { val1 = readl(&ptr1[i]); val2 = readl(&ptr2[i]);ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb14);
@@ -542,12 +542,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;
@@ -569,7 +569,7 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 8); clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
- ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x484);
- ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x484); for (i = 0; i < 9; i++) { writel_relaxed(0x16, ptr); writel_relaxed(0x16, ptr + 0x30);
@@ -580,7 +580,7 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x4cc); writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x58c);
- ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x4d8);
- ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d8); for (i = 0; i < 9; i++) { writel_relaxed(0x1a, ptr); writel_relaxed(0x1a, ptr + 0x30);
@@ -591,7 +591,7 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x520); writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x5e0);
- ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x604);
- ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x604); for (i = 0; i < 9; i++) { writel_relaxed(0x1a, ptr); writel_relaxed(0x1a, ptr + 0x30);
@@ -602,7 +602,7 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x64c); writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x70c);
- ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x658);
- ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x658); for (i = 0; i < 9; i++) { writel_relaxed(0x1a, ptr); writel_relaxed(0x1a, ptr + 0x30);
@@ -621,7 +621,7 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80); clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
- ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x480);
- ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x480); for (i = 0; i < 9; i++) { writel_relaxed(0x10, ptr); writel_relaxed(0x10, ptr + 0x30);
@@ -632,7 +632,7 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) writel_relaxed(0x18, SUNXI_DRAM_PHY0_BASE + 0x4c8); writel_relaxed(0x18, SUNXI_DRAM_PHY0_BASE + 0x588);
- ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x4d4);
- ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d4); for (i = 0; i < 9; i++) { writel_relaxed(0x12, ptr); writel_relaxed(0x12, ptr + 0x30);
@@ -643,7 +643,7 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x51c); writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x5dc);
- ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x600);
- ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x600); for (i = 0; i < 9; i++) { writel_relaxed(0x12, ptr); writel_relaxed(0x12, ptr + 0x30);
@@ -654,7 +654,7 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x648); writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x708);
- ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x654);
- ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x654); for (i = 0; i < 9; i++) { writel_relaxed(0x14, ptr); writel_relaxed(0x14, ptr + 0x30);
@@ -702,12 +702,12 @@ static bool mctl_phy_init(struct dram_para *para) writel(9, SUNXI_DRAM_PHY0_BASE + 0x370); writel(9, 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);ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x780);
@@ -738,7 +738,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);

While ODT values for same memory type are similar, they are not necessary the same. Let's parameterize them and make parameter same as in vendor DRAM settings. That way it will be easy to introduce new board support.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com --- .../include/asm/arch-sunxi/dram_sun50i_h616.h | 3 + arch/arm/mach-sunxi/Kconfig | 15 +++++ arch/arm/mach-sunxi/dram_sun50i_h616.c | 59 ++++++++++++------- configs/orangepi_zero2_defconfig | 3 + 4 files changed, 58 insertions(+), 22 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 134679d55205..c9e1f84bfcdd 100644 --- a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h +++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h @@ -144,6 +144,9 @@ struct dram_para { u8 rows; u8 ranks; u8 bus_full_width; + u32 dx_odt; + u32 dx_dri; + u32 ca_dri; };
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index dbe6005daab1..cad53f19912c 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -83,6 +83,21 @@ config DRAM_SUN50I_H616_UNKNOWN_FEATURE ---help--- Select this when DRAM on your H616 board needs this unknown feature. + +config DRAM_SUN50I_H616_DX_ODT + hex "H616 DRAM DX ODT parameter" + help + DX ODT value from vendor DRAM settings. + +config DRAM_SUN50I_H616_DX_DRI + hex "H616 DRAM DX DRI parameter" + help + DX DRI value from vendor DRAM settings. + +config DRAM_SUN50I_H616_CA_DRI + hex "H616 DRAM CA DRI parameter" + help + CA DRI value from vendor DRAM settings. endif
config SUN6I_PRCM diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 49983bf7a1b8..06a07dfbf9cc 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(); } @@ -722,7 +734,7 @@ static bool mctl_phy_init(struct dram_para *para) 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);
@@ -1007,6 +1019,9 @@ 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, }; unsigned long size;
diff --git a/configs/orangepi_zero2_defconfig b/configs/orangepi_zero2_defconfig index 877eccf31bd6..ca398faef1d3 100644 --- a/configs/orangepi_zero2_defconfig +++ b/configs/orangepi_zero2_defconfig @@ -6,6 +6,9 @@ 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=0x8080808 +CONFIG_DRAM_SUN50I_H616_DX_DRI=0xe0e0e0e +CONFIG_DRAM_SUN50I_H616_CA_DRI=0xe0e CONFIG_MACH_SUN50I_H616=y CONFIG_MMC0_CD_PIN="PF6" CONFIG_R_I2C_ENABLE=y

On Sun, 11 Dec 2022 17:32:08 +0100 Jernej Skrabec jernej.skrabec@gmail.com wrote:
Hi Jernej,
While ODT values for same memory type are similar, they are not necessary the same. Let's parameterize them and make parameter same as in vendor DRAM settings. That way it will be easy to introduce new board support.
checked that this results in the same parameters to writel(). One small thing below:
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com
.../include/asm/arch-sunxi/dram_sun50i_h616.h | 3 + arch/arm/mach-sunxi/Kconfig | 15 +++++ arch/arm/mach-sunxi/dram_sun50i_h616.c | 59 ++++++++++++------- configs/orangepi_zero2_defconfig | 3 + 4 files changed, 58 insertions(+), 22 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 134679d55205..c9e1f84bfcdd 100644 --- a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h +++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h @@ -144,6 +144,9 @@ struct dram_para { u8 rows; u8 ranks; u8 bus_full_width;
- u32 dx_odt;
- u32 dx_dri;
- u32 ca_dri;
};
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index dbe6005daab1..cad53f19912c 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -83,6 +83,21 @@ config DRAM_SUN50I_H616_UNKNOWN_FEATURE ---help--- Select this when DRAM on your H616 board needs this unknown feature.
+config DRAM_SUN50I_H616_DX_ODT
- hex "H616 DRAM DX ODT parameter"
- help
DX ODT value from vendor DRAM settings.
+config DRAM_SUN50I_H616_DX_DRI
- hex "H616 DRAM DX DRI parameter"
- help
DX DRI value from vendor DRAM settings.
+config DRAM_SUN50I_H616_CA_DRI
- hex "H616 DRAM CA DRI parameter"
- help
CA DRI value from vendor DRAM settings.
endif
config SUN6I_PRCM diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 49983bf7a1b8..06a07dfbf9cc 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();
} @@ -722,7 +734,7 @@ static bool mctl_phy_init(struct dram_para *para) 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);
@@ -1007,6 +1019,9 @@ 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,
}; unsigned long size;.ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI,
diff --git a/configs/orangepi_zero2_defconfig b/configs/orangepi_zero2_defconfig index 877eccf31bd6..ca398faef1d3 100644 --- a/configs/orangepi_zero2_defconfig +++ b/configs/orangepi_zero2_defconfig @@ -6,6 +6,9 @@ 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=0x8080808 +CONFIG_DRAM_SUN50I_H616_DX_DRI=0xe0e0e0e +CONFIG_DRAM_SUN50I_H616_CA_DRI=0xe0e
Can you make those values 8 nibbles and 4 nibbles long (so starting with a 0)? It's somewhat confusing to read like this, it *looks* like a 32-bit value, but it's actually only 28 bits wide. This gets confusing when matching up values against dumps or a hex editor.
With that fixed: Reviewed-by: Andre Przywara andre.przywara@arm.com
Cheers, Andre
CONFIG_MACH_SUN50I_H616=y CONFIG_MMC0_CD_PIN="PF6" CONFIG_R_I2C_ENABLE=y

Vendor DRAM settings use TPR10 parameter to enable various features. There are many mores features that just those that are currently mentioned. Since new will be added later and most are not known, let's reuse value from vendor DRAM driver as-is. This will also help adding support for new boards.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com --- .../include/asm/arch-sunxi/dram_sun50i_h616.h | 10 + arch/arm/mach-sunxi/Kconfig | 38 +--- arch/arm/mach-sunxi/dram_sun50i_h616.c | 197 +++++++++--------- configs/orangepi_zero2_defconfig | 5 +- 4 files changed, 117 insertions(+), 133 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 c9e1f84bfcdd..b5140c79b70e 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,15 @@ 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)
+/* TODO: figure out what unknown features do */ +#define TPR10_UNKNOWN_FEAT0 BIT(16) +#define TPR10_UNKNOWN_FEAT1 BIT(17) +#define TPR10_UNKNOWN_FEAT2 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; @@ -147,6 +156,7 @@ struct dram_para { u32 dx_odt; u32 dx_dri; u32 ca_dri; + u32 tpr10; };
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index cad53f19912c..abcbd0fb9061 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -52,38 +52,6 @@ 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_READ_CALIBRATION - bool "H616 DRAM read calibration" - ---help--- - Select this when DRAM on your H616 board needs read calibration. - -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_WRITE_TRAINING - bool "H616 DRAM write training" - ---help--- - Select this when DRAM on your H616 board needs write training. - -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_UNKNOWN_FEATURE - bool "H616 DRAM unknown feature" - ---help--- - Select this when DRAM on your H616 board needs this unknown - feature. - config DRAM_SUN50I_H616_DX_ODT hex "H616 DRAM DX ODT parameter" help @@ -98,6 +66,12 @@ config DRAM_SUN50I_H616_CA_DRI hex "H616 DRAM CA DRI parameter" help CA DRI 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. endif
config SUN6I_PRCM diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 06a07dfbf9cc..14a01a3c4e54 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -577,109 +577,112 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) u32 *ptr; 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_UNKNOWN_FEAT2) { + 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); + 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);
- 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 + 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 + 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); + 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);
- 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); + 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);
- dmb(); + dmb();
- setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1); + setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1); + }
- /* second part */ - clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80); - clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4); + if (para->tpr10 & TPR10_UNKNOWN_FEAT1) { + clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80); + clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
- 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); + 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);
- 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); + 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);
- 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 + 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 + 0x654); - for (i = 0; i < 9; i++) { - writel_relaxed(0x14, ptr); - writel_relaxed(0x14, ptr + 0x30); - ptr += 2; - } - 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); + ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x654); + for (i = 0; i < 9; i++) { + writel_relaxed(0x14, ptr); + writel_relaxed(0x14, ptr + 0x30); + ptr += 2; + } + 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(); + dmb();
- setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80); + setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80); + }
return true; } @@ -718,7 +721,7 @@ static bool mctl_phy_init(struct dram_para *para) for (i = 0; i < ARRAY_SIZE(phy_init); i++) writel(phy_init[i], &ptr[i]);
- if (IS_ENABLED(CONFIG_DRAM_SUN50I_H616_UNKNOWN_FEATURE)) { + if (para->tpr10 & TPR10_UNKNOWN_FEAT0) { ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x780); for (i = 0; i < 32; i++) writel(0x16, &ptr[i]); @@ -800,7 +803,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; @@ -810,7 +813,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; @@ -820,7 +823,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; @@ -830,7 +833,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; @@ -840,8 +843,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);
@@ -1022,6 +1024,7 @@ unsigned long sunxi_dram_init(void) .dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT, .dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI, .ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI, + .tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10, }; unsigned long size;
diff --git a/configs/orangepi_zero2_defconfig b/configs/orangepi_zero2_defconfig index ca398faef1d3..f2024a2502c7 100644 --- a/configs/orangepi_zero2_defconfig +++ b/configs/orangepi_zero2_defconfig @@ -2,13 +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=0x8080808 CONFIG_DRAM_SUN50I_H616_DX_DRI=0xe0e0e0e CONFIG_DRAM_SUN50I_H616_CA_DRI=0xe0e +CONFIG_DRAM_SUN50I_H616_TPR10=0xf83438 CONFIG_MACH_SUN50I_H616=y CONFIG_MMC0_CD_PIN="PF6" CONFIG_R_I2C_ENABLE=y

On Sun, 11 Dec 2022 17:32:09 +0100 Jernej Skrabec jernej.skrabec@gmail.com wrote:
Hi,
Vendor DRAM settings use TPR10 parameter to enable various features. There are many mores features that just those that are currently mentioned. Since new will be added later and most are not known, let's reuse value from vendor DRAM driver as-is. This will also help adding support for new boards.
Looks good. I checked that the actual code in mctl_phy_bit_delay_compensation() just gets indented (no real changes), and is now guarded by the new checks. The values in the _defconfig still result in the same decisions, though many are blocked anyway by no one actually calling that bit_delay function at all. (I wonder what happens when we enable it?) One small thing below.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com
.../include/asm/arch-sunxi/dram_sun50i_h616.h | 10 + arch/arm/mach-sunxi/Kconfig | 38 +--- arch/arm/mach-sunxi/dram_sun50i_h616.c | 197 +++++++++--------- configs/orangepi_zero2_defconfig | 5 +- 4 files changed, 117 insertions(+), 133 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 c9e1f84bfcdd..b5140c79b70e 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,15 @@ 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)
+/* TODO: figure out what unknown features do */ +#define TPR10_UNKNOWN_FEAT0 BIT(16) +#define TPR10_UNKNOWN_FEAT1 BIT(17) +#define TPR10_UNKNOWN_FEAT2 BIT(18)
Could you just put the bit number in the macro? Like TPR10_BIT16? That both avoids inventing meaningless names, and helps readers to correlate code more easily. Or skip the symbol altogether for those and use just "BIT(16)" in the code.
Cheers, Andre
+#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; @@ -147,6 +156,7 @@ struct dram_para { u32 dx_odt; u32 dx_dri; u32 ca_dri;
- u32 tpr10;
};
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index cad53f19912c..abcbd0fb9061 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -52,38 +52,6 @@ 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_READ_CALIBRATION
- bool "H616 DRAM read calibration"
- ---help---
Select this when DRAM on your H616 board needs read calibration.
-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_WRITE_TRAINING
- bool "H616 DRAM write training"
- ---help---
Select this when DRAM on your H616 board needs write training.
-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_UNKNOWN_FEATURE
- bool "H616 DRAM unknown feature"
- ---help---
Select this when DRAM on your H616 board needs this unknown
feature.
config DRAM_SUN50I_H616_DX_ODT hex "H616 DRAM DX ODT parameter" help @@ -98,6 +66,12 @@ config DRAM_SUN50I_H616_CA_DRI hex "H616 DRAM CA DRI parameter" help CA DRI 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.
endif
config SUN6I_PRCM diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 06a07dfbf9cc..14a01a3c4e54 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -577,109 +577,112 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para) u32 *ptr; 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_UNKNOWN_FEAT2) {
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);
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);
- 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 + 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 + 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);
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);
- 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);
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);
- dmb();
dmb();
- setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
- }
- /* second part */
- clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
- clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
- if (para->tpr10 & TPR10_UNKNOWN_FEAT1) {
clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
- 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);
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);
- 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);
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);
- 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 + 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 + 0x654);
- for (i = 0; i < 9; i++) {
writel_relaxed(0x14, ptr);
writel_relaxed(0x14, ptr + 0x30);
ptr += 2;
- }
- 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);
ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x654);
for (i = 0; i < 9; i++) {
writel_relaxed(0x14, ptr);
writel_relaxed(0x14, ptr + 0x30);
ptr += 2;
}
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();
dmb();
- setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
}
return true;
} @@ -718,7 +721,7 @@ static bool mctl_phy_init(struct dram_para *para) for (i = 0; i < ARRAY_SIZE(phy_init); i++) writel(phy_init[i], &ptr[i]);
- if (IS_ENABLED(CONFIG_DRAM_SUN50I_H616_UNKNOWN_FEATURE)) {
- if (para->tpr10 & TPR10_UNKNOWN_FEAT0) { ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x780); for (i = 0; i < 32; i++) writel(0x16, &ptr[i]);
@@ -800,7 +803,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;
@@ -810,7 +813,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++)
B> if (mctl_phy_read_calibration(para))
break;
@@ -820,7 +823,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;
@@ -830,7 +833,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;
@@ -840,8 +843,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);
@@ -1022,6 +1024,7 @@ unsigned long sunxi_dram_init(void) .dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT, .dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI, .ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI,
}; unsigned long size;.tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10,
diff --git a/configs/orangepi_zero2_defconfig b/configs/orangepi_zero2_defconfig index ca398faef1d3..f2024a2502c7 100644 --- a/configs/orangepi_zero2_defconfig +++ b/configs/orangepi_zero2_defconfig @@ -2,13 +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=0x8080808 CONFIG_DRAM_SUN50I_H616_DX_DRI=0xe0e0e0e CONFIG_DRAM_SUN50I_H616_CA_DRI=0xe0e +CONFIG_DRAM_SUN50I_H616_TPR10=0xf83438 CONFIG_MACH_SUN50I_H616=y CONFIG_MMC0_CD_PIN="PF6" CONFIG_R_I2C_ENABLE=y

Hi,
Dne ponedeljek, 12. december 2022 ob 18:50:44 CET je Andre Przywara napisal(a):
On Sun, 11 Dec 2022 17:32:09 +0100 Jernej Skrabec jernej.skrabec@gmail.com wrote:
Hi,
Vendor DRAM settings use TPR10 parameter to enable various features. There are many mores features that just those that are currently mentioned. Since new will be added later and most are not known, let's reuse value from vendor DRAM driver as-is. This will also help adding support for new boards.
Looks good. I checked that the actual code in mctl_phy_bit_delay_compensation() just gets indented (no real changes), and is now guarded by the new checks. The values in the _defconfig still result in the same decisions, though many are blocked anyway by no one actually calling that bit_delay function at all. (I wonder what happens when we enable it?)
I'm not sure I understand. Bit delay compensation should be enabled for X96 Mate, according to values you send in previous e-mail. In any case, DRAM configuration looks like a black magic at times, so I would rather stick to vendor procedure, especially due to missing register documentation, and not just randomly enable things which sounds nice. I tried enabling unused procedures for T95 and either they didn't went through or amount of detected RAM was lower than presetn.
One small thing below.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com
.../include/asm/arch-sunxi/dram_sun50i_h616.h | 10 + arch/arm/mach-sunxi/Kconfig | 38 +--- arch/arm/mach-sunxi/dram_sun50i_h616.c | 197 +++++++++--------- configs/orangepi_zero2_defconfig | 5 +- 4 files changed, 117 insertions(+), 133 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 c9e1f84bfcdd..b5140c79b70e 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,15 @@ 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)
+/* TODO: figure out what unknown features do */ +#define TPR10_UNKNOWN_FEAT0 BIT(16) +#define TPR10_UNKNOWN_FEAT1 BIT(17) +#define TPR10_UNKNOWN_FEAT2 BIT(18)
Could you just put the bit number in the macro? Like TPR10_BIT16? That both avoids inventing meaningless names, and helps readers to correlate code more easily. Or skip the symbol altogether for those and use just "BIT(16)" in the code.
I actually know what these are for now, so I can give much better names. However, I still don't know what TPR10_UNKNOWN_FEAT3 does, which is in the last commit, so I'll rework that one to use BIT(30) directly.
Best regards, Jernej
Cheers, Andre
+#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;
@@ -147,6 +156,7 @@ struct dram_para {
u32 dx_odt; u32 dx_dri; u32 ca_dri;
- u32 tpr10;
};
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index cad53f19912c..abcbd0fb9061 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -52,38 +52,6 @@ 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_READ_CALIBRATION
- bool "H616 DRAM read calibration"
- ---help---
Select this when DRAM on your H616 board needs read
calibration.
-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_WRITE_TRAINING
- bool "H616 DRAM write training"
- ---help---
Select this when DRAM on your H616 board needs write training.
-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_UNKNOWN_FEATURE
- bool "H616 DRAM unknown feature"
- ---help---
Select this when DRAM on your H616 board needs this unknown
feature.
config DRAM_SUN50I_H616_DX_ODT
hex "H616 DRAM DX ODT parameter" help
@@ -98,6 +66,12 @@ config DRAM_SUN50I_H616_CA_DRI
hex "H616 DRAM CA DRI parameter" help
CA DRI 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.
endif
config SUN6I_PRCM
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 06a07dfbf9cc..14a01a3c4e54 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -577,109 +577,112 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para)> u32 *ptr; 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_UNKNOWN_FEAT2) {
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);
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);
- 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 + 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 + 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);
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);
- 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);
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);
- dmb();
dmb();
- setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
- }
- /* second part */
- clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
- clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
- if (para->tpr10 & TPR10_UNKNOWN_FEAT1) {
clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
- 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);
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);
- 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);
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);
- 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 + 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 + 0x654);
- for (i = 0; i < 9; i++) {
writel_relaxed(0x14, ptr);
writel_relaxed(0x14, ptr + 0x30);
ptr += 2;
- }
- 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);
ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x654);
for (i = 0; i < 9; i++) {
writel_relaxed(0x14, ptr);
writel_relaxed(0x14, ptr + 0x30);
ptr += 2;
}
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();
dmb();
- setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
}
return true;
}
@@ -718,7 +721,7 @@ static bool mctl_phy_init(struct dram_para *para)
for (i = 0; i < ARRAY_SIZE(phy_init); i++)
writel(phy_init[i], &ptr[i]);
- if (IS_ENABLED(CONFIG_DRAM_SUN50I_H616_UNKNOWN_FEATURE)) {
if (para->tpr10 & TPR10_UNKNOWN_FEAT0) {
ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x780); for (i = 0; i < 32; i++)
writel(0x16, &ptr[i]);
@@ -800,7 +803,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;
@@ -810,7 +813,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++)
B> if (mctl_phy_read_calibration(para))
break;
@@ -820,7 +823,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;
@@ -830,7 +833,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;
@@ -840,8 +843,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);
@@ -1022,6 +1024,7 @@ unsigned long sunxi_dram_init(void)
.dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT, .dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI, .ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI,
.tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10,
}; unsigned long size;
diff --git a/configs/orangepi_zero2_defconfig b/configs/orangepi_zero2_defconfig index ca398faef1d3..f2024a2502c7 100644 --- a/configs/orangepi_zero2_defconfig +++ b/configs/orangepi_zero2_defconfig @@ -2,13 +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=0x8080808 CONFIG_DRAM_SUN50I_H616_DX_DRI=0xe0e0e0e CONFIG_DRAM_SUN50I_H616_CA_DRI=0xe0e
+CONFIG_DRAM_SUN50I_H616_TPR10=0xf83438
CONFIG_MACH_SUN50I_H616=y CONFIG_MMC0_CD_PIN="PF6" CONFIG_R_I2C_ENABLE=y

On Tue, 13 Dec 2022 17:23:12 +0100 Jernej Škrabec jernej.skrabec@gmail.com wrote:
Hi,
Dne ponedeljek, 12. december 2022 ob 18:50:44 CET je Andre Przywara napisal(a):
On Sun, 11 Dec 2022 17:32:09 +0100 Jernej Skrabec jernej.skrabec@gmail.com wrote:
Hi,
Vendor DRAM settings use TPR10 parameter to enable various features. There are many mores features that just those that are currently mentioned. Since new will be added later and most are not known, let's reuse value from vendor DRAM driver as-is. This will also help adding support for new boards.
Looks good. I checked that the actual code in mctl_phy_bit_delay_compensation() just gets indented (no real changes), and is now guarded by the new checks. The values in the _defconfig still result in the same decisions, though many are blocked anyway by no one actually calling that bit_delay function at all. (I wonder what happens when we enable it?)
I'm not sure I understand. Bit delay compensation should be enabled for X96 Mate, according to values you send in previous e-mail.
But DRAM_SUN50I_H616_BIT_DELAY_COMPENSATION is not set by any (of the two) defconfigs atm, and I don't see this in your t95 (WIP?) branch on github either. So that whole code was completely unused (until now).
In any case, DRAM configuration looks like a black magic at times, so I would rather stick to vendor procedure, especially due to missing register documentation, and not just randomly enable things which sounds nice. I tried enabling unused procedures for T95 and either they didn't went through or amount of detected RAM was lower than presetn.
Sure, I was just confused that we have some elaborate code, with values backed by the vendor BSP, but then don't use that. But if it gets used now, it's all fine, I guess.
One small thing below.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com
.../include/asm/arch-sunxi/dram_sun50i_h616.h | 10 + arch/arm/mach-sunxi/Kconfig | 38 +--- arch/arm/mach-sunxi/dram_sun50i_h616.c | 197 +++++++++--------- configs/orangepi_zero2_defconfig | 5 +- 4 files changed, 117 insertions(+), 133 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 c9e1f84bfcdd..b5140c79b70e 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,15 @@ 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)
+/* TODO: figure out what unknown features do */ +#define TPR10_UNKNOWN_FEAT0 BIT(16) +#define TPR10_UNKNOWN_FEAT1 BIT(17) +#define TPR10_UNKNOWN_FEAT2 BIT(18)
Could you just put the bit number in the macro? Like TPR10_BIT16? That both avoids inventing meaningless names, and helps readers to correlate code more easily. Or skip the symbol altogether for those and use just "BIT(16)" in the code.
I actually know what these are for now, so I can give much better names. However, I still don't know what TPR10_UNKNOWN_FEAT3 does, which is in the last commit, so I'll rework that one to use BIT(30) directly.
Great, thanks!
Cheers, Andre
Best regards, Jernej
Cheers, Andre
+#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;
@@ -147,6 +156,7 @@ struct dram_para {
u32 dx_odt; u32 dx_dri; u32 ca_dri;
- u32 tpr10;
};
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index cad53f19912c..abcbd0fb9061 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -52,38 +52,6 @@ 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_READ_CALIBRATION
- bool "H616 DRAM read calibration"
- ---help---
Select this when DRAM on your H616 board needs read
calibration.
-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_WRITE_TRAINING
- bool "H616 DRAM write training"
- ---help---
Select this when DRAM on your H616 board needs write training.
-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_UNKNOWN_FEATURE
- bool "H616 DRAM unknown feature"
- ---help---
Select this when DRAM on your H616 board needs this unknown
feature.
config DRAM_SUN50I_H616_DX_ODT
hex "H616 DRAM DX ODT parameter" help
@@ -98,6 +66,12 @@ config DRAM_SUN50I_H616_CA_DRI
hex "H616 DRAM CA DRI parameter" help
CA DRI 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.
endif
config SUN6I_PRCM
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 06a07dfbf9cc..14a01a3c4e54 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -577,109 +577,112 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para)> u32 *ptr; 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_UNKNOWN_FEAT2) {
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);
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);
- 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 + 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 + 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);
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);
- 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);
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);
- dmb();
dmb();
- setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
- }
- /* second part */
- clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
- clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
- if (para->tpr10 & TPR10_UNKNOWN_FEAT1) {
clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
- 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);
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);
- 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);
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);
- 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 + 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 + 0x654);
- for (i = 0; i < 9; i++) {
writel_relaxed(0x14, ptr);
writel_relaxed(0x14, ptr + 0x30);
ptr += 2;
- }
- 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);
ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x654);
for (i = 0; i < 9; i++) {
writel_relaxed(0x14, ptr);
writel_relaxed(0x14, ptr + 0x30);
ptr += 2;
}
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();
dmb();
- setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
}
return true;
}
@@ -718,7 +721,7 @@ static bool mctl_phy_init(struct dram_para *para)
for (i = 0; i < ARRAY_SIZE(phy_init); i++)
writel(phy_init[i], &ptr[i]);
- if (IS_ENABLED(CONFIG_DRAM_SUN50I_H616_UNKNOWN_FEATURE)) {
if (para->tpr10 & TPR10_UNKNOWN_FEAT0) {
ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x780); for (i = 0; i < 32; i++)
writel(0x16, &ptr[i]);
@@ -800,7 +803,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;
@@ -810,7 +813,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++)
B> if (mctl_phy_read_calibration(para))
break;
@@ -820,7 +823,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;
@@ -830,7 +833,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;
@@ -840,8 +843,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);
@@ -1022,6 +1024,7 @@ unsigned long sunxi_dram_init(void)
.dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT, .dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI, .ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI,
.tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10,
}; unsigned long size;
diff --git a/configs/orangepi_zero2_defconfig b/configs/orangepi_zero2_defconfig index ca398faef1d3..f2024a2502c7 100644 --- a/configs/orangepi_zero2_defconfig +++ b/configs/orangepi_zero2_defconfig @@ -2,13 +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=0x8080808 CONFIG_DRAM_SUN50I_H616_DX_DRI=0xe0e0e0e CONFIG_DRAM_SUN50I_H616_CA_DRI=0xe0e
+CONFIG_DRAM_SUN50I_H616_TPR10=0xf83438
CONFIG_MACH_SUN50I_H616=y CONFIG_MMC0_CD_PIN="PF6" CONFIG_R_I2C_ENABLE=y

Dne torek, 13. december 2022 ob 17:51:35 CET je Andre Przywara napisal(a):
On Tue, 13 Dec 2022 17:23:12 +0100
Jernej Škrabec jernej.skrabec@gmail.com wrote:
Hi,
Dne ponedeljek, 12. december 2022 ob 18:50:44 CET je Andre Przywara
napisal(a):
On Sun, 11 Dec 2022 17:32:09 +0100 Jernej Skrabec jernej.skrabec@gmail.com wrote:
Hi,
Vendor DRAM settings use TPR10 parameter to enable various features. There are many mores features that just those that are currently mentioned. Since new will be added later and most are not known, let's reuse value from vendor DRAM driver as-is. This will also help adding support for new boards.
Looks good. I checked that the actual code in mctl_phy_bit_delay_compensation() just gets indented (no real changes), and is now guarded by the new checks. The values in the _defconfig still result in the same decisions, though many are blocked anyway by no one actually calling that bit_delay function at all. (I wonder what happens when we enable it?)
I'm not sure I understand. Bit delay compensation should be enabled for X96 Mate, according to values you send in previous e-mail.
But DRAM_SUN50I_H616_BIT_DELAY_COMPENSATION is not set by any (of the two) defconfigs atm, and I don't see this in your t95 (WIP?) branch on github either. So that whole code was completely unused (until now).
Hm, I remember writing this code for T95, but I'm not sure why it's not enabled in defconfig. I'm sure values are ok and match vendor driver.
It's interesting to see how some parts of initialization procedure have some wiggle room and still appear to be stable.
In any case, DRAM configuration looks like a black magic at times, so I would rather stick to vendor procedure, especially due to missing register documentation, and not just randomly enable things which sounds nice. I tried enabling unused procedures for T95 and either they didn't went through or amount of detected RAM was lower than presetn.
Sure, I was just confused that we have some elaborate code, with values backed by the vendor BSP, but then don't use that. But if it gets used now, it's all fine, I guess.
Great!
Best regards, Jernej
One small thing below.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com
.../include/asm/arch-sunxi/dram_sun50i_h616.h | 10 + arch/arm/mach-sunxi/Kconfig | 38 +--- arch/arm/mach-sunxi/dram_sun50i_h616.c | 197 +++++++++--------- configs/orangepi_zero2_defconfig | 5 +- 4 files changed, 117 insertions(+), 133 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 c9e1f84bfcdd..b5140c79b70e 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,15 @@ 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)
+/* TODO: figure out what unknown features do */ +#define TPR10_UNKNOWN_FEAT0 BIT(16) +#define TPR10_UNKNOWN_FEAT1 BIT(17) +#define TPR10_UNKNOWN_FEAT2 BIT(18)
Could you just put the bit number in the macro? Like TPR10_BIT16? That both avoids inventing meaningless names, and helps readers to correlate code more easily. Or skip the symbol altogether for those and use just "BIT(16)" in the code.
I actually know what these are for now, so I can give much better names. However, I still don't know what TPR10_UNKNOWN_FEAT3 does, which is in the last commit, so I'll rework that one to use BIT(30) directly.
Great, thanks!
Cheers, Andre
Best regards, Jernej
Cheers, Andre
+#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;
@@ -147,6 +156,7 @@ struct dram_para {
u32 dx_odt; u32 dx_dri; u32 ca_dri;
- u32 tpr10;
};
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index cad53f19912c..abcbd0fb9061 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -52,38 +52,6 @@ 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_READ_CALIBRATION
- bool "H616 DRAM read calibration"
- ---help---
Select this when DRAM on your H616 board needs read
calibration.
-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_WRITE_TRAINING
- bool "H616 DRAM write training"
- ---help---
Select this when DRAM on your H616 board needs write training.
-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_UNKNOWN_FEATURE
- bool "H616 DRAM unknown feature"
- ---help---
Select this when DRAM on your H616 board needs this unknown
feature.
config DRAM_SUN50I_H616_DX_ODT
hex "H616 DRAM DX ODT parameter" help
@@ -98,6 +66,12 @@ config DRAM_SUN50I_H616_CA_DRI
hex "H616 DRAM CA DRI parameter" help
CA DRI 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.
endif
config SUN6I_PRCM
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 06a07dfbf9cc..14a01a3c4e54 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -577,109 +577,112 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para)>
u32 *ptr; 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_UNKNOWN_FEAT2) {
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);
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);
- 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 + 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 + 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);
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);
- 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);
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);
- dmb();
dmb();
- setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
- }
- /* second part */
- clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
- clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
- if (para->tpr10 & TPR10_UNKNOWN_FEAT1) {
clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
- 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);
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);
- 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);
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);
- 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 + 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 + 0x654);
- for (i = 0; i < 9; i++) {
writel_relaxed(0x14, ptr);
writel_relaxed(0x14, ptr + 0x30);
ptr += 2;
- }
- 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);
ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x654);
for (i = 0; i < 9; i++) {
writel_relaxed(0x14, ptr);
writel_relaxed(0x14, ptr + 0x30);
ptr += 2;
}
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();
dmb();
- setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
}
return true;
}
@@ -718,7 +721,7 @@ static bool mctl_phy_init(struct dram_para *para)
for (i = 0; i < ARRAY_SIZE(phy_init); i++)
writel(phy_init[i], &ptr[i]);
- if (IS_ENABLED(CONFIG_DRAM_SUN50I_H616_UNKNOWN_FEATURE)) {
if (para->tpr10 & TPR10_UNKNOWN_FEAT0) {
ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x780); for (i = 0; i < 32; i++)
writel(0x16, &ptr[i]);
@@ -800,7 +803,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;
@@ -810,7 +813,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++)
B> if (mctl_phy_read_calibration(para))
break;
@@ -820,7 +823,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;
@@ -830,7 +833,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;
@@ -840,8 +843,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);
@@ -1022,6 +1024,7 @@ unsigned long sunxi_dram_init(void)
.dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT, .dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI, .ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI,
.tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10,
}; unsigned long size;
diff --git a/configs/orangepi_zero2_defconfig b/configs/orangepi_zero2_defconfig index ca398faef1d3..f2024a2502c7 100644 --- a/configs/orangepi_zero2_defconfig +++ b/configs/orangepi_zero2_defconfig @@ -2,13 +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=0x8080808 CONFIG_DRAM_SUN50I_H616_DX_DRI=0xe0e0e0e CONFIG_DRAM_SUN50I_H616_CA_DRI=0xe0e
+CONFIG_DRAM_SUN50I_H616_TPR10=0xf83438
CONFIG_MACH_SUN50I_H616=y CONFIG_MMC0_CD_PIN="PF6" CONFIG_R_I2C_ENABLE=y

Vendor H616 DRAM code always configure part which we call ODT configuration. Let's reflect that here too.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com --- arch/arm/mach-sunxi/Kconfig | 2 +- arch/arm/mach-sunxi/dram_sun50i_h616.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index abcbd0fb9061..778304b77e26 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -488,12 +488,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 14a01a3c4e54..bf5b4ddfb5c2 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -736,8 +736,7 @@ static bool mctl_phy_init(struct dram_para *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(para); + mctl_phy_configure_odt(para);
clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 7, 0xa);

On Sun, 11 Dec 2022 17:32:10 +0100 Jernej Skrabec jernej.skrabec@gmail.com wrote:
Vendor H616 DRAM code always configure part which we call ODT configuration. Let's reflect that here too.
I wonder if we need this patch at all. "depends on !H616" looks counter-intuitive, since this suggests it's always off. As it stands, it doesn't hurt. "default y" does the right thing, and if people want to shoot themselves in the foot: fine by me.
At least I would like to keep the Kconfig part. We could change the condition in the code into an explaining comment, if you still want to force this on.
And coming back from patch 7/8: how does this correspond to DRAM_SUN50I_H616_ODT_EN?
Cheers, Andre
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com
arch/arm/mach-sunxi/Kconfig | 2 +- arch/arm/mach-sunxi/dram_sun50i_h616.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index abcbd0fb9061..778304b77e26 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -488,12 +488,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 14a01a3c4e54..bf5b4ddfb5c2 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -736,8 +736,7 @@ static bool mctl_phy_init(struct dram_para *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(para);
mctl_phy_configure_odt(para);
clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 7, 0xa);

Dne sreda, 04. januar 2023 ob 01:37:17 CET je Andre Przywara napisal(a):
On Sun, 11 Dec 2022 17:32:10 +0100
Jernej Skrabec jernej.skrabec@gmail.com wrote:
Vendor H616 DRAM code always configure part which we call ODT configuration. Let's reflect that here too.
I wonder if we need this patch at all. "depends on !H616" looks counter-intuitive, since this suggests it's always off.
I don't see it that way. It just means it's unused for H616.
As it stands, it doesn't hurt. "default y" does the right thing, and if people want to shoot themselves in the foot: fine by me.
At least I would like to keep the Kconfig part. We could change the condition in the code into an explaining comment, if you still want to force this on.
And coming back from patch 7/8: how does this correspond to DRAM_SUN50I_H616_ODT_EN?
The thing is that I can't give you good explanation for anything above due to nature of reverse engineering. It's just how vendor code is done and I would argue that my original assumption when I was writing this driver was wrong and I shouldn't use this symbol at all in first place. I'm not even sure if I named mctl_phy_configure_odt() completely correct. It has to do something with ODT, but I don't know if it gets enabled here or not. To me, it looks more like that just some parameters are set here.
Best regards, Jernej
Cheers, Andre
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com
arch/arm/mach-sunxi/Kconfig | 2 +- arch/arm/mach-sunxi/dram_sun50i_h616.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index abcbd0fb9061..778304b77e26 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -488,12 +488,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 14a01a3c4e54..bf5b4ddfb5c2 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -736,8 +736,7 @@ static bool mctl_phy_init(struct dram_para *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(para);
mctl_phy_configure_odt(para);
clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 7, 0xa);

Mentioned function result is always true and result isn't checked anyway. Let's make it void.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com --- arch/arm/mach-sunxi/dram_sun50i_h616.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index bf5b4ddfb5c2..3b2ba168498c 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -572,7 +572,7 @@ 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; int i; @@ -683,8 +683,6 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para)
setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80); } - - return true; }
static bool mctl_phy_init(struct dram_para *para)

On Sun, 11 Dec 2022 17:32:11 +0100 Jernej Skrabec jernej.skrabec@gmail.com wrote:
Mentioned function result is always true and result isn't checked anyway. Let's make it void.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com
Reviewed-by: Andre Przywara andre.przywara@arm.com
Cheers, Andre
arch/arm/mach-sunxi/dram_sun50i_h616.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index bf5b4ddfb5c2..3b2ba168498c 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -572,7 +572,7 @@ 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; int i; @@ -683,8 +683,6 @@ static bool mctl_phy_bit_delay_compensation(struct dram_para *para)
setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
}
- return true;
}
static bool mctl_phy_init(struct dram_para *para)

These values are highly board specific and thus make sense to add parameter for them. To ease adding support for new boards, let's make them same as in vendor DRAM settings.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com --- .../include/asm/arch-sunxi/dram_sun50i_h616.h | 4 + arch/arm/mach-sunxi/Kconfig | 18 ++ arch/arm/mach-sunxi/dram_sun50i_h616.c | 189 +++++++++++++----- 3 files changed, 162 insertions(+), 49 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 b5140c79b70e..c7890c83391f 100644 --- a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h +++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h @@ -145,6 +145,7 @@ check_member(sunxi_mctl_ctl_reg, unk_0x4240, 0x4240); #define TPR10_READ_CALIBRATION BIT(21) #define TPR10_READ_TRAINING BIT(22) #define TPR10_WRITE_TRAINING BIT(23) +#define TPR10_UNKNOWN_FEAT3 BIT(30)
struct dram_para { u32 clk; @@ -156,7 +157,10 @@ struct dram_para { u32 dx_odt; u32 dx_dri; u32 ca_dri; + u32 odt_en; u32 tpr10; + u32 tpr11; + u32 tpr12; };
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 778304b77e26..b050f0a56971 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -67,11 +67,29 @@ config DRAM_SUN50I_H616_CA_DRI help CA DRI value from vendor DRAM settings.
+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_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 diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 3b2ba168498c..df06cea42464 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -574,7 +574,7 @@ static bool mctl_phy_write_training(struct dram_para *para)
static void mctl_phy_bit_delay_compensation(struct dram_para *para) { - u32 *ptr; + u32 *ptr, val; int i;
if (para->tpr10 & TPR10_UNKNOWN_FEAT2) { @@ -582,49 +582,93 @@ static void mctl_phy_bit_delay_compensation(struct dram_para *para) setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 8); clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
+ if (para->tpr10 & TPR10_UNKNOWN_FEAT3) + val = para->tpr11 & 0x3f; + else + val = (para->tpr11 & 0xf) << 1; + ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x484); for (i = 0; i < 9; i++) { - writel_relaxed(0x16, ptr); - writel_relaxed(0x16, ptr + 0x30); + writel_relaxed(val, ptr); + writel_relaxed(val, 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 & TPR10_UNKNOWN_FEAT3) + val = (para->odt_en >> 15) & 0x1e; + else + val = (para->tpr11 >> 15) & 0x1e; + + 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); + + if (para->tpr10 & TPR10_UNKNOWN_FEAT3) + val = (para->tpr11 >> 8) & 0x3f; + else + val = (para->tpr11 >> 3) & 0x1e;
ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d8); for (i = 0; i < 9; i++) { - writel_relaxed(0x1a, ptr); - writel_relaxed(0x1a, ptr + 0x30); + writel_relaxed(val, ptr); + writel_relaxed(val, 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); + + if (para->tpr10 & TPR10_UNKNOWN_FEAT3) + val = (para->odt_en >> 19) & 0x1e; + else + val = (para->tpr11 >> 19) & 0x1e; + + 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); + + if (para->tpr10 & TPR10_UNKNOWN_FEAT3) + val = (para->tpr11 >> 16) & 0x3f; + else + val = (para->tpr11 >> 7) & 0x1e;
ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x604); for (i = 0; i < 9; i++) { - writel_relaxed(0x1a, ptr); - writel_relaxed(0x1a, ptr + 0x30); + writel_relaxed(val, ptr); + writel_relaxed(val, 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 & TPR10_UNKNOWN_FEAT3) + 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 & TPR10_UNKNOWN_FEAT3) + 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(0x1a, ptr); - writel_relaxed(0x1a, ptr + 0x30); + writel_relaxed(val, ptr); + writel_relaxed(val, 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); + + if (para->tpr10 & TPR10_UNKNOWN_FEAT3) + 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();
@@ -635,49 +679,93 @@ static void mctl_phy_bit_delay_compensation(struct dram_para *para) clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80); clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
+ if (para->tpr10 & TPR10_UNKNOWN_FEAT3) + 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(0x10, ptr); - writel_relaxed(0x10, ptr + 0x30); + writel_relaxed(val, ptr); + writel_relaxed(val, 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); + + if (para->tpr10 & TPR10_UNKNOWN_FEAT3) + val = (para->odt_en << 1) & 0x1e; + else + val = (para->tpr12 >> 15) & 0x1e; + + 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 & TPR10_UNKNOWN_FEAT3) + 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(0x12, ptr); - writel_relaxed(0x12, ptr + 0x30); + writel_relaxed(val, ptr); + writel_relaxed(val, 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 & TPR10_UNKNOWN_FEAT3) + 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 & TPR10_UNKNOWN_FEAT3) + 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(0x12, ptr); - writel_relaxed(0x12, ptr + 0x30); + writel_relaxed(val, ptr); + writel_relaxed(val, 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); + + if (para->tpr10 & TPR10_UNKNOWN_FEAT3) + 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 & TPR10_UNKNOWN_FEAT3) + 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(0x14, ptr); - writel_relaxed(0x14, ptr + 0x30); + writel_relaxed(val, ptr); + writel_relaxed(val, ptr + 0x30); ptr += 2; } - 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); + + if (para->tpr10 & TPR10_UNKNOWN_FEAT3) + 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();
@@ -1021,7 +1109,10 @@ unsigned long sunxi_dram_init(void) .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, .tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10, + .tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11, + .tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12, }; unsigned long size;

On Sun, 11 Dec 2022 17:32:12 +0100 Jernej Skrabec jernej.skrabec@gmail.com wrote:
Hi Jernej,
These values are highly board specific and thus make sense to add parameter for them. To ease adding support for new boards, let's make them same as in vendor DRAM settings.
So scrolling up and down: does this patch miss the TPR11 and TPR12 values in the OPi-Zero2 defconfig? And should we not default to 0 in Kconfig to help spotting this omission more easily for new boards? If I pieced the bits together correctly, we end up with the same values in the register with TPR11=0xfffedddb and TPR12=0xeddca998, and ODT_EN being irrelevant.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com
.../include/asm/arch-sunxi/dram_sun50i_h616.h | 4 + arch/arm/mach-sunxi/Kconfig | 18 ++ arch/arm/mach-sunxi/dram_sun50i_h616.c | 189 +++++++++++++----- 3 files changed, 162 insertions(+), 49 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 b5140c79b70e..c7890c83391f 100644 --- a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h +++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h @@ -145,6 +145,7 @@ check_member(sunxi_mctl_ctl_reg, unk_0x4240, 0x4240); #define TPR10_READ_CALIBRATION BIT(21) #define TPR10_READ_TRAINING BIT(22) #define TPR10_WRITE_TRAINING BIT(23) +#define TPR10_UNKNOWN_FEAT3 BIT(30)
As mentioned in the other patch: if we don't know the meaning of this bit, I'd prefer using BIT(30) directly, or at least encode BIT30 in the name.
struct dram_para { u32 clk; @@ -156,7 +157,10 @@ struct dram_para { u32 dx_odt; u32 dx_dri; u32 ca_dri;
- u32 odt_en; u32 tpr10;
- u32 tpr11;
- u32 tpr12;
};
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 778304b77e26..b050f0a56971 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -67,11 +67,29 @@ config DRAM_SUN50I_H616_CA_DRI help CA DRI value from vendor DRAM settings.
+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_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 diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 3b2ba168498c..df06cea42464 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -574,7 +574,7 @@ static bool mctl_phy_write_training(struct dram_para *para)
static void mctl_phy_bit_delay_compensation(struct dram_para *para) {
- u32 *ptr;
u32 *ptr, val; int i;
if (para->tpr10 & TPR10_UNKNOWN_FEAT2) {
@@ -582,49 +582,93 @@ static void mctl_phy_bit_delay_compensation(struct dram_para *para) setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 8); clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
val = para->tpr11 & 0x3f;
else
val = (para->tpr11 & 0xf) << 1;
- ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x484); for (i = 0; i < 9; i++) {
writel_relaxed(0x16, ptr);
writel_relaxed(0x16, ptr + 0x30);
writel_relaxed(val, ptr);
}writel_relaxed(val, 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 & TPR10_UNKNOWN_FEAT3)
val = (para->odt_en >> 15) & 0x1e;
So I guess odt_en stands for "ODT enable". Looking at the D1 DRAM driver, they have a boot0 parameter odt_en which is either 0x0 or 0x1, so it looks like a boolean value. This seems to be also the case here? In the D1 driver, this seems to gate the ZQ value being used, which provides the actual timing values. So is TPR10_UNKNOWN_FEAT3 actually this ODT_EN switch, and the variable containing the timing bits should be zq_value or CONFIG_DRAM_ZQ?
else
val = (para->tpr11 >> 15) & 0x1e;
So I am wondering if it's less confusing to mask first, then shift? Granted, this here is shift from [19:16] into [5:1], so it's not easy either way, but I think it's easier to match the mask with the provided TPR11 value.
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);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
val = (para->tpr11 >> 8) & 0x3f;
else
val = (para->tpr11 >> 3) & 0x1e;
ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d8); for (i = 0; i < 9; i++) {
writel_relaxed(0x1a, ptr);
writel_relaxed(0x1a, ptr + 0x30);
writel_relaxed(val, ptr);
}writel_relaxed(val, 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);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
val = (para->odt_en >> 19) & 0x1e;
Is this really odt_en as a base, while *most* of the other bits use TPR11 as well? Just asking, since it doesn't fit into my naive pattern matching ;-)
The rest looks correct (minus the repeat of the above mentioned issues), I compared the register offsets between - and +.
Cheers, Andre
else
val = (para->tpr11 >> 19) & 0x1e;
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);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
val = (para->tpr11 >> 16) & 0x3f;
else
val = (para->tpr11 >> 7) & 0x1e;
ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x604); for (i = 0; i < 9; i++) {
writel_relaxed(0x1a, ptr);
writel_relaxed(0x1a, ptr + 0x30);
writel_relaxed(val, ptr);
}writel_relaxed(val, 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 & TPR10_UNKNOWN_FEAT3)
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 & TPR10_UNKNOWN_FEAT3)
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(0x1a, ptr);
writel_relaxed(0x1a, ptr + 0x30);
writel_relaxed(val, ptr);
}writel_relaxed(val, 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);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
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();
@@ -635,49 +679,93 @@ static void mctl_phy_bit_delay_compensation(struct dram_para *para) clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80); clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
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(0x10, ptr);
writel_relaxed(0x10, ptr + 0x30);
writel_relaxed(val, ptr);
}writel_relaxed(val, 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);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
val = (para->odt_en << 1) & 0x1e;
else
val = (para->tpr12 >> 15) & 0x1e;
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 & TPR10_UNKNOWN_FEAT3)
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(0x12, ptr);
writel_relaxed(0x12, ptr + 0x30);
writel_relaxed(val, ptr);
}writel_relaxed(val, 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 & TPR10_UNKNOWN_FEAT3)
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 & TPR10_UNKNOWN_FEAT3)
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(0x12, ptr);
writel_relaxed(0x12, ptr + 0x30);
writel_relaxed(val, ptr);
}writel_relaxed(val, 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);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
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 & TPR10_UNKNOWN_FEAT3)
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(0x14, ptr);
writel_relaxed(0x14, ptr + 0x30);
writel_relaxed(val, ptr);
}writel_relaxed(val, ptr + 0x30); ptr += 2;
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);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
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();
@@ -1021,7 +1109,10 @@ unsigned long sunxi_dram_init(void) .dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT, .dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI, .ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI,
.tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10,.odt_en = CONFIG_DRAM_SUN50I_H616_ODT_EN,
.tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11,
}; unsigned long size;.tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12,

Dne sreda, 04. januar 2023 ob 01:37:47 CET je Andre Przywara napisal(a):
On Sun, 11 Dec 2022 17:32:12 +0100 Jernej Skrabec jernej.skrabec@gmail.com wrote:
Hi Jernej,
These values are highly board specific and thus make sense to add parameter for them. To ease adding support for new boards, let's make them same as in vendor DRAM settings.
So scrolling up and down: does this patch miss the TPR11 and TPR12 values in the OPi-Zero2 defconfig?
No, because 0 (which is default) is correct here.
And should we not default to 0 in Kconfig to help spotting this omission more easily for new boards?
Not all boards need to set all the values. I set default values for symbols which seem to have same value for multiple boards.
If I pieced the bits together correctly, we end up with the same values in the register with TPR11=0xfffedddb and TPR12=0xeddca998, and ODT_EN being irrelevant.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com
.../include/asm/arch-sunxi/dram_sun50i_h616.h | 4 + arch/arm/mach-sunxi/Kconfig | 18 ++ arch/arm/mach-sunxi/dram_sun50i_h616.c | 189 +++++++++++++----- 3 files changed, 162 insertions(+), 49 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 b5140c79b70e..c7890c83391f 100644 --- a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h +++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h @@ -145,6 +145,7 @@ check_member(sunxi_mctl_ctl_reg, unk_0x4240, 0x4240);
#define TPR10_READ_CALIBRATION BIT(21) #define TPR10_READ_TRAINING BIT(22) #define TPR10_WRITE_TRAINING BIT(23)
+#define TPR10_UNKNOWN_FEAT3 BIT(30)
As mentioned in the other patch: if we don't know the meaning of this bit, I'd prefer using BIT(30) directly, or at least encode BIT30 in the name.
struct dram_para {
u32 clk;
@@ -156,7 +157,10 @@ struct dram_para {
u32 dx_odt; u32 dx_dri; u32 ca_dri;
u32 odt_en;
u32 tpr10;
u32 tpr11;
u32 tpr12;
};
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 778304b77e26..b050f0a56971 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -67,11 +67,29 @@ config DRAM_SUN50I_H616_CA_DRI
help
CA DRI value from vendor DRAM settings.
+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_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
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 3b2ba168498c..df06cea42464 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -574,7 +574,7 @@ static bool mctl_phy_write_training(struct dram_para *para)> static void mctl_phy_bit_delay_compensation(struct dram_para *para) {
- u32 *ptr;
u32 *ptr, val;
int i;
if (para->tpr10 & TPR10_UNKNOWN_FEAT2) {
@@ -582,49 +582,93 @@ static void mctl_phy_bit_delay_compensation(struct dram_para *para)> setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 8); clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
val = para->tpr11 & 0x3f;
else
val = (para->tpr11 & 0xf) << 1;
ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x484); for (i = 0; i < 9; i++) {
writel_relaxed(0x16, ptr);
writel_relaxed(0x16, ptr + 0x30);
writel_relaxed(val, ptr);
writel_relaxed(val, 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 & TPR10_UNKNOWN_FEAT3)
val = (para->odt_en >> 15) & 0x1e;
So I guess odt_en stands for "ODT enable". Looking at the D1 DRAM driver, they have a boot0 parameter odt_en which is either 0x0 or 0x1, so it looks like a boolean value. This seems to be also the case here?
Nope. While I only ever see odt_en being 1, based on vendor code it can have additional bits set, as it can be seen from above code.
In the D1 driver, this seems to gate the ZQ value being used, which provides the actual timing values. So is TPR10_UNKNOWN_FEAT3 actually this ODT_EN switch, and the variable containing the timing bits should be zq_value or CONFIG_DRAM_ZQ?
No idea.
else
val = (para->tpr11 >> 15) & 0x1e;
So I am wondering if it's less confusing to mask first, then shift? Granted, this here is shift from [19:16] into [5:1], so it's not easy either way, but I think it's easier to match the mask with the provided TPR11 value.
I did it this way because mask is much smaller and easier to read, but neither are straightforward to understand. I guess some macro could be crafted for such purpose.
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);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
val = (para->tpr11 >> 8) & 0x3f;
else
val = (para->tpr11 >> 3) & 0x1e;
ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d8); for (i = 0; i < 9; i++) {
writel_relaxed(0x1a, ptr);
writel_relaxed(0x1a, ptr + 0x30);
writel_relaxed(val, ptr);
writel_relaxed(val, 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);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
val = (para->odt_en >> 19) & 0x1e;
Is this really odt_en as a base, while *most* of the other bits use TPR11 as well? Just asking, since it doesn't fit into my naive pattern matching ;-)
odt_en is name from device tree. It doesn't seem to match actual purpose, but there is not much we can do without documentation.
Best regards, Jernej
The rest looks correct (minus the repeat of the above mentioned issues), I compared the register offsets between - and +.
Cheers, Andre
else
val = (para->tpr11 >> 19) & 0x1e;
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);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
val = (para->tpr11 >> 16) & 0x3f;
else
val = (para->tpr11 >> 7) & 0x1e;
ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x604); for (i = 0; i < 9; i++) {
writel_relaxed(0x1a, ptr);
writel_relaxed(0x1a, ptr + 0x30);
writel_relaxed(val, ptr);
writel_relaxed(val, 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 & TPR10_UNKNOWN_FEAT3)
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 & TPR10_UNKNOWN_FEAT3)
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(0x1a, ptr);
writel_relaxed(0x1a, ptr + 0x30);
writel_relaxed(val, ptr);
writel_relaxed(val, 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);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
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();
@@ -635,49 +679,93 @@ static void mctl_phy_bit_delay_compensation(struct dram_para *para)> clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80); clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
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(0x10, ptr);
writel_relaxed(0x10, ptr + 0x30);
writel_relaxed(val, ptr);
writel_relaxed(val, 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);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
val = (para->odt_en << 1) & 0x1e;
else
val = (para->tpr12 >> 15) & 0x1e;
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 & TPR10_UNKNOWN_FEAT3)
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(0x12, ptr);
writel_relaxed(0x12, ptr + 0x30);
writel_relaxed(val, ptr);
writel_relaxed(val, 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 & TPR10_UNKNOWN_FEAT3)
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 & TPR10_UNKNOWN_FEAT3)
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(0x12, ptr);
writel_relaxed(0x12, ptr + 0x30);
writel_relaxed(val, ptr);
writel_relaxed(val, 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);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
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 & TPR10_UNKNOWN_FEAT3)
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(0x14, ptr);
writel_relaxed(0x14, ptr + 0x30);
writel_relaxed(val, ptr);
writel_relaxed(val, ptr + 0x30); ptr += 2;
}
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);
if (para->tpr10 & TPR10_UNKNOWN_FEAT3)
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();
@@ -1021,7 +1109,10 @@ unsigned long sunxi_dram_init(void)
.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,
.tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10,
.tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11,
.tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12,
}; unsigned long size;

Part of the code, previously known as "unknown feature" also doesn't have constant values. They are derived from TPR0 parameter in vendor DRAM code. Introduce that parameter here too, to ease adding new boards.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com --- .../include/asm/arch-sunxi/dram_sun50i_h616.h | 1 + arch/arm/mach-sunxi/Kconfig | 6 ++++ arch/arm/mach-sunxi/dram_sun50i_h616.c | 35 +++++++++++++++---- 3 files changed, 35 insertions(+), 7 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 c7890c83391f..ff736bd88d10 100644 --- a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h +++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h @@ -158,6 +158,7 @@ struct dram_para { u32 dx_dri; u32 ca_dri; u32 odt_en; + u32 tpr0; u32 tpr10; u32 tpr11; u32 tpr12; diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index b050f0a56971..7858a7045f7e 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -73,6 +73,12 @@ config DRAM_SUN50I_H616_ODT_EN help ODT EN value from vendor DRAM settings.
+config DRAM_SUN50I_H616_TPR0 + hex "H616 DRAM TPR0 parameter" + default 0x0 + help + TPR0 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 df06cea42464..6d8f8d371bfe 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -808,15 +808,35 @@ static bool mctl_phy_init(struct dram_para *para) writel(phy_init[i], &ptr[i]);
if (para->tpr10 & TPR10_UNKNOWN_FEAT0) { + 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(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); + writel(val, &ptr[i]); + + val = (para->tpr10 << 1) & 0x1e; + writel(val, SUNXI_DRAM_PHY0_BASE + 0x7dc); + writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e0); + + /* following configuration is DDR3 specific */ + val = (para->tpr10 >> 7) & 0x1e; + writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d4); + /* + * TODO: Offsets 0x79c, 0x794 and 0x7e4 may need + * to be set here. However, this doesn't seem to + * be needed by any board seen in the wild for now. + * It's not implemented because it would unnecessarily + * introduce PARA2 and TPR2 options. + */ + 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); + } }
writel(0x80, SUNXI_DRAM_PHY0_BASE + 0x3dc); @@ -1110,6 +1130,7 @@ unsigned long sunxi_dram_init(void) .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, .tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10, .tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11, .tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12,

Dne nedelja, 11. december 2022 ob 17:32:13 CET je Jernej Skrabec napisal(a):
Part of the code, previously known as "unknown feature" also doesn't have constant values. They are derived from TPR0 parameter in vendor DRAM code. Introduce that parameter here too, to ease adding new boards.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com
.../include/asm/arch-sunxi/dram_sun50i_h616.h | 1 + arch/arm/mach-sunxi/Kconfig | 6 ++++ arch/arm/mach-sunxi/dram_sun50i_h616.c | 35 +++++++++++++++---- 3 files changed, 35 insertions(+), 7 deletions(-)
<snip>
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index df06cea42464..6d8f8d371bfe 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -808,15 +808,35 @@ static bool mctl_phy_init(struct dram_para *para) writel(phy_init[i], &ptr[i]);
if (para->tpr10 & TPR10_UNKNOWN_FEAT0) {
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(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);
writel(val, &ptr[i]);
val = (para->tpr10 << 1) & 0x1e;
writel(val, SUNXI_DRAM_PHY0_BASE + 0x7dc);
writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e0);
/* following configuration is DDR3 specific */
val = (para->tpr10 >> 7) & 0x1e;
writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d4);
/*
* TODO: Offsets 0x79c, 0x794 and 0x7e4 may need
* to be set here. However, this doesn't seem to
* be needed by any board seen in the wild for now.
* It's not implemented because it would unnecessarily
* introduce PARA2 and TPR2 options.
*/
I just noticed that PARA2 check actually checks rank. I think it's important to implement it (register 0x79c) and uses only TPR10 value, which is already present.
Best regards, Jernej
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);
}
}
writel(0x80, SUNXI_DRAM_PHY0_BASE + 0x3dc);

On Sun, 11 Dec 2022 17:32:13 +0100 Jernej Skrabec jernej.skrabec@gmail.com wrote:
Part of the code, previously known as "unknown feature" also doesn't have constant values. They are derived from TPR0 parameter in vendor DRAM code. Introduce that parameter here too, to ease adding new boards.
That seems to also miss the value for the OPi Zero2 defconfig.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com
.../include/asm/arch-sunxi/dram_sun50i_h616.h | 1 + arch/arm/mach-sunxi/Kconfig | 6 ++++ arch/arm/mach-sunxi/dram_sun50i_h616.c | 35 +++++++++++++++---- 3 files changed, 35 insertions(+), 7 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 c7890c83391f..ff736bd88d10 100644 --- a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h +++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h @@ -158,6 +158,7 @@ struct dram_para { u32 dx_dri; u32 ca_dri; u32 odt_en;
- u32 tpr0; u32 tpr10; u32 tpr11; u32 tpr12;
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index b050f0a56971..7858a7045f7e 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -73,6 +73,12 @@ config DRAM_SUN50I_H616_ODT_EN help ODT EN value from vendor DRAM settings.
+config DRAM_SUN50I_H616_TPR0
- hex "H616 DRAM TPR0 parameter"
- default 0x0
Is 0x0 really a feasible default value? I'd suggest we don't provide a default, so force people to be prompted for a value, if nothing is in (a new board's) defconfig.
The rest looks OK, though I can't really comment on the actual bits - but who can anyway ;-)
Cheers, Andre
- help
TPR0 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 df06cea42464..6d8f8d371bfe 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -808,15 +808,35 @@ static bool mctl_phy_init(struct dram_para *para) writel(phy_init[i], &ptr[i]);
if (para->tpr10 & TPR10_UNKNOWN_FEAT0) {
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(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);
writel(val, &ptr[i]);
val = (para->tpr10 << 1) & 0x1e;
writel(val, SUNXI_DRAM_PHY0_BASE + 0x7dc);
writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e0);
/* following configuration is DDR3 specific */
val = (para->tpr10 >> 7) & 0x1e;
writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d4);
/*
* TODO: Offsets 0x79c, 0x794 and 0x7e4 may need
* to be set here. However, this doesn't seem to
* be needed by any board seen in the wild for now.
* It's not implemented because it would unnecessarily
* introduce PARA2 and TPR2 options.
*/
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);
}
}
writel(0x80, SUNXI_DRAM_PHY0_BASE + 0x3dc);
@@ -1110,6 +1130,7 @@ unsigned long sunxi_dram_init(void) .dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI, .ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI, .odt_en = CONFIG_DRAM_SUN50I_H616_ODT_EN,
.tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10, .tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11, .tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12,.tpr0 = CONFIG_DRAM_SUN50I_H616_TPR0,

Dne sreda, 04. januar 2023 ob 01:38:12 CET je Andre Przywara napisal(a):
On Sun, 11 Dec 2022 17:32:13 +0100
Jernej Skrabec jernej.skrabec@gmail.com wrote:
Part of the code, previously known as "unknown feature" also doesn't have constant values. They are derived from TPR0 parameter in vendor DRAM code. Introduce that parameter here too, to ease adding new boards.
That seems to also miss the value for the OPi Zero2 defconfig.
Again, Zero2 doesn't use all features.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com
.../include/asm/arch-sunxi/dram_sun50i_h616.h | 1 + arch/arm/mach-sunxi/Kconfig | 6 ++++ arch/arm/mach-sunxi/dram_sun50i_h616.c | 35 +++++++++++++++---- 3 files changed, 35 insertions(+), 7 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 c7890c83391f..ff736bd88d10 100644 --- a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h +++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h @@ -158,6 +158,7 @@ struct dram_para {
u32 dx_dri; u32 ca_dri; u32 odt_en;
u32 tpr0;
u32 tpr10; u32 tpr11; u32 tpr12;
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index b050f0a56971..7858a7045f7e 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -73,6 +73,12 @@ config DRAM_SUN50I_H616_ODT_EN
help
ODT EN value from vendor DRAM settings.
+config DRAM_SUN50I_H616_TPR0
- hex "H616 DRAM TPR0 parameter"
- default 0x0
Is 0x0 really a feasible default value? I'd suggest we don't provide a default, so force people to be prompted for a value, if nothing is in (a new board's) defconfig.
This is not used on all boards, so imo is ok to have it as default.
Best regards, Jernej
The rest looks OK, though I can't really comment on the actual bits - but who can anyway ;-)
Cheers, Andre
- help
TPR0 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 df06cea42464..6d8f8d371bfe 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -808,15 +808,35 @@ static bool mctl_phy_init(struct dram_para *para)
writel(phy_init[i], &ptr[i]);
if (para->tpr10 & TPR10_UNKNOWN_FEAT0) {
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(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);
writel(val, &ptr[i]);
val = (para->tpr10 << 1) & 0x1e;
writel(val, SUNXI_DRAM_PHY0_BASE + 0x7dc);
writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e0);
/* following configuration is DDR3 specific */
val = (para->tpr10 >> 7) & 0x1e;
writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d4);
/*
* TODO: Offsets 0x79c, 0x794 and 0x7e4 may need
* to be set here. However, this doesn't seem to
* be needed by any board seen in the wild for now.
* It's not implemented because it would unnecessarily
* introduce PARA2 and TPR2 options.
*/
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);
}
}
writel(0x80, SUNXI_DRAM_PHY0_BASE + 0x3dc);
@@ -1110,6 +1130,7 @@ unsigned long sunxi_dram_init(void)
.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,
.tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10, .tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11, .tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12,

On Sun, 11 Dec 2022 17:32:05 +0100 Jernej Skrabec jernej.skrabec@gmail.com wrote:
Hi Jernej,
many thanks for putting this together! I will have a more elaborate look at each patch later.
Current H616 DRAM driver is completely customized to Orange Pi Zero2 board, which is currently the only H616 board supported by U-Boot.
Not anymore, I merged the X96 Mate support lately, after the DT got merged into the Linux tree.
Those are the values for the box I came up with: 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
based on this boot0 found in some firmware update image: 00045400 be 02 00 ea 65 47 4f 4e 2e 42 54 30 cc ba f3 80 |....eGON.BT0....| 00045410 00 c0 00 00 30 00 00 00 00 00 00 00 00 00 02 00 |....0...........| 00045420 00 00 02 00 00 00 00 00 00 00 00 00 34 2e 30 00 |............4.0.| 00045430 00 00 00 00 03 00 00 00 88 02 00 00 03 00 00 00 |................| 00045440 03 03 03 03 0e 0e 0e 0e 12 1c 00 00 01 00 00 00 |................| 00045450 fb 30 00 00 00 00 00 00 40 08 00 00 04 00 00 00 |.0......@.......| 00045460 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00045470 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00045480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00045490 05 0c 00 c0 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000454a0 80 80 80 33 07 00 2f 00 dd dd ff ff 57 75 df fe |...3../.....Wu..| 000454b0 40 00 00 00 00 00 00 00 00 00 00 00 08 00 02 01 |@...............|
I would be grateful if you could verify this.
I built it, and it reported the 4GB correctly, also managed to boot into Linux just fine. No extensive testing, nor didn't I compare register dumps or disassembly (yet).
Cheers, Andre
P.S. Any plans on upstreaming support for your T95 <whatever> H616 TV box? That would probably help the case here.
Needless to say, this is not ideal for adding new boards. With changes in this series, all DDR3 boards are supported and all that is needed is just vendor DRAM values extracted from Android image. New DRAM types should also be easier to support, since a lot of constants used before are not really DRAM type dependent.
Changes were verified by decompiling driver and generated values were compared to previous, hard coded ones. This was done without dram_para structures, so compiler was able to heavily optimize code and produce constants.
Please take a look.
Best regards, Jernej
Jernej Skrabec (8): sunxi: Fix write to H616 DRAM CR register sunxi: cosmetic: Fix H616 DRAM driver code style sunxi: parameterize H616 DRAM ODT values sunxi: Convert H616 DRAM options to single setting sunxi: Always configure ODT on H616 DRAM sunxi: Make bit delay function in H616 DRAM code void sunxi: Parameterize bit delay code in H616 DRAM driver sunxi: Parameterize H616 DRAM code some more
.../include/asm/arch-sunxi/dram_sun50i_h616.h | 18 + arch/arm/mach-sunxi/Kconfig | 67 +-- arch/arm/mach-sunxi/dram_sun50i_h616.c | 445 +++++++++++------- configs/orangepi_zero2_defconfig | 8 +- 4 files changed, 348 insertions(+), 190 deletions(-)

Hi Andre,
Dne ponedeljek, 12. december 2022 ob 02:04:51 CET je Andre Przywara napisal(a):
On Sun, 11 Dec 2022 17:32:05 +0100 Jernej Skrabec jernej.skrabec@gmail.com wrote:
Hi Jernej,
many thanks for putting this together! I will have a more elaborate look at each patch later.
Current H616 DRAM driver is completely customized to Orange Pi Zero2 board, which is currently the only H616 board supported by U-Boot.
Not anymore, I merged the X96 Mate support lately, after the DT got merged into the Linux tree.
Right. First part of sentence is still true, although I later remembered that some values are based on T95 values, those that are not used by Orange Pi Zero2.
Those are the values for the box I came up with: 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
based on this boot0 found in some firmware update image: 00045400 be 02 00 ea 65 47 4f 4e 2e 42 54 30 cc ba f3 80 |....eGON.BT0....| 00045410 00 c0 00 00 30 00 00 00 00 00 00 00 00 00 02 00 |....0...........| 00045420 00 00 02 00 00 00 00 00 00 00 00 00 34 2e 30 00 |............4.0.| 00045430 00 00 00 00 03 00 00 00 88 02 00 00 03 00 00 00 |................| 00045440 03 03 03 03 0e 0e 0e 0e 12 1c 00 00 01 00 00 00 |................| 00045450 fb 30 00 00 00 00 00 00 40 08 00 00 04 00 00 00 |.0......@.......| 00045460 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00045470 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00045480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00045490 05 0c 00 c0 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000454a0 80 80 80 33 07 00 2f 00 dd dd ff ff 57 75 df fe |...3../.....Wu..| 000454b0 40 00 00 00 00 00 00 00 00 00 00 00 08 00 02 01 |@...............|
I would be grateful if you could verify this.
Looks correct. I'll use them in my v2 patches.
I built it, and it reported the 4GB correctly, also managed to boot into Linux just fine. No extensive testing, nor didn't I compare register dumps or disassembly (yet).
Cheers, Andre
P.S. Any plans on upstreaming support for your T95 <whatever> H616 TV box? That would probably help the case here.
Not really, X96 Mate is basically the same as T95, except DRAM configuration. As I said, I verified that these patches provide same register values as before. This includes those which were modeled after T95 DRAM values.
Best regards, Jernej
Needless to say, this is not ideal for adding new boards. With changes in this series, all DDR3 boards are supported and all that is needed is just vendor DRAM values extracted from Android image. New DRAM types should also be easier to support, since a lot of constants used before are not really DRAM type dependent.
Changes were verified by decompiling driver and generated values were compared to previous, hard coded ones. This was done without dram_para structures, so compiler was able to heavily optimize code and produce constants.
Please take a look.
Best regards, Jernej
Jernej Skrabec (8): sunxi: Fix write to H616 DRAM CR register sunxi: cosmetic: Fix H616 DRAM driver code style sunxi: parameterize H616 DRAM ODT values sunxi: Convert H616 DRAM options to single setting sunxi: Always configure ODT on H616 DRAM sunxi: Make bit delay function in H616 DRAM code void sunxi: Parameterize bit delay code in H616 DRAM driver sunxi: Parameterize H616 DRAM code some more
.../include/asm/arch-sunxi/dram_sun50i_h616.h | 18 + arch/arm/mach-sunxi/Kconfig | 67 +-- arch/arm/mach-sunxi/dram_sun50i_h616.c | 445 +++++++++++------- configs/orangepi_zero2_defconfig | 8 +- 4 files changed, 348 insertions(+), 190 deletions(-)

On Sun, 11 Dec 2022 17:32:05 +0100 Jernej Skrabec jernej.skrabec@gmail.com wrote:
Hi Jernej,
Current H616 DRAM driver is completely customized to Orange Pi Zero2 board, which is currently the only H616 board supported by U-Boot. Needless to say, this is not ideal for adding new boards. With changes in this series, all DDR3 boards are supported and all that is needed is just vendor DRAM values extracted from Android image. New DRAM types should also be easier to support, since a lot of constants used before are not really DRAM type dependent.
Changes were verified by decompiling driver and generated values were compared to previous, hard coded ones. This was done without dram_para structures, so compiler was able to heavily optimize code and produce constants.
so many thanks again for putting this together! I came to like (the idea of) this series very much lately, as this removes timing/delay values from the code, and easily allows putting the vendor provided values in the defconfig. I used that approach as well for the D1 driver, and am wondering if we should extend this to other SoCs, potentially unifying the Kconfig part?
And you hinted at a v2, can you provide an estimate for this? If you send it still this week, I would like to put it into U-Boot's next branch, otherwise it goes straight into master, should the merge window open next week as planned.
Btw., to verify the feasibility of drivers/ram/sunxi, I moved the H616 driver into there, together with the Kconfig parts, I wonder what you think about this? An example of how this looks is in the D1 driver patches.
Cheers, Andre
Please take a look.
Best regards, Jernej
Jernej Skrabec (8): sunxi: Fix write to H616 DRAM CR register sunxi: cosmetic: Fix H616 DRAM driver code style sunxi: parameterize H616 DRAM ODT values sunxi: Convert H616 DRAM options to single setting sunxi: Always configure ODT on H616 DRAM sunxi: Make bit delay function in H616 DRAM code void sunxi: Parameterize bit delay code in H616 DRAM driver sunxi: Parameterize H616 DRAM code some more
.../include/asm/arch-sunxi/dram_sun50i_h616.h | 18 + arch/arm/mach-sunxi/Kconfig | 67 +-- arch/arm/mach-sunxi/dram_sun50i_h616.c | 445 +++++++++++------- configs/orangepi_zero2_defconfig | 8 +- 4 files changed, 348 insertions(+), 190 deletions(-)

Hi Andre!
Dne sreda, 04. januar 2023 ob 01:47:16 CET je Andre Przywara napisal(a):
On Sun, 11 Dec 2022 17:32:05 +0100 Jernej Skrabec jernej.skrabec@gmail.com wrote:
Hi Jernej,
Current H616 DRAM driver is completely customized to Orange Pi Zero2 board, which is currently the only H616 board supported by U-Boot. Needless to say, this is not ideal for adding new boards. With changes in this series, all DDR3 boards are supported and all that is needed is just vendor DRAM values extracted from Android image. New DRAM types should also be easier to support, since a lot of constants used before are not really DRAM type dependent.
Changes were verified by decompiling driver and generated values were compared to previous, hard coded ones. This was done without dram_para structures, so compiler was able to heavily optimize code and produce constants.
so many thanks again for putting this together! I came to like (the idea of) this series very much lately, as this removes timing/delay values from the code, and easily allows putting the vendor provided values in the defconfig. I used that approach as well for the D1 driver, and am wondering if we should extend this to other SoCs, potentially unifying the Kconfig part?
While it would be nice, I'm not sure it's worth the effort and there is a chance that something might break during rework.
And you hinted at a v2, can you provide an estimate for this? If you send it still this week, I would like to put it into U-Boot's next branch, otherwise it goes straight into master, should the merge window open next week as planned.
I have changes for v2 in my github repo. I don't have any estimation, since I had some time off from programming lately and I'm just only catching up. Weekend at earliest, but no promises.
Btw., to verify the feasibility of drivers/ram/sunxi, I moved the H616 driver into there, together with the Kconfig parts, I wonder what you think about this? An example of how this looks is in the D1 driver patches.
Looks good, but I don't know what are implications regarding interface. Is just code move or that implies that some ram framework must be used?
Best regards, Jernej
Cheers, Andre
Please take a look.
Best regards, Jernej
Jernej Skrabec (8): sunxi: Fix write to H616 DRAM CR register sunxi: cosmetic: Fix H616 DRAM driver code style sunxi: parameterize H616 DRAM ODT values sunxi: Convert H616 DRAM options to single setting sunxi: Always configure ODT on H616 DRAM sunxi: Make bit delay function in H616 DRAM code void sunxi: Parameterize bit delay code in H616 DRAM driver sunxi: Parameterize H616 DRAM code some more
.../include/asm/arch-sunxi/dram_sun50i_h616.h | 18 + arch/arm/mach-sunxi/Kconfig | 67 +-- arch/arm/mach-sunxi/dram_sun50i_h616.c | 445 +++++++++++------- configs/orangepi_zero2_defconfig | 8 +- 4 files changed, 348 insertions(+), 190 deletions(-)

On Wed, 04 Jan 2023 22:02:33 +0100 Jernej Škrabec jernej.skrabec@gmail.com wrote:
Hi Jernej,
Dne sreda, 04. januar 2023 ob 01:47:16 CET je Andre Przywara napisal(a):
On Sun, 11 Dec 2022 17:32:05 +0100 Jernej Skrabec jernej.skrabec@gmail.com wrote:
Hi Jernej,
Current H616 DRAM driver is completely customized to Orange Pi Zero2 board, which is currently the only H616 board supported by U-Boot. Needless to say, this is not ideal for adding new boards. With changes in this series, all DDR3 boards are supported and all that is needed is just vendor DRAM values extracted from Android image. New DRAM types should also be easier to support, since a lot of constants used before are not really DRAM type dependent.
Changes were verified by decompiling driver and generated values were compared to previous, hard coded ones. This was done without dram_para structures, so compiler was able to heavily optimize code and produce constants.
so many thanks again for putting this together! I came to like (the idea of) this series very much lately, as this removes timing/delay values from the code, and easily allows putting the vendor provided values in the defconfig. I used that approach as well for the D1 driver, and am wondering if we should extend this to other SoCs, potentially unifying the Kconfig part?
While it would be nice, I'm not sure it's worth the effort and there is a chance that something might break during rework.
Fair enough, was just an idea.
And you hinted at a v2, can you provide an estimate for this? If you send it still this week, I would like to put it into U-Boot's next branch, otherwise it goes straight into master, should the merge window open next week as planned.
I have changes for v2 in my github repo. I don't have any estimation, since I had some time off from programming lately
Sounds good!
and I'm just only catching up. Weekend at earliest, but no promises.
No worries, that was a genuine question, for my planning. I have plenty of other things to do, and we have still plenty of time (till end of January or so) to get things merged.
Btw., to verify the feasibility of drivers/ram/sunxi, I moved the H616 driver into there, together with the Kconfig parts, I wonder what you think about this? An example of how this looks is in the D1 driver patches.
Looks good, but I don't know what are implications regarding interface. Is just code move or that implies that some ram framework must be used?
I don't know what Simon and Tom will say, but I was cheekily just using the directory, ignoring the current DM_SPL preference for code in there. For the D1/T113s code this is probably a no-brainer, but I also found it a nice and simple solution to declutter and cleanup arch/arm/mach-sunxi and its Kconfig. So yeah, it's just moving the files and Kconfig stanzas there, and otherwise leaves the actual code untouched. We still call sunxi_dram_init() from our legacy SPL code.
Cheers, Andre
Best regards, Jernej
Cheers, Andre
Please take a look.
Best regards, Jernej
Jernej Skrabec (8): sunxi: Fix write to H616 DRAM CR register sunxi: cosmetic: Fix H616 DRAM driver code style sunxi: parameterize H616 DRAM ODT values sunxi: Convert H616 DRAM options to single setting sunxi: Always configure ODT on H616 DRAM sunxi: Make bit delay function in H616 DRAM code void sunxi: Parameterize bit delay code in H616 DRAM driver sunxi: Parameterize H616 DRAM code some more
.../include/asm/arch-sunxi/dram_sun50i_h616.h | 18 + arch/arm/mach-sunxi/Kconfig | 67 +-- arch/arm/mach-sunxi/dram_sun50i_h616.c | 445 +++++++++++------- configs/orangepi_zero2_defconfig | 8 +- 4 files changed, 348 insertions(+), 190 deletions(-)
participants (3)
-
Andre Przywara
-
Jernej Skrabec
-
Jernej Škrabec