sunxi: Add TPR2 parameter for H616 DRAM driver
It turns out that some H616 and related SoCs (like H313) need TPR2
parameter for proper working. Add it.
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index fe34755..6be8a4d 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -79,6 +79,12 @@
help
TPR0 value from vendor DRAM settings.
+config DRAM_SUN50I_H616_TPR2
+ hex "H616 DRAM TPR2 parameter"
+ default 0x0
+ help
+ TPR2 value from vendor DRAM settings.
+
config DRAM_SUN50I_H616_TPR10
hex "H616 DRAM TPR10 parameter"
help
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c
index 44bb153..1f9416d 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h616.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c
@@ -788,21 +788,37 @@
writel(val, &ptr[i]);
val = (para->tpr10 << 1) & 0x1e;
+ writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d8);
writel(val, SUNXI_DRAM_PHY0_BASE + 0x7dc);
writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e0);
+ writel(val, SUNXI_DRAM_PHY0_BASE + 0x7f4);
/* following configuration is DDR3 specific */
val = (para->tpr10 >> 7) & 0x1e;
- writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d4);
- if (para->ranks == 2) {
- val = (para->tpr10 >> 11) & 0x1e;
- writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c);
- }
- if (para->tpr0 & BIT(31)) {
- val = (para->tpr0 << 1) & 0x3e;
- writel(val, SUNXI_DRAM_PHY0_BASE + 0x78c);
- writel(val, SUNXI_DRAM_PHY0_BASE + 0x7a4);
- writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8);
+ if (para->tpr2 & 1) {
+ writel(val, SUNXI_DRAM_PHY0_BASE + 0x794);
+ if (para->ranks == 2) {
+ val = (para->tpr10 >> 11) & 0x1e;
+ writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e4);
+ }
+ if (para->tpr0 & BIT(31)) {
+ val = (para->tpr0 << 1) & 0x3e;
+ writel(val, SUNXI_DRAM_PHY0_BASE + 0x790);
+ writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8);
+ writel(val, SUNXI_DRAM_PHY0_BASE + 0x7cc);
+ }
+ } else {
+ writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d4);
+ if (para->ranks == 2) {
+ val = (para->tpr10 >> 11) & 0x1e;
+ writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c);
+ }
+ if (para->tpr0 & BIT(31)) {
+ val = (para->tpr0 << 1) & 0x3e;
+ writel(val, SUNXI_DRAM_PHY0_BASE + 0x78c);
+ writel(val, SUNXI_DRAM_PHY0_BASE + 0x7a4);
+ writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8);
+ }
}
}
@@ -812,7 +828,7 @@
(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
struct sunxi_mctl_ctl_reg * const mctl_ctl =
(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
- u32 val, *ptr;
+ u32 val, val2, *ptr, mr0, mr2;
int i;
if (para->bus_full_width)
@@ -821,20 +837,28 @@
val = 3;
clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x3c, 0xf, val);
- writel(0xd, SUNXI_DRAM_PHY0_BASE + 0x14);
- writel(0xd, SUNXI_DRAM_PHY0_BASE + 0x35c);
- writel(0xd, SUNXI_DRAM_PHY0_BASE + 0x368);
- writel(0xd, SUNXI_DRAM_PHY0_BASE + 0x374);
+ if (para->tpr2 & 0x100) {
+ val = 9;
+ val2 = 7;
+ } else {
+ val = 13;
+ val2 = 9;
+ }
+
+ writel(val, SUNXI_DRAM_PHY0_BASE + 0x14);
+ writel(val, SUNXI_DRAM_PHY0_BASE + 0x35c);
+ writel(val, SUNXI_DRAM_PHY0_BASE + 0x368);
+ writel(val, SUNXI_DRAM_PHY0_BASE + 0x374);
writel(0, SUNXI_DRAM_PHY0_BASE + 0x18);
writel(0, SUNXI_DRAM_PHY0_BASE + 0x360);
writel(0, SUNXI_DRAM_PHY0_BASE + 0x36c);
writel(0, SUNXI_DRAM_PHY0_BASE + 0x378);
- writel(9, SUNXI_DRAM_PHY0_BASE + 0x1c);
- writel(9, SUNXI_DRAM_PHY0_BASE + 0x364);
- writel(9, SUNXI_DRAM_PHY0_BASE + 0x370);
- writel(9, SUNXI_DRAM_PHY0_BASE + 0x37c);
+ writel(val2, SUNXI_DRAM_PHY0_BASE + 0x1c);
+ writel(val2, SUNXI_DRAM_PHY0_BASE + 0x364);
+ writel(val2, SUNXI_DRAM_PHY0_BASE + 0x370);
+ writel(val2, SUNXI_DRAM_PHY0_BASE + 0x37c);
ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xc0);
for (i = 0; i < ARRAY_SIZE(phy_init); i++)
@@ -890,7 +914,15 @@
writel(1, &mctl_ctl->swctl);
mctl_await_completion(&mctl_ctl->swstat, 1, 1);
- writel(0x1f14, &mctl_ctl->mrctrl1);
+ if (para->tpr2 & 0x100) {
+ mr0 = 0x1b50;
+ mr2 = 0x10;
+ } else {
+ mr0 = 0x1f14;
+ mr2 = 0x20;
+ }
+
+ writel(mr0, &mctl_ctl->mrctrl1);
writel(0x80000030, &mctl_ctl->mrctrl0);
mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
@@ -898,7 +930,7 @@
writel(0x80001030, &mctl_ctl->mrctrl0);
mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
- writel(0x20, &mctl_ctl->mrctrl1);
+ writel(mr2, &mctl_ctl->mrctrl1);
writel(0x80002030, &mctl_ctl->mrctrl0);
mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
@@ -1135,6 +1167,7 @@
.ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI,
.odt_en = CONFIG_DRAM_SUN50I_H616_ODT_EN,
.tpr0 = CONFIG_DRAM_SUN50I_H616_TPR0,
+ .tpr2 = CONFIG_DRAM_SUN50I_H616_TPR2,
.tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10,
.tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11,
.tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12,
diff --git a/arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c b/arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c
index f109e92..eea4d6a 100644
--- a/arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c
+++ b/arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c
@@ -50,9 +50,20 @@
u8 t_rdata_en = 9; /* ? */
u8 t_wr_lat = 5; /* ? */
- u8 twtp = tcl + 2 + tcwl; /* (WL + BL / 2 + tWR) / 2 */
- u8 twr2rd = trtp + 2 + tcwl; /* (WL + BL / 2 + tWTR) / 2 */
- u8 trd2wr = tcl + 3 - tcwl; /* (RL + BL / 2 + 2 - WL) / 2 */
+ u8 twtp; /* (WL + BL / 2 + tWR) / 2 */
+ u8 twr2rd; /* (WL + BL / 2 + tWTR) / 2 */
+ u8 trd2wr; /* (RL + BL / 2 + 2 - WL) / 2 */
+
+ if (para->tpr2 & 0x100) {
+ tcl = 5;
+ tcwl = 4;
+ t_rdata_en = 5;
+ t_wr_lat = 3;
+ }
+
+ twtp = tcl + 2 + tcwl;
+ twr2rd = trtp + 2 + tcwl;
+ trd2wr = tcl + 3 - tcwl;
/* set DRAM timing */
writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | tras,