summaryrefslogtreecommitdiff
path: root/drivers/ram
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2019-11-17 21:15:57 -0500
committerTom Rini <trini@konsulko.com>2019-11-17 21:15:57 -0500
commitd64efd920e429f1c5dc085e2e8614c5d139ec37d (patch)
treefb1b00b875c2efd1a3d5310227c0d214cd48cf45 /drivers/ram
parentfd8adc33b8f999cb09c3ba8ea8860ded28e8d6ca (diff)
parent59b01eb7a17a7c0915fd8aff8f818699b4624137 (diff)
Merge tag 'u-boot-rockchip-20191118' of https://gitlab.denx.de/u-boot/custodians/u-boot-rockchip
- Add support for rockchip SoC: PX30, RK3308 - Add and migrate to use common dram driver: PX30, RK3328, RK3399 - Add rk3399 board Tinker-s support - Board config update for Rock960, Rockpro64
Diffstat (limited to 'drivers/ram')
-rw-r--r--drivers/ram/Kconfig2
-rw-r--r--drivers/ram/rockchip/Kconfig17
-rw-r--r--drivers/ram/rockchip/Makefile8
-rw-r--r--drivers/ram/rockchip/dmc-rk3368.c2
-rw-r--r--drivers/ram/rockchip/sdram-px30-ddr3-detect-333.inc72
-rw-r--r--drivers/ram/rockchip/sdram-px30-ddr4-detect-333.inc75
-rw-r--r--drivers/ram/rockchip/sdram-px30-ddr_skew.inc121
-rw-r--r--drivers/ram/rockchip/sdram-px30-lpddr2-detect-333.inc73
-rw-r--r--drivers/ram/rockchip/sdram-px30-lpddr3-detect-333.inc74
-rw-r--r--drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc28
-rw-r--r--drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc28
-rw-r--r--drivers/ram/rockchip/sdram_common.c429
-rw-r--r--drivers/ram/rockchip/sdram_debug.c147
-rw-r--r--drivers/ram/rockchip/sdram_pctl_px30.c205
-rw-r--r--drivers/ram/rockchip/sdram_phy_px30.c205
-rw-r--r--drivers/ram/rockchip/sdram_px30.c751
-rw-r--r--drivers/ram/rockchip/sdram_rk3128.c2
-rw-r--r--drivers/ram/rockchip/sdram_rk3188.c2
-rw-r--r--drivers/ram/rockchip/sdram_rk322x.c2
-rw-r--r--drivers/ram/rockchip/sdram_rk3288.c2
-rw-r--r--drivers/ram/rockchip/sdram_rk3308.c55
-rw-r--r--drivers/ram/rockchip/sdram_rk3328.c765
-rw-r--r--drivers/ram/rockchip/sdram_rk3399.c1201
23 files changed, 3092 insertions, 1174 deletions
diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig
index bb431ccfbf..b454ceb599 100644
--- a/drivers/ram/Kconfig
+++ b/drivers/ram/Kconfig
@@ -19,7 +19,7 @@ config SPL_RAM
config TPL_RAM
bool "Enable RAM support in TPL"
- depends on RAM && TPL_DM
+ depends on RAM
help
The RAM subsystem adds a small amount of overhead to the image.
If this is acceptable and you have a need to use RAM drivers in
diff --git a/drivers/ram/rockchip/Kconfig b/drivers/ram/rockchip/Kconfig
index 4f274e01b3..b75d581f57 100644
--- a/drivers/ram/rockchip/Kconfig
+++ b/drivers/ram/rockchip/Kconfig
@@ -5,10 +5,15 @@ config RAM_ROCKCHIP
help
This enables support for ram drivers Rockchip SoCs.
-if RAM_ROCKCHIP
+config ROCKCHIP_SDRAM_COMMON
+ bool "Enable rockchip sdram common driver"
+ depends on TPL_RAM || SPL_RAM
+ help
+ This enable sdram common driver
config RAM_ROCKCHIP_DEBUG
bool "Rockchip ram drivers debugging"
+ default y
help
This enables debugging ram driver API's for the platforms
based on Rockchip SoCs.
@@ -16,18 +21,10 @@ config RAM_ROCKCHIP_DEBUG
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 feb1f82d00..c3ec89ada4 100644
--- a/drivers/ram/rockchip/Makefile
+++ b/drivers/ram/rockchip/Makefile
@@ -3,11 +3,13 @@
# Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH
#
-obj-$(CONFIG_RAM_ROCKCHIP_DEBUG) += sdram_debug.o
+obj-$(CONFIG_ROCKCHIP_PX30) += sdram_px30.o sdram_pctl_px30.o sdram_phy_px30.o
obj-$(CONFIG_ROCKCHIP_RK3368) = dmc-rk3368.o
obj-$(CONFIG_ROCKCHIP_RK3128) = sdram_rk3128.o
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
-obj-$(CONFIG_RAM_RK3399) += sdram_rk3399.o
+obj-$(CONFIG_ROCKCHIP_RK3308) = sdram_rk3308.o
+obj-$(CONFIG_ROCKCHIP_RK3328) = sdram_rk3328.o sdram_pctl_px30.o sdram_phy_px30.o
+obj-$(CONFIG_ROCKCHIP_RK3399) += sdram_rk3399.o
+obj-$(CONFIG_ROCKCHIP_SDRAM_COMMON) += sdram_common.o
diff --git a/drivers/ram/rockchip/dmc-rk3368.c b/drivers/ram/rockchip/dmc-rk3368.c
index e52fc3baad..9df8f8f4af 100644
--- a/drivers/ram/rockchip/dmc-rk3368.c
+++ b/drivers/ram/rockchip/dmc-rk3368.c
@@ -17,7 +17,7 @@
#include <asm/arch-rockchip/grf_rk3368.h>
#include <asm/arch-rockchip/ddr_rk3368.h>
#include <asm/arch-rockchip/sdram.h>
-#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_rk3288.h>
struct dram_info {
struct ram_info info;
diff --git a/drivers/ram/rockchip/sdram-px30-ddr3-detect-333.inc b/drivers/ram/rockchip/sdram-px30-ddr3-detect-333.inc
new file mode 100644
index 0000000000..76cd8dc1a5
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-px30-ddr3-detect-333.inc
@@ -0,0 +1,72 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xC,
+ .bk = 0x3,
+ .bw = 0x1,
+ .dbw = 0x0,
+ .row_3_4 = 0x0,
+ .cs0_row = 0x10,
+ .cs1_row = 0x10,
+ .cs0_high16bit_row = 0x10,
+ .cs1_high16bit_row = 0x10,
+ .ddrconfig = 0,
+ },
+ {
+ {0x290b0609},
+ {0x08020401},
+ {0x00000002},
+ {0x00001111},
+ {0x0000000c},
+ {0x00000222},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 333,
+ .dramtype = DDR3,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 0,
+ },
+ {
+ {
+ {0x00000000, 0x43041001}, /* MSTR */
+ {0x00000064, 0x0028003b}, /* RFSHTMG */
+ {0x000000d0, 0x00020053}, /* INIT0 */
+ {0x000000d4, 0x00020000}, /* INIT1 */
+ {0x000000d8, 0x00000100}, /* INIT2 */
+ {0x000000dc, 0x03200000}, /* INIT3 */
+ {0x000000e0, 0x00000000}, /* INIT4 */
+ {0x000000e4, 0x00090000}, /* INIT5 */
+ {0x000000f4, 0x000f012f}, /* RANKCTL */
+ {0x00000100, 0x07090b06}, /* DRAMTMG0 */
+ {0x00000104, 0x00050209}, /* DRAMTMG1 */
+ {0x00000108, 0x03030407}, /* DRAMTMG2 */
+ {0x0000010c, 0x00202006}, /* DRAMTMG3 */
+ {0x00000110, 0x03020204}, /* DRAMTMG4 */
+ {0x00000114, 0x03030202}, /* DRAMTMG5 */
+ {0x00000120, 0x00000903}, /* DRAMTMG8 */
+ {0x00000180, 0x00800020}, /* ZQCTL0 */
+ {0x00000184, 0x00000000}, /* ZQCTL1 */
+ {0x00000190, 0x07010001}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x06000604}, /* ODTCFG */
+ {0x00000244, 0x00000201}, /* ODTMAP */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x0000000a}, /* PHYREG01 */
+ {0x00000028, 0x00000006}, /* PHYREG0A */
+ {0x0000002c, 0x00000000}, /* PHYREG0B */
+ {0x00000030, 0x00000005}, /* PHYREG0C */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+},
diff --git a/drivers/ram/rockchip/sdram-px30-ddr4-detect-333.inc b/drivers/ram/rockchip/sdram-px30-ddr4-detect-333.inc
new file mode 100644
index 0000000000..f804d28393
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-px30-ddr4-detect-333.inc
@@ -0,0 +1,75 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xA,
+ .bk = 0x2,
+ .bw = 0x1,
+ .dbw = 0x0,
+ .row_3_4 = 0x0,
+ .cs0_row = 0x11,
+ .cs1_row = 0x0,
+ .cs0_high16bit_row = 0x11,
+ .cs1_high16bit_row = 0x0,
+ .ddrconfig = 0,
+ },
+ {
+ {0x4d110a08},
+ {0x06020501},
+ {0x00000002},
+ {0x00001111},
+ {0x0000000c},
+ {0x0000022a},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 333,
+ .dramtype = DDR4,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 0,
+ },
+ {
+ {
+ {0x00000000, 0x43049010}, /* MSTR */
+ {0x00000064, 0x0028003b}, /* RFSHTMG */
+ {0x000000d0, 0x00020053}, /* INIT0 */
+ {0x000000d4, 0x00220000}, /* INIT1 */
+ {0x000000d8, 0x00000100}, /* INIT2 */
+ {0x000000dc, 0x00040000}, /* INIT3 */
+ {0x000000e0, 0x00000000}, /* INIT4 */
+ {0x000000e4, 0x00110000}, /* INIT5 */
+ {0x000000e8, 0x00000420}, /* INIT6 */
+ {0x000000ec, 0x00000400}, /* INIT7 */
+ {0x000000f4, 0x000f012f}, /* RANKCTL */
+ {0x00000100, 0x09060b06}, /* DRAMTMG0 */
+ {0x00000104, 0x00020209}, /* DRAMTMG1 */
+ {0x00000108, 0x0505040a}, /* DRAMTMG2 */
+ {0x0000010c, 0x0040400c}, /* DRAMTMG3 */
+ {0x00000110, 0x05030206}, /* DRAMTMG4 */
+ {0x00000114, 0x03030202}, /* DRAMTMG5 */
+ {0x00000120, 0x03030b03}, /* DRAMTMG8 */
+ {0x00000124, 0x00020208}, /* DRAMTMG9 */
+ {0x00000180, 0x01000040}, /* ZQCTL0 */
+ {0x00000184, 0x00000000}, /* ZQCTL1 */
+ {0x00000190, 0x07030003}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x06000604}, /* ODTCFG */
+ {0x00000244, 0x00000201}, /* ODTMAP */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x0000000c}, /* PHYREG01 */
+ {0x00000028, 0x0000000a}, /* PHYREG0A */
+ {0x0000002c, 0x00000000}, /* PHYREG0B */
+ {0x00000030, 0x00000009}, /* PHYREG0C */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+}, \ No newline at end of file
diff --git a/drivers/ram/rockchip/sdram-px30-ddr_skew.inc b/drivers/ram/rockchip/sdram-px30-ddr_skew.inc
new file mode 100644
index 0000000000..f24343dda1
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-px30-ddr_skew.inc
@@ -0,0 +1,121 @@
+ {
+ 0x77,
+ 0x88,
+ 0x79,
+ 0x79,
+ 0x87,
+ 0x97,
+ 0x87,
+ 0x78,
+ 0x77,
+ 0x78,
+ 0x87,
+ 0x88,
+ 0x87,
+ 0x87,
+ 0x77
+ },
+ {
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x69,
+ 0x9,
+ },
+ {
+ 0x77,
+ 0x78,
+ 0x77,
+ 0x78,
+ 0x77,
+ 0x78,
+ 0x77,
+ 0x78,
+ 0x77,
+ 0x79,
+ 0x9,
+ },
+ {
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x69,
+ 0x9,
+ },
+ {
+ 0x77,
+ 0x78,
+ 0x77,
+ 0x77,
+ 0x77,
+ 0x77,
+ 0x77,
+ 0x77,
+ 0x77,
+ 0x79,
+ 0x9,
+ },
+ {
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x69,
+ 0x9,
+ },
+ {
+ 0x77,
+ 0x78,
+ 0x77,
+ 0x78,
+ 0x77,
+ 0x78,
+ 0x77,
+ 0x78,
+ 0x77,
+ 0x79,
+ 0x9,
+ },
+ {
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x78,
+ 0x69,
+ 0x9,
+ },
+ {
+ 0x77,
+ 0x78,
+ 0x77,
+ 0x77,
+ 0x77,
+ 0x77,
+ 0x77,
+ 0x77,
+ 0x77,
+ 0x79,
+ 0x9,
+ }
diff --git a/drivers/ram/rockchip/sdram-px30-lpddr2-detect-333.inc b/drivers/ram/rockchip/sdram-px30-lpddr2-detect-333.inc
new file mode 100644
index 0000000000..948ade483b
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-px30-lpddr2-detect-333.inc
@@ -0,0 +1,73 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xC,
+ .bk = 0x3,
+ .bw = 0x1,
+ .dbw = 0x0,
+ .row_3_4 = 0x0,
+ .cs0_row = 0xF,
+ .cs1_row = 0xF,
+ .cs0_high16bit_row = 0xF,
+ .cs1_high16bit_row = 0xF,
+ .ddrconfig = 0,
+ },
+ {
+ {0x2b0c070a},
+ {0x08020303},
+ {0x00000002},
+ {0x00001111},
+ {0x0000000c},
+ {0x00000219},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 333,
+ .dramtype = LPDDR2,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 0,
+ },
+ {
+ {
+ {0x00000000, 0x41041004}, /* MSTR */
+ {0x00000064, 0x00140023}, /* RFSHTMG */
+ {0x000000d0, 0x00220002}, /* INIT0 */
+ {0x000000d4, 0x00010000}, /* INIT1 */
+ {0x000000d8, 0x00000703}, /* INIT2 */
+ {0x000000dc, 0x00630005}, /* INIT3 */
+ {0x000000e0, 0x00010000}, /* INIT4 */
+ {0x000000e4, 0x00070003}, /* INIT5 */
+ {0x000000f4, 0x000f012f}, /* RANKCTL */
+ {0x00000100, 0x07090b07}, /* DRAMTMG0 */
+ {0x00000104, 0x0002010b}, /* DRAMTMG1 */
+ {0x00000108, 0x02040506}, /* DRAMTMG2 */
+ {0x0000010c, 0x00303000}, /* DRAMTMG3 */
+ {0x00000110, 0x04010204}, /* DRAMTMG4 */
+ {0x00000114, 0x01010303}, /* DRAMTMG5 */
+ {0x00000118, 0x02020003}, /* DRAMTMG6 */
+ {0x00000120, 0x00000303}, /* DRAMTMG8 */
+ {0x00000138, 0x00000025}, /* DRAMTMG14 */
+ {0x00000180, 0x003c000f}, /* ZQCTL0 */
+ {0x00000184, 0x00900000}, /* ZQCTL1 */
+ {0x00000190, 0x07020001}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x07030718}, /* ODTCFG */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x00000009}, /* PHYREG01 */
+ {0x00000028, 0x00000007}, /* PHYREG0A */
+ {0x0000002c, 0x00000000}, /* PHYREG0B */
+ {0x00000030, 0x00000004}, /* PHYREG0C */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+},
diff --git a/drivers/ram/rockchip/sdram-px30-lpddr3-detect-333.inc b/drivers/ram/rockchip/sdram-px30-lpddr3-detect-333.inc
new file mode 100644
index 0000000000..f694a0e5b0
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-px30-lpddr3-detect-333.inc
@@ -0,0 +1,74 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xC,
+ .bk = 0x3,
+ .bw = 0x1,
+ .dbw = 0x0,
+ .row_3_4 = 0x0,
+ .cs0_row = 0x10,
+ .cs1_row = 0x10,
+ .cs0_high16bit_row = 0x10,
+ .cs1_high16bit_row = 0x10,
+ .ddrconfig = 0,
+ },
+ {
+ {0x290a060a},
+ {0x08020303},
+ {0x00000002},
+ {0x00001111},
+ {0x0000000c},
+ {0x0000021a},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 333,
+ .dramtype = LPDDR3,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 0,
+ },
+ {
+ {
+ {0x00000000, 0x43041008}, /* MSTR */
+ {0x00000064, 0x00140023}, /* RFSHTMG */
+ {0x000000d0, 0x00220002}, /* INIT0 */
+ {0x000000d4, 0x00010000}, /* INIT1 */
+ {0x000000d8, 0x00000703}, /* INIT2 */
+ {0x000000dc, 0x00830004}, /* INIT3 */
+ {0x000000e0, 0x00010000}, /* INIT4 */
+ {0x000000e4, 0x00070003}, /* INIT5 */
+ {0x000000f4, 0x000f012f}, /* RANKCTL */
+ {0x00000100, 0x06090b07}, /* DRAMTMG0 */
+ {0x00000104, 0x0002020b}, /* DRAMTMG1 */
+ {0x00000108, 0x02030506}, /* DRAMTMG2 */
+ {0x0000010c, 0x00505000}, /* DRAMTMG3 */
+ {0x00000110, 0x03020204}, /* DRAMTMG4 */
+ {0x00000114, 0x01010303}, /* DRAMTMG5 */
+ {0x00000118, 0x02020003}, /* DRAMTMG6 */
+ {0x00000120, 0x00000303}, /* DRAMTMG8 */
+ {0x00000138, 0x00000025}, /* DRAMTMG14 */
+ {0x00000180, 0x003c000f}, /* ZQCTL0 */
+ {0x00000184, 0x00900000}, /* ZQCTL1 */
+ {0x00000190, 0x07020000}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x0900090c}, /* ODTCFG */
+ {0x00000244, 0x00000101}, /* ODTMAP */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x0000000b}, /* PHYREG01 */
+ {0x00000028, 0x00000006}, /* PHYREG0A */
+ {0x0000002c, 0x00000000}, /* PHYREG0B */
+ {0x00000030, 0x00000003}, /* PHYREG0C */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+},
diff --git a/drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc b/drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc
index c50a03d9dd..209ef57228 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 = {
+ 0x8010100d,
+ },
+ .ddrtimingb0 = {
+ 0x08020b04,
+ },
.ddrtimingc0 = {
0x00000602,
},
- .devtodev0 = 0x00002122,
+ .devtodev0 = {
+ 0x00002562,
+ },
.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 = {
+ 0x8010100d,
+ },
+ .ddrtimingb0 = {
+ 0x08020b04,
+ },
.ddrtimingc0 = {
0x00000602,
},
- .devtodev0 = 0x00002122,
+ .devtodev0 = {
+ 0x00002562,
+ },
.ddrmode = {
0x0000004c,
},
diff --git a/drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc b/drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc
index d8ae3359a3..7d11b4c563 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 = {
+ 0x801c1819,
+ },
+ .ddrtimingb0 = {
+ 0x10040c05,
+ },
.ddrtimingc0 = {
0x00000602,
},
- .devtodev0 = 0x00002122,
+ .devtodev0 = {
+ 0x00002672,
+ },
.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_common.c b/drivers/ram/rockchip/sdram_common.c
new file mode 100644
index 0000000000..6bc51572b2
--- /dev/null
+++ b/drivers/ram/rockchip/sdram_common.c
@@ -0,0 +1,429 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2018 Rockchip Electronics Co., Ltd.
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <ram.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/sdram.h>
+#include <asm/arch-rockchip/sdram_common.h>
+
+#ifdef CONFIG_RAM_ROCKCHIP_DEBUG
+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;
+ }
+}
+
+void sdram_print_ddr_info(struct sdram_cap_info *cap_info,
+ struct sdram_base_params *base)
+{
+ u64 cap;
+ u32 bg;
+
+ 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->cs0_high16bit_row !=
+ cap_info->cs0_row) {
+ printascii("/");
+ printdec(cap_info->cs0_high16bit_row);
+ }
+ if (cap_info->rank > 1) {
+ printascii(" CS1 Row=");
+ printdec(cap_info->cs1_row);
+ if (cap_info->cs1_high16bit_row !=
+ cap_info->cs1_row) {
+ printascii("/");
+ printdec(cap_info->cs1_high16bit_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");
+ }
+}
+#endif
+
+/*
+ * cs: 0:cs0
+ * 1:cs1
+ * else 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]);
+}
+
+/* n: Unit bytes */
+void sdram_copy_to_reg(u32 *dest, const u32 *src, u32 n)
+{
+ int i;
+
+ for (i = 0; i < n / sizeof(u32); i++) {
+ writel(*src, dest);
+ src++;
+ dest++;
+ }
+}
+
+void sdram_org_config(struct sdram_cap_info *cap_info,
+ struct sdram_base_params *base,
+ u32 *p_os_reg2, u32 *p_os_reg3, u32 channel)
+{
+ *p_os_reg2 |= SYS_REG_ENC_DDRTYPE(base->dramtype);
+ *p_os_reg2 |= SYS_REG_ENC_NUM_CH(base->num_channels);
+
+ *p_os_reg2 |= SYS_REG_ENC_ROW_3_4(cap_info->row_3_4, channel);
+ *p_os_reg2 |= SYS_REG_ENC_CHINFO(channel);
+ *p_os_reg2 |= SYS_REG_ENC_RANK(cap_info->rank, channel);
+ *p_os_reg2 |= SYS_REG_ENC_COL(cap_info->col, channel);
+ *p_os_reg2 |= SYS_REG_ENC_BK(cap_info->bk, channel);
+ *p_os_reg2 |= SYS_REG_ENC_BW(cap_info->bw, channel);
+ *p_os_reg2 |= SYS_REG_ENC_DBW(cap_info->dbw, channel);
+
+ SYS_REG_ENC_CS0_ROW(cap_info->cs0_row, *p_os_reg2, *p_os_reg3, channel);
+ if (cap_info->cs1_row)
+ SYS_REG_ENC_CS1_ROW(cap_info->cs1_row, *p_os_reg2,
+ *p_os_reg3, channel);
+ *p_os_reg3 |= SYS_REG_ENC_CS1_COL(cap_info->col, channel);
+ *p_os_reg3 |= SYS_REG_ENC_VERSION(DDR_SYS_REG_VERSION);
+}
+
+int sdram_detect_bw(struct sdram_cap_info *cap_info)
+{
+ return 0;
+}
+
+int sdram_detect_cs(struct sdram_cap_info *cap_info)
+{
+ return 0;
+}
+
+int sdram_detect_col(struct sdram_cap_info *cap_info,
+ u32 coltmp)
+{
+ void __iomem *test_addr;
+ u32 col;
+ u32 bw = cap_info->bw;
+
+ for (col = coltmp; col >= 9; col -= 1) {
+ writel(0, CONFIG_SYS_SDRAM_BASE);
+ test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
+ (1ul << (col + bw - 1ul)));
+ writel(PATTERN, test_addr);
+ if ((readl(test_addr) == PATTERN) &&
+ (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+ break;
+ }
+ if (col == 8) {
+ printascii("col error\n");
+ return -1;
+ }
+
+ cap_info->col = col;
+
+ return 0;
+}
+
+int sdram_detect_bank(struct sdram_cap_info *cap_info,
+ u32 coltmp, u32 bktmp)
+{
+ void __iomem *test_addr;
+ u32 bk;
+ u32 bw = cap_info->bw;
+
+ test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
+ (1ul << (coltmp + bktmp + bw - 1ul)));
+ writel(0, CONFIG_SYS_SDRAM_BASE);
+ writel(PATTERN, test_addr);
+ if ((readl(test_addr) == PATTERN) &&
+ (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+ bk = 3;
+ else
+ bk = 2;
+
+ cap_info->bk = bk;
+
+ return 0;
+}
+
+/* detect bg for ddr4 */
+int sdram_detect_bg(struct sdram_cap_info *cap_info,
+ u32 coltmp)
+{
+ void __iomem *test_addr;
+ u32 dbw;
+ u32 bw = cap_info->bw;
+
+ test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
+ (1ul << (coltmp + bw + 1ul)));
+ writel(0, CONFIG_SYS_SDRAM_BASE);
+ writel(PATTERN, test_addr);
+ if ((readl(test_addr) == PATTERN) &&
+ (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+ dbw = 0;
+ else
+ dbw = 1;
+
+ cap_info->dbw = dbw;
+
+ return 0;
+}
+
+/* detect dbw for ddr3,lpddr2,lpddr3,lpddr4 */
+int sdram_detect_dbw(struct sdram_cap_info *cap_info, u32 dram_type)
+{
+ u32 row, col, bk, bw, cs_cap, cs;
+ u32 die_bw_0 = 0, die_bw_1 = 0;
+
+ if (dram_type == DDR3 || dram_type == LPDDR4) {
+ cap_info->dbw = 1;
+ } else if (dram_type == LPDDR3 || dram_type == LPDDR2) {
+ row = cap_info->cs0_row;
+ col = cap_info->col;
+ bk = cap_info->bk;
+ cs = cap_info->rank;
+ bw = cap_info->bw;
+ cs_cap = (1 << (row + col + bk + bw - 20));
+ if (bw == 2) {
+ if (cs_cap <= 0x2000000) /* 256Mb */
+ die_bw_0 = (col < 9) ? 2 : 1;
+ else if (cs_cap <= 0x10000000) /* 2Gb */
+ die_bw_0 = (col < 10) ? 2 : 1;
+ else if (cs_cap <= 0x40000000) /* 8Gb */
+ die_bw_0 = (col < 11) ? 2 : 1;
+ else
+ die_bw_0 = (col < 12) ? 2 : 1;
+ if (cs > 1) {
+ row = cap_info->cs1_row;
+ cs_cap = (1 << (row + col + bk + bw - 20));
+ if (cs_cap <= 0x2000000) /* 256Mb */
+ die_bw_0 = (col < 9) ? 2 : 1;
+ else if (cs_cap <= 0x10000000) /* 2Gb */
+ die_bw_0 = (col < 10) ? 2 : 1;
+ else if (cs_cap <= 0x40000000) /* 8Gb */
+ die_bw_0 = (col < 11) ? 2 : 1;
+ else
+ die_bw_0 = (col < 12) ? 2 : 1;
+ }
+ } else {
+ die_bw_1 = 1;
+ die_bw_0 = 1;
+ }
+ cap_info->dbw = (die_bw_0 > die_bw_1) ? die_bw_0 : die_bw_1;
+ }
+
+ return 0;
+}
+
+int sdram_detect_row(struct sdram_cap_info *cap_info,
+ u32 coltmp, u32 bktmp, u32 rowtmp)
+{
+ u32 row;
+ u32 bw = cap_info->bw;
+ void __iomem *test_addr;
+
+ for (row = rowtmp; row > 12; row--) {
+ writel(0, CONFIG_SYS_SDRAM_BASE);
+ test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
+ (1ul << (row + bktmp + coltmp + bw - 1ul)));
+ writel(PATTERN, test_addr);
+ if ((readl(test_addr) == PATTERN) &&
+ (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+ break;
+ }
+ if (row == 12) {
+ printascii("row error");
+ return -1;
+ }
+
+ cap_info->cs0_row = row;
+
+ return 0;
+}
+
+int sdram_detect_row_3_4(struct sdram_cap_info *cap_info,
+ u32 coltmp, u32 bktmp)
+{
+ u32 row_3_4;
+ u32 bw = cap_info->bw;
+ u32 row = cap_info->cs0_row;
+ void __iomem *test_addr, *test_addr1;
+
+ test_addr = CONFIG_SYS_SDRAM_BASE;
+ test_addr1 = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
+ (0x3ul << (row + bktmp + coltmp + bw - 1ul - 1ul)));
+
+ writel(0, test_addr);
+ writel(PATTERN, test_addr1);
+ if ((readl(test_addr) == 0) && (readl(test_addr1) == PATTERN))
+ row_3_4 = 0;
+ else
+ row_3_4 = 1;
+
+ cap_info->row_3_4 = row_3_4;
+
+ return 0;
+}
+
+int sdram_detect_high_row(struct sdram_cap_info *cap_info)
+{
+ cap_info->cs0_high16bit_row = cap_info->cs0_row;
+ cap_info->cs1_high16bit_row = cap_info->cs1_row;
+
+ return 0;
+}
+
+int sdram_detect_cs1_row(struct sdram_cap_info *cap_info, u32 dram_type)
+{
+ void __iomem *test_addr;
+ u32 row = 0, bktmp, coltmp, bw;
+ ulong cs0_cap;
+ u32 byte_mask;
+
+ if (cap_info->rank == 2) {
+ cs0_cap = sdram_get_cs_cap(cap_info, 0, dram_type);
+
+ if (dram_type == DDR4) {
+ if (cap_info->dbw == 0)
+ bktmp = cap_info->bk + 2;
+ else
+ bktmp = cap_info->bk + 1;
+ } else {
+ bktmp = cap_info->bk;
+ }
+ bw = cap_info->bw;
+ coltmp = cap_info->col;
+
+ /*
+ * because px30 support axi split,min bandwidth
+ * is 8bit. if cs0 is 32bit, cs1 may 32bit or 16bit
+ * so we check low 16bit data when detect cs1 row.
+ * if cs0 is 16bit/8bit, we check low 8bit data.
+ */
+ if (bw == 2)
+ byte_mask = 0xFFFF;
+ else
+ byte_mask = 0xFF;
+
+ /* detect cs1 row */
+ for (row = cap_info->cs0_row; row > 12; row--) {
+ test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
+ cs0_cap +
+ (1ul << (row + bktmp + coltmp + bw - 1ul)));
+ writel(0, CONFIG_SYS_SDRAM_BASE + cs0_cap);
+ writel(PATTERN, test_addr);
+
+ if (((readl(test_addr) & byte_mask) ==
+ (PATTERN & byte_mask)) &&
+ ((readl(CONFIG_SYS_SDRAM_BASE + cs0_cap) &
+ byte_mask) == 0)) {
+ break;
+ }
+ }
+ }
+
+ cap_info->cs1_row = row;
+
+ return 0;
+}
diff --git a/drivers/ram/rockchip/sdram_debug.c b/drivers/ram/rockchip/sdram_debug.c
deleted file mode 100644
index 9cf662675b..0000000000
--- a/drivers/ram/rockchip/sdram_debug.c
+++ /dev/null
@@ -1,147 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * (C) Copyright 2019 Rockchip Electronics Co., Ltd
- * (C) Copyright 2019 Amarula Solutions.
- * Author: Jagan Teki <jagan@amarulasolutions.com>
- */
-
-#include <common.h>
-#include <debug_uart.h>
-#include <asm/arch-rockchip/sdram_common.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_pctl_px30.c b/drivers/ram/rockchip/sdram_pctl_px30.c
new file mode 100644
index 0000000000..1839cebb67
--- /dev/null
+++ b/drivers/ram/rockchip/sdram_pctl_px30.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2018 Rockchip Electronics Co., Ltd.
+ */
+
+#include <common.h>
+#include <ram.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/sdram.h>
+#include <asm/arch-rockchip/sdram_pctl_px30.h>
+
+/*
+ * rank = 1: cs0
+ * rank = 2: cs1
+ */
+void pctl_read_mr(void __iomem *pctl_base, u32 rank, u32 mr_num)
+{
+ writel((rank << 4) | (1 << 0), pctl_base + DDR_PCTL2_MRCTRL0);
+ writel((mr_num << 8), pctl_base + DDR_PCTL2_MRCTRL1);
+ setbits_le32(pctl_base + DDR_PCTL2_MRCTRL0, 1u << 31);
+ while (readl(pctl_base + DDR_PCTL2_MRCTRL0) & (1u << 31))
+ continue;
+ while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
+ continue;
+}
+
+/* rank = 1: cs0
+ * rank = 2: cs1
+ * rank = 3: cs0 & cs1
+ * note: be careful of keep mr original val
+ */
+int pctl_write_mr(void __iomem *pctl_base, u32 rank, u32 mr_num, u32 arg,
+ u32 dramtype)
+{
+ while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
+ continue;
+ if (dramtype == DDR3 || dramtype == DDR4) {
+ writel((mr_num << 12) | (rank << 4) | (0 << 0),
+ pctl_base + DDR_PCTL2_MRCTRL0);
+ writel(arg, pctl_base + DDR_PCTL2_MRCTRL1);
+ } else {
+ writel((rank << 4) | (0 << 0),
+ pctl_base + DDR_PCTL2_MRCTRL0);
+ writel((mr_num << 8) | (arg & 0xff),
+ pctl_base + DDR_PCTL2_MRCTRL1);
+ }
+
+ setbits_le32(pctl_base + DDR_PCTL2_MRCTRL0, 1u << 31);
+ while (readl(pctl_base + DDR_PCTL2_MRCTRL0) & (1u << 31))
+ continue;
+ while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
+ continue;
+
+ return 0;
+}
+
+/*
+ * rank : 1:cs0, 2:cs1, 3:cs0&cs1
+ * vrefrate: 4500: 45%,
+ */
+int pctl_write_vrefdq(void __iomem *pctl_base, u32 rank, u32 vrefrate,
+ u32 dramtype)
+{
+ u32 tccd_l, value;
+ u32 dis_auto_zq = 0;
+
+ if (dramtype != DDR4 || vrefrate < 4500 ||
+ vrefrate > 9200)
+ return (-1);
+
+ tccd_l = (readl(pctl_base + DDR_PCTL2_DRAMTMG4) >> 16) & 0xf;
+ tccd_l = (tccd_l - 4) << 10;
+
+ if (vrefrate > 7500) {
+ /* range 1 */
+ value = ((vrefrate - 6000) / 65) | tccd_l;
+ } else {
+ /* range 2 */
+ value = ((vrefrate - 4500) / 65) | tccd_l | (1 << 6);
+ }
+
+ dis_auto_zq = pctl_dis_zqcs_aref(pctl_base);
+
+ /* enable vrefdq calibratin */
+ pctl_write_mr(pctl_base, rank, 6, value | (1 << 7), dramtype);
+ udelay(1);/* tvrefdqe */
+ /* write vrefdq value */
+ pctl_write_mr(pctl_base, rank, 6, value | (1 << 7), dramtype);
+ udelay(1);/* tvref_time */
+ pctl_write_mr(pctl_base, rank, 6, value | (0 << 7), dramtype);
+ udelay(1);/* tvrefdqx */
+
+ pctl_rest_zqcs_aref(pctl_base, dis_auto_zq);
+
+ return 0;
+}
+
+static int upctl2_update_ref_reg(void __iomem *pctl_base)
+{
+ u32 ret;
+
+ ret = readl(pctl_base + DDR_PCTL2_RFSHCTL3) ^ (1 << 1);
+ writel(ret, pctl_base + DDR_PCTL2_RFSHCTL3);
+
+ return 0;
+}
+
+u32 pctl_dis_zqcs_aref(void __iomem *pctl_base)
+{
+ u32 dis_auto_zq = 0;
+
+ /* disable zqcs */
+ if (!(readl(pctl_base + DDR_PCTL2_ZQCTL0) &
+ (1ul << 31))) {
+ dis_auto_zq = 1;
+ setbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
+ }
+
+ /* disable auto refresh */
+ setbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
+
+ upctl2_update_ref_reg(pctl_base);
+
+ return dis_auto_zq;
+}
+
+void pctl_rest_zqcs_aref(void __iomem *pctl_base, u32 dis_auto_zq)
+{
+ /* restore zqcs */
+ if (dis_auto_zq)
+ clrbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
+
+ /* restore auto refresh */
+ clrbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
+
+ upctl2_update_ref_reg(pctl_base);
+}
+
+u32 pctl_remodify_sdram_params(struct ddr_pctl_regs *pctl_regs,
+ struct sdram_cap_info *cap_info,
+ u32 dram_type)
+{
+ u32 tmp = 0, tmp_adr = 0, i;
+
+ for (i = 0; pctl_regs->pctl[i][0] != 0xFFFFFFFF; i++) {
+ if (pctl_regs->pctl[i][0] == 0) {
+ tmp = pctl_regs->pctl[i][1];/* MSTR */
+ tmp_adr = i;
+ }
+ }
+
+ tmp &= ~((3ul << 30) | (3ul << 24) | (3ul << 12));
+
+ switch (cap_info->dbw) {
+ case 2:
+ tmp |= (3ul << 30);
+ break;
+ case 1:
+ tmp |= (2ul << 30);
+ break;
+ case 0:
+ default:
+ tmp |= (1ul << 30);
+ break;
+ }
+
+ /*
+ * If DDR3 or DDR4 MSTR.active_ranks=1,
+ * it will gate memory clock when enter power down.
+ * Force set active_ranks to 3 to workaround it.
+ */
+ if (cap_info->rank == 2 || dram_type == DDR3 ||
+ dram_type == DDR4)
+ tmp |= 3 << 24;
+ else
+ tmp |= 1 << 24;
+
+ tmp |= (2 - cap_info->bw) << 12;
+
+ pctl_regs->pctl[tmp_adr][1] = tmp;
+
+ return 0;
+}
+
+int pctl_cfg(void __iomem *pctl_base, struct ddr_pctl_regs *pctl_regs,
+ u32 sr_idle, u32 pd_idle)
+{
+ u32 i;
+
+ for (i = 0; pctl_regs->pctl[i][0] != 0xFFFFFFFF; i++) {
+ writel(pctl_regs->pctl[i][1],
+ pctl_base + pctl_regs->pctl[i][0]);
+ }
+ clrsetbits_le32(pctl_base + DDR_PCTL2_PWRTMG,
+ (0xff << 16) | 0x1f,
+ ((sr_idle & 0xff) << 16) | (pd_idle & 0x1f));
+
+ clrsetbits_le32(pctl_base + DDR_PCTL2_HWLPCTL,
+ 0xfff << 16,
+ 5 << 16);
+ /* disable zqcs */
+ setbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1u << 31);
+
+ return 0;
+}
diff --git a/drivers/ram/rockchip/sdram_phy_px30.c b/drivers/ram/rockchip/sdram_phy_px30.c
new file mode 100644
index 0000000000..5de73770a8
--- /dev/null
+++ b/drivers/ram/rockchip/sdram_phy_px30.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2018 Rockchip Electronics Co., Ltd.
+ */
+
+#include <common.h>
+#include <ram.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/sdram.h>
+#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_phy_px30.h>
+
+static void sdram_phy_dll_bypass_set(void __iomem *phy_base, u32 freq)
+{
+ u32 tmp;
+ u32 i, j;
+ u32 dqs_dll_freq;
+
+ setbits_le32(PHY_REG(phy_base, 0x13), 1 << 4);
+ clrbits_le32(PHY_REG(phy_base, 0x14), 1 << 3);
+ for (i = 0; i < 4; i++) {
+ j = 0x26 + i * 0x10;
+ setbits_le32(PHY_REG(phy_base, j), 1 << 4);
+ clrbits_le32(PHY_REG(phy_base, j + 0x1), 1 << 3);
+ }
+
+ if (freq <= 400)
+ /* DLL bypass */
+ setbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
+ else
+ clrbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
+
+ #ifdef CONFIG_ROCKCHIP_RK3328
+ dqs_dll_freq = 680;
+ #else
+ dqs_dll_freq = 801;
+ #endif
+
+ if (freq <= dqs_dll_freq)
+ tmp = 2;
+ else
+ tmp = 1;
+
+ for (i = 0; i < 4; i++) {
+ j = 0x28 + i * 0x10;
+ writel(tmp, PHY_REG(phy_base, j));
+ }
+}
+
+static void sdram_phy_set_ds_odt(void __iomem *phy_base,
+ u32 dram_type)
+{
+ u32 cmd_drv, clk_drv, dqs_drv, dqs_odt;
+ u32 i, j;
+
+ if (dram_type == DDR3) {
+ cmd_drv = PHY_DDR3_RON_RTT_34ohm;
+ clk_drv = PHY_DDR3_RON_RTT_45ohm;
+ dqs_drv = PHY_DDR3_RON_RTT_34ohm;
+ dqs_odt = PHY_DDR3_RON_RTT_225ohm;
+ } else {
+ cmd_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
+ clk_drv = PHY_DDR4_LPDDR3_RON_RTT_43ohm;
+ dqs_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
+ if (dram_type == LPDDR2)
+ dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_DISABLE;
+ else
+ dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_240ohm;
+ }
+ /* DS */
+ writel(cmd_drv, PHY_REG(phy_base, 0x11));
+ clrsetbits_le32(PHY_REG(phy_base, 0x12), 0x1f << 3, cmd_drv << 3);
+ writel(clk_drv, PHY_REG(phy_base, 0x16));
+ writel(clk_drv, PHY_REG(phy_base, 0x18));
+
+ for (i = 0; i < 4; i++) {
+ j = 0x20 + i * 0x10;
+ writel(dqs_drv, PHY_REG(phy_base, j));
+ writel(dqs_drv, PHY_REG(phy_base, j + 0xf));
+ /* ODT */
+ writel(dqs_odt, PHY_REG(phy_base, j + 0x1));
+ writel(dqs_odt, PHY_REG(phy_base, j + 0xe));
+ }
+}
+
+void phy_soft_reset(void __iomem *phy_base)
+{
+ clrbits_le32(PHY_REG(phy_base, 0), 0x3 << 2);
+ udelay(1);
+ setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET);
+ udelay(5);
+ setbits_le32(PHY_REG(phy_base, 0), DIGITAL_DERESET);
+ udelay(1);
+}
+
+void phy_dram_set_bw(void __iomem *phy_base, u32 bw)
+{
+ if (bw == 2) {
+ clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4);
+ setbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
+ setbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
+ } else if (bw == 1) {
+ clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4);
+ clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
+ clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
+ } else if (bw == 0) {
+ clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 1 << 4);
+ clrbits_le32(PHY_REG(phy_base, 0x36), 1 << 3);
+ clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
+ clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
+ }
+
+ phy_soft_reset(phy_base);
+}
+
+int phy_data_training(void __iomem *phy_base, u32 cs, u32 dramtype)
+{
+ u32 ret;
+ u32 odt_val;
+ u32 i, j;
+
+ odt_val = readl(PHY_REG(phy_base, 0x2e));
+
+ for (i = 0; i < 4; i++) {
+ j = 0x20 + i * 0x10;
+ writel(PHY_DDR3_RON_RTT_225ohm, PHY_REG(phy_base, j + 0x1));
+ writel(0, PHY_REG(phy_base, j + 0xe));
+ }
+
+ if (dramtype == DDR4) {
+ clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0);
+ clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0);
+ clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0);
+ clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0);
+ }
+ /* choose training cs */
+ clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs));
+ /* enable gate training */
+ clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1);
+ udelay(50);
+ ret = readl(PHY_REG(phy_base, 0xff));
+ /* disable gate training */
+ clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0);
+ #ifndef CONFIG_ROCKCHIP_RK3328
+ clrbits_le32(PHY_REG(phy_base, 2), 0x30);
+ #endif
+
+ if (dramtype == DDR4) {
+ clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0x2);
+ clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0x2);
+ clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0x2);
+ clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0x2);
+ }
+
+ if (ret & 0x10) {
+ ret = -1;
+ } else {
+ ret = (ret & 0xf) ^ (readl(PHY_REG(phy_base, 0)) >> 4);
+ ret = (ret == 0) ? 0 : -1;
+ }
+
+ for (i = 0; i < 4; i++) {
+ j = 0x20 + i * 0x10;
+ writel(odt_val, PHY_REG(phy_base, j + 0x1));
+ writel(odt_val, PHY_REG(phy_base, j + 0xe));
+ }
+ return ret;
+}
+
+void phy_cfg(void __iomem *phy_base,
+ struct ddr_phy_regs *phy_regs, struct ddr_phy_skew *skew,
+ struct sdram_base_params *base, u32 bw)
+{
+ u32 i;
+
+ sdram_phy_dll_bypass_set(phy_base, base->ddr_freq);
+ for (i = 0; phy_regs->phy[i][0] != 0xFFFFFFFF; i++) {
+ writel(phy_regs->phy[i][1],
+ phy_base + phy_regs->phy[i][0]);
+ }
+ if (bw == 2) {
+ clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4);
+ } else if (bw == 1) {
+ clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4);
+ /* disable DQS2,DQS3 tx dll for saving power */
+ clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
+ clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
+ } else {
+ clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 1 << 4);
+ /* disable DQS2,DQS3 tx dll for saving power */
+ clrbits_le32(PHY_REG(phy_base, 0x36), 1 << 3);
+ clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
+ clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
+ }
+ sdram_phy_set_ds_odt(phy_base, base->dramtype);
+
+ /* deskew */
+ setbits_le32(PHY_REG(phy_base, 2), 8);
+ sdram_copy_to_reg(PHY_REG(phy_base, 0xb0),
+ &skew->a0_a1_skew[0], 15 * 4);
+ sdram_copy_to_reg(PHY_REG(phy_base, 0x70),
+ &skew->cs0_dm0_skew[0], 44 * 4);
+ sdram_copy_to_reg(PHY_REG(phy_base, 0xc0),
+ &skew->cs1_dm0_skew[0], 44 * 4);
+}
diff --git a/drivers/ram/rockchip/sdram_px30.c b/drivers/ram/rockchip/sdram_px30.c
new file mode 100644
index 0000000000..729255493a
--- /dev/null
+++ b/drivers/ram/rockchip/sdram_px30.c
@@ -0,0 +1,751 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2018 Rockchip Electronics Co., Ltd.
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <ram.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/cru_px30.h>
+#include <asm/arch-rockchip/grf_px30.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <asm/arch-rockchip/sdram.h>
+#include <asm/arch-rockchip/sdram_px30.h>
+
+struct dram_info {
+#ifdef CONFIG_TPL_BUILD
+ struct ddr_pctl_regs *pctl;
+ struct ddr_phy_regs *phy;
+ struct px30_cru *cru;
+ struct msch_regs *msch;
+ struct px30_ddr_grf_regs *ddr_grf;
+ struct px30_grf *grf;
+#endif
+ struct ram_info info;
+ struct px30_pmugrf *pmugrf;
+};
+
+#ifdef CONFIG_TPL_BUILD
+
+u8 ddr_cfg_2_rbc[] = {
+ /*
+ * [6:4] max row: 13+n
+ * [3] bank(0:4bank,1:8bank)
+ * [2:0] col(10+n)
+ */
+ ((5 << 4) | (1 << 3) | 0), /* 0 */
+ ((5 << 4) | (1 << 3) | 1), /* 1 */
+ ((4 << 4) | (1 << 3) | 2), /* 2 */
+ ((3 << 4) | (1 << 3) | 3), /* 3 */
+ ((2 << 4) | (1 << 3) | 4), /* 4 */
+ ((5 << 4) | (0 << 3) | 2), /* 5 */
+ ((4 << 4) | (1 << 3) | 2), /* 6 */
+ /*((0<<3)|3),*/ /* 12 for ddr4 */
+ /*((1<<3)|1),*/ /* 13 B,C exchange for rkvdec */
+};
+
+/*
+ * for ddr4 if ddrconfig=7, upctl should set 7 and noc should
+ * set to 1 for more efficient.
+ * noc ddrconf, upctl addrmap
+ * 1 7
+ * 2 8
+ * 3 9
+ * 12 10
+ * 5 11
+ */
+u8 d4_rbc_2_d3_rbc[] = {
+ 1, /* 7 */
+ 2, /* 8 */
+ 3, /* 9 */
+ 12, /* 10 */
+ 5, /* 11 */
+};
+
+/*
+ * row higher than cs should be disabled by set to 0xf
+ * rank addrmap calculate by real cap.
+ */
+u32 addrmap[][8] = {
+ /* map0 map1, map2, map3, map4, map5
+ * map6, map7, map8
+ * -------------------------------------------------------
+ * bk2-0 col 5-2 col 9-6 col 11-10 row 11-0
+ * row 15-12 row 17-16 bg1,0
+ * -------------------------------------------------------
+ * 4,3,2 5-2 9-6 6
+ * 3,2
+ */
+ {0x00060606, 0x00000000, 0x1f1f0000, 0x00001f1f, 0x05050505,
+ 0x05050505, 0x00000505, 0x3f3f}, /* 0 */
+ {0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x06060606,
+ 0x06060606, 0x06060606, 0x3f3f}, /* 1 */
+ {0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
+ 0x07070707, 0x00000f07, 0x3f3f}, /* 2 */
+ {0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
+ 0x08080808, 0x00000f0f, 0x3f3f}, /* 3 */
+ {0x000a0a0a, 0x00000000, 0x00000000, 0x00000000, 0x09090909,
+ 0x0f090909, 0x00000f0f, 0x3f3f}, /* 4 */
+ {0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x06060606,
+ 0x06060606, 0x00000606, 0x3f3f}, /* 5 */
+ {0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
+ 0x07070707, 0x00000f0f, 0x3f3f}, /* 6 */
+ {0x003f0808, 0x00000006, 0x1f1f0000, 0x00001f1f, 0x06060606,
+ 0x06060606, 0x00000606, 0x0600}, /* 7 */
+ {0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
+ 0x07070707, 0x00000f07, 0x0700}, /* 8 */
+ {0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
+ 0x08080808, 0x00000f0f, 0x0801}, /* 9 */
+ {0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
+ 0x07070707, 0x00000f07, 0x3f01}, /* 10 */
+ {0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x06060606,
+ 0x06060606, 0x00000606, 0x3f00}, /* 11 */
+ /* when ddr4 12 map to 10, when ddr3 12 unused */
+ {0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
+ 0x07070707, 0x00000f07, 0x3f01}, /* 10 */
+ {0x00070706, 0x00000000, 0x1f010000, 0x00001f1f, 0x06060606,
+ 0x06060606, 0x00000606, 0x3f3f}, /* 13 */
+};
+
+#define PMUGRF_BASE_ADDR 0xFF010000
+#define CRU_BASE_ADDR 0xFF2B0000
+#define GRF_BASE_ADDR 0xFF140000
+#define DDRC_BASE_ADDR 0xFF600000
+#define DDR_PHY_BASE_ADDR 0xFF2A0000
+#define SERVER_MSCH0_BASE_ADDR 0xFF530000
+#define DDR_GRF_BASE_ADDR 0xff630000
+
+struct dram_info dram_info;
+
+struct px30_sdram_params sdram_configs[] = {
+#include "sdram-px30-ddr3-detect-333.inc"
+};
+
+struct ddr_phy_skew skew = {
+#include "sdram-px30-ddr_skew.inc"
+};
+
+static void rkclk_ddr_reset(struct dram_info *dram,
+ u32 ctl_srstn, u32 ctl_psrstn,
+ u32 phy_srstn, u32 phy_psrstn)
+{
+ writel(upctl2_srstn_req(ctl_srstn) | upctl2_psrstn_req(ctl_psrstn) |
+ upctl2_asrstn_req(ctl_srstn),
+ &dram->cru->softrst_con[1]);
+ writel(ddrphy_srstn_req(phy_srstn) | ddrphy_psrstn_req(phy_psrstn),
+ &dram->cru->softrst_con[2]);
+}
+
+static void rkclk_set_dpll(struct dram_info *dram, unsigned int hz)
+{
+ unsigned int refdiv, postdiv1, postdiv2, fbdiv;
+ int delay = 1000;
+ u32 mhz = hz / MHz;
+
+ refdiv = 1;
+ if (mhz <= 300) {
+ postdiv1 = 4;
+ postdiv2 = 2;
+ } else if (mhz <= 400) {
+ postdiv1 = 6;
+ postdiv2 = 1;
+ } else if (mhz <= 600) {
+ postdiv1 = 4;
+ postdiv2 = 1;
+ } else if (mhz <= 800) {
+ postdiv1 = 3;
+ postdiv2 = 1;
+ } else if (mhz <= 1600) {
+ postdiv1 = 2;
+ postdiv2 = 1;
+ } else {
+ postdiv1 = 1;
+ postdiv2 = 1;
+ }
+ fbdiv = (mhz * refdiv * postdiv1 * postdiv2) / 24;
+
+ writel(DPLL_MODE(CLOCK_FROM_XIN_OSC), &dram->cru->mode);
+
+ writel(POSTDIV1(postdiv1) | FBDIV(fbdiv), &dram->cru->pll[1].con0);
+ writel(DSMPD(1) | POSTDIV2(postdiv2) | REFDIV(refdiv),
+ &dram->cru->pll[1].con1);
+
+ while (delay > 0) {
+ udelay(1);
+ if (LOCK(readl(&dram->cru->pll[1].con1)))
+ break;
+ delay--;
+ }
+
+ writel(DPLL_MODE(CLOCK_FROM_PLL), &dram->cru->mode);
+}
+
+static void rkclk_configure_ddr(struct dram_info *dram,
+ struct px30_sdram_params *sdram_params)
+{
+ /* for inno ddr phy need 2*freq */
+ rkclk_set_dpll(dram, sdram_params->base.ddr_freq * MHz * 2);
+}
+
+/* return ddrconfig value
+ * (-1), find ddrconfig fail
+ * other, the ddrconfig value
+ * only support cs0_row >= cs1_row
+ */
+static unsigned int calculate_ddrconfig(struct px30_sdram_params *sdram_params)
+{
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+ u32 bw, die_bw, col, bank;
+ u32 i, tmp;
+ u32 ddrconf = -1;
+
+ bw = cap_info->bw;
+ die_bw = cap_info->dbw;
+ col = cap_info->col;
+ bank = cap_info->bk;
+
+ if (sdram_params->base.dramtype == DDR4) {
+ if (die_bw == 0)
+ ddrconf = 7 + bw;
+ else
+ ddrconf = 12 - bw;
+ ddrconf = d4_rbc_2_d3_rbc[ddrconf - 7];
+ } else {
+ tmp = ((bank - 2) << 3) | (col + bw - 10);
+ for (i = 0; i < 7; i++)
+ if ((ddr_cfg_2_rbc[i] & 0xf) == tmp) {
+ ddrconf = i;
+ break;
+ }
+ if (i > 6)
+ printascii("calculate ddrconfig error\n");
+ }
+
+ return ddrconf;
+}
+
+/*
+ * calculate controller dram address map, and setting to register.
+ * argument sdram_params->ch.ddrconf must be right value before
+ * call this function.
+ */
+static void set_ctl_address_map(struct dram_info *dram,
+ struct px30_sdram_params *sdram_params)
+{
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+ void __iomem *pctl_base = dram->pctl;
+ u32 cs_pst, bg, max_row, ddrconf;
+ u32 i;
+
+ if (sdram_params->base.dramtype == 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;
+
+ cs_pst = cap_info->bw + cap_info->col +
+ bg + cap_info->bk + cap_info->cs0_row;
+ if (cs_pst >= 32 || cap_info->rank == 1)
+ writel(0x1f, pctl_base + DDR_PCTL2_ADDRMAP0);
+ else
+ writel(cs_pst - 8, pctl_base + DDR_PCTL2_ADDRMAP0);
+
+ ddrconf = cap_info->ddrconfig;
+ if (sdram_params->base.dramtype == DDR4) {
+ for (i = 0; i < ARRAY_SIZE(d4_rbc_2_d3_rbc); i++) {
+ if (d4_rbc_2_d3_rbc[i] == ddrconf) {
+ ddrconf = 7 + i;
+ break;
+ }
+ }
+ }
+
+ sdram_copy_to_reg((u32 *)(pctl_base + DDR_PCTL2_ADDRMAP1),
+ &addrmap[ddrconf][0], 8 * 4);
+ max_row = cs_pst - 1 - 8 - (addrmap[ddrconf][5] & 0xf);
+
+ if (max_row < 12)
+ printascii("set addrmap fail\n");
+ /* need to disable row ahead of rank by set to 0xf */
+ for (i = 17; i > max_row; i--)
+ clrsetbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6 +
+ ((i - 12) * 8 / 32) * 4,
+ 0xf << ((i - 12) * 8 % 32),
+ 0xf << ((i - 12) * 8 % 32));
+
+ if ((sdram_params->base.dramtype == LPDDR3 ||
+ sdram_params->base.dramtype == LPDDR2) &&
+ cap_info->row_3_4)
+ setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6, 1 << 31);
+ if (sdram_params->base.dramtype == DDR4 && cap_info->bw != 0x2)
+ setbits_le32(pctl_base + DDR_PCTL2_PCCFG, 1 << 8);
+}
+
+/*
+ * rank = 1: cs0
+ * rank = 2: cs1
+ */
+int read_mr(struct dram_info *dram, u32 rank, u32 mr_num)
+{
+ void __iomem *ddr_grf_base = dram->ddr_grf;
+
+ pctl_read_mr(dram->pctl, rank, mr_num);
+
+ return (readl(ddr_grf_base + DDR_GRF_STATUS(0)) & 0xff);
+}
+
+#define MIN(a, b) (((a) > (b)) ? (b) : (a))
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+static u32 check_rd_gate(struct dram_info *dram)
+{
+ void __iomem *phy_base = dram->phy;
+
+ u32 max_val = 0;
+ u32 min_val = 0xff;
+ u32 gate[4];
+ u32 i, bw;
+
+ bw = (readl(PHY_REG(phy_base, 0x0)) >> 4) & 0xf;
+ switch (bw) {
+ case 0x1:
+ bw = 1;
+ break;
+ case 0x3:
+ bw = 2;
+ break;
+ case 0xf:
+ default:
+ bw = 4;
+ break;
+ }
+
+ for (i = 0; i < bw; i++) {
+ gate[i] = readl(PHY_REG(phy_base, 0xfb + i));
+ max_val = MAX(max_val, gate[i]);
+ min_val = MIN(min_val, gate[i]);
+ }
+
+ if (max_val > 0x80 || min_val < 0x20)
+ return -1;
+ else
+ return 0;
+}
+
+static int data_training(struct dram_info *dram, u32 cs, u32 dramtype)
+{
+ void __iomem *pctl_base = dram->pctl;
+ u32 dis_auto_zq = 0;
+ u32 pwrctl;
+ u32 ret;
+
+ /* disable auto low-power */
+ pwrctl = readl(pctl_base + DDR_PCTL2_PWRCTL);
+ writel(0, pctl_base + DDR_PCTL2_PWRCTL);
+
+ dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
+
+ ret = phy_data_training(dram->phy, cs, dramtype);
+
+ pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
+
+ /* restore auto low-power */
+ writel(pwrctl, pctl_base + DDR_PCTL2_PWRCTL);
+
+ return ret;
+}
+
+static void dram_set_bw(struct dram_info *dram, u32 bw)
+{
+ phy_dram_set_bw(dram->phy, bw);
+}
+
+static void set_ddrconfig(struct dram_info *dram, u32 ddrconfig)
+{
+ writel(ddrconfig | (ddrconfig << 8), &dram->msch->deviceconf);
+ rk_clrsetreg(&dram->grf->soc_noc_con[1], 0x3 << 14, 0 << 14);
+}
+
+static void sdram_msch_config(struct msch_regs *msch,
+ struct sdram_msch_timings *noc_timings,
+ struct sdram_cap_info *cap_info,
+ struct sdram_base_params *base)
+{
+ u64 cs_cap[2];
+
+ cs_cap[0] = sdram_get_cs_cap(cap_info, 0, base->dramtype);
+ cs_cap[1] = sdram_get_cs_cap(cap_info, 1, base->dramtype);
+ writel(((((cs_cap[1] >> 20) / 64) & 0xff) << 8) |
+ (((cs_cap[0] >> 20) / 64) & 0xff),
+ &msch->devicesize);
+
+ writel(noc_timings->ddrtiminga0.d32,
+ &msch->ddrtiminga0);
+ writel(noc_timings->ddrtimingb0.d32,
+ &msch->ddrtimingb0);
+ writel(noc_timings->ddrtimingc0.d32,
+ &msch->ddrtimingc0);
+ writel(noc_timings->devtodev0.d32,
+ &msch->devtodev0);
+ writel(noc_timings->ddrmode.d32, &msch->ddrmode);
+ writel(noc_timings->ddr4timing.d32,
+ &msch->ddr4timing);
+ writel(noc_timings->agingx0, &msch->agingx0);
+ writel(noc_timings->agingx0, &msch->aging0);
+ writel(noc_timings->agingx0, &msch->aging1);
+ writel(noc_timings->agingx0, &msch->aging2);
+ writel(noc_timings->agingx0, &msch->aging3);
+}
+
+static void dram_all_config(struct dram_info *dram,
+ struct px30_sdram_params *sdram_params)
+{
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+ u32 sys_reg2 = 0;
+ u32 sys_reg3 = 0;
+
+ set_ddrconfig(dram, cap_info->ddrconfig);
+ sdram_org_config(cap_info, &sdram_params->base, &sys_reg2,
+ &sys_reg3, 0);
+ writel(sys_reg2, &dram->pmugrf->os_reg[2]);
+ writel(sys_reg3, &dram->pmugrf->os_reg[3]);
+ sdram_msch_config(dram->msch, &sdram_params->ch.noc_timings, cap_info,
+ &sdram_params->base);
+}
+
+static void enable_low_power(struct dram_info *dram,
+ struct px30_sdram_params *sdram_params)
+{
+ void __iomem *pctl_base = dram->pctl;
+ void __iomem *phy_base = dram->phy;
+ void __iomem *ddr_grf_base = dram->ddr_grf;
+ u32 grf_lp_con;
+
+ /*
+ * bit0: grf_upctl_axi_cg_en = 1 enable upctl2 axi clk auto gating
+ * bit1: grf_upctl_apb_cg_en = 1 ungated axi,core clk for apb access
+ * bit2: grf_upctl_core_cg_en = 1 enable upctl2 core clk auto gating
+ * bit3: grf_selfref_type2_en = 0 disable core clk gating when type2 sr
+ * bit4: grf_upctl_syscreq_cg_en = 1
+ * ungating coreclk when c_sysreq assert
+ * bit8-11: grf_auto_sr_dly = 6
+ */
+ writel(0x1f1f0617, &dram->ddr_grf->ddr_grf_con[1]);
+
+ if (sdram_params->base.dramtype == DDR4)
+ grf_lp_con = (0x7 << 16) | (1 << 1);
+ else if (sdram_params->base.dramtype == DDR3)
+ grf_lp_con = (0x7 << 16) | (1 << 0);
+ else
+ grf_lp_con = (0x7 << 16) | (1 << 2);
+
+ /* en lpckdis_en */
+ grf_lp_con = grf_lp_con | (0x1 << (9 + 16)) | (0x1 << 9);
+ writel(grf_lp_con, ddr_grf_base + DDR_GRF_LP_CON);
+
+ /* off digit module clock when enter power down */
+ setbits_le32(PHY_REG(phy_base, 7), 1 << 7);
+
+ /* enable sr, pd */
+ if (PD_IDLE == 0)
+ clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
+ else
+ setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
+ if (SR_IDLE == 0)
+ clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
+ else
+ setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
+ setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 3));
+}
+
+/*
+ * pre_init: 0: pre init for dram cap detect
+ * 1: detect correct cap(except cs1 row)info, than reinit
+ * 2: after reinit, we detect cs1_row, if cs1_row not equal
+ * to cs0_row and cs is in middle on ddrconf map, we need
+ * to reinit dram, than set the correct ddrconf.
+ */
+static int sdram_init_(struct dram_info *dram,
+ struct px30_sdram_params *sdram_params, u32 pre_init)
+{
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+ void __iomem *pctl_base = dram->pctl;
+
+ rkclk_ddr_reset(dram, 1, 1, 1, 1);
+ udelay(10);
+ /*
+ * dereset ddr phy psrstn to config pll,
+ * if using phy pll psrstn must be dereset
+ * before config pll
+ */
+ rkclk_ddr_reset(dram, 1, 1, 1, 0);
+ rkclk_configure_ddr(dram, sdram_params);
+
+ /* release phy srst to provide clk to ctrl */
+ rkclk_ddr_reset(dram, 1, 1, 0, 0);
+ udelay(10);
+ phy_soft_reset(dram->phy);
+ /* release ctrl presetn, and config ctl registers */
+ rkclk_ddr_reset(dram, 1, 0, 0, 0);
+ pctl_cfg(dram->pctl, &sdram_params->pctl_regs, SR_IDLE, PD_IDLE);
+ cap_info->ddrconfig = calculate_ddrconfig(sdram_params);
+ set_ctl_address_map(dram, sdram_params);
+ phy_cfg(dram->phy, &sdram_params->phy_regs, sdram_params->skew,
+ &sdram_params->base, cap_info->bw);
+
+ /* enable dfi_init_start to init phy after ctl srstn deassert */
+ setbits_le32(pctl_base + DDR_PCTL2_DFIMISC, (1 << 5) | (1 << 4));
+
+ rkclk_ddr_reset(dram, 0, 0, 0, 0);
+ /* wait for dfi_init_done and dram init complete */
+ while ((readl(pctl_base + DDR_PCTL2_STAT) & 0x7) == 0)
+ continue;
+
+ if (sdram_params->base.dramtype == LPDDR3)
+ pctl_write_mr(dram->pctl, 3, 11, 3, LPDDR3);
+
+ /* do ddr gate training */
+redo_cs0_training:
+ if (data_training(dram, 0, sdram_params->base.dramtype) != 0) {
+ if (pre_init != 0)
+ printascii("DTT cs0 error\n");
+ return -1;
+ }
+ if (check_rd_gate(dram)) {
+ printascii("re training cs0");
+ goto redo_cs0_training;
+ }
+
+ if (sdram_params->base.dramtype == LPDDR3) {
+ if ((read_mr(dram, 1, 8) & 0x3) != 0x3)
+ return -1;
+ } else if (sdram_params->base.dramtype == LPDDR2) {
+ if ((read_mr(dram, 1, 8) & 0x3) != 0x0)
+ return -1;
+ }
+ /* for px30: when 2cs, both 2 cs should be training */
+ if (pre_init != 0 && cap_info->rank == 2) {
+redo_cs1_training:
+ if (data_training(dram, 1, sdram_params->base.dramtype) != 0) {
+ printascii("DTT cs1 error\n");
+ return -1;
+ }
+ if (check_rd_gate(dram)) {
+ printascii("re training cs1");
+ goto redo_cs1_training;
+ }
+ }
+
+ if (sdram_params->base.dramtype == DDR4)
+ pctl_write_vrefdq(dram->pctl, 0x3, 5670,
+ sdram_params->base.dramtype);
+
+ dram_all_config(dram, sdram_params);
+ enable_low_power(dram, sdram_params);
+
+ return 0;
+}
+
+static int dram_detect_cap(struct dram_info *dram,
+ struct px30_sdram_params *sdram_params,
+ unsigned char channel)
+{
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+
+ /*
+ * for ddr3: ddrconf = 3
+ * for ddr4: ddrconf = 12
+ * for lpddr3: ddrconf = 3
+ * default bw = 1
+ */
+ u32 bk, bktmp;
+ u32 col, coltmp;
+ u32 rowtmp;
+ u32 cs;
+ u32 bw = 1;
+ u32 dram_type = sdram_params->base.dramtype;
+
+ if (dram_type != DDR4) {
+ /* detect col and bk for ddr3/lpddr3 */
+ coltmp = 12;
+ bktmp = 3;
+ if (dram_type == LPDDR2)
+ rowtmp = 15;
+ else
+ rowtmp = 16;
+
+ if (sdram_detect_col(cap_info, coltmp) != 0)
+ goto cap_err;
+ sdram_detect_bank(cap_info, coltmp, bktmp);
+ sdram_detect_dbw(cap_info, dram_type);
+ } else {
+ /* detect bg for ddr4 */
+ coltmp = 10;
+ bktmp = 4;
+ rowtmp = 17;
+
+ col = 10;
+ bk = 2;
+ cap_info->col = col;
+ cap_info->bk = bk;
+ sdram_detect_bg(cap_info, coltmp);
+ }
+
+ /* detect row */
+ if (sdram_detect_row(cap_info, coltmp, bktmp, rowtmp) != 0)
+ goto cap_err;
+
+ /* detect row_3_4 */
+ sdram_detect_row_3_4(cap_info, coltmp, bktmp);
+
+ /* bw and cs detect using data training */
+ if (data_training(dram, 1, dram_type) == 0)
+ cs = 1;
+ else
+ cs = 0;
+ cap_info->rank = cs + 1;
+
+ dram_set_bw(dram, 2);
+ if (data_training(dram, 0, dram_type) == 0)
+ bw = 2;
+ else
+ bw = 1;
+ cap_info->bw = bw;
+
+ cap_info->cs0_high16bit_row = cap_info->cs0_row;
+ if (cs) {
+ cap_info->cs1_row = cap_info->cs0_row;
+ cap_info->cs1_high16bit_row = cap_info->cs0_row;
+ } else {
+ cap_info->cs1_row = 0;
+ cap_info->cs1_high16bit_row = 0;
+ }
+
+ return 0;
+cap_err:
+ return -1;
+}
+
+/* return: 0 = success, other = fail */
+static int sdram_init_detect(struct dram_info *dram,
+ struct px30_sdram_params *sdram_params)
+{
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+ u32 ret;
+ u32 sys_reg = 0;
+ u32 sys_reg3 = 0;
+
+ if (sdram_init_(dram, sdram_params, 0) != 0)
+ return -1;
+
+ if (dram_detect_cap(dram, sdram_params, 0) != 0)
+ return -1;
+
+ /* modify bw, cs related timing */
+ pctl_remodify_sdram_params(&sdram_params->pctl_regs, cap_info,
+ sdram_params->base.dramtype);
+ /* reinit sdram by real dram cap */
+ ret = sdram_init_(dram, sdram_params, 1);
+ if (ret != 0)
+ goto out;
+
+ /* redetect cs1 row */
+ sdram_detect_cs1_row(cap_info, sdram_params->base.dramtype);
+ if (cap_info->cs1_row) {
+ sys_reg = readl(&dram->pmugrf->os_reg[2]);
+ sys_reg3 = readl(&dram->pmugrf->os_reg[3]);
+ SYS_REG_ENC_CS1_ROW(cap_info->cs1_row,
+ sys_reg, sys_reg3, 0);
+ writel(sys_reg, &dram->pmugrf->os_reg[2]);
+ writel(sys_reg3, &dram->pmugrf->os_reg[3]);
+ }
+
+ ret = sdram_detect_high_row(cap_info);
+
+out:
+ return ret;
+}
+
+struct px30_sdram_params
+ *get_default_sdram_config(void)
+{
+ sdram_configs[0].skew = &skew;
+
+ return &sdram_configs[0];
+}
+
+/* return: 0 = success, other = fail */
+int sdram_init(void)
+{
+ struct px30_sdram_params *sdram_params;
+ int ret = 0;
+
+ dram_info.phy = (void *)DDR_PHY_BASE_ADDR;
+ dram_info.pctl = (void *)DDRC_BASE_ADDR;
+ dram_info.grf = (void *)GRF_BASE_ADDR;
+ dram_info.cru = (void *)CRU_BASE_ADDR;
+ dram_info.msch = (void *)SERVER_MSCH0_BASE_ADDR;
+ dram_info.ddr_grf = (void *)DDR_GRF_BASE_ADDR;
+ dram_info.pmugrf = (void *)PMUGRF_BASE_ADDR;
+
+ sdram_params = get_default_sdram_config();
+ ret = sdram_init_detect(&dram_info, sdram_params);
+
+ if (ret)
+ goto error;
+
+ sdram_print_ddr_info(&sdram_params->ch.cap_info, &sdram_params->base);
+
+ printascii("out\n");
+ return ret;
+error:
+ return (-1);
+}
+#else
+
+static int px30_dmc_probe(struct udevice *dev)
+{
+ struct dram_info *priv = dev_get_priv(dev);
+
+ priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
+ debug("%s: grf=%p\n", __func__, priv->pmugrf);
+ priv->info.base = CONFIG_SYS_SDRAM_BASE;
+ priv->info.size =
+ rockchip_sdram_size((phys_addr_t)&priv->pmugrf->os_reg[2]);
+
+ return 0;
+}
+
+static int px30_dmc_get_info(struct udevice *dev, struct ram_info *info)
+{
+ struct dram_info *priv = dev_get_priv(dev);
+
+ *info = priv->info;
+
+ return 0;
+}
+
+static struct ram_ops px30_dmc_ops = {
+ .get_info = px30_dmc_get_info,
+};
+
+static const struct udevice_id px30_dmc_ids[] = {
+ { .compatible = "rockchip,px30-dmc" },
+ { }
+};
+
+U_BOOT_DRIVER(dmc_px30) = {
+ .name = "rockchip_px30_dmc",
+ .id = UCLASS_RAM,
+ .of_match = px30_dmc_ids,
+ .ops = &px30_dmc_ops,
+ .probe = px30_dmc_probe,
+ .priv_auto_alloc_size = sizeof(struct dram_info),
+};
+#endif /* CONFIG_TPL_BUILD */
diff --git a/drivers/ram/rockchip/sdram_rk3128.c b/drivers/ram/rockchip/sdram_rk3128.c
index bfabc22a7d..8486653c6f 100644
--- a/drivers/ram/rockchip/sdram_rk3128.c
+++ b/drivers/ram/rockchip/sdram_rk3128.c
@@ -9,7 +9,7 @@
#include <syscon.h>
#include <asm/arch-rockchip/clock.h>
#include <asm/arch-rockchip/grf_rk3128.h>
-#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram.h>
struct dram_info {
struct ram_info info;
diff --git a/drivers/ram/rockchip/sdram_rk3188.c b/drivers/ram/rockchip/sdram_rk3188.c
index 00e52ec949..d3e4316ef0 100644
--- a/drivers/ram/rockchip/sdram_rk3188.c
+++ b/drivers/ram/rockchip/sdram_rk3188.c
@@ -21,7 +21,7 @@
#include <asm/arch-rockchip/grf_rk3188.h>
#include <asm/arch-rockchip/pmu_rk3188.h>
#include <asm/arch-rockchip/sdram.h>
-#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_rk3288.h>
#include <linux/err.h>
struct chan_info {
diff --git a/drivers/ram/rockchip/sdram_rk322x.c b/drivers/ram/rockchip/sdram_rk322x.c
index 94893e17cf..223f048161 100644
--- a/drivers/ram/rockchip/sdram_rk322x.c
+++ b/drivers/ram/rockchip/sdram_rk322x.c
@@ -17,7 +17,7 @@
#include <asm/arch-rockchip/hardware.h>
#include <asm/arch-rockchip/sdram_rk322x.h>
#include <asm/arch-rockchip/uart.h>
-#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram.h>
#include <asm/types.h>
#include <linux/err.h>
diff --git a/drivers/ram/rockchip/sdram_rk3288.c b/drivers/ram/rockchip/sdram_rk3288.c
index 5775254007..690751d074 100644
--- a/drivers/ram/rockchip/sdram_rk3288.c
+++ b/drivers/ram/rockchip/sdram_rk3288.c
@@ -21,7 +21,7 @@
#include <asm/arch-rockchip/grf_rk3288.h>
#include <asm/arch-rockchip/pmu_rk3288.h>
#include <asm/arch-rockchip/sdram.h>
-#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_rk3288.h>
#include <linux/err.h>
#include <power/regulator.h>
#include <power/rk8xx_pmic.h>
diff --git a/drivers/ram/rockchip/sdram_rk3308.c b/drivers/ram/rockchip/sdram_rk3308.c
new file mode 100644
index 0000000000..310df79123
--- /dev/null
+++ b/drivers/ram/rockchip/sdram_rk3308.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ram.h>
+#include <syscon.h>
+#include <asm/arch/grf_rk3308.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/sdram.h>
+
+struct dram_info {
+ struct ram_info info;
+ struct rk3308_grf *grf;
+};
+
+static int rk3308_dmc_probe(struct udevice *dev)
+{
+ struct dram_info *priv = dev_get_priv(dev);
+
+ priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+ priv->info.base = CONFIG_SYS_SDRAM_BASE;
+ priv->info.size = rockchip_sdram_size((phys_addr_t)&priv->grf->os_reg2);
+
+ return 0;
+}
+
+static int rk3308_dmc_get_info(struct udevice *dev, struct ram_info *info)
+{
+ struct dram_info *priv = dev_get_priv(dev);
+
+ *info = priv->info;
+
+ return 0;
+}
+
+static struct ram_ops rk3308_dmc_ops = {
+ .get_info = rk3308_dmc_get_info,
+};
+
+static const struct udevice_id rk3308_dmc_ids[] = {
+ { .compatible = "rockchip,rk3308-dmc" },
+ { }
+};
+
+U_BOOT_DRIVER(dmc_rk3308) = {
+ .name = "rockchip_rk3308_dmc",
+ .id = UCLASS_RAM,
+ .of_match = rk3308_dmc_ids,
+ .ops = &rk3308_dmc_ops,
+ .probe = rk3308_dmc_probe,
+ .priv_auto_alloc_size = sizeof(struct dram_info),
+};
diff --git a/drivers/ram/rockchip/sdram_rk3328.c b/drivers/ram/rockchip/sdram_rk3328.c
index e84c9be6a2..69521cef69 100644
--- a/drivers/ram/rockchip/sdram_rk3328.c
+++ b/drivers/ram/rockchip/sdram_rk3328.c
@@ -14,17 +14,17 @@
#include <asm/arch-rockchip/clock.h>
#include <asm/arch-rockchip/cru_rk3328.h>
#include <asm/arch-rockchip/grf_rk3328.h>
-#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram.h>
#include <asm/arch-rockchip/sdram_rk3328.h>
#include <asm/arch-rockchip/uart.h>
struct dram_info {
#ifdef CONFIG_TPL_BUILD
- struct rk3328_ddr_pctl_regs *pctl;
- struct rk3328_ddr_phy_regs *phy;
+ struct ddr_pctl_regs *pctl;
+ struct ddr_phy_regs *phy;
struct clk ddr_clk;
struct rk3328_cru *cru;
- struct rk3328_msch_regs *msch;
+ struct msch_regs *msch;
struct rk3328_ddr_grf_regs *ddr_grf;
#endif
struct ram_info info;
@@ -71,10 +71,11 @@ static void rkclk_ddr_reset(struct dram_info *dram,
writel(ddrctrl_asrstn_req(ctl_srstn), &dram->cru->softrst_con[9]);
}
-static void rkclk_set_dpll(struct dram_info *dram, unsigned int mhz)
+static void rkclk_set_dpll(struct dram_info *dram, unsigned int hz)
{
unsigned int refdiv, postdiv1, postdiv2, fbdiv;
int delay = 1000;
+ u32 mhz = hz / MHZ;
refdiv = 1;
if (mhz <= 300) {
@@ -122,52 +123,7 @@ static void rkclk_configure_ddr(struct dram_info *dram,
clrbits_le32(PHY_REG(phy_base, 0xef), 1 << 7);
/* for inno ddr phy need 2*freq */
- rkclk_set_dpll(dram, sdram_params->ddr_freq * 2);
-}
-
-static void phy_soft_reset(struct dram_info *dram)
-{
- void __iomem *phy_base = dram->phy;
-
- clrbits_le32(PHY_REG(phy_base, 0), 0x3 << 2);
- udelay(1);
- setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET);
- udelay(5);
- setbits_le32(PHY_REG(phy_base, 0), DIGITAL_DERESET);
- udelay(1);
-}
-
-static int pctl_cfg(struct dram_info *dram,
- struct rk3328_sdram_params *sdram_params)
-{
- u32 i;
- void __iomem *pctl_base = dram->pctl;
-
- for (i = 0; sdram_params->pctl_regs.pctl[i][0] != 0xFFFFFFFF; i++) {
- writel(sdram_params->pctl_regs.pctl[i][1],
- pctl_base + sdram_params->pctl_regs.pctl[i][0]);
- }
- clrsetbits_le32(pctl_base + DDR_PCTL2_PWRTMG,
- (0xff << 16) | 0x1f,
- ((SR_IDLE & 0xff) << 16) | (PD_IDLE & 0x1f));
- /*
- * dfi_lp_en_pd=1,dfi_lp_wakeup_pd=2
- * hw_lp_idle_x32=1
- */
- if (sdram_params->dramtype == LPDDR3) {
- setbits_le32(pctl_base + DDR_PCTL2_DFILPCFG0, 1);
- clrsetbits_le32(pctl_base + DDR_PCTL2_DFILPCFG0,
- 0xf << 4,
- 2 << 4);
- }
- clrsetbits_le32(pctl_base + DDR_PCTL2_HWLPCTL,
- 0xfff << 16,
- 1 << 16);
- /* disable zqcs */
- setbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1u << 31);
- setbits_le32(pctl_base + 0x2000 + DDR_PCTL2_ZQCTL0, 1u << 31);
-
- return 0;
+ rkclk_set_dpll(dram, sdram_params->base.ddr_freq * MHZ * 2);
}
/* return ddrconfig value
@@ -175,62 +131,39 @@ static int pctl_cfg(struct dram_info *dram,
* other, the ddrconfig value
* only support cs0_row >= cs1_row
*/
-static unsigned int calculate_ddrconfig(struct rk3328_sdram_params *sdram_params)
+static u32 calculate_ddrconfig(struct rk3328_sdram_params *sdram_params)
{
- static const u16 ddr_cfg_2_rbc[] = {
- /***************************
- * [5:4] row(13+n)
- * [3] cs(0:0 cs, 1:2 cs)
- * [2] bank(0:0bank,1:8bank)
- * [1:0] col(11+n)
- ****************************/
- /* row, cs, bank, col */
- ((3 << 4) | (0 << 3) | (1 << 2) | 0),
- ((3 << 4) | (0 << 3) | (1 << 2) | 1),
- ((2 << 4) | (0 << 3) | (1 << 2) | 2),
- ((3 << 4) | (0 << 3) | (1 << 2) | 2),
- ((2 << 4) | (0 << 3) | (1 << 2) | 3),
- ((3 << 4) | (1 << 3) | (1 << 2) | 0),
- ((3 << 4) | (1 << 3) | (1 << 2) | 1),
- ((2 << 4) | (1 << 3) | (1 << 2) | 2),
- ((3 << 4) | (0 << 3) | (0 << 2) | 1),
- ((2 << 4) | (0 << 3) | (1 << 2) | 1),
- };
-
- static const u16 ddr4_cfg_2_rbc[] = {
- /***************************
- * [6] cs 0:0cs 1:2 cs
- * [5:3] row(13+n)
- * [2] cs(0:0 cs, 1:2 cs)
- * [1] bw 0: 16bit 1:32bit
- * [0] diebw 0:8bit 1:16bit
- ***************************/
- /* cs, row, cs, bw, diebw */
- ((0 << 6) | (3 << 3) | (0 << 2) | (1 << 1) | 0),
- ((1 << 6) | (2 << 3) | (0 << 2) | (1 << 1) | 0),
- ((0 << 6) | (4 << 3) | (0 << 2) | (0 << 1) | 0),
- ((1 << 6) | (3 << 3) | (0 << 2) | (0 << 1) | 0),
- ((0 << 6) | (4 << 3) | (0 << 2) | (1 << 1) | 1),
- ((1 << 6) | (3 << 3) | (0 << 2) | (1 << 1) | 1),
- ((1 << 6) | (4 << 3) | (0 << 2) | (0 << 1) | 1),
- ((0 << 6) | (2 << 3) | (1 << 2) | (1 << 1) | 0),
- ((0 << 6) | (3 << 3) | (1 << 2) | (0 << 1) | 0),
- ((0 << 6) | (3 << 3) | (1 << 2) | (1 << 1) | 1),
- ((0 << 6) | (4 << 3) | (1 << 2) | (0 << 1) | 1),
- };
-
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
u32 cs, bw, die_bw, col, row, bank;
+ u32 cs1_row;
u32 i, tmp;
u32 ddrconf = -1;
- cs = sdram_ch.rank;
- bw = sdram_ch.bw;
- die_bw = sdram_ch.dbw;
- col = sdram_ch.col;
- row = sdram_ch.cs0_row;
- bank = sdram_ch.bk;
+ cs = cap_info->rank;
+ bw = cap_info->bw;
+ die_bw = cap_info->dbw;
+ col = cap_info->col;
+ row = cap_info->cs0_row;
+ cs1_row = cap_info->cs1_row;
+ bank = cap_info->bk;
+
+ if (sdram_params->base.dramtype == DDR4) {
+ /* when DDR_TEST, CS always at MSB position for easy test */
+ if (cs == 2 && row == cs1_row) {
+ /* include 2cs cap both 2^n or both (2^n - 2^(n-2)) */
+ tmp = ((row - 13) << 3) | (1 << 2) | (bw & 0x2) |
+ die_bw;
+ for (i = 17; i < 21; i++) {
+ if (((tmp & 0x7) ==
+ (ddr4_cfg_2_rbc[i - 10] & 0x7)) &&
+ ((tmp & 0x3c) <=
+ (ddr4_cfg_2_rbc[i - 10] & 0x3c))) {
+ ddrconf = i;
+ goto out;
+ }
+ }
+ }
- if (sdram_params->dramtype == DDR4) {
tmp = ((cs - 1) << 6) | ((row - 13) << 3) | (bw & 0x2) | die_bw;
for (i = 10; i < 17; i++) {
if (((tmp & 0x7) == (ddr4_cfg_2_rbc[i - 10] & 0x7)) &&
@@ -246,6 +179,18 @@ static unsigned int calculate_ddrconfig(struct rk3328_sdram_params *sdram_params
goto out;
}
+ /* when DDR_TEST, CS always at MSB position for easy test */
+ if (cs == 2 && row == cs1_row) {
+ /* include 2cs cap both 2^n or both (2^n - 2^(n-2)) */
+ for (i = 5; i < 8; i++) {
+ if ((bw + col - 11) == (ddr_cfg_2_rbc[i] &
+ 0x3)) {
+ ddrconf = i;
+ goto out;
+ }
+ }
+ }
+
tmp = ((row - 13) << 4) | (1 << 2) | ((bw + col - 11) << 0);
for (i = 0; i < 5; i++)
if (((tmp & 0xf) == (ddr_cfg_2_rbc[i] & 0xf)) &&
@@ -257,23 +202,11 @@ static unsigned int calculate_ddrconfig(struct rk3328_sdram_params *sdram_params
out:
if (ddrconf > 20)
- printf("calculate_ddrconfig error\n");
+ printf("calculate ddrconfig error\n");
return ddrconf;
}
-/* n: Unit bytes */
-static void copy_to_reg(u32 *dest, u32 *src, u32 n)
-{
- int i;
-
- for (i = 0; i < n / sizeof(u32); i++) {
- writel(*src, dest);
- src++;
- dest++;
- }
-}
-
/*******
* calculate controller dram address map, and setting to register.
* argument sdram_ch.ddrconf must be right value before
@@ -282,273 +215,42 @@ static void copy_to_reg(u32 *dest, u32 *src, u32 n)
static void set_ctl_address_map(struct dram_info *dram,
struct rk3328_sdram_params *sdram_params)
{
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
void __iomem *pctl_base = dram->pctl;
- copy_to_reg((u32 *)(pctl_base + DDR_PCTL2_ADDRMAP0),
- &addrmap[sdram_ch.ddrconfig][0], 9 * 4);
- if (sdram_params->dramtype == LPDDR3 && sdram_ch.row_3_4)
+ sdram_copy_to_reg((u32 *)(pctl_base + DDR_PCTL2_ADDRMAP0),
+ &addrmap[cap_info->ddrconfig][0], 9 * 4);
+ if (sdram_params->base.dramtype == LPDDR3 && cap_info->row_3_4)
setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6, 1 << 31);
- if (sdram_params->dramtype == DDR4 && sdram_ch.bw == 0x1)
+ if (sdram_params->base.dramtype == DDR4 && cap_info->bw == 0x1)
setbits_le32(pctl_base + DDR_PCTL2_PCCFG, 1 << 8);
- if (sdram_ch.rank == 1)
+ if (cap_info->rank == 1)
clrsetbits_le32(pctl_base + DDR_PCTL2_ADDRMAP0, 0x1f, 0x1f);
}
-static void phy_dll_bypass_set(struct dram_info *dram, u32 freq)
-{
- u32 tmp;
- void __iomem *phy_base = dram->phy;
-
- setbits_le32(PHY_REG(phy_base, 0x13), 1 << 4);
- clrbits_le32(PHY_REG(phy_base, 0x14), 1 << 3);
- setbits_le32(PHY_REG(phy_base, 0x26), 1 << 4);
- clrbits_le32(PHY_REG(phy_base, 0x27), 1 << 3);
- setbits_le32(PHY_REG(phy_base, 0x36), 1 << 4);
- clrbits_le32(PHY_REG(phy_base, 0x37), 1 << 3);
- setbits_le32(PHY_REG(phy_base, 0x46), 1 << 4);
- clrbits_le32(PHY_REG(phy_base, 0x47), 1 << 3);
- setbits_le32(PHY_REG(phy_base, 0x56), 1 << 4);
- clrbits_le32(PHY_REG(phy_base, 0x57), 1 << 3);
-
- if (freq <= 400)
- /* DLL bypass */
- setbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
- else
- clrbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
- if (freq <= 680)
- tmp = 2;
- else
- tmp = 1;
- writel(tmp, PHY_REG(phy_base, 0x28));
- writel(tmp, PHY_REG(phy_base, 0x38));
- writel(tmp, PHY_REG(phy_base, 0x48));
- writel(tmp, PHY_REG(phy_base, 0x58));
-}
-
-static void set_ds_odt(struct dram_info *dram,
- struct rk3328_sdram_params *sdram_params)
-{
- u32 cmd_drv, clk_drv, dqs_drv, dqs_odt;
- void __iomem *phy_base = dram->phy;
-
- if (sdram_params->dramtype == DDR3) {
- cmd_drv = PHY_DDR3_RON_RTT_34ohm;
- clk_drv = PHY_DDR3_RON_RTT_45ohm;
- dqs_drv = PHY_DDR3_RON_RTT_34ohm;
- dqs_odt = PHY_DDR3_RON_RTT_225ohm;
- } else {
- cmd_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
- clk_drv = PHY_DDR4_LPDDR3_RON_RTT_43ohm;
- dqs_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
- dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_240ohm;
- }
- /* DS */
- writel(cmd_drv, PHY_REG(phy_base, 0x11));
- clrsetbits_le32(PHY_REG(phy_base, 0x12), 0x1f << 3, cmd_drv << 3);
- writel(clk_drv, PHY_REG(phy_base, 0x16));
- writel(clk_drv, PHY_REG(phy_base, 0x18));
- writel(dqs_drv, PHY_REG(phy_base, 0x20));
- writel(dqs_drv, PHY_REG(phy_base, 0x2f));
- writel(dqs_drv, PHY_REG(phy_base, 0x30));
- writel(dqs_drv, PHY_REG(phy_base, 0x3f));
- writel(dqs_drv, PHY_REG(phy_base, 0x40));
- writel(dqs_drv, PHY_REG(phy_base, 0x4f));
- writel(dqs_drv, PHY_REG(phy_base, 0x50));
- writel(dqs_drv, PHY_REG(phy_base, 0x5f));
- /* ODT */
- writel(dqs_odt, PHY_REG(phy_base, 0x21));
- writel(dqs_odt, PHY_REG(phy_base, 0x2e));
- writel(dqs_odt, PHY_REG(phy_base, 0x31));
- writel(dqs_odt, PHY_REG(phy_base, 0x3e));
- writel(dqs_odt, PHY_REG(phy_base, 0x41));
- writel(dqs_odt, PHY_REG(phy_base, 0x4e));
- writel(dqs_odt, PHY_REG(phy_base, 0x51));
- writel(dqs_odt, PHY_REG(phy_base, 0x5e));
-}
-
-static void phy_cfg(struct dram_info *dram,
- struct rk3328_sdram_params *sdram_params)
-{
- u32 i;
- void __iomem *phy_base = dram->phy;
-
- phy_dll_bypass_set(dram, sdram_params->ddr_freq);
- for (i = 0; sdram_params->phy_regs.phy[i][0] != 0xFFFFFFFF; i++) {
- writel(sdram_params->phy_regs.phy[i][1],
- phy_base + sdram_params->phy_regs.phy[i][0]);
- }
- if (sdram_ch.bw == 2) {
- clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4);
- } else {
- clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4);
- /* disable DQS2,DQS3 tx dll for saving power */
- clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
- clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
- }
- set_ds_odt(dram, sdram_params);
- /* deskew */
- setbits_le32(PHY_REG(phy_base, 2), 8);
- copy_to_reg(PHY_REG(phy_base, 0xb0),
- &sdram_params->skew.a0_a1_skew[0], 15 * 4);
- copy_to_reg(PHY_REG(phy_base, 0x70),
- &sdram_params->skew.cs0_dm0_skew[0], 44 * 4);
- copy_to_reg(PHY_REG(phy_base, 0xc0),
- &sdram_params->skew.cs1_dm0_skew[0], 44 * 4);
-}
-
-static int update_refresh_reg(struct dram_info *dram)
-{
- void __iomem *pctl_base = dram->pctl;
- u32 ret;
-
- ret = readl(pctl_base + DDR_PCTL2_RFSHCTL3) ^ (1 << 1);
- writel(ret, pctl_base + DDR_PCTL2_RFSHCTL3);
-
- return 0;
-}
-
static int data_training(struct dram_info *dram, u32 cs, u32 dramtype)
{
- u32 ret;
- u32 dis_auto_zq = 0;
- void __iomem *pctl_base = dram->pctl;
- void __iomem *phy_base = dram->phy;
-
- /* disable zqcs */
- if (!(readl(pctl_base + DDR_PCTL2_ZQCTL0) &
- (1ul << 31))) {
- dis_auto_zq = 1;
- setbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
- }
- /* disable auto refresh */
- setbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
- update_refresh_reg(dram);
-
- if (dramtype == DDR4) {
- clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0);
- clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0);
- clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0);
- clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0);
- }
- /* choose training cs */
- clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs));
- /* enable gate training */
- clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1);
- udelay(50);
- ret = readl(PHY_REG(phy_base, 0xff));
- /* disable gate training */
- clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0);
- /* restore zqcs */
- if (dis_auto_zq)
- clrbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
- /* restore auto refresh */
- clrbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
- update_refresh_reg(dram);
-
- if (dramtype == DDR4) {
- clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0x2);
- clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0x2);
- clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0x2);
- clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0x2);
- }
-
- if (ret & 0x10) {
- ret = -1;
- } else {
- ret = (ret & 0xf) ^ (readl(PHY_REG(phy_base, 0)) >> 4);
- ret = (ret == 0) ? 0 : -1;
- }
- return ret;
-}
-
-/* rank = 1: cs0
- * rank = 2: cs1
- * rank = 3: cs0 & cs1
- * note: be careful of keep mr original val
- */
-static int write_mr(struct dram_info *dram, u32 rank, u32 mr_num, u32 arg,
- u32 dramtype)
-{
void __iomem *pctl_base = dram->pctl;
-
- while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
- continue;
- if (dramtype == DDR3 || dramtype == DDR4) {
- writel((mr_num << 12) | (rank << 4) | (0 << 0),
- pctl_base + DDR_PCTL2_MRCTRL0);
- writel(arg, pctl_base + DDR_PCTL2_MRCTRL1);
- } else {
- writel((rank << 4) | (0 << 0),
- pctl_base + DDR_PCTL2_MRCTRL0);
- writel((mr_num << 8) | (arg & 0xff),
- pctl_base + DDR_PCTL2_MRCTRL1);
- }
-
- setbits_le32(pctl_base + DDR_PCTL2_MRCTRL0, 1u << 31);
- while (readl(pctl_base + DDR_PCTL2_MRCTRL0) & (1u << 31))
- continue;
- while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
- continue;
-
- return 0;
-}
-
-/*
- * rank : 1:cs0, 2:cs1, 3:cs0&cs1
- * vrefrate: 4500: 45%,
- */
-static int write_vrefdq(struct dram_info *dram, u32 rank, u32 vrefrate,
- u32 dramtype)
-{
- u32 tccd_l, value;
u32 dis_auto_zq = 0;
- void __iomem *pctl_base = dram->pctl;
+ u32 pwrctl;
+ u32 ret;
- if (dramtype != DDR4 || vrefrate < 4500 || vrefrate > 9200)
- return -1;
+ /* disable auto low-power */
+ pwrctl = readl(pctl_base + DDR_PCTL2_PWRCTL);
+ writel(0, pctl_base + DDR_PCTL2_PWRCTL);
- tccd_l = (readl(pctl_base + DDR_PCTL2_DRAMTMG4) >> 16) & 0xf;
- tccd_l = (tccd_l - 4) << 10;
+ dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
- if (vrefrate > 7500) {
- /* range 1 */
- value = ((vrefrate - 6000) / 65) | tccd_l;
- } else {
- /* range 2 */
- value = ((vrefrate - 4500) / 65) | tccd_l | (1 << 6);
- }
+ ret = phy_data_training(dram->phy, cs, dramtype);
- /* disable zqcs */
- if (!(readl(pctl_base + DDR_PCTL2_ZQCTL0) &
- (1ul << 31))) {
- dis_auto_zq = 1;
- setbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
- }
- /* disable auto refresh */
- setbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
- update_refresh_reg(dram);
-
- /* enable vrefdq calibratin */
- write_mr(dram, rank, 6, value | (1 << 7), dramtype);
- udelay(1);/* tvrefdqe */
- /* write vrefdq value */
- write_mr(dram, rank, 6, value | (1 << 7), dramtype);
- udelay(1);/* tvref_time */
- write_mr(dram, rank, 6, value | (0 << 7), dramtype);
- udelay(1);/* tvrefdqx */
-
- /* restore zqcs */
- if (dis_auto_zq)
- clrbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
- /* restore auto refresh */
- clrbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
- update_refresh_reg(dram);
+ pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
- return 0;
-}
+ /* restore auto low-power */
+ writel(pwrctl, pctl_base + DDR_PCTL2_PWRCTL);
-#define _MAX_(x, y) ((x) > (y) ? (x) : (y))
+ return ret;
+}
static void rx_deskew_switch_adjust(struct dram_info *dram)
{
@@ -557,7 +259,7 @@ static void rx_deskew_switch_adjust(struct dram_info *dram)
void __iomem *phy_base = dram->phy;
for (i = 0; i < 4; i++)
- gate_val = _MAX_(readl(PHY_REG(phy_base, 0xfb + i)), gate_val);
+ gate_val = MAX(readl(PHY_REG(phy_base, 0xfb + i)), gate_val);
deskew_val = (gate_val >> 3) + 1;
deskew_val = (deskew_val > 0x1f) ? 0x1f : deskew_val;
@@ -566,8 +268,6 @@ static void rx_deskew_switch_adjust(struct dram_info *dram)
(deskew_val & 0x1c) << 2);
}
-#undef _MAX_
-
static void tx_deskew_switch_adjust(struct dram_info *dram)
{
void __iomem *phy_base = dram->phy;
@@ -580,40 +280,39 @@ static void set_ddrconfig(struct dram_info *dram, u32 ddrconfig)
writel(ddrconfig, &dram->msch->ddrconf);
}
+static void sdram_msch_config(struct msch_regs *msch,
+ struct sdram_msch_timings *noc_timings)
+{
+ writel(noc_timings->ddrtiming.d32, &msch->ddrtiming);
+
+ writel(noc_timings->ddrmode.d32, &msch->ddrmode);
+ writel(noc_timings->readlatency, &msch->readlatency);
+
+ writel(noc_timings->activate.d32, &msch->activate);
+ writel(noc_timings->devtodev.d32, &msch->devtodev);
+ writel(noc_timings->ddr4timing.d32, &msch->ddr4_timing);
+ writel(noc_timings->agingx0, &msch->aging0);
+ writel(noc_timings->agingx0, &msch->aging1);
+ writel(noc_timings->agingx0, &msch->aging2);
+ writel(noc_timings->agingx0, &msch->aging3);
+ writel(noc_timings->agingx0, &msch->aging4);
+ writel(noc_timings->agingx0, &msch->aging5);
+}
+
static void dram_all_config(struct dram_info *dram,
struct rk3328_sdram_params *sdram_params)
{
- u32 sys_reg = 0, tmp = 0;
-
- set_ddrconfig(dram, sdram_ch.ddrconfig);
-
- sys_reg |= SYS_REG_ENC_DDRTYPE(sdram_params->dramtype);
- sys_reg |= SYS_REG_ENC_ROW_3_4(sdram_ch.row_3_4, 0);
- sys_reg |= SYS_REG_ENC_RANK(sdram_ch.rank, 0);
- sys_reg |= SYS_REG_ENC_COL(sdram_ch.col, 0);
- sys_reg |= SYS_REG_ENC_BK(sdram_ch.bk, 0);
- SYS_REG_ENC_CS0_ROW(sdram_ch.cs0_row, sys_reg, tmp, 0);
- if (sdram_ch.cs1_row)
- SYS_REG_ENC_CS1_ROW(sdram_ch.cs1_row, sys_reg, tmp, 0);
- sys_reg |= SYS_REG_ENC_BW(sdram_ch.bw, 0);
- sys_reg |= SYS_REG_ENC_DBW(sdram_ch.dbw, 0);
-
- writel(sys_reg, &dram->grf->os_reg[2]);
-
- writel(sdram_ch.noc_timings.ddrtiming.d32, &dram->msch->ddrtiming);
-
- writel(sdram_ch.noc_timings.ddrmode.d32, &dram->msch->ddrmode);
- writel(sdram_ch.noc_timings.readlatency, &dram->msch->readlatency);
-
- writel(sdram_ch.noc_timings.activate.d32, &dram->msch->activate);
- writel(sdram_ch.noc_timings.devtodev.d32, &dram->msch->devtodev);
- writel(sdram_ch.noc_timings.ddr4timing.d32, &dram->msch->ddr4_timing);
- writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging0);
- writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging1);
- writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging2);
- writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging3);
- writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging4);
- writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging5);
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+ u32 sys_reg2 = 0;
+ u32 sys_reg3 = 0;
+
+ set_ddrconfig(dram, cap_info->ddrconfig);
+ sdram_org_config(cap_info, &sdram_params->base, &sys_reg2,
+ &sys_reg3, 0);
+ writel(sys_reg2, &dram->grf->os_reg[2]);
+ writel(sys_reg3, &dram->grf->os_reg[3]);
+
+ sdram_msch_config(dram->msch, &sdram_ch.noc_timings);
}
static void enable_low_power(struct dram_info *dram,
@@ -641,6 +340,7 @@ static void enable_low_power(struct dram_info *dram,
static int sdram_init(struct dram_info *dram,
struct rk3328_sdram_params *sdram_params, u32 pre_init)
{
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
void __iomem *pctl_base = dram->pctl;
rkclk_ddr_reset(dram, 1, 1, 1, 1);
@@ -652,30 +352,18 @@ static int sdram_init(struct dram_info *dram,
*/
rkclk_ddr_reset(dram, 1, 1, 1, 0);
rkclk_configure_ddr(dram, sdram_params);
- if (pre_init == 0) {
- switch (sdram_params->dramtype) {
- case DDR3:
- printf("DDR3\n");
- break;
- case DDR4:
- printf("DDR4\n");
- break;
- case LPDDR3:
- default:
- printf("LPDDR3\n");
- break;
- }
- }
+
/* release phy srst to provide clk to ctrl */
rkclk_ddr_reset(dram, 1, 1, 0, 0);
udelay(10);
- phy_soft_reset(dram);
+ phy_soft_reset(dram->phy);
/* release ctrl presetn, and config ctl registers */
rkclk_ddr_reset(dram, 1, 0, 0, 0);
- pctl_cfg(dram, sdram_params);
- sdram_ch.ddrconfig = calculate_ddrconfig(sdram_params);
+ pctl_cfg(dram->pctl, &sdram_params->pctl_regs, SR_IDLE, PD_IDLE);
+ cap_info->ddrconfig = calculate_ddrconfig(sdram_params);
set_ctl_address_map(dram, sdram_params);
- phy_cfg(dram, sdram_params);
+ phy_cfg(dram->phy, &sdram_params->phy_regs, &sdram_params->skew,
+ &sdram_params->base, cap_info->bw);
/* enable dfi_init_start to init phy after ctl srstn deassert */
setbits_le32(pctl_base + DDR_PCTL2_DFIMISC, (1 << 5) | (1 << 4));
@@ -685,13 +373,18 @@ static int sdram_init(struct dram_info *dram,
continue;
/* do ddr gate training */
- if (data_training(dram, 0, sdram_params->dramtype) != 0) {
+ if (data_training(dram, 0, sdram_params->base.dramtype) != 0) {
+ printf("data training error\n");
+ return -1;
+ }
+ if (data_training(dram, 1, sdram_params->base.dramtype) != 0) {
printf("data training error\n");
return -1;
}
- if (sdram_params->dramtype == DDR4)
- write_vrefdq(dram, 0x3, 5670, sdram_params->dramtype);
+ if (sdram_params->base.dramtype == DDR4)
+ pctl_write_vrefdq(dram->pctl, 0x3, 5670,
+ sdram_params->base.dramtype);
if (pre_init == 0) {
rx_deskew_switch_adjust(dram);
@@ -708,7 +401,7 @@ static u64 dram_detect_cap(struct dram_info *dram,
struct rk3328_sdram_params *sdram_params,
unsigned char channel)
{
- void __iomem *pctl_base = dram->pctl;
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
/*
* for ddr3: ddrconf = 3
@@ -718,14 +411,10 @@ static u64 dram_detect_cap(struct dram_info *dram,
*/
u32 bk, bktmp;
u32 col, coltmp;
- u32 row, rowtmp, row_3_4;
- void __iomem *test_addr, *test_addr1;
- u32 dbw;
+ u32 rowtmp;
u32 cs;
u32 bw = 1;
- u64 cap = 0;
- u32 dram_type = sdram_params->dramtype;
- u32 pwrctl;
+ u32 dram_type = sdram_params->base.dramtype;
if (dram_type != DDR4) {
/* detect col and bk for ddr3/lpddr3 */
@@ -733,33 +422,10 @@ static u64 dram_detect_cap(struct dram_info *dram,
bktmp = 3;
rowtmp = 16;
- for (col = coltmp; col >= 9; col -= 1) {
- writel(0, SDRAM_ADDR);
- test_addr = (void __iomem *)(SDRAM_ADDR +
- (1ul << (col + bw - 1ul)));
- writel(PATTERN, test_addr);
- if ((readl(test_addr) == PATTERN) &&
- (readl(SDRAM_ADDR) == 0))
- break;
- }
- if (col == 8) {
- printf("col error\n");
+ if (sdram_detect_col(cap_info, coltmp) != 0)
goto cap_err;
- }
-
- test_addr = (void __iomem *)(SDRAM_ADDR +
- (1ul << (coltmp + bktmp + bw - 1ul)));
- writel(0, SDRAM_ADDR);
- writel(PATTERN, test_addr);
- if ((readl(test_addr) == PATTERN) &&
- (readl(SDRAM_ADDR) == 0))
- bk = 3;
- else
- bk = 2;
- if (dram_type == LPDDR3)
- dbw = 2;
- else
- dbw = 1;
+ sdram_detect_bank(cap_info, coltmp, bktmp);
+ sdram_detect_dbw(cap_info, dram_type);
} else {
/* detect bg for ddr4 */
coltmp = 10;
@@ -768,178 +434,49 @@ static u64 dram_detect_cap(struct dram_info *dram,
col = 10;
bk = 2;
- test_addr = (void __iomem *)(SDRAM_ADDR +
- (1ul << (coltmp + bw + 1ul)));
- writel(0, SDRAM_ADDR);
- writel(PATTERN, test_addr);
- if ((readl(test_addr) == PATTERN) &&
- (readl(SDRAM_ADDR) == 0))
- dbw = 0;
- else
- dbw = 1;
+ cap_info->col = col;
+ cap_info->bk = bk;
+ sdram_detect_bg(cap_info, coltmp);
}
+
/* detect row */
- for (row = rowtmp; row > 12; row--) {
- writel(0, SDRAM_ADDR);
- test_addr = (void __iomem *)(SDRAM_ADDR +
- (1ul << (row + bktmp + coltmp + bw - 1ul)));
- writel(PATTERN, test_addr);
- if ((readl(test_addr) == PATTERN) &&
- (readl(SDRAM_ADDR) == 0))
- break;
- }
- if (row == 12) {
- printf("row error");
+ if (sdram_detect_row(cap_info, coltmp, bktmp, rowtmp) != 0)
goto cap_err;
- }
- /* detect row_3_4 */
- test_addr = SDRAM_ADDR;
- test_addr1 = (void __iomem *)(SDRAM_ADDR +
- (0x3ul << (row + bktmp + coltmp + bw - 1ul - 1ul)));
-
- writel(0, test_addr);
- writel(PATTERN, test_addr1);
- if ((readl(test_addr) == 0) &&
- (readl(test_addr1) == PATTERN))
- row_3_4 = 0;
- else
- row_3_4 = 1;
- /* disable auto low-power */
- pwrctl = readl(pctl_base + DDR_PCTL2_PWRCTL);
- writel(0, pctl_base + DDR_PCTL2_PWRCTL);
+ /* detect row_3_4 */
+ sdram_detect_row_3_4(cap_info, coltmp, bktmp);
- /* bw and cs detect using phy read gate training */
+ /* bw and cs detect using data training */
if (data_training(dram, 1, dram_type) == 0)
cs = 1;
else
cs = 0;
+ cap_info->rank = cs + 1;
bw = 2;
+ cap_info->bw = bw;
- /* restore auto low-power */
- writel(pwrctl, pctl_base + DDR_PCTL2_PWRCTL);
-
- sdram_ch.rank = cs + 1;
- sdram_ch.col = col;
- sdram_ch.bk = bk;
- sdram_ch.dbw = dbw;
- sdram_ch.bw = bw;
- sdram_ch.cs0_row = row;
- if (cs)
- sdram_ch.cs1_row = row;
- else
- sdram_ch.cs1_row = 0;
- sdram_ch.row_3_4 = row_3_4;
-
- if (dram_type == DDR4)
- cap = 1llu << (cs + row + bk + col + ((dbw == 0) ? 2 : 1) + bw);
- else
- cap = 1llu << (cs + row + bk + col + bw);
-
- return cap;
-
-cap_err:
- return 0;
-}
-
-static u32 remodify_sdram_params(struct rk3328_sdram_params *sdram_params)
-{
- u32 tmp = 0, tmp_adr = 0, i;
-
- for (i = 0; sdram_params->pctl_regs.pctl[i][0] != 0xFFFFFFFF; i++) {
- if (sdram_params->pctl_regs.pctl[i][0] == 0) {
- tmp = sdram_params->pctl_regs.pctl[i][1];/* MSTR */
- tmp_adr = i;
- }
- }
-
- tmp &= ~((3ul << 30) | (3ul << 24) | (3ul << 12));
-
- switch (sdram_ch.dbw) {
- case 2:
- tmp |= (3ul << 30);
- break;
- case 1:
- tmp |= (2ul << 30);
- break;
- case 0:
- default:
- tmp |= (1ul << 30);
- break;
+ cap_info->cs0_high16bit_row = cap_info->cs0_row;
+ if (cs) {
+ cap_info->cs1_row = cap_info->cs0_row;
+ cap_info->cs1_high16bit_row = cap_info->cs0_row;
+ } else {
+ cap_info->cs1_row = 0;
+ cap_info->cs1_high16bit_row = 0;
}
- if (sdram_ch.rank == 2)
- tmp |= 3 << 24;
- else
- tmp |= 1 << 24;
-
- tmp |= (2 - sdram_ch.bw) << 12;
-
- sdram_params->pctl_regs.pctl[tmp_adr][1] = tmp;
-
- if (sdram_ch.bw == 2)
- sdram_ch.noc_timings.ddrtiming.b.bwratio = 0;
- else
- sdram_ch.noc_timings.ddrtiming.b.bwratio = 1;
-
return 0;
-}
-
-static int dram_detect_cs1_row(struct rk3328_sdram_params *sdram_params,
- unsigned char channel)
-{
- u32 ret = 0;
- u32 cs1_bit;
- void __iomem *test_addr, *cs1_addr;
- u32 row, bktmp, coltmp, bw;
- u32 ddrconf = sdram_ch.ddrconfig;
-
- if (sdram_ch.rank == 2) {
- cs1_bit = addrmap[ddrconf][0] + 8;
-
- if (cs1_bit > 31)
- goto out;
-
- cs1_addr = (void __iomem *)(1ul << cs1_bit);
- if (cs1_bit < 20)
- cs1_bit = 1;
- else
- cs1_bit = 0;
-
- if (sdram_params->dramtype == DDR4) {
- if (sdram_ch.dbw == 0)
- bktmp = sdram_ch.bk + 2;
- else
- bktmp = sdram_ch.bk + 1;
- } else {
- bktmp = sdram_ch.bk;
- }
- bw = sdram_ch.bw;
- coltmp = sdram_ch.col;
-
- /* detect cs1 row */
- for (row = sdram_ch.cs0_row; row > 12; row--) {
- test_addr = (void __iomem *)(SDRAM_ADDR + cs1_addr +
- (1ul << (row + cs1_bit + bktmp +
- coltmp + bw - 1ul)));
- writel(0, SDRAM_ADDR + cs1_addr);
- writel(PATTERN, test_addr);
- if ((readl(test_addr) == PATTERN) &&
- (readl(SDRAM_ADDR + cs1_addr) == 0)) {
- ret = row;
- break;
- }
- }
- }
-
-out:
- return ret;
+cap_err:
+ return -1;
}
static int sdram_init_detect(struct dram_info *dram,
struct rk3328_sdram_params *sdram_params)
{
+ u32 sys_reg = 0;
+ u32 sys_reg3 = 0;
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+
debug("Starting SDRAM initialization...\n");
memcpy(&sdram_ch, &sdram_params->ch,
@@ -949,13 +486,29 @@ static int sdram_init_detect(struct dram_info *dram,
dram_detect_cap(dram, sdram_params, 0);
/* modify bw, cs related timing */
- remodify_sdram_params(sdram_params);
+ pctl_remodify_sdram_params(&sdram_params->pctl_regs, cap_info,
+ sdram_params->base.dramtype);
+
+ if (cap_info->bw == 2)
+ sdram_ch.noc_timings.ddrtiming.b.bwratio = 0;
+ else
+ sdram_ch.noc_timings.ddrtiming.b.bwratio = 1;
+
/* reinit sdram by real dram cap */
sdram_init(dram, sdram_params, 0);
/* redetect cs1 row */
- sdram_ch.cs1_row =
- dram_detect_cs1_row(sdram_params, 0);
+ sdram_detect_cs1_row(cap_info, sdram_params->base.dramtype);
+ if (cap_info->cs1_row) {
+ sys_reg = readl(&dram->grf->os_reg[2]);
+ sys_reg3 = readl(&dram->grf->os_reg[3]);
+ SYS_REG_ENC_CS1_ROW(cap_info->cs1_row,
+ sys_reg, sys_reg3, 0);
+ writel(sys_reg, &dram->grf->os_reg[2]);
+ writel(sys_reg3, &dram->grf->os_reg[3]);
+ }
+
+ sdram_print_ddr_info(&sdram_params->ch.cap_info, &sdram_params->base);
return 0;
}
diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c
index ed70137ce7..7b2bba03fe 100644
--- a/drivers/ram/rockchip/sdram_rk3399.c
+++ b/drivers/ram/rockchip/sdram_rk3399.c
@@ -18,7 +18,7 @@
#include <asm/arch-rockchip/grf_rk3399.h>
#include <asm/arch-rockchip/pmu_rk3399.h>
#include <asm/arch-rockchip/hardware.h>
-#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram.h>
#include <asm/arch-rockchip/sdram_rk3399.h>
#include <linux/err.h>
#include <time.h>
@@ -44,6 +44,11 @@
#define CS0_MR22_VAL 0
#define CS1_MR22_VAL 3
+/* LPDDR3 DRAM DS */
+#define LPDDR3_DS_34 0x1
+#define LPDDR3_DS_40 0x2
+#define LPDDR3_DS_48 0x3
+
#define CRU_SFTRST_DDR_CTRL(ch, n) ((0x1 << (8 + 16 + (ch) * 4)) | \
((n) << (8 + (ch) * 4)))
#define CRU_SFTRST_DDR_PHY(ch, n) ((0x1 << (9 + 16 + (ch) * 4)) | \
@@ -52,7 +57,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 +79,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) || \
@@ -144,38 +154,21 @@ struct io_setting {
32, /* rd_vref; (unit %, range 3.3% - 48.7%) */
},
{
- 800 * MHz,
+ 933 * MHz,
0,
/* dram side */
1, /* dq_odt; */
0, /* ca_odt; */
- 1, /* pdds; */
+ 3, /* pdds; */
0x72, /* dq_vref; */
0x72, /* ca_vref; */
/* phy side */
- PHY_DRV_ODT_40, /* rd_odt; */
- PHY_DRV_ODT_48, /* wr_dq_drv; */
+ PHY_DRV_ODT_80, /* rd_odt; */
+ PHY_DRV_ODT_40, /* wr_dq_drv; */
PHY_DRV_ODT_40, /* wr_ca_drv; */
PHY_DRV_ODT_40, /* wr_ckcs_drv; */
1, /* rd_odt_en; */
- 17, /* rd_vref; (unit %, range 3.3% - 48.7%) */
- },
- {
- 933 * MHz,
- 0,
- /* dram side */
- 3, /* dq_odt; */
- 0, /* ca_odt; */
- 6, /* pdds; */
- 0x59, /* dq_vref; 32% */
- 0x72, /* ca_vref; */
- /* phy side */
- PHY_DRV_ODT_HI_Z, /* rd_odt; */
- PHY_DRV_ODT_48, /* wr_dq_drv; */
- PHY_DRV_ODT_40, /* wr_ca_drv; */
- PHY_DRV_ODT_40, /* wr_ckcs_drv; */
- 0, /* rd_odt_en; */
- 32, /* rd_vref; (unit %, range 3.3% - 48.7%) */
+ 20, /* rd_vref; (unit %, range 3.3% - 48.7%) */
},
{
1066 * MHz,
@@ -183,24 +176,19 @@ struct io_setting {
/* dram side */
6, /* dq_odt; */
0, /* ca_odt; */
- 1, /* pdds; */
+ 3, /* pdds; */
0x10, /* dq_vref; */
0x72, /* ca_vref; */
/* phy side */
- PHY_DRV_ODT_40, /* rd_odt; */
+ PHY_DRV_ODT_80, /* rd_odt; */
PHY_DRV_ODT_60, /* wr_dq_drv; */
PHY_DRV_ODT_40, /* wr_ca_drv; */
PHY_DRV_ODT_40, /* wr_ckcs_drv; */
1, /* rd_odt_en; */
- 17, /* rd_vref; (unit %, range 3.3% - 48.7%) */
+ 20, /* rd_vref; (unit %, range 3.3% - 48.7%) */
},
};
-/**
- * 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 +211,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 : &params->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 : &params->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 : &params->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,
@@ -319,7 +296,8 @@ static void set_memory_map(const struct chan_info *chan, u32 channel,
if (sdram_ch->cap_info.ddrconfig < 2 ||
sdram_ch->cap_info.ddrconfig == 4)
row = 16;
- else if (sdram_ch->cap_info.ddrconfig == 3)
+ else if (sdram_ch->cap_info.ddrconfig == 3 ||
+ sdram_ch->cap_info.ddrconfig == 5)
row = 14;
else
row = 15;
@@ -344,7 +322,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)
@@ -363,11 +341,12 @@ static int phy_io_config(const struct chan_info *chan,
const struct rk3399_sdram_params *params, u32 mr5)
{
u32 *denali_phy = chan->publ->denali_phy;
+ u32 *denali_ctl = chan->pctl->denali_ctl;
u32 vref_mode_dq, vref_value_dq, vref_mode_ac, vref_value_ac;
u32 mode_sel;
- u32 reg_value;
- u32 drv_value, odt_value;
u32 speed;
+ u32 reg_value;
+ u32 ds_value, odt_value;
/* vref setting & mode setting */
if (params->base.dramtype == LPDDR4) {
@@ -393,12 +372,12 @@ static int phy_io_config(const struct chan_info *chan,
} else if (params->base.dramtype == LPDDR3) {
if (params->base.odt == 1) {
vref_mode_dq = 0x5; /* LPDDR3 ODT */
- drv_value = (readl(&denali_phy[6]) >> 12) & 0xf;
+ ds_value = readl(&denali_ctl[138]) & 0xf;
odt_value = (readl(&denali_phy[6]) >> 4) & 0xf;
- if (drv_value == PHY_DRV_ODT_48) {
+ if (ds_value == LPDDR3_DS_48) {
switch (odt_value) {
case PHY_DRV_ODT_240:
- vref_value_dq = 0x16;
+ vref_value_dq = 0x1B;
break;
case PHY_DRV_ODT_120:
vref_value_dq = 0x26;
@@ -410,7 +389,7 @@ static int phy_io_config(const struct chan_info *chan,
debug("Invalid ODT value.\n");
return -EINVAL;
}
- } else if (drv_value == PHY_DRV_ODT_40) {
+ } else if (ds_value == LPDDR3_DS_40) {
switch (odt_value) {
case PHY_DRV_ODT_240:
vref_value_dq = 0x19;
@@ -425,7 +404,7 @@ static int phy_io_config(const struct chan_info *chan,
debug("Invalid ODT value.\n");
return -EINVAL;
}
- } else if (drv_value == PHY_DRV_ODT_34_3) {
+ } else if (ds_value == LPDDR3_DS_34) {
switch (odt_value) {
case PHY_DRV_ODT_240:
vref_value_dq = 0x17;
@@ -496,7 +475,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 */
@@ -537,14 +516,7 @@ static int phy_io_config(const struct chan_info *chan,
}
/* speed setting */
- if (params->base.ddr_freq < 400)
- speed = 0x0;
- else if (params->base.ddr_freq < 800)
- speed = 0x1;
- else if (params->base.ddr_freq < 1200)
- speed = 0x2;
- else
- speed = 0x3;
+ speed = 0x2;
/* PHY_924 PHY_PAD_FDBK_DRIVE */
clrsetbits_le32(&denali_phy[924], 0x3 << 21, speed << 21);
@@ -563,7 +535,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 */
@@ -610,16 +582,17 @@ static void set_ds_odt(const struct chan_info *chan,
tsel_rd_select_n = io->rd_odt;
tsel_idle_select_p = PHY_DRV_ODT_HI_Z;
- tsel_idle_select_n = PHY_DRV_ODT_240;
+ tsel_idle_select_n = PHY_DRV_ODT_HI_Z;
tsel_wr_select_dq_p = io->wr_dq_drv;
- tsel_wr_select_dq_n = PHY_DRV_ODT_40;
+ tsel_wr_select_dq_n = PHY_DRV_ODT_34_3;
tsel_wr_select_ca_p = io->wr_ca_drv;
- tsel_wr_select_ca_n = PHY_DRV_ODT_40;
+ tsel_wr_select_ca_n = PHY_DRV_ODT_34_3;
tsel_ckcs_select_p = io->wr_ckcs_drv;
tsel_ckcs_select_n = PHY_DRV_ODT_34_3;
+
switch (tsel_rd_select_n) {
case PHY_DRV_ODT_240:
soc_odt = 1;
@@ -659,8 +632,8 @@ static void set_ds_odt(const struct chan_info *chan,
tsel_wr_select_dq_p = PHY_DRV_ODT_34_3;
tsel_wr_select_dq_n = PHY_DRV_ODT_34_3;
- tsel_wr_select_ca_p = PHY_DRV_ODT_48;
- tsel_wr_select_ca_n = PHY_DRV_ODT_48;
+ tsel_wr_select_ca_p = PHY_DRV_ODT_34_3;
+ tsel_wr_select_ca_n = PHY_DRV_ODT_34_3;
tsel_ckcs_select_p = PHY_DRV_ODT_34_3;
tsel_ckcs_select_n = PHY_DRV_ODT_34_3;
@@ -733,7 +706,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
*/
@@ -766,9 +739,9 @@ static void set_ds_odt(const struct chan_info *chan,
/* phy_pad_fdbk_drive 23bit DENALI_PHY_924/925 */
clrsetbits_le32(&denali_phy[924], 0xff,
- tsel_wr_select_dq_n | (tsel_wr_select_dq_p << 4));
+ tsel_wr_select_ca_n | (tsel_wr_select_ca_p << 4));
clrsetbits_le32(&denali_phy[925], 0xff,
- tsel_rd_select_n | (tsel_rd_select_p << 4));
+ tsel_wr_select_dq_n | (tsel_wr_select_dq_p << 4));
/* phy_dq_tsel_enable_X 3bits DENALI_PHY_5/133/261/389 offset_16 */
reg_value = (tsel_rd_en | (tsel_wr_en << 1) | (tsel_idle_en << 2))
@@ -810,46 +783,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 +895,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], &params_ctl[1],
- sizeof(struct rk3399_ddr_pctl_regs) - 4);
+ sdram_copy_to_reg(&denali_ctl[1], &params_ctl[1],
+ sizeof(struct rk3399_ddr_pctl_regs) - 4);
writel(params_ctl[0], &denali_ctl[0]);
/*
@@ -884,8 +921,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, &params->pi_regs.denali_pi[0],
- sizeof(struct rk3399_ddr_pi_regs));
+ sdram_copy_to_reg(denali_pi, &params->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 +931,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 +964,67 @@ static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,
}
}
- copy_to_reg(&denali_phy[896], &params_phy[896], (958 - 895) * 4);
- copy_to_reg(&denali_phy[0], &params_phy[0], (90 - 0 + 1) * 4);
- copy_to_reg(&denali_phy[128], &params_phy[128], (218 - 128 + 1) * 4);
- copy_to_reg(&denali_phy[256], &params_phy[256], (346 - 256 + 1) * 4);
- copy_to_reg(&denali_phy[384], &params_phy[384], (474 - 384 + 1) * 4);
- copy_to_reg(&denali_phy[512], &params_phy[512], (549 - 512 + 1) * 4);
- copy_to_reg(&denali_phy[640], &params_phy[640], (677 - 640 + 1) * 4);
- copy_to_reg(&denali_phy[768], &params_phy[768], (805 - 768 + 1) * 4);
- set_ds_odt(chan, params, true, 0);
+ sdram_copy_to_reg(&denali_phy[896], &params_phy[896], (958 - 895) * 4);
+ sdram_copy_to_reg(&denali_phy[0], &params_phy[0], (90 - 0 + 1) * 4);
+ sdram_copy_to_reg(&denali_phy[128], &params_phy[128],
+ (218 - 128 + 1) * 4);
+ sdram_copy_to_reg(&denali_phy[256], &params_phy[256],
+ (346 - 256 + 1) * 4);
+ sdram_copy_to_reg(&denali_phy[384], &params_phy[384],
+ (474 - 384 + 1) * 4);
+ sdram_copy_to_reg(&denali_phy[512], &params_phy[512],
+ (549 - 512 + 1) * 4);
+ sdram_copy_to_reg(&denali_phy[640], &params_phy[640],
+ (677 - 640 + 1) * 4);
+ sdram_copy_to_reg(&denali_phy[768], &params_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(&params_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;
}
@@ -1277,10 +1340,9 @@ static int data_training_wdql(const struct chan_info *chan, u32 channel,
/*
* disable PI_WDQLVL_VREF_EN before wdq leveling?
- * PI_181 PI_WDQLVL_VREF_EN:RW:8:1
+ * PI_117 PI_WDQLVL_VREF_EN:RW:8:1
*/
- clrbits_le32(&denali_pi[181], 0x1 << 8);
-
+ clrbits_le32(&denali_pi[117], 0x1 << 8);
/* PI_124 PI_WDQLVL_EN:RW:16:2 */
clrsetbits_le32(&denali_pi[124], 0x3 << 16, 0x2 << 16);
@@ -1392,7 +1454,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 +1475,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 = &params->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(&params->ch[channel].cap_info,
+ &params->base, &sys_reg2,
+ &sys_reg3, channel);
ddr_msch_regs = dram->chan[channel].msch;
noc_timing = &params->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 +1547,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 +1619,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 +1687,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 : &params->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 +1760,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 +1891,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 +1899,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 +1938,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 +1946,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 +1985,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 +1997,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 +2032,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 +2044,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 +2081,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 +2093,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 +2129,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 +2255,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 +2361,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 +2397,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 +2421,63 @@ 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);
+
+ 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);
- 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 +2496,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 +2519,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,35 +2540,237 @@ 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 = &params->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;
- unsigned int channel, chinfo = 0;
+ unsigned int gstride_type;
+ unsigned int channel;
+ unsigned int chinfo = 0;
+ unsigned int cap = 0;
+ unsigned int stride = -1;
unsigned int ch_cap[2] = {0, 0};
- u64 cap;
+
+ gstride_type = STRIDE_256B;
for (channel = 0; channel < 2; channel++) {
unsigned int cs0_cap = 0;
unsigned int cs1_cap = 0;
- struct sdram_cap_info *cap_info = &params->ch[channel].cap_info;
+ struct sdram_cap_info *cap_info =
+ &params->ch[channel].cap_info;
if (cap_info->col == 0)
continue;
@@ -2433,49 +2788,124 @@ static unsigned char calculate_stride(struct rk3399_sdram_params *params)
chinfo |= 1 << channel;
}
- /* stride calculation for 1 channel */
- if (params->base.num_channels == 1 && chinfo & 1)
- return 0x17; /* channel a */
-
- /* stride calculation for 2 channels, default gstride type is 256B */
- if (ch_cap[0] == ch_cap[1]) {
- cap = ch_cap[0] + ch_cap[1];
- switch (cap) {
- /* 512MB */
- case 512:
- stride = 0;
- break;
- /* 1GB */
- case 1024:
- stride = 0x5;
- break;
+ cap = ch_cap[0] + ch_cap[1];
+ if (params->base.num_channels == 1) {
+ if (chinfo & 1) /* channel a only */
+ stride = 0x17;
+ else /* channel b only */
+ stride = 0x18;
+ } else {/* 2 channel */
+ if (ch_cap[0] == ch_cap[1]) {
+ /* interleaved */
+ if (gstride_type == PART_STRIDE) {
+ /*
+ * first 64MB no interleaved other 256B interleaved
+ * if 786M+768M.useful space from 0-1280MB and
+ * 1536MB-1792MB
+ * if 1.5G+1.5G(continuous).useful space from 0-2560MB
+ * and 3072MB-3584MB
+ */
+ stride = 0x1F;
+ } else {
+ switch (cap) {
+ /* 512MB */
+ case 512:
+ stride = 0;
+ break;
+ /* 1GB unstride or 256B stride*/
+ case 1024:
+ stride = (gstride_type == UN_STRIDE) ?
+ 0x1 : 0x5;
+ break;
+ /*
+ * 768MB + 768MB same as total 2GB memory
+ * useful space: 0-768MB 1GB-1792MB
+ */
+ case 1536:
+ /* 2GB unstride or 256B or 512B stride */
+ case 2048:
+ stride = (gstride_type == UN_STRIDE) ?
+ 0x2 :
+ ((gstride_type == STRIDE_512B) ?
+ 0xA : 0x9);
+ break;
+ /* 1536MB + 1536MB */
+ case 3072:
+ stride = (gstride_type == UN_STRIDE) ?
+ 0x3 :
+ ((gstride_type == STRIDE_512B) ?
+ 0x12 : 0x11);
+ break;
+ /* 4GB unstride or 128B,256B,512B,4KB stride */
+ case 4096:
+ stride = (gstride_type == UN_STRIDE) ?
+ 0x3 : (0xC + gstride_type);
+ break;
+ }
+ }
+ }
+ if (ch_cap[0] == 2048 && ch_cap[1] == 1024) {
+ /* 2GB + 1GB */
+ stride = (gstride_type == UN_STRIDE) ? 0x3 : 0x19;
+ }
/*
- * 768MB + 768MB same as total 2GB memory
- * useful space: 0-768MB 1GB-1792MB
+ * remain two channel capability not equal OR capability
+ * power function of 2
*/
- case 1536:
- /* 2GB */
- case 2048:
- stride = 0x9;
- break;
- /* 1536MB + 1536MB */
- case 3072:
- stride = 0x11;
- break;
- /* 4GB */
- case 4096:
- stride = 0xD;
- break;
- default:
- printf("%s: Unable to calculate stride for ", __func__);
- print_size((cap * (1 << 20)), " capacity\n");
- break;
+ if (stride == (-1)) {
+ switch ((ch_cap[0] > ch_cap[1]) ?
+ ch_cap[0] : ch_cap[1]) {
+ case 256: /* 256MB + 128MB */
+ stride = 0;
+ break;
+ case 512: /* 512MB + 256MB */
+ stride = 1;
+ break;
+ case 1024:/* 1GB + 128MB/256MB/384MB/512MB/768MB */
+ stride = 2;
+ break;
+ case 2048: /* 2GB + 128MB/256MB/384MB/512MB/768MB/1GB */
+ stride = 3;
+ break;
+ default:
+ break;
+ }
}
+ if (stride == (-1))
+ goto error;
+ }
+ 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");
}
sdram_print_stride(stride);
return stride;
+error:
+ printf("Cap not support!\n");
+ return (-1);
}
static void clear_channel_params(struct rk3399_sdram_params *params, u8 channel)
@@ -2491,39 +2921,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 +2938,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 +2980,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 = &params->ch[channel].cap_info;
- u8 training_flag = PI_FULL_TRAINING;
+ struct sdram_cap_info *cap_info =
+ &params->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, &params->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 +3024,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 +3072,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
};