[U-Boot] [PATCH v2 13/17] ram: rk3399: use common sdram driver
Kever Yang
kever.yang at rock-chips.com
Fri Oct 25 01:34:00 UTC 2019
From: YouMin Chen <cym at rock-chips.com>
RK3399's controller and phy are able to re-use the common code, migrate
to use the common driver and remove duplicated code.
Signed-off-by: YouMin Chen <cym at rock-chips.com>
Signed-off-by: Kever Yang <kever.yang at rock-chips.com>
---
Changes in v2: None
arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi | 4 +
arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi | 4 +
arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi | 4 +
.../arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi | 4 +
.../arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi | 4 +
.../rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi | 4 +
arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi | 4 +
.../include/asm/arch-rockchip/sdram_rk3399.h | 97 +-
arch/arm/mach-rockchip/Kconfig | 1 +
drivers/ram/rockchip/Kconfig | 21 +-
drivers/ram/rockchip/Makefile | 2 +-
.../ram/rockchip/sdram-rk3399-lpddr4-400.inc | 28 +-
.../ram/rockchip/sdram-rk3399-lpddr4-800.inc | 28 +-
drivers/ram/rockchip/sdram_debug.c | 147 +++
drivers/ram/rockchip/sdram_rk3399.c | 968 ++++++++++++------
15 files changed, 932 insertions(+), 388 deletions(-)
create mode 100644 drivers/ram/rockchip/sdram_debug.c
diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi
index 3708bd674b..7fae249536 100644
--- a/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi
+++ b/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi
@@ -13,6 +13,8 @@
0x0
0xf
0xf
+ 0xf
+ 0xf
1
0x80120e12
0x11030802
@@ -28,6 +30,8 @@
0x0
0xf
0xf
+ 0xf
+ 0xf
1
0x80120e12
0x11030802
diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi
index fcd01f8b46..23c7c34a9a 100644
--- a/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi
+++ b/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi
@@ -13,6 +13,8 @@
0x0
0xf
0xf
+ 0xf
+ 0xf
1
0x80151015
0x14040902
@@ -28,6 +30,8 @@
0x0
0xf
0xf
+ 0xf
+ 0xf
1
0x80151015
0x14040902
diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi
index c46c1996be..ea029ca90a 100644
--- a/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi
+++ b/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi
@@ -13,6 +13,8 @@
0x0
0xf
0xf
+ 0xf
+ 0xf
1
0x80181219
0x17050a03
@@ -28,6 +30,8 @@
0x0
0xf
0xf
+ 0xf
+ 0xf
1
0x80181219
0x17050a03
diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi
index d14e833d22..7296dbb80e 100644
--- a/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi
+++ b/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi
@@ -14,6 +14,8 @@
0x0
0xf
0xf
+ 0xf
+ 0xf
1
0x1d191519
0x14040808
@@ -29,6 +31,8 @@
0x0
0xf
0xf
+ 0xf
+ 0xf
1
0x1d191519
0x14040808
diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
index fc4cccb6a0..bf429c21e4 100644
--- a/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
+++ b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
@@ -13,6 +13,8 @@
0x0
0xf
0xf
+ 0xf
+ 0xf
1
0x1d191519
0x14040808
@@ -28,6 +30,8 @@
0x0
0xf
0xf
+ 0xf
+ 0xf
1
0x1d191519
0x14040808
diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi
index 2a627e1be5..96f459fd0b 100644
--- a/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi
+++ b/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi
@@ -13,6 +13,8 @@
0x0
0xf
0xf
+ 0xf
+ 0xf
1
0x801d181e
@@ -30,6 +32,8 @@
0x0
0xf
0xf
+ 0xf
+ 0xf
1
0x801d181e
diff --git a/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi b/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi
index 4a4414a960..f0c478d189 100644
--- a/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi
+++ b/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi
@@ -15,6 +15,8 @@
0x0
0xf
0xf
+ 0xf
+ 0xf
1
0x80241d22
0x15050f08
@@ -30,6 +32,8 @@
0x0
0xf
0xf
+ 0xf
+ 0xf
1
0x80241d22
0x15050f08
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h b/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
index 485bb3d889..9e1e22520f 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
@@ -6,6 +6,7 @@
#ifndef _ASM_ARCH_SDRAM_RK3399_H
#define _ASM_ARCH_SDRAM_RK3399_H
#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_msch.h>
struct rk3399_ddr_pctl_regs {
u32 denali_ctl[332];
@@ -19,55 +20,6 @@ struct rk3399_ddr_pi_regs {
u32 denali_pi[200];
};
-union noc_ddrtimingc0 {
- u32 d32;
- struct {
- unsigned burstpenalty : 4;
- unsigned reserved0 : 4;
- unsigned wrtomwr : 6;
- unsigned reserved1 : 18;
- } b;
-};
-
-union noc_ddrmode {
- u32 d32;
- struct {
- unsigned autoprecharge : 1;
- unsigned bypassfiltering : 1;
- unsigned fawbank : 1;
- unsigned burstsize : 2;
- unsigned mwrsize : 2;
- unsigned reserved2 : 1;
- unsigned forceorder : 8;
- unsigned forceorderstate : 8;
- unsigned reserved3 : 8;
- } b;
-};
-
-struct rk3399_msch_regs {
- u32 coreid;
- u32 revisionid;
- u32 ddrconf;
- u32 ddrsize;
- u32 ddrtiminga0;
- u32 ddrtimingb0;
- u32 ddrtimingc0;
- u32 devtodev0;
- u32 reserved0[(0x110 - 0x20) / 4];
- u32 ddrmode;
- u32 reserved1[(0x1000 - 0x114) / 4];
- u32 agingx0;
-};
-
-struct rk3399_msch_timings {
- u32 ddrtiminga0;
- u32 ddrtimingb0;
- union noc_ddrtimingc0 ddrtimingc0;
- u32 devtodev0;
- union noc_ddrmode ddrmode;
- u32 agingx0;
-};
-
struct rk3399_ddr_cic_regs {
u32 cic_ctrl0;
u32 cic_ctrl1;
@@ -84,14 +36,38 @@ struct rk3399_ddr_cic_regs {
#define START 1
/* DENALI_CTL_68 */
-#define PWRUP_SREFRESH_EXIT (1 << 16)
+#define PWRUP_SREFRESH_EXIT BIT(16)
/* DENALI_CTL_274 */
#define MEM_RST_VALID 1
+struct msch_regs {
+ u32 coreid;
+ u32 revisionid;
+ u32 ddrconf;
+ u32 ddrsize;
+ union noc_ddrtiminga0 ddrtiminga0;
+ union noc_ddrtimingb0 ddrtimingb0;
+ union noc_ddrtimingc0 ddrtimingc0;
+ union noc_devtodev0 devtodev0;
+ u32 reserved0[(0x110 - 0x20) / 4];
+ union noc_ddrmode ddrmode;
+ u32 reserved1[(0x1000 - 0x114) / 4];
+ u32 agingx0;
+};
+
+struct sdram_msch_timings {
+ union noc_ddrtiminga0 ddrtiminga0;
+ union noc_ddrtimingb0 ddrtimingb0;
+ union noc_ddrtimingc0 ddrtimingc0;
+ union noc_devtodev0 devtodev0;
+ union noc_ddrmode ddrmode;
+ u32 agingx0;
+};
+
struct rk3399_sdram_channel {
struct sdram_cap_info cap_info;
- struct rk3399_msch_timings noc_timings;
+ struct sdram_msch_timings noc_timings;
};
struct rk3399_sdram_params {
@@ -102,11 +78,20 @@ struct rk3399_sdram_params {
struct rk3399_ddr_publ_regs phy_regs;
};
-#define PI_CA_TRAINING (1 << 0)
-#define PI_WRITE_LEVELING (1 << 1)
-#define PI_READ_GATE_TRAINING (1 << 2)
-#define PI_READ_LEVELING (1 << 3)
-#define PI_WDQ_LEVELING (1 << 4)
+#define PI_CA_TRAINING BIT(0)
+#define PI_WRITE_LEVELING BIT(1)
+#define PI_READ_GATE_TRAINING BIT(2)
+#define PI_READ_LEVELING BIT(3)
+#define PI_WDQ_LEVELING BIT(4)
#define PI_FULL_TRAINING 0xff
+enum {
+ STRIDE_128B = 0,
+ STRIDE_256B = 1,
+ STRIDE_512B = 2,
+ STRIDE_4KB = 3,
+ UN_STRIDE = 4,
+ PART_STRIDE = 5
+};
+
#endif
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 5f1ad51cac..7746b661e5 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -184,6 +184,7 @@ config ROCKCHIP_RK3399
select DM_REGULATOR_FIXED
select BOARD_LATE_INIT
imply ROCKCHIP_COMMON_BOARD
+ imply ROCKCHIP_SDRAM_COMMON
imply SPL_ROCKCHIP_COMMON_BOARD
imply TPL_SERIAL_SUPPORT
imply TPL_LIBCOMMON_SUPPORT
diff --git a/drivers/ram/rockchip/Kconfig b/drivers/ram/rockchip/Kconfig
index dcc06b3fd3..3f44fb3fce 100644
--- a/drivers/ram/rockchip/Kconfig
+++ b/drivers/ram/rockchip/Kconfig
@@ -11,29 +11,10 @@ config ROCKCHIP_SDRAM_COMMON
help
This enable sdram common driver
-if RAM_ROCKCHIP
-
-config RAM_ROCKCHIP_DEBUG
- bool "Rockchip ram drivers debugging"
- help
- This enables debugging ram driver API's for the platforms
- based on Rockchip SoCs.
-
- This is an option for developers to understand the ram drivers
- initialization, configurations and etc.
-
-config RAM_RK3399
- bool "Ram driver for Rockchip RK3399"
- default ROCKCHIP_RK3399
- help
- This enables ram drivers support for the platforms based on
- Rockchip RK3399 SoC.
-
config RAM_RK3399_LPDDR4
bool "LPDDR4 support for Rockchip RK3399"
- depends on RAM_RK3399
+ depends on RAM_ROCKCHIP && ROCKCHIP_RK3399
help
This enables LPDDR4 sdram code support for the platforms based
on Rockchip RK3399 SoC.
-endif # RAM_ROCKCHIP
diff --git a/drivers/ram/rockchip/Makefile b/drivers/ram/rockchip/Makefile
index b42ef91c21..47b9b1bebb 100644
--- a/drivers/ram/rockchip/Makefile
+++ b/drivers/ram/rockchip/Makefile
@@ -9,4 +9,4 @@ obj-$(CONFIG_ROCKCHIP_RK3188) = sdram_rk3188.o
obj-$(CONFIG_ROCKCHIP_RK322X) = sdram_rk322x.o
obj-$(CONFIG_ROCKCHIP_RK3288) = sdram_rk3288.o
obj-$(CONFIG_ROCKCHIP_RK3328) += sdram_rk3328.o sdram_pctl_px30.o sdram_phy_px30.o
-obj-$(CONFIG_RAM_RK3399) += sdram_rk3399.o
+obj-$(CONFIG_ROCKCHIP_RK3399) += sdram_rk3399.o
diff --git a/drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc b/drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc
index c50a03d9dd..6ddc01c49d 100644
--- a/drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc
+++ b/drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc
@@ -16,15 +16,23 @@
.row_3_4 = 0x0,
.cs0_row = 0xF,
.cs1_row = 0xF,
+ .cs0_high16bit_row = 0xF,
+ .cs1_high16bit_row = 0xF,
.ddrconfig = 1,
},
{
- .ddrtiminga0 = 0x80241d22,
- .ddrtimingb0 = 0x15050f08,
+ .ddrtiminga0 = {
+ 0x80241d22,
+ },
+ .ddrtimingb0 = {
+ 0x15050f08,
+ },
.ddrtimingc0 = {
0x00000602,
},
- .devtodev0 = 0x00002122,
+ .devtodev0 = {
+ 0x00002122,
+ },
.ddrmode = {
0x0000004c,
},
@@ -41,15 +49,23 @@
.row_3_4 = 0x0,
.cs0_row = 0xF,
.cs1_row = 0xF,
+ .cs0_high16bit_row = 0xF,
+ .cs1_high16bit_row = 0xF,
.ddrconfig = 1,
},
{
- .ddrtiminga0 = 0x80241d22,
- .ddrtimingb0 = 0x15050f08,
+ .ddrtiminga0 = {
+ 0x80241d22,
+ },
+ .ddrtimingb0 = {
+ 0x15050f08,
+ },
.ddrtimingc0 = {
0x00000602,
},
- .devtodev0 = 0x00002122,
+ .devtodev0 = {
+ 0x00002122,
+ },
.ddrmode = {
0x0000004c,
},
diff --git a/drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc b/drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc
index d8ae3359a3..307f6ee458 100644
--- a/drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc
+++ b/drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc
@@ -16,15 +16,23 @@
.row_3_4 = 0x0,
.cs0_row = 0xF,
.cs1_row = 0xF,
+ .cs0_high16bit_row = 0xF,
+ .cs1_high16bit_row = 0xF,
.ddrconfig = 1,
},
{
- .ddrtiminga0 = 0x80241d22,
- .ddrtimingb0 = 0x15050f08,
+ .ddrtiminga0 = {
+ 0x80241d22,
+ },
+ .ddrtimingb0 = {
+ 0x15050f08,
+ },
.ddrtimingc0 = {
0x00000602,
},
- .devtodev0 = 0x00002122,
+ .devtodev0 = {
+ 0x00002122,
+ },
.ddrmode = {
0x0000004c,
},
@@ -41,15 +49,23 @@
.row_3_4 = 0x0,
.cs0_row = 0xF,
.cs1_row = 0xF,
+ .cs0_high16bit_row = 0xF,
+ .cs1_high16bit_row = 0xF,
.ddrconfig = 1,
},
{
- .ddrtiminga0 = 0x80241d22,
- .ddrtimingb0 = 0x15050f08,
+ .ddrtiminga0 = {
+ 0x80241d22,
+ },
+ .ddrtimingb0 = {
+ 0x15050f08,
+ },
.ddrtimingc0 = {
0x00000602,
},
- .devtodev0 = 0x00002122,
+ .devtodev0 = {
+ 0x00002122,
+ },
.ddrmode = {
0x0000004c,
},
diff --git a/drivers/ram/rockchip/sdram_debug.c b/drivers/ram/rockchip/sdram_debug.c
new file mode 100644
index 0000000000..133d1938d5
--- /dev/null
+++ b/drivers/ram/rockchip/sdram_debug.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ * (C) Copyright 2019 Amarula Solutions.
+ * Author: Jagan Teki <jagan at amarulasolutions.com>
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <asm/arch-rockchip/sdram.h>
+
+void sdram_print_dram_type(unsigned char dramtype)
+{
+ switch (dramtype) {
+ case DDR3:
+ printascii("DDR3");
+ break;
+ case DDR4:
+ printascii("DDR4");
+ break;
+ case LPDDR2:
+ printascii("LPDDR2");
+ break;
+ case LPDDR3:
+ printascii("LPDDR3");
+ break;
+ case LPDDR4:
+ printascii("LPDDR4");
+ break;
+ default:
+ printascii("Unknown Device");
+ break;
+ }
+}
+
+/**
+ * cs = 0, cs0
+ * cs = 1, cs1
+ * cs => 2, cs0+cs1
+ * note: it didn't consider about row_3_4
+ */
+u64 sdram_get_cs_cap(struct sdram_cap_info *cap_info, u32 cs, u32 dram_type)
+{
+ u32 bg;
+ u64 cap[2];
+
+ if (dram_type == DDR4)
+ /* DDR4 8bit dram BG = 2(4bank groups),
+ * 16bit dram BG = 1 (2 bank groups)
+ */
+ bg = (cap_info->dbw == 0) ? 2 : 1;
+ else
+ bg = 0;
+
+ cap[0] = 1llu << (cap_info->bw + cap_info->col +
+ bg + cap_info->bk + cap_info->cs0_row);
+
+ if (cap_info->rank == 2)
+ cap[1] = 1llu << (cap_info->bw + cap_info->col +
+ bg + cap_info->bk + cap_info->cs1_row);
+ else
+ cap[1] = 0;
+
+ if (cs == 0)
+ return cap[0];
+ else if (cs == 1)
+ return cap[1];
+ else
+ return (cap[0] + cap[1]);
+}
+
+void sdram_print_ddr_info(struct sdram_cap_info *cap_info,
+ struct sdram_base_params *base)
+{
+ u32 bg, cap;
+
+ bg = (cap_info->dbw == 0) ? 2 : 1;
+
+ sdram_print_dram_type(base->dramtype);
+
+ printascii(", ");
+ printdec(base->ddr_freq);
+ printascii("MHz\n");
+
+ printascii("BW=");
+ printdec(8 << cap_info->bw);
+
+ printascii(" Col=");
+ printdec(cap_info->col);
+
+ printascii(" Bk=");
+ printdec(0x1 << cap_info->bk);
+ if (base->dramtype == DDR4) {
+ printascii(" BG=");
+ printdec(1 << bg);
+ }
+
+ printascii(" CS0 Row=");
+ printdec(cap_info->cs0_row);
+ if (cap_info->rank > 1) {
+ printascii(" CS1 Row=");
+ printdec(cap_info->cs1_row);
+ }
+
+ printascii(" CS=");
+ printdec(cap_info->rank);
+
+ printascii(" Die BW=");
+ printdec(8 << cap_info->dbw);
+
+ cap = sdram_get_cs_cap(cap_info, 3, base->dramtype);
+ if (cap_info->row_3_4)
+ cap = cap * 3 / 4;
+
+ printascii(" Size=");
+ printdec(cap >> 20);
+ printascii("MB\n");
+}
+
+void sdram_print_stride(unsigned int stride)
+{
+ switch (stride) {
+ case 0xc:
+ printf("128B stride\n");
+ break;
+ case 5:
+ case 9:
+ case 0xd:
+ case 0x11:
+ case 0x19:
+ printf("256B stride\n");
+ break;
+ case 0xa:
+ case 0xe:
+ case 0x12:
+ printf("512B stride\n");
+ break;
+ case 0xf:
+ printf("4K stride\n");
+ break;
+ case 0x1f:
+ printf("32MB + 256B stride\n");
+ break;
+ default:
+ printf("no stride\n");
+ }
+}
diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c
index 9b7de4ae41..073fba0990 100644
--- a/drivers/ram/rockchip/sdram_rk3399.c
+++ b/drivers/ram/rockchip/sdram_rk3399.c
@@ -52,7 +52,7 @@ struct chan_info {
struct rk3399_ddr_pctl_regs *pctl;
struct rk3399_ddr_pi_regs *pi;
struct rk3399_ddr_publ_regs *publ;
- struct rk3399_msch_regs *msch;
+ struct msch_regs *msch;
};
struct dram_info {
@@ -74,10 +74,15 @@ struct dram_info {
};
struct sdram_rk3399_ops {
- int (*data_training)(struct dram_info *dram, u32 channel, u8 rank,
- struct rk3399_sdram_params *sdram);
- int (*set_rate)(struct dram_info *dram,
- struct rk3399_sdram_params *params);
+ int (*data_training_first)(struct dram_info *dram, u32 channel, u8 rank,
+ struct rk3399_sdram_params *sdram);
+ int (*set_rate_index)(struct dram_info *dram,
+ struct rk3399_sdram_params *params);
+ void (*modify_param)(const struct chan_info *chan,
+ struct rk3399_sdram_params *params);
+ struct rk3399_sdram_params *
+ (*get_phy_index_params)(u32 phy_fn,
+ struct rk3399_sdram_params *params);
};
#if defined(CONFIG_TPL_BUILD) || \
@@ -196,11 +201,6 @@ struct io_setting {
},
};
-/**
- * phy = 0, PHY boot freq
- * phy = 1, PHY index 0
- * phy = 2, PHY index 1
- */
static struct io_setting *
lpddr4_get_io_settings(const struct rk3399_sdram_params *params, u32 mr5)
{
@@ -223,32 +223,21 @@ lpddr4_get_io_settings(const struct rk3399_sdram_params *params, u32 mr5)
return io;
}
-static void *get_denali_phy(const struct chan_info *chan,
- struct rk3399_sdram_params *params, bool reg)
-{
- return reg ? &chan->publ->denali_phy : ¶ms->phy_regs.denali_phy;
-}
-
static void *get_denali_ctl(const struct chan_info *chan,
struct rk3399_sdram_params *params, bool reg)
{
return reg ? &chan->pctl->denali_ctl : ¶ms->pctl_regs.denali_ctl;
}
-static void *get_ddrc0_con(struct dram_info *dram, u8 channel)
+static void *get_denali_phy(const struct chan_info *chan,
+ struct rk3399_sdram_params *params, bool reg)
{
- return (channel == 0) ? &dram->grf->ddrc0_con0 : &dram->grf->ddrc0_con1;
+ return reg ? &chan->publ->denali_phy : ¶ms->phy_regs.denali_phy;
}
-static void copy_to_reg(u32 *dest, const u32 *src, u32 n)
+static void *get_ddrc0_con(struct dram_info *dram, u8 channel)
{
- int i;
-
- for (i = 0; i < n / sizeof(u32); i++) {
- writel(*src, dest);
- src++;
- dest++;
- }
+ return (channel == 0) ? &dram->grf->ddrc0_con0 : &dram->grf->ddrc1_con0;
}
static void rkclk_ddr_reset(struct rk3399_cru *cru, u32 channel, u32 ctl,
@@ -344,7 +333,7 @@ static void set_memory_map(const struct chan_info *chan, u32 channel,
((3 - sdram_ch->cap_info.bk) << 16) |
((16 - row) << 24));
- if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) {
+ if (params->base.dramtype == LPDDR4) {
if (cs_map == 1)
cs_map = 0x5;
else if (cs_map == 2)
@@ -496,7 +485,7 @@ static int phy_io_config(const struct chan_info *chan,
/* PHY_939 PHY_PAD_CS_DRIVE */
clrsetbits_le32(&denali_phy[939], 0x7 << 14, mode_sel << 14);
- if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) {
+ if (params->base.dramtype == LPDDR4) {
/* BOOSTP_EN & BOOSTN_EN */
reg_value = ((PHY_BOOSTP_EN << 4) | PHY_BOOSTN_EN);
/* PHY_925 PHY_PAD_FDBK_DRIVE2 */
@@ -563,7 +552,7 @@ static int phy_io_config(const struct chan_info *chan,
/* PHY_939 PHY_PAD_CS_DRIVE */
clrsetbits_le32(&denali_phy[939], 0x3 << 17, speed << 17);
- if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) {
+ if (params->base.dramtype == LPDDR4) {
/* RX_CM_INPUT */
reg_value = PHY_RX_CM_INPUT;
/* PHY_924 PHY_PAD_FDBK_DRIVE */
@@ -733,7 +722,7 @@ static void set_ds_odt(const struct chan_info *chan,
/* phy_adr_tsel_select_ 8bits DENALI_PHY_544/672/800 offset_0 */
reg_value = tsel_wr_select_ca_n | (tsel_wr_select_ca_p << 0x4);
- if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) {
+ if (params->base.dramtype == LPDDR4) {
/* LPDDR4 these register read always return 0, so
* can not use clrsetbits_le32(), need to write32
*/
@@ -810,46 +799,107 @@ static void set_ds_odt(const struct chan_info *chan,
phy_io_config(chan, params, mr5);
}
-static void pctl_start(struct dram_info *dram, u8 channel)
+static void pctl_start(struct dram_info *dram,
+ struct rk3399_sdram_params *params,
+ u32 channel_mask)
{
- const struct chan_info *chan = &dram->chan[channel];
- u32 *denali_ctl = chan->pctl->denali_ctl;
- u32 *denali_phy = chan->publ->denali_phy;
- u32 *ddrc0_con = get_ddrc0_con(dram, channel);
+ const struct chan_info *chan_0 = &dram->chan[0];
+ const struct chan_info *chan_1 = &dram->chan[1];
+
+ u32 *denali_ctl_0 = chan_0->pctl->denali_ctl;
+ u32 *denali_phy_0 = chan_0->publ->denali_phy;
+ u32 *ddrc0_con_0 = get_ddrc0_con(dram, 0);
+ u32 *denali_ctl_1 = chan_1->pctl->denali_ctl;
+ u32 *denali_phy_1 = chan_1->publ->denali_phy;
+ u32 *ddrc1_con_0 = get_ddrc0_con(dram, 1);
u32 count = 0;
u32 byte, tmp;
- writel(0x01000000, &ddrc0_con);
+ /* PHY_DLL_RST_EN */
+ if (channel_mask & 1) {
+ writel(0x01000000, &ddrc0_con_0);
+ clrsetbits_le32(&denali_phy_0[957], 0x3 << 24, 0x2 << 24);
+ }
- clrsetbits_le32(&denali_phy[957], 0x3 << 24, 0x2 << 24);
+ if (channel_mask & 1) {
+ count = 0;
+ while (!(readl(&denali_ctl_0[203]) & (1 << 3))) {
+ if (count > 1000) {
+ printf("%s: Failed to init pctl channel 0\n",
+ __func__);
+ while (1)
+ ;
+ }
+ udelay(1);
+ count++;
+ }
- while (!(readl(&denali_ctl[203]) & (1 << 3))) {
- if (count > 1000) {
- printf("%s: Failed to init pctl for channel %d\n",
- __func__, channel);
- while (1)
- ;
+ writel(0x01000100, &ddrc0_con_0);
+ for (byte = 0; byte < 4; byte++) {
+ tmp = 0x820;
+ writel((tmp << 16) | tmp,
+ &denali_phy_0[53 + (128 * byte)]);
+ writel((tmp << 16) | tmp,
+ &denali_phy_0[54 + (128 * byte)]);
+ writel((tmp << 16) | tmp,
+ &denali_phy_0[55 + (128 * byte)]);
+ writel((tmp << 16) | tmp,
+ &denali_phy_0[56 + (128 * byte)]);
+ writel((tmp << 16) | tmp,
+ &denali_phy_0[57 + (128 * byte)]);
+ clrsetbits_le32(&denali_phy_0[58 + (128 * byte)],
+ 0xffff, tmp);
}
+ clrsetbits_le32(&denali_ctl_0[68], PWRUP_SREFRESH_EXIT,
+ dram->pwrup_srefresh_exit[0]);
+ }
- udelay(1);
- count++;
+ if (channel_mask & 2) {
+ writel(0x01000000, &ddrc1_con_0);
+ clrsetbits_le32(&denali_phy_1[957], 0x3 << 24, 0x2 << 24);
}
+ if (channel_mask & 2) {
+ count = 0;
+ while (!(readl(&denali_ctl_1[203]) & (1 << 3))) {
+ if (count > 1000) {
+ printf("%s: Failed to init pctl channel 1\n",
+ __func__);
+ while (1)
+ ;
+ }
+ udelay(1);
+ count++;
+ }
- writel(0x01000100, &ddrc0_con);
+ writel(0x01000100, &ddrc1_con_0);
+ for (byte = 0; byte < 4; byte++) {
+ tmp = 0x820;
+ writel((tmp << 16) | tmp,
+ &denali_phy_1[53 + (128 * byte)]);
+ writel((tmp << 16) | tmp,
+ &denali_phy_1[54 + (128 * byte)]);
+ writel((tmp << 16) | tmp,
+ &denali_phy_1[55 + (128 * byte)]);
+ writel((tmp << 16) | tmp,
+ &denali_phy_1[56 + (128 * byte)]);
+ writel((tmp << 16) | tmp,
+ &denali_phy_1[57 + (128 * byte)]);
+ clrsetbits_le32(&denali_phy_1[58 + (128 * byte)],
+ 0xffff, tmp);
+ }
- for (byte = 0; byte < 4; byte++) {
- tmp = 0x820;
- writel((tmp << 16) | tmp, &denali_phy[53 + (128 * byte)]);
- writel((tmp << 16) | tmp, &denali_phy[54 + (128 * byte)]);
- writel((tmp << 16) | tmp, &denali_phy[55 + (128 * byte)]);
- writel((tmp << 16) | tmp, &denali_phy[56 + (128 * byte)]);
- writel((tmp << 16) | tmp, &denali_phy[57 + (128 * byte)]);
+ clrsetbits_le32(&denali_ctl_1[68], PWRUP_SREFRESH_EXIT,
+ dram->pwrup_srefresh_exit[1]);
- clrsetbits_le32(&denali_phy[58 + (128 * byte)], 0xffff, tmp);
+ /*
+ * restore channel 1 RESET original setting
+ * to avoid 240ohm too weak to prevent ESD test
+ */
+ if (params->base.dramtype == LPDDR4)
+ clrsetbits_le32(&denali_phy_1[937], 0xff,
+ params->phy_regs.denali_phy[937] &
+ 0xFF);
}
-
- clrsetbits_le32(&denali_ctl[68], PWRUP_SREFRESH_EXIT,
- dram->pwrup_srefresh_exit[channel]);
}
static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,
@@ -861,13 +911,16 @@ static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,
const u32 *params_ctl = params->pctl_regs.denali_ctl;
const u32 *params_phy = params->phy_regs.denali_phy;
u32 tmp, tmp1, tmp2;
+ struct rk3399_sdram_params *params_cfg;
+ u32 byte;
+ dram->ops->modify_param(chan, params);
/*
* work around controller bug:
* Do not program DRAM_CLASS until NO_PHY_IND_TRAIN_INT is programmed
*/
- copy_to_reg(&denali_ctl[1], ¶ms_ctl[1],
- sizeof(struct rk3399_ddr_pctl_regs) - 4);
+ sdram_copy_to_reg(&denali_ctl[1], ¶ms_ctl[1],
+ sizeof(struct rk3399_ddr_pctl_regs) - 4);
writel(params_ctl[0], &denali_ctl[0]);
/*
@@ -884,8 +937,8 @@ static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,
writel(tmp + tmp1, &denali_ctl[14]);
}
- copy_to_reg(denali_pi, ¶ms->pi_regs.denali_pi[0],
- sizeof(struct rk3399_ddr_pi_regs));
+ sdram_copy_to_reg(denali_pi, ¶ms->pi_regs.denali_pi[0],
+ sizeof(struct rk3399_ddr_pi_regs));
/* rank count need to set for init */
set_memory_map(chan, channel, params);
@@ -894,7 +947,7 @@ static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,
writel(params->phy_regs.denali_phy[911], &denali_phy[911]);
writel(params->phy_regs.denali_phy[912], &denali_phy[912]);
- if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) {
+ if (params->base.dramtype == LPDDR4) {
writel(params->phy_regs.denali_phy[898], &denali_phy[898]);
writel(params->phy_regs.denali_phy[919], &denali_phy[919]);
}
@@ -927,41 +980,67 @@ static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,
}
}
- copy_to_reg(&denali_phy[896], ¶ms_phy[896], (958 - 895) * 4);
- copy_to_reg(&denali_phy[0], ¶ms_phy[0], (90 - 0 + 1) * 4);
- copy_to_reg(&denali_phy[128], ¶ms_phy[128], (218 - 128 + 1) * 4);
- copy_to_reg(&denali_phy[256], ¶ms_phy[256], (346 - 256 + 1) * 4);
- copy_to_reg(&denali_phy[384], ¶ms_phy[384], (474 - 384 + 1) * 4);
- copy_to_reg(&denali_phy[512], ¶ms_phy[512], (549 - 512 + 1) * 4);
- copy_to_reg(&denali_phy[640], ¶ms_phy[640], (677 - 640 + 1) * 4);
- copy_to_reg(&denali_phy[768], ¶ms_phy[768], (805 - 768 + 1) * 4);
- set_ds_odt(chan, params, true, 0);
+ sdram_copy_to_reg(&denali_phy[896], ¶ms_phy[896], (958 - 895) * 4);
+ sdram_copy_to_reg(&denali_phy[0], ¶ms_phy[0], (90 - 0 + 1) * 4);
+ sdram_copy_to_reg(&denali_phy[128], ¶ms_phy[128],
+ (218 - 128 + 1) * 4);
+ sdram_copy_to_reg(&denali_phy[256], ¶ms_phy[256],
+ (346 - 256 + 1) * 4);
+ sdram_copy_to_reg(&denali_phy[384], ¶ms_phy[384],
+ (474 - 384 + 1) * 4);
+ sdram_copy_to_reg(&denali_phy[512], ¶ms_phy[512],
+ (549 - 512 + 1) * 4);
+ sdram_copy_to_reg(&denali_phy[640], ¶ms_phy[640],
+ (677 - 640 + 1) * 4);
+ sdram_copy_to_reg(&denali_phy[768], ¶ms_phy[768],
+ (805 - 768 + 1) * 4);
- /*
- * phy_dqs_tsel_wr_timing_X 8bits DENALI_PHY_84/212/340/468 offset_8
- * dqs_tsel_wr_end[7:4] add Half cycle
- */
- tmp = (readl(&denali_phy[84]) >> 8) & 0xff;
- clrsetbits_le32(&denali_phy[84], 0xff << 8, (tmp + 0x10) << 8);
- tmp = (readl(&denali_phy[212]) >> 8) & 0xff;
- clrsetbits_le32(&denali_phy[212], 0xff << 8, (tmp + 0x10) << 8);
- tmp = (readl(&denali_phy[340]) >> 8) & 0xff;
- clrsetbits_le32(&denali_phy[340], 0xff << 8, (tmp + 0x10) << 8);
- tmp = (readl(&denali_phy[468]) >> 8) & 0xff;
- clrsetbits_le32(&denali_phy[468], 0xff << 8, (tmp + 0x10) << 8);
+ if (params->base.dramtype == LPDDR4)
+ params_cfg = dram->ops->get_phy_index_params(1, params);
+ else
+ params_cfg = dram->ops->get_phy_index_params(0, params);
+
+ clrsetbits_le32(¶ms_cfg->phy_regs.denali_phy[896], 0x3 << 8,
+ 0 << 8);
+ writel(params_cfg->phy_regs.denali_phy[896], &denali_phy[896]);
+
+ writel(params->phy_regs.denali_phy[83] + (0x10 << 16),
+ &denali_phy[83]);
+ writel(params->phy_regs.denali_phy[84] + (0x10 << 8),
+ &denali_phy[84]);
+ writel(params->phy_regs.denali_phy[211] + (0x10 << 16),
+ &denali_phy[211]);
+ writel(params->phy_regs.denali_phy[212] + (0x10 << 8),
+ &denali_phy[212]);
+ writel(params->phy_regs.denali_phy[339] + (0x10 << 16),
+ &denali_phy[339]);
+ writel(params->phy_regs.denali_phy[340] + (0x10 << 8),
+ &denali_phy[340]);
+ writel(params->phy_regs.denali_phy[467] + (0x10 << 16),
+ &denali_phy[467]);
+ writel(params->phy_regs.denali_phy[468] + (0x10 << 8),
+ &denali_phy[468]);
- /*
- * phy_dqs_tsel_wr_timing_X 8bits DENALI_PHY_83/211/339/467 offset_8
- * dq_tsel_wr_end[7:4] add Half cycle
- */
- tmp = (readl(&denali_phy[83]) >> 16) & 0xff;
- clrsetbits_le32(&denali_phy[83], 0xff << 16, (tmp + 0x10) << 16);
- tmp = (readl(&denali_phy[211]) >> 16) & 0xff;
- clrsetbits_le32(&denali_phy[211], 0xff << 16, (tmp + 0x10) << 16);
- tmp = (readl(&denali_phy[339]) >> 16) & 0xff;
- clrsetbits_le32(&denali_phy[339], 0xff << 16, (tmp + 0x10) << 16);
- tmp = (readl(&denali_phy[467]) >> 16) & 0xff;
- clrsetbits_le32(&denali_phy[467], 0xff << 16, (tmp + 0x10) << 16);
+ if (params->base.dramtype == LPDDR4) {
+ /*
+ * to improve write dqs and dq phase from 1.5ns to 3.5ns
+ * at 50MHz. this's the measure result from oscilloscope
+ * of dqs and dq write signal.
+ */
+ for (byte = 0; byte < 4; byte++) {
+ tmp = 0x680;
+ clrsetbits_le32(&denali_phy[1 + (128 * byte)],
+ 0xfff << 8, tmp << 8);
+ }
+ /*
+ * to workaround 366ball two channel's RESET connect to
+ * one RESET signal of die
+ */
+ if (channel == 1)
+ clrsetbits_le32(&denali_phy[937], 0xff,
+ PHY_DRV_ODT_240 |
+ (PHY_DRV_ODT_240 << 0x4));
+ }
return 0;
}
@@ -1392,7 +1471,7 @@ static void set_ddrconfig(const struct chan_info *chan,
unsigned char channel, u32 ddrconfig)
{
/* only need to set ddrconfig */
- struct rk3399_msch_regs *ddr_msch_regs = chan->msch;
+ struct msch_regs *ddr_msch_regs = chan->msch;
unsigned int cs0_cap = 0;
unsigned int cs1_cap = 0;
@@ -1413,52 +1492,43 @@ static void set_ddrconfig(const struct chan_info *chan,
&ddr_msch_regs->ddrsize);
}
+static void sdram_msch_config(struct msch_regs *msch,
+ struct sdram_msch_timings *noc_timings)
+{
+ writel(noc_timings->ddrtiminga0.d32,
+ &msch->ddrtiminga0.d32);
+ writel(noc_timings->ddrtimingb0.d32,
+ &msch->ddrtimingb0.d32);
+ writel(noc_timings->ddrtimingc0.d32,
+ &msch->ddrtimingc0.d32);
+ writel(noc_timings->devtodev0.d32,
+ &msch->devtodev0.d32);
+ writel(noc_timings->ddrmode.d32,
+ &msch->ddrmode.d32);
+}
+
static void dram_all_config(struct dram_info *dram,
- const struct rk3399_sdram_params *params)
+ struct rk3399_sdram_params *params)
{
u32 sys_reg2 = 0;
u32 sys_reg3 = 0;
unsigned int channel, idx;
- sys_reg2 |= SYS_REG_ENC_DDRTYPE(params->base.dramtype);
- sys_reg2 |= SYS_REG_ENC_NUM_CH(params->base.num_channels);
-
for (channel = 0, idx = 0;
(idx < params->base.num_channels) && (channel < 2);
channel++) {
- const struct rk3399_sdram_channel *info = ¶ms->ch[channel];
- struct rk3399_msch_regs *ddr_msch_regs;
- const struct rk3399_msch_timings *noc_timing;
+ struct msch_regs *ddr_msch_regs;
+ struct sdram_msch_timings *noc_timing;
if (params->ch[channel].cap_info.col == 0)
continue;
idx++;
- sys_reg2 |= SYS_REG_ENC_ROW_3_4(info->cap_info.row_3_4, channel);
- sys_reg2 |= SYS_REG_ENC_CHINFO(channel);
- sys_reg2 |= SYS_REG_ENC_RANK(info->cap_info.rank, channel);
- sys_reg2 |= SYS_REG_ENC_COL(info->cap_info.col, channel);
- sys_reg2 |= SYS_REG_ENC_BK(info->cap_info.bk, channel);
- sys_reg2 |= SYS_REG_ENC_BW(info->cap_info.bw, channel);
- sys_reg2 |= SYS_REG_ENC_DBW(info->cap_info.dbw, channel);
- SYS_REG_ENC_CS0_ROW(info->cap_info.cs0_row, sys_reg2, sys_reg3, channel);
- if (info->cap_info.cs1_row)
- SYS_REG_ENC_CS1_ROW(info->cap_info.cs1_row, sys_reg2,
- sys_reg3, channel);
- sys_reg3 |= SYS_REG_ENC_CS1_COL(info->cap_info.col, channel);
- sys_reg3 |= SYS_REG_ENC_VERSION(DDR_SYS_REG_VERSION);
-
+ sdram_org_config(¶ms->ch[channel].cap_info,
+ ¶ms->base, &sys_reg2,
+ &sys_reg3, channel);
ddr_msch_regs = dram->chan[channel].msch;
noc_timing = ¶ms->ch[channel].noc_timings;
- writel(noc_timing->ddrtiminga0,
- &ddr_msch_regs->ddrtiminga0);
- writel(noc_timing->ddrtimingb0,
- &ddr_msch_regs->ddrtimingb0);
- writel(noc_timing->ddrtimingc0.d32,
- &ddr_msch_regs->ddrtimingc0);
- writel(noc_timing->devtodev0,
- &ddr_msch_regs->devtodev0);
- writel(noc_timing->ddrmode.d32,
- &ddr_msch_regs->ddrmode);
+ sdram_msch_config(ddr_msch_regs, noc_timing);
/**
* rank 1 memory clock disable (dfi_dram_clk_disable = 1)
@@ -1494,7 +1564,7 @@ static void set_cap_relate_config(const struct chan_info *chan,
{
u32 *denali_ctl = chan->pctl->denali_ctl;
u32 tmp;
- struct rk3399_msch_timings *noc_timing;
+ struct sdram_msch_timings *noc_timing;
if (params->base.dramtype == LPDDR3) {
tmp = (8 << params->ch[channel].cap_info.bw) /
@@ -1566,9 +1636,14 @@ static u32 calculate_ddrconfig(struct rk3399_sdram_params *params, u32 channel)
return i;
}
+static void set_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf, u32 stride)
+{
+ rk_clrsetreg(&pmusgrf->soc_con4, 0x1f << 10, stride << 10);
+}
+
#if !defined(CONFIG_RAM_RK3399_LPDDR4)
-static int default_data_training(struct dram_info *dram, u32 channel, u8 rank,
- struct rk3399_sdram_params *params)
+static int data_training_first(struct dram_info *dram, u32 channel, u8 rank,
+ struct rk3399_sdram_params *params)
{
u8 training_flag = PI_READ_GATE_TRAINING;
@@ -1629,31 +1704,72 @@ static int switch_to_phy_index1(struct dram_info *dram,
return 0;
}
+struct rk3399_sdram_params
+ *get_phy_index_params(u32 phy_fn,
+ struct rk3399_sdram_params *params)
+{
+ if (phy_fn == 0)
+ return params;
+ else
+ return NULL;
+}
+
+void modify_param(const struct chan_info *chan,
+ struct rk3399_sdram_params *params)
+{
+ struct rk3399_sdram_params *params_cfg;
+ u32 *denali_pi_params;
+
+ denali_pi_params = params->pi_regs.denali_pi;
+
+ /* modify PHY F0/F1/F2 params */
+ params_cfg = get_phy_index_params(0, params);
+ set_ds_odt(chan, params_cfg, false, 0);
+
+ clrsetbits_le32(&denali_pi_params[45], 0x1 << 24, 0x1 << 24);
+ clrsetbits_le32(&denali_pi_params[61], 0x1 << 24, 0x1 << 24);
+ clrsetbits_le32(&denali_pi_params[76], 0x1 << 24, 0x1 << 24);
+ clrsetbits_le32(&denali_pi_params[77], 0x1, 0x1);
+}
#else
-struct rk3399_sdram_params lpddr4_timings[] = {
- #include "sdram-rk3399-lpddr4-400.inc"
- #include "sdram-rk3399-lpddr4-800.inc"
+struct rk3399_sdram_params dfs_cfgs_lpddr4[] = {
+#include "sdram-rk3399-lpddr4-400.inc"
+#include "sdram-rk3399-lpddr4-800.inc"
};
+static struct rk3399_sdram_params
+ *lpddr4_get_phy_index_params(u32 phy_fn,
+ struct rk3399_sdram_params *params)
+{
+ if (phy_fn == 0)
+ return params;
+ else if (phy_fn == 1)
+ return &dfs_cfgs_lpddr4[1];
+ else if (phy_fn == 2)
+ return &dfs_cfgs_lpddr4[0];
+ else
+ return NULL;
+}
+
static void *get_denali_pi(const struct chan_info *chan,
struct rk3399_sdram_params *params, bool reg)
{
return reg ? &chan->pi->denali_pi : ¶ms->pi_regs.denali_pi;
}
-static u32 lpddr4_get_phy(struct rk3399_sdram_params *params, u32 ctl)
+static u32 lpddr4_get_phy_fn(struct rk3399_sdram_params *params, u32 ctl_fn)
{
- u32 lpddr4_phy[] = {1, 0, 0xb};
+ u32 lpddr4_phy_fn[] = {1, 0, 0xb};
- return lpddr4_phy[ctl];
+ return lpddr4_phy_fn[ctl_fn];
}
-static u32 lpddr4_get_ctl(struct rk3399_sdram_params *params, u32 phy)
+static u32 lpddr4_get_ctl_fn(struct rk3399_sdram_params *params, u32 phy_fn)
{
- u32 lpddr4_ctl[] = {1, 0, 2};
+ u32 lpddr4_ctl_fn[] = {1, 0, 2};
- return lpddr4_ctl[phy];
+ return lpddr4_ctl_fn[phy_fn];
}
static u32 get_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf)
@@ -1661,12 +1777,7 @@ static u32 get_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf)
return ((readl(&pmusgrf->soc_con4) >> 10) & 0x1F);
}
-static void set_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf, u32 stride)
-{
- rk_clrsetreg(&pmusgrf->soc_con4, 0x1f << 10, stride << 10);
-}
-
-/**
+/*
* read mr_num mode register
* rank = 1: cs0
* rank = 2: cs1
@@ -1797,7 +1908,7 @@ end:
}
static void set_lpddr4_dq_odt(const struct chan_info *chan,
- struct rk3399_sdram_params *params, u32 ctl,
+ struct rk3399_sdram_params *params, u32 ctl_fn,
bool en, bool ctl_phy_reg, u32 mr5)
{
u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);
@@ -1805,14 +1916,13 @@ static void set_lpddr4_dq_odt(const struct chan_info *chan,
struct io_setting *io;
u32 reg_value;
- if (!en)
- return;
-
io = lpddr4_get_io_settings(params, mr5);
+ if (en)
+ reg_value = io->dq_odt;
+ else
+ reg_value = 0;
- reg_value = io->dq_odt;
-
- switch (ctl) {
+ switch (ctl_fn) {
case 0:
clrsetbits_le32(&denali_ctl[139], 0x7 << 24, reg_value << 24);
clrsetbits_le32(&denali_ctl[153], 0x7 << 24, reg_value << 24);
@@ -1845,7 +1955,7 @@ static void set_lpddr4_dq_odt(const struct chan_info *chan,
}
static void set_lpddr4_ca_odt(const struct chan_info *chan,
- struct rk3399_sdram_params *params, u32 ctl,
+ struct rk3399_sdram_params *params, u32 ctl_fn,
bool en, bool ctl_phy_reg, u32 mr5)
{
u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);
@@ -1853,14 +1963,13 @@ static void set_lpddr4_ca_odt(const struct chan_info *chan,
struct io_setting *io;
u32 reg_value;
- if (!en)
- return;
-
io = lpddr4_get_io_settings(params, mr5);
+ if (en)
+ reg_value = io->ca_odt;
+ else
+ reg_value = 0;
- reg_value = io->ca_odt;
-
- switch (ctl) {
+ switch (ctl_fn) {
case 0:
clrsetbits_le32(&denali_ctl[139], 0x7 << 28, reg_value << 28);
clrsetbits_le32(&denali_ctl[153], 0x7 << 28, reg_value << 28);
@@ -1893,7 +2002,7 @@ static void set_lpddr4_ca_odt(const struct chan_info *chan,
}
static void set_lpddr4_MR3(const struct chan_info *chan,
- struct rk3399_sdram_params *params, u32 ctl,
+ struct rk3399_sdram_params *params, u32 ctl_fn,
bool ctl_phy_reg, u32 mr5)
{
u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);
@@ -1905,7 +2014,7 @@ static void set_lpddr4_MR3(const struct chan_info *chan,
reg_value = ((io->pdds << 3) | 1);
- switch (ctl) {
+ switch (ctl_fn) {
case 0:
clrsetbits_le32(&denali_ctl[138], 0xFFFF, reg_value);
clrsetbits_le32(&denali_ctl[152], 0xFFFF, reg_value);
@@ -1940,7 +2049,7 @@ static void set_lpddr4_MR3(const struct chan_info *chan,
}
static void set_lpddr4_MR12(const struct chan_info *chan,
- struct rk3399_sdram_params *params, u32 ctl,
+ struct rk3399_sdram_params *params, u32 ctl_fn,
bool ctl_phy_reg, u32 mr5)
{
u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);
@@ -1952,7 +2061,7 @@ static void set_lpddr4_MR12(const struct chan_info *chan,
reg_value = io->ca_vref;
- switch (ctl) {
+ switch (ctl_fn) {
case 0:
clrsetbits_le32(&denali_ctl[140], 0xFFFF << 16,
reg_value << 16);
@@ -1989,7 +2098,7 @@ static void set_lpddr4_MR12(const struct chan_info *chan,
}
static void set_lpddr4_MR14(const struct chan_info *chan,
- struct rk3399_sdram_params *params, u32 ctl,
+ struct rk3399_sdram_params *params, u32 ctl_fn,
bool ctl_phy_reg, u32 mr5)
{
u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);
@@ -2001,7 +2110,7 @@ static void set_lpddr4_MR14(const struct chan_info *chan,
reg_value = io->dq_vref;
- switch (ctl) {
+ switch (ctl_fn) {
case 0:
clrsetbits_le32(&denali_ctl[142], 0xFFFF << 16,
reg_value << 16);
@@ -2037,22 +2146,73 @@ static void set_lpddr4_MR14(const struct chan_info *chan,
}
}
+void lpddr4_modify_param(const struct chan_info *chan,
+ struct rk3399_sdram_params *params)
+{
+ struct rk3399_sdram_params *params_cfg;
+ u32 *denali_ctl_params;
+ u32 *denali_pi_params;
+ u32 *denali_phy_params;
+
+ denali_ctl_params = params->pctl_regs.denali_ctl;
+ denali_pi_params = params->pi_regs.denali_pi;
+ denali_phy_params = params->phy_regs.denali_phy;
+
+ set_lpddr4_dq_odt(chan, params, 2, true, false, 0);
+ set_lpddr4_ca_odt(chan, params, 2, true, false, 0);
+ set_lpddr4_MR3(chan, params, 2, false, 0);
+ set_lpddr4_MR12(chan, params, 2, false, 0);
+ set_lpddr4_MR14(chan, params, 2, false, 0);
+ params_cfg = lpddr4_get_phy_index_params(0, params);
+ set_ds_odt(chan, params_cfg, false, 0);
+ /* read two cycle preamble */
+ clrsetbits_le32(&denali_ctl_params[200], 0x3 << 24, 0x3 << 24);
+ clrsetbits_le32(&denali_phy_params[7], 0x3 << 24, 0x3 << 24);
+ clrsetbits_le32(&denali_phy_params[135], 0x3 << 24, 0x3 << 24);
+ clrsetbits_le32(&denali_phy_params[263], 0x3 << 24, 0x3 << 24);
+ clrsetbits_le32(&denali_phy_params[391], 0x3 << 24, 0x3 << 24);
+
+ /* boot frequency two cycle preamble */
+ clrsetbits_le32(&denali_phy_params[2], 0x3 << 16, 0x3 << 16);
+ clrsetbits_le32(&denali_phy_params[130], 0x3 << 16, 0x3 << 16);
+ clrsetbits_le32(&denali_phy_params[258], 0x3 << 16, 0x3 << 16);
+ clrsetbits_le32(&denali_phy_params[386], 0x3 << 16, 0x3 << 16);
+
+ clrsetbits_le32(&denali_pi_params[45], 0x3 << 8, 0x3 << 8);
+ clrsetbits_le32(&denali_pi_params[58], 0x1, 0x1);
+
+ /*
+ * bypass mode need PHY_SLICE_PWR_RDC_DISABLE_x = 1,
+ * boot frequency mode use bypass mode
+ */
+ setbits_le32(&denali_phy_params[10], 1 << 16);
+ setbits_le32(&denali_phy_params[138], 1 << 16);
+ setbits_le32(&denali_phy_params[266], 1 << 16);
+ setbits_le32(&denali_phy_params[394], 1 << 16);
+
+ clrsetbits_le32(&denali_pi_params[45], 0x1 << 24, 0x1 << 24);
+ clrsetbits_le32(&denali_pi_params[61], 0x1 << 24, 0x1 << 24);
+ clrsetbits_le32(&denali_pi_params[76], 0x1 << 24, 0x1 << 24);
+ clrsetbits_le32(&denali_pi_params[77], 0x1, 0x1);
+}
+
static void lpddr4_copy_phy(struct dram_info *dram,
- struct rk3399_sdram_params *params, u32 phy,
- struct rk3399_sdram_params *timings,
+ struct rk3399_sdram_params *params, u32 phy_fn,
+ struct rk3399_sdram_params *params_cfg,
u32 channel)
{
u32 *denali_ctl, *denali_phy;
u32 *denali_phy_params;
u32 speed = 0;
- u32 ctl, mr5;
+ u32 ctl_fn, mr5;
denali_ctl = dram->chan[channel].pctl->denali_ctl;
denali_phy = dram->chan[channel].publ->denali_phy;
- denali_phy_params = timings->phy_regs.denali_phy;
+ denali_phy_params = params_cfg->phy_regs.denali_phy;
/* switch index */
- clrsetbits_le32(&denali_phy_params[896], 0x3 << 8, phy << 8);
+ clrsetbits_le32(&denali_phy_params[896], 0x3 << 8,
+ phy_fn << 8);
writel(denali_phy_params[896], &denali_phy[896]);
/* phy_pll_ctrl_ca, phy_pll_ctrl */
@@ -2112,14 +2272,14 @@ static void lpddr4_copy_phy(struct dram_info *dram,
* phy_clk_wrdqz_slave_delay_x
* phy_clk_wrdqs_slave_delay_x
*/
- copy_to_reg((u32 *)&denali_phy[59], (u32 *)&denali_phy_params[59],
- (63 - 58) * 4);
- copy_to_reg((u32 *)&denali_phy[187], (u32 *)&denali_phy_params[187],
- (191 - 186) * 4);
- copy_to_reg((u32 *)&denali_phy[315], (u32 *)&denali_phy_params[315],
- (319 - 314) * 4);
- copy_to_reg((u32 *)&denali_phy[443], (u32 *)&denali_phy_params[443],
- (447 - 442) * 4);
+ sdram_copy_to_reg((u32 *)&denali_phy[59],
+ (u32 *)&denali_phy_params[59], (63 - 58) * 4);
+ sdram_copy_to_reg((u32 *)&denali_phy[187],
+ (u32 *)&denali_phy_params[187], (191 - 186) * 4);
+ sdram_copy_to_reg((u32 *)&denali_phy[315],
+ (u32 *)&denali_phy_params[315], (319 - 314) * 4);
+ sdram_copy_to_reg((u32 *)&denali_phy[443],
+ (u32 *)&denali_phy_params[443], (447 - 442) * 4);
/*
* phy_dqs_tsel_wr_timing_x 8bits denali_phy_84/212/340/468 offset_8
@@ -2218,31 +2378,30 @@ static void lpddr4_copy_phy(struct dram_info *dram,
* phy_wrlvl_delay_period_threshold_x
* phy_wrlvl_early_force_zero_x
*/
- copy_to_reg((u32 *)&denali_phy[64], (u32 *)&denali_phy_params[64],
- (67 - 63) * 4);
+ sdram_copy_to_reg((u32 *)&denali_phy[64],
+ (u32 *)&denali_phy_params[64], (67 - 63) * 4);
clrsetbits_le32(&denali_phy[68], 0xfffffc00,
denali_phy_params[68] & 0xfffffc00);
- copy_to_reg((u32 *)&denali_phy[69], (u32 *)&denali_phy_params[69],
- (79 - 68) * 4);
- copy_to_reg((u32 *)&denali_phy[192], (u32 *)&denali_phy_params[192],
- (195 - 191) * 4);
+ sdram_copy_to_reg((u32 *)&denali_phy[69],
+ (u32 *)&denali_phy_params[69], (79 - 68) * 4);
+ sdram_copy_to_reg((u32 *)&denali_phy[192],
+ (u32 *)&denali_phy_params[192], (195 - 191) * 4);
clrsetbits_le32(&denali_phy[196], 0xfffffc00,
denali_phy_params[196] & 0xfffffc00);
- copy_to_reg((u32 *)&denali_phy[197], (u32 *)&denali_phy_params[197],
- (207 - 196) * 4);
- copy_to_reg((u32 *)&denali_phy[320], (u32 *)&denali_phy_params[320],
- (323 - 319) * 4);
+ sdram_copy_to_reg((u32 *)&denali_phy[197],
+ (u32 *)&denali_phy_params[197], (207 - 196) * 4);
+ sdram_copy_to_reg((u32 *)&denali_phy[320],
+ (u32 *)&denali_phy_params[320], (323 - 319) * 4);
clrsetbits_le32(&denali_phy[324], 0xfffffc00,
denali_phy_params[324] & 0xfffffc00);
- copy_to_reg((u32 *)&denali_phy[325], (u32 *)&denali_phy_params[325],
- (335 - 324) * 4);
-
- copy_to_reg((u32 *)&denali_phy[448], (u32 *)&denali_phy_params[448],
- (451 - 447) * 4);
+ sdram_copy_to_reg((u32 *)&denali_phy[325],
+ (u32 *)&denali_phy_params[325], (335 - 324) * 4);
+ sdram_copy_to_reg((u32 *)&denali_phy[448],
+ (u32 *)&denali_phy_params[448], (451 - 447) * 4);
clrsetbits_le32(&denali_phy[452], 0xfffffc00,
denali_phy_params[452] & 0xfffffc00);
- copy_to_reg((u32 *)&denali_phy[453], (u32 *)&denali_phy_params[453],
- (463 - 452) * 4);
+ sdram_copy_to_reg((u32 *)&denali_phy[453],
+ (u32 *)&denali_phy_params[453], (463 - 452) * 4);
/* phy_two_cyc_preamble_x */
clrsetbits_le32(&denali_phy[7], 0x3 << 24,
@@ -2255,11 +2414,11 @@ static void lpddr4_copy_phy(struct dram_info *dram,
denali_phy_params[391] & (0x3 << 24));
/* speed */
- if (timings->base.ddr_freq < 400 * MHz)
+ if (params_cfg->base.ddr_freq < 400)
speed = 0x0;
- else if (timings->base.ddr_freq < 800 * MHz)
+ else if (params_cfg->base.ddr_freq < 800)
speed = 0x1;
- else if (timings->base.ddr_freq < 1200 * MHz)
+ else if (params_cfg->base.ddr_freq < 1200)
speed = 0x2;
/* phy_924 phy_pad_fdbk_drive */
@@ -2279,52 +2438,75 @@ static void lpddr4_copy_phy(struct dram_info *dram,
/* phy_939 phy_pad_cs_drive */
clrsetbits_le32(&denali_phy[939], 0x3 << 17, speed << 17);
- read_mr(dram->chan[channel].pctl, 1, 5, &mr5);
- set_ds_odt(&dram->chan[channel], timings, true, mr5);
+ if (params_cfg->base.dramtype == LPDDR4) {
+ read_mr(dram->chan[channel].pctl, 1, 5, &mr5);
+ set_ds_odt(&dram->chan[channel], params_cfg, true, mr5);
+ set_ds_odt(&dram->chan[channel], params_cfg, true, mr5);
+
+ ctl_fn = lpddr4_get_ctl_fn(params_cfg, phy_fn);
+ set_lpddr4_dq_odt(&dram->chan[channel], params_cfg,
+ ctl_fn, true, true, mr5);
+ set_lpddr4_ca_odt(&dram->chan[channel], params_cfg,
+ ctl_fn, true, true, mr5);
+ set_lpddr4_MR3(&dram->chan[channel], params_cfg,
+ ctl_fn, true, mr5);
+ set_lpddr4_MR12(&dram->chan[channel], params_cfg,
+ ctl_fn, true, mr5);
+ set_lpddr4_MR14(&dram->chan[channel], params_cfg,
+ ctl_fn, true, mr5);
+
+ set_lpddr4_dq_odt(&dram->chan[channel], params_cfg,
+ ctl_fn, true, true, mr5);
+ set_lpddr4_ca_odt(&dram->chan[channel], params_cfg,
+ ctl_fn, true, true, mr5);
+ set_lpddr4_MR3(&dram->chan[channel], params_cfg,
+ ctl_fn, true, mr5);
+ set_lpddr4_MR12(&dram->chan[channel], params_cfg,
+ ctl_fn, true, mr5);
+ set_lpddr4_MR14(&dram->chan[channel], params_cfg,
+ ctl_fn, true, mr5);
- ctl = lpddr4_get_ctl(timings, phy);
- set_lpddr4_dq_odt(&dram->chan[channel], timings, ctl, true, true, mr5);
- set_lpddr4_ca_odt(&dram->chan[channel], timings, ctl, true, true, mr5);
- set_lpddr4_MR3(&dram->chan[channel], timings, ctl, true, mr5);
- set_lpddr4_MR12(&dram->chan[channel], timings, ctl, true, mr5);
- set_lpddr4_MR14(&dram->chan[channel], timings, ctl, true, mr5);
-
- /*
- * if phy_sw_master_mode_x not bypass mode,
- * clear phy_slice_pwr_rdc_disable.
- * note: need use timings, not ddr_publ_regs
- */
- if (!((denali_phy_params[86] >> 8) & (1 << 2))) {
- clrbits_le32(&denali_phy[10], 1 << 16);
- clrbits_le32(&denali_phy[138], 1 << 16);
- clrbits_le32(&denali_phy[266], 1 << 16);
- clrbits_le32(&denali_phy[394], 1 << 16);
- }
+ /*
+ * if phy_sw_master_mode_x not bypass mode,
+ * clear phy_slice_pwr_rdc_disable.
+ * note: need use timings, not ddr_publ_regs
+ */
+ if (!((denali_phy_params[86] >> 8) & (1 << 2))) {
+ clrbits_le32(&denali_phy[10], 1 << 16);
+ clrbits_le32(&denali_phy[138], 1 << 16);
+ clrbits_le32(&denali_phy[266], 1 << 16);
+ clrbits_le32(&denali_phy[394], 1 << 16);
+ }
- /*
- * when PHY_PER_CS_TRAINING_EN=1, W2W_DIFFCS_DLY_Fx can't
- * smaller than 8
- * NOTE: need use timings, not ddr_publ_regs
- */
- if ((denali_phy_params[84] >> 16) & 1) {
- if (((readl(&denali_ctl[217 + ctl]) >> 16) & 0x1f) < 8)
- clrsetbits_le32(&denali_ctl[217 + ctl],
- 0x1f << 16, 8 << 16);
+ /*
+ * when PHY_PER_CS_TRAINING_EN=1, W2W_DIFFCS_DLY_Fx can't
+ * smaller than 8
+ * NOTE: need use timings, not ddr_publ_regs
+ */
+ if ((denali_phy_params[84] >> 16) & 1) {
+ if (((readl(&denali_ctl[217 + ctl_fn]) >>
+ 16) & 0x1f) < 8)
+ clrsetbits_le32(&denali_ctl[217 + ctl_fn],
+ 0x1f << 16,
+ 8 << 16);
+ }
}
}
static void lpddr4_set_phy(struct dram_info *dram,
- struct rk3399_sdram_params *params, u32 phy,
- struct rk3399_sdram_params *timings)
+ struct rk3399_sdram_params *params, u32 phy_fn,
+ struct rk3399_sdram_params *params_cfg)
{
u32 channel;
for (channel = 0; channel < 2; channel++)
- lpddr4_copy_phy(dram, params, phy, timings, channel);
+ lpddr4_copy_phy(dram, params, phy_fn, params_cfg,
+ channel);
}
static int lpddr4_set_ctl(struct dram_info *dram,
- struct rk3399_sdram_params *params, u32 ctl, u32 hz)
+ struct rk3399_sdram_params *params,
+ u32 fn, u32 hz)
{
u32 channel;
int ret_clk, ret;
@@ -2343,7 +2525,7 @@ static int lpddr4_set_ctl(struct dram_info *dram,
/* change freq */
writel((((0x3 << 4) | (1 << 2) | 1) << 16) |
- (ctl << 4) | (1 << 2) | 1, &dram->cic->cic_ctrl0);
+ (fn << 4) | (1 << 2) | 1, &dram->cic->cic_ctrl0);
while (!(readl(&dram->cic->cic_status0) & (1 << 2)))
;
@@ -2366,12 +2548,12 @@ static int lpddr4_set_ctl(struct dram_info *dram,
clrbits_le32(&dram->pmu->pmu_noc_auto_ena, (0x3 << 7));
/* lpddr4 ctl2 can not do training, all training will fail */
- if (!(params->base.dramtype == LPDDR4 && ctl == 2)) {
+ if (!(params->base.dramtype == LPDDR4 && fn == 2)) {
for (channel = 0; channel < 2; channel++) {
if (!(params->ch[channel].cap_info.col))
continue;
ret = data_training(dram, channel, params,
- PI_FULL_TRAINING);
+ PI_FULL_TRAINING);
if (ret)
printf("%s: channel %d training failed!\n",
__func__, channel);
@@ -2387,24 +2569,221 @@ static int lpddr4_set_ctl(struct dram_info *dram,
static int lpddr4_set_rate(struct dram_info *dram,
struct rk3399_sdram_params *params)
{
- u32 ctl;
- u32 phy;
+ u32 ctl_fn;
+ u32 phy_fn;
- for (ctl = 0; ctl < 2; ctl++) {
- phy = lpddr4_get_phy(params, ctl);
+ for (ctl_fn = 0; ctl_fn < 2; ctl_fn++) {
+ phy_fn = lpddr4_get_phy_fn(params, ctl_fn);
- lpddr4_set_phy(dram, params, phy, &lpddr4_timings[ctl]);
- lpddr4_set_ctl(dram, params, ctl,
- lpddr4_timings[ctl].base.ddr_freq);
+ lpddr4_set_phy(dram, params, phy_fn, &dfs_cfgs_lpddr4[ctl_fn]);
+ lpddr4_set_ctl(dram, params, ctl_fn,
+ dfs_cfgs_lpddr4[ctl_fn].base.ddr_freq);
- debug("%s: change freq to %d mhz %d, %d\n", __func__,
- lpddr4_timings[ctl].base.ddr_freq / MHz, ctl, phy);
+ printf("%s: change freq to %d mhz %d, %d\n", __func__,
+ dfs_cfgs_lpddr4[ctl_fn].base.ddr_freq, ctl_fn, phy_fn);
}
return 0;
}
#endif /* CONFIG_RAM_RK3399_LPDDR4 */
+/* CS0,n=1
+ * CS1,n=2
+ * CS0 & CS1, n=3
+ * cs0_cap: MB unit
+ */
+static void dram_set_cs(const struct chan_info *chan, u32 cs_map, u32 cs0_cap,
+ unsigned char dramtype)
+{
+ u32 *denali_ctl = chan->pctl->denali_ctl;
+ u32 *denali_pi = chan->pi->denali_pi;
+ struct msch_regs *ddr_msch_regs = chan->msch;
+
+ clrsetbits_le32(&denali_ctl[196], 0x3, cs_map);
+ writel((cs0_cap / 32) | (((4096 - cs0_cap) / 32) << 8),
+ &ddr_msch_regs->ddrsize);
+ if (dramtype == LPDDR4) {
+ if (cs_map == 1)
+ cs_map = 0x5;
+ else if (cs_map == 2)
+ cs_map = 0xa;
+ else
+ cs_map = 0xF;
+ }
+ /*PI_41 PI_CS_MAP:RW:24:4*/
+ clrsetbits_le32(&denali_pi[41],
+ 0xf << 24, cs_map << 24);
+ if (cs_map == 1 && dramtype == DDR3)
+ writel(0x2EC7FFFF, &denali_pi[34]);
+}
+
+static void dram_set_bw(const struct chan_info *chan, u32 bw)
+{
+ u32 *denali_ctl = chan->pctl->denali_ctl;
+
+ if (bw == 2)
+ clrbits_le32(&denali_ctl[196], 1 << 16);
+ else
+ setbits_le32(&denali_ctl[196], 1 << 16);
+}
+
+static void dram_set_max_col(const struct chan_info *chan, u32 bw, u32 *pcol)
+{
+ u32 *denali_ctl = chan->pctl->denali_ctl;
+ struct msch_regs *ddr_msch_regs = chan->msch;
+ u32 *denali_pi = chan->pi->denali_pi;
+ u32 ddrconfig;
+
+ clrbits_le32(&denali_ctl[191], 0xf);
+ clrsetbits_le32(&denali_ctl[190],
+ (7 << 24),
+ ((16 - ((bw == 2) ? 14 : 15)) << 24));
+ /*PI_199 PI_COL_DIFF:RW:0:4*/
+ clrbits_le32(&denali_pi[199], 0xf);
+ /*PI_155 PI_ROW_DIFF:RW:24:3*/
+ clrsetbits_le32(&denali_pi[155],
+ (7 << 24),
+ ((16 - 12) << 24));
+ ddrconfig = (bw == 2) ? 3 : 2;
+ writel(ddrconfig | (ddrconfig << 8), &ddr_msch_regs->ddrconf);
+ /* set max cs0 size */
+ writel((4096 / 32) | ((0 / 32) << 8),
+ &ddr_msch_regs->ddrsize);
+
+ *pcol = 12;
+}
+
+static void dram_set_max_bank(const struct chan_info *chan, u32 bw, u32 *pbank,
+ u32 *pcol)
+{
+ u32 *denali_ctl = chan->pctl->denali_ctl;
+ u32 *denali_pi = chan->pi->denali_pi;
+
+ clrbits_le32(&denali_ctl[191], 0xf);
+ clrbits_le32(&denali_ctl[190], (3 << 16));
+ /*PI_199 PI_COL_DIFF:RW:0:4*/
+ clrbits_le32(&denali_pi[199], 0xf);
+ /*PI_155 PI_BANK_DIFF:RW:16:2*/
+ clrbits_le32(&denali_pi[155], (3 << 16));
+
+ *pbank = 3;
+ *pcol = 12;
+}
+
+static void dram_set_max_row(const struct chan_info *chan, u32 bw, u32 *prow,
+ u32 *pbank, u32 *pcol)
+{
+ u32 *denali_ctl = chan->pctl->denali_ctl;
+ u32 *denali_pi = chan->pi->denali_pi;
+ struct msch_regs *ddr_msch_regs = chan->msch;
+
+ clrsetbits_le32(&denali_ctl[191], 0xf, 12 - 10);
+ clrbits_le32(&denali_ctl[190],
+ (0x3 << 16) | (0x7 << 24));
+ /*PI_199 PI_COL_DIFF:RW:0:4*/
+ clrsetbits_le32(&denali_pi[199], 0xf, 12 - 10);
+ /*PI_155 PI_ROW_DIFF:RW:24:3 PI_BANK_DIFF:RW:16:2*/
+ clrbits_le32(&denali_pi[155],
+ (0x3 << 16) | (0x7 << 24));
+ writel(1 | (1 << 8), &ddr_msch_regs->ddrconf);
+ /* set max cs0 size */
+ writel((4096 / 32) | ((0 / 32) << 8),
+ &ddr_msch_regs->ddrsize);
+
+ *prow = 16;
+ *pbank = 3;
+ *pcol = (bw == 2) ? 10 : 11;
+}
+
+static u64 dram_detect_cap(struct dram_info *dram,
+ struct rk3399_sdram_params *params,
+ unsigned char channel)
+{
+ const struct chan_info *chan = &dram->chan[channel];
+ struct sdram_cap_info *cap_info = ¶ms->ch[channel].cap_info;
+ u32 bw;
+ u32 col_tmp;
+ u32 bk_tmp;
+ u32 row_tmp;
+ u32 cs0_cap;
+ u32 training_flag;
+ u32 ddrconfig;
+
+ /* detect bw */
+ bw = 2;
+ if (params->base.dramtype != LPDDR4) {
+ dram_set_bw(chan, bw);
+ cap_info->bw = bw;
+ if (data_training(dram, channel, params,
+ PI_READ_GATE_TRAINING)) {
+ bw = 1;
+ dram_set_bw(chan, 1);
+ cap_info->bw = bw;
+ if (data_training(dram, channel, params,
+ PI_READ_GATE_TRAINING)) {
+ printf("16bit error!!!\n");
+ goto error;
+ }
+ }
+ }
+ /*
+ * LPDDR3 CA training msut be trigger before other training.
+ * DDR3 is not have CA training.
+ */
+ if (params->base.dramtype == LPDDR3)
+ training_flag = PI_WRITE_LEVELING;
+ else
+ training_flag = PI_FULL_TRAINING;
+
+ if (params->base.dramtype != LPDDR4) {
+ if (data_training(dram, channel, params, training_flag)) {
+ printf("full training error!!!\n");
+ goto error;
+ }
+ }
+
+ /* detect col */
+ dram_set_max_col(chan, bw, &col_tmp);
+ if (sdram_detect_col(cap_info, col_tmp) != 0)
+ goto error;
+
+ /* detect bank */
+ dram_set_max_bank(chan, bw, &bk_tmp, &col_tmp);
+ sdram_detect_bank(cap_info, col_tmp, bk_tmp);
+
+ /* detect row */
+ dram_set_max_row(chan, bw, &row_tmp, &bk_tmp, &col_tmp);
+ if (sdram_detect_row(cap_info, col_tmp, bk_tmp, row_tmp) != 0)
+ goto error;
+
+ /* detect row_3_4 */
+ sdram_detect_row_3_4(cap_info, col_tmp, bk_tmp);
+
+ /* set ddrconfig */
+ cs0_cap = (1 << (cap_info->cs0_row + cap_info->col + cap_info->bk +
+ cap_info->bw - 20));
+ if (cap_info->row_3_4)
+ cs0_cap = cs0_cap * 3 / 4;
+
+ cap_info->cs1_row = cap_info->cs0_row;
+ set_memory_map(chan, channel, params);
+ ddrconfig = calculate_ddrconfig(params, channel);
+ if (-1 == ddrconfig)
+ goto error;
+ set_ddrconfig(chan, params, channel,
+ cap_info->ddrconfig);
+
+ /* detect cs1 row */
+ sdram_detect_cs1_row(cap_info, params->base.dramtype);
+
+ /* detect die bw */
+ sdram_detect_dbw(cap_info, params->base.dramtype);
+
+ return 0;
+error:
+ return (-1);
+}
+
static unsigned char calculate_stride(struct rk3399_sdram_params *params)
{
unsigned int stride = params->base.stride;
@@ -2491,39 +2870,13 @@ static void clear_channel_params(struct rk3399_sdram_params *params, u8 channel)
params->ch[channel].cap_info.ddrconfig = 0;
}
-static int pctl_init(struct dram_info *dram, struct rk3399_sdram_params *params)
-{
- int channel;
- int ret;
-
- for (channel = 0; channel < 2; channel++) {
- const struct chan_info *chan = &dram->chan[channel];
- struct rk3399_cru *cru = dram->cru;
- struct rk3399_ddr_publ_regs *publ = chan->publ;
-
- phy_pctrl_reset(cru, channel);
- phy_dll_bypass_set(publ, params->base.ddr_freq);
-
- ret = pctl_cfg(dram, chan, channel, params);
- if (ret < 0) {
- printf("%s: pctl config failed\n", __func__);
- return ret;
- }
-
- /* start to trigger initialization */
- pctl_start(dram, channel);
- }
-
- return 0;
-}
-
static int sdram_init(struct dram_info *dram,
struct rk3399_sdram_params *params)
{
unsigned char dramtype = params->base.dramtype;
unsigned int ddr_freq = params->base.ddr_freq;
int channel, ch, rank;
- int ret;
+ u32 tmp, ret;
debug("Starting SDRAM initialization...\n");
@@ -2534,22 +2887,35 @@ static int sdram_init(struct dram_info *dram,
return -E2BIG;
}
+ /* detect rank */
for (ch = 0; ch < 2; ch++) {
params->ch[ch].cap_info.rank = 2;
for (rank = 2; rank != 0; rank--) {
- ret = pctl_init(dram, params);
- if (ret < 0) {
- printf("%s: pctl init failed\n", __func__);
- return ret;
+ for (channel = 0; channel < 2; channel++) {
+ const struct chan_info *chan =
+ &dram->chan[channel];
+ struct rk3399_cru *cru = dram->cru;
+ struct rk3399_ddr_publ_regs *publ = chan->publ;
+
+ phy_pctrl_reset(cru, channel);
+ phy_dll_bypass_set(publ, ddr_freq);
+ pctl_cfg(dram, chan, channel, params);
}
+ /* start to trigger initialization */
+ pctl_start(dram, params, 3);
+
/* LPDDR2/LPDDR3 need to wait DAI complete, max 10us */
if (dramtype == LPDDR3)
udelay(10);
+ tmp = (rank == 2) ? 3 : 1;
+ dram_set_cs(&dram->chan[ch], tmp, 2048,
+ params->base.dramtype);
params->ch[ch].cap_info.rank = rank;
- ret = dram->ops->data_training(dram, ch, rank, params);
+ ret = dram->ops->data_training_first(dram, ch,
+ rank, params);
if (!ret) {
debug("%s: data trained for rank %d, ch %d\n",
__func__, rank, ch);
@@ -2563,38 +2929,37 @@ static int sdram_init(struct dram_info *dram,
params->base.num_channels = 0;
for (channel = 0; channel < 2; channel++) {
const struct chan_info *chan = &dram->chan[channel];
- struct sdram_cap_info *cap_info = ¶ms->ch[channel].cap_info;
- u8 training_flag = PI_FULL_TRAINING;
+ struct sdram_cap_info *cap_info =
+ ¶ms->ch[channel].cap_info;
if (cap_info->rank == 0) {
- clear_channel_params(params, channel);
+ clear_channel_params(params, 1);
continue;
} else {
params->base.num_channels++;
}
- debug("Channel ");
- debug(channel ? "1: " : "0: ");
+ printf("Channel ");
+ printf(channel ? "1: " : "0: ");
- /* LPDDR3 should have write and read gate training */
- if (params->base.dramtype == LPDDR3)
- training_flag = PI_WRITE_LEVELING |
- PI_READ_GATE_TRAINING;
+ if (channel == 0)
+ set_ddr_stride(dram->pmusgrf, 0x17);
+ else
+ set_ddr_stride(dram->pmusgrf, 0x18);
- if (params->base.dramtype != LPDDR4) {
- ret = data_training(dram, channel, params,
- training_flag);
- if (!ret) {
- debug("%s: data train failed for channel %d\n",
- __func__, ret);
- continue;
- }
+ if (dram_detect_cap(dram, params, channel)) {
+ printf("Cap error!\n");
+ continue;
}
sdram_print_ddr_info(cap_info, ¶ms->base);
set_memory_map(chan, channel, params);
- cap_info->ddrconfig = calculate_ddrconfig(params, channel);
-
+ cap_info->ddrconfig =
+ calculate_ddrconfig(params, channel);
+ if (-1 == cap_info->ddrconfig) {
+ printf("no ddrconfig find, Cap not support!\n");
+ continue;
+ }
set_ddrconfig(chan, params, channel, cap_info->ddrconfig);
set_cap_relate_config(chan, params, channel);
}
@@ -2608,7 +2973,8 @@ static int sdram_init(struct dram_info *dram,
params->base.stride = calculate_stride(params);
dram_all_config(dram, params);
- dram->ops->set_rate(dram, params);
+
+ dram->ops->set_rate_index(dram, params);
debug("Finish SDRAM initialization...\n");
return 0;
@@ -2655,11 +3021,15 @@ static int conv_of_platdata(struct udevice *dev)
static const struct sdram_rk3399_ops rk3399_ops = {
#if !defined(CONFIG_RAM_RK3399_LPDDR4)
- .data_training = default_data_training,
- .set_rate = switch_to_phy_index1,
+ .data_training_first = data_training_first,
+ .set_rate_index = switch_to_phy_index1,
+ .modify_param = modify_param,
+ .get_phy_index_params = get_phy_index_params,
#else
- .data_training = lpddr4_mr_detect,
- .set_rate = lpddr4_set_rate,
+ .data_training_first = lpddr4_mr_detect,
+ .set_rate_index = lpddr4_set_rate,
+ .modify_param = lpddr4_modify_param,
+ .get_phy_index_params = lpddr4_get_phy_index_params,
#endif
};
--
2.17.1
More information about the U-Boot
mailing list