summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Muellner <christoph.muellner@theobroma-systems.com>2019-04-24 14:39:44 +0200
committerChristoph Muellner <christoph.muellner@theobroma-systems.com>2019-04-30 13:18:43 +0200
commit85f6551b230771849c959f67779d719794be7e49 (patch)
tree5287b4b943029c68dd3e838245271e4242ea866e
parent174758ba8511f68e331d586a8643d96835cbfd33 (diff)
rk3399: New DMC (denali) driver.
The upstream dynamic memory controller driver suffers from being: * unreliable (we have a drop-out rate of about 10% for 2GB 1600 Micron RAM) * non-maintainable (the RAM description in the DTS is register contents to write) * incorrect (it does not follow the specified initialisation sequence from the RAM specification) To address this issues, the patch introduces a new SPD data based driver. Tested on RK3399-Q7 with several RAM chip vendors (Micron, Issi, Nanya) and speed grades (1600 and 1866). This patch is based on ba29f7b1 of ptomsich/denali-neuronsw. Signed-off-by: Christoph Muellner <christoph.muellner@theobroma-systems.com>
-rw-r--r--arch/arm/dts/Makefile2
-rw-r--r--arch/arm/dts/rk3399-puma-ddr1600-4gb.dts10
-rw-r--r--arch/arm/dts/rk3399-puma-ddr1866-4gb.dts11
-rw-r--r--arch/arm/dts/rk3399-sdram-ddr3-1600-4gb.dtsi140
-rw-r--r--arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi1631
-rw-r--r--arch/arm/dts/rk3399-sdram-ddr3-1866-4gb.dtsi141
-rw-r--r--arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi1629
-rw-r--r--arch/arm/include/asm/arch-rockchip/sdram_rk3399.h2
-rw-r--r--drivers/ram/rockchip/Makefile2
-rw-r--r--drivers/ram/rockchip/dram_spec_timing.c1327
-rw-r--r--drivers/ram/rockchip/dram_spec_timing.h507
-rw-r--r--drivers/ram/rockchip/sdram_rk3399.c2794
12 files changed, 5071 insertions, 3125 deletions
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 0e2ffdb87f..16595a95c8 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -89,7 +89,9 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
rk3399-gru-bob.dtb \
rk3399-puma-ddr1333.dtb \
rk3399-puma-ddr1600.dtb \
+ rk3399-puma-ddr1600-4gb.dtb \
rk3399-puma-ddr1866.dtb \
+ rk3399-puma-ddr1866-4gb.dtb \
rk3399-rock960.dtb \
rv1108-elgin-r1.dtb \
rv1108-evb.dtb
diff --git a/arch/arm/dts/rk3399-puma-ddr1600-4gb.dts b/arch/arm/dts/rk3399-puma-ddr1600-4gb.dts
new file mode 100644
index 0000000000..ff2f878fd4
--- /dev/null
+++ b/arch/arm/dts/rk3399-puma-ddr1600-4gb.dts
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ */
+
+/dts-v1/;
+
+#include "rk3399-puma.dtsi"
+#include "rk3399-sdram-ddr3-1600-4gb.dtsi"
+
diff --git a/arch/arm/dts/rk3399-puma-ddr1866-4gb.dts b/arch/arm/dts/rk3399-puma-ddr1866-4gb.dts
new file mode 100644
index 0000000000..81223a309b
--- /dev/null
+++ b/arch/arm/dts/rk3399-puma-ddr1866-4gb.dts
@@ -0,0 +1,11 @@
+/*
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier: GPL-2.0+ X11
+ */
+
+/dts-v1/;
+
+#include "rk3399-puma.dtsi"
+#include "rk3399-sdram-ddr3-1866-4gb.dtsi"
+
diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1600-4gb.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1600-4gb.dtsi
new file mode 100644
index 0000000000..afee3df325
--- /dev/null
+++ b/arch/arm/dts/rk3399-sdram-ddr3-1600-4gb.dtsi
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) 2019 Theobroma Systems Design und Consulting GmbH
+ */
+
+&dmc {
+ /* This SPD models a DDR3-1866M speed-bin. */
+ theobroma-systems,spd-data = /bits/ 8 <
+ 0x01 /* CRC covers 0~125, 128 bytes data */
+ 0x10 /* revision level 1.0 */
+ 0x0b /* DDR3 SDRAM */
+ 0x0b /* module-specific section (bytes 60 ~ 116): LRDIMM */
+ 0x35 /* 8 banks, 8 Gb devices */
+ 0x21 /* 16 rows, 10 columns */
+ 0x03 /* 1.35V and 1.5V operable */
+ 0x02 /* 1 rank, x16 device-width */
+ 0x02 /* 32 bit (primary) bus-width */
+ 0x11 /* fine timebase: 1/1 = 1ps */
+ 0x01 /* medium timebase dividend */
+ 0x08 /* medium timebase divisor */
+ 0x09 /* tCKmin(MTB) .. DDR-1866 */
+ 0x00 /* */
+ 0x54 /* CAS supported: CL=10, CL=8, CL=6 */
+ 0x02 /* CAS supported: CL=13 */
+ 0x70 /* tAAmin(MTB) */
+ 0x78 /* tWRmin(MTB) */
+ 0x70 /* tRCDmin(MTB) */
+ 0x30 /* tRRDmin(MTB): 6.0 ns */
+ 0x70 /* tRPmin(MTB) */
+ 0x11 /* upper nibble for tRC (bits 7~4) and tRAS bits (3~0) */
+ 0x10 /* tRASmin(MTB), LSB */
+ 0x80 /* tRCmin(MTB), LSB */
+ 0xF0 /* tRFCmin(MTB), LSB */
+ 0x0A /* tRFCmin(MTB), MSB */
+ 0x3C /* tWTRmin(MTB) */
+ 0x3C /* tRTPmin(MTB) */
+ 0x01 /* upper nibble for tFAWmin */
+ 0x18 /* tFAWmin(MTB), LSB */
+ 0x00 /* optional features: no DLL-Off, no RZQ/7, no RZQ/6 */
+ 0x05 /* thermal/refresh: ASR, 85-95 @ 2x refresh, 0-95 degC */
+ 0x00 /* no thermal sensor */
+ 0x10 /* stacking/signal-loading: not specified */
+ 0xca /* tCKmin(FTB) */
+ 0xa6 /* tAAmin(FTB) */
+ 0xa6 /* tRCDmin(FTB) */
+ 0xa6 /* tRPmin(FTB) */
+ 0xa6 /* tRCmin */
+ 0x00 /* MAC: tMAW = 8192*tREFI, untested MAC */
+ 0x00 /* reserved -- 39 */
+ 0x00 /* reserved -- 40 */
+ 0x00 /* reserved -- byte 42 */
+ 0x00 /* reserved -- byte 43 */
+ 0x00 /* reserved -- byte 44 */
+ 0x00 /* reserved -- byte 45 */
+ 0x00 /* reserved -- byte 46 */
+ 0x00 /* reserved -- byte 47 */
+ 0x00 /* reserved -- byte 48 */
+ 0x00 /* reserved -- byte 49 */
+ 0x00 /* reserved -- byte 50 */
+ 0x00 /* reserved -- byte 51 */
+ 0x00 /* reserved -- byte 52 */
+ 0x00 /* reserved -- byte 53 */
+ 0x00 /* reserved -- byte 54 */
+ 0x00 /* reserved -- byte 55 */
+ 0x00 /* reserved -- byte 56 */
+ 0x00 /* reserved -- byte 57 */
+ 0x00 /* reserved -- byte 58 */
+ 0x00 /* reserved -- byte 59 */
+ 0x00 /* 60 */
+ 0x00 /* 61 */
+ 0x1F /* not based on a JEDEC card reference design */
+ 0x00 /* 63 */
+ 0x00 /* 64 */
+ 0x00 /* 65 */
+ 0x00 /* 66 */
+ 0x00 /* 67 */
+ 0x00 /* 68 */
+ 0x00 /* 69 */
+ 0x00 /* 70 */
+ 0x00 /* 71 */
+ 0x16 /* 72: DDR3-800 and DDR3-1066: 34ohm drive-strength, 240ohm ODT */
+ 0x33 /* 73: DDR3-800 and DDR3-1066: QxODT Control, enable for rank 1 */
+ 0x00 /* 74 */
+ 0x00 /* 75 */
+ 0x00 /* 76 */
+ 0x05 /* 77: MR1,2 for 800 & 1066: 60ohm Rtt_Nom, 34ohm drive */
+ 0x00 /* 78 */
+ 0x00 /* 79 */
+ 0x00 /* 80 */
+ 0x00 /* 81 */
+ 0x00 /* 82 */
+ 0x05 /* 83: MR1,2 for 1333 & 1600: 60ohm Rtt_Nom, 34ohm drive */
+ 0x84 /* 84 */
+ 0x85 /* 85 */
+ 0x86 /* 86 */
+ 0x87 /* 87 */
+ 0x88 /* 88 */
+ 0x05 /* 89: MR1,2 for 1866 & 2133: 60ohm Rtt_Nom, 34ohm drive */
+ 0x90
+ >;
+
+ rockchip,sdram-params = <
+ 0x1 /* ch0: rank */
+ 0xa /* ch0: col */
+ 0x3 /* ch0: bk */
+ 0x2 /* ch0: bw */
+ 0x1 /* ch0: dbw */
+ 0x0 /* ch0: row_3_4 */
+ 0x10 /* ch0: cs0_row */
+ 0x10 /* ch0: cs1_row */
+ 1 /* ch0: ddrconfig */
+ 0x80151015 /* ch0: ddrtiminga0 */
+ 0x14040902 /* ch0: ddrtimingb0 */
+ 0x00000002 /* ch0: ddrtimingc0 */
+ 0x00006346 /* ch0: devtodev0 */
+ 0x0000004c /* ch0: ddrmode */
+ 0x00000000 /* ch0: agingx0 */
+ 0x1
+ 0xa
+ 0x3
+ 0x2
+ 0x1
+ 0x0
+ 0x10
+ 0x10
+ 1
+ 0x80151015
+ 0x14040902
+ 0x00000002
+ 0x00006346
+ 0x0000004c
+ 0x00000000
+ 800 /* base: ddr_freq */
+ 3 /* base: dramtype */
+ 2 /* base: num_channels */
+ 13 /* base: stride */
+ 1 /* base: odt */
+ >;
+};
+
diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi
index fcd01f8b46..6fa4dd9ac6 100644
--- a/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi
+++ b/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi
@@ -1,25 +1,120 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * (C) 2017 Theobroma Systems Design und Consulting GmbH
+ * (C) 2019 Theobroma Systems Design und Consulting GmbH
*/
&dmc {
- rockchip,sdram-params = <
- 0x1
- 0xa
- 0x3
- 0x2
- 0x1
- 0x0
- 0xf
- 0xf
- 1
- 0x80151015
- 0x14040902
- 0x00000002
- 0x00006346
- 0x0000004c
- 0x00000000
+ /* This SPD models a DDR3-1866M speed-bin. */
+ theobroma-systems,spd-data = /bits/ 8 <
+ 0x01 /* CRC covers 0~125, 128 bytes data */
+ 0x10 /* revision level 1.0 */
+ 0x0b /* DDR3 SDRAM */
+ 0x0b /* module-specific section (bytes 60 ~ 116): LRDIMM */
+ 0x34 /* 8 banks, 4 Gb devices */
+ 0x19 /* 15 rows, 10 columns */
+ 0x03 /* 1.35V and 1.5V operable */
+ 0x02 /* 1 rank, x16 device-width */
+ 0x02 /* 32 bit (primary) bus-width */
+ 0x11 /* fine timebase: 1/1 = 1ps */
+ 0x01 /* medium timebase dividend */
+ 0x08 /* medium timebase divisor */
+ 0x09 /* tCKmin(MTB) .. DDR-1866 */
+ 0x00 /* */
+ 0x54 /* CAS supported: CL=10, CL=8, CL=6 */
+ 0x02 /* CAS supported: CL=13 */
+ 0x70 /* tAAmin(MTB) */
+ 0x78 /* tWRmin(MTB) */
+ 0x70 /* tRCDmin(MTB) */
+ 0x30 /* tRRDmin(MTB): 6.0 ns */
+ 0x70 /* tRPmin(MTB) */
+ 0x11 /* upper nibble for tRC (bits 7~4) and tRAS bits (3~0) */
+ 0x10 /* tRASmin(MTB), LSB */
+ 0x80 /* tRCmin(MTB), LSB */
+ 0xF0 /* tRFCmin(MTB), LSB */
+ 0x0A /* tRFCmin(MTB), MSB */
+ 0x3C /* tWTRmin(MTB) */
+ 0x3C /* tRTPmin(MTB) */
+ 0x01 /* upper nibble for tFAWmin */
+ 0x18 /* tFAWmin(MTB), LSB */
+ 0x00 /* optional features: no DLL-Off, no RZQ/7, no RZQ/6 */
+ 0x05 /* thermal/refresh: ASR, 85-95 @ 2x refresh, 0-95 degC */
+ 0x00 /* no thermal sensor */
+ 0x10 /* stacking/signal-loading: not specified */
+ 0xca /* tCKmin(FTB) */
+ 0xa6 /* tAAmin(FTB) */
+ 0xa6 /* tRCDmin(FTB) */
+ 0xa6 /* tRPmin(FTB) */
+ 0xa6 /* tRCmin */
+ 0x00 /* MAC: tMAW = 8192*tREFI, untested MAC */
+ 0x00 /* reserved -- 39 */
+ 0x00 /* reserved -- 40 */
+ 0x00 /* reserved -- byte 42 */
+ 0x00 /* reserved -- byte 43 */
+ 0x00 /* reserved -- byte 44 */
+ 0x00 /* reserved -- byte 45 */
+ 0x00 /* reserved -- byte 46 */
+ 0x00 /* reserved -- byte 47 */
+ 0x00 /* reserved -- byte 48 */
+ 0x00 /* reserved -- byte 49 */
+ 0x00 /* reserved -- byte 50 */
+ 0x00 /* reserved -- byte 51 */
+ 0x00 /* reserved -- byte 52 */
+ 0x00 /* reserved -- byte 53 */
+ 0x00 /* reserved -- byte 54 */
+ 0x00 /* reserved -- byte 55 */
+ 0x00 /* reserved -- byte 56 */
+ 0x00 /* reserved -- byte 57 */
+ 0x00 /* reserved -- byte 58 */
+ 0x00 /* reserved -- byte 59 */
+ 0x00 /* 60 */
+ 0x00 /* 61 */
+ 0x1F /* not based on a JEDEC card reference design */
+ 0x00 /* 63 */
+ 0x00 /* 64 */
+ 0x00 /* 65 */
+ 0x00 /* 66 */
+ 0x00 /* 67 */
+ 0x00 /* 68 */
+ 0x00 /* 69 */
+ 0x00 /* 70 */
+ 0x00 /* 71 */
+ 0x16 /* 72: DDR3-800 and DDR3-1066: 34ohm drive-strength, 240ohm ODT */
+ 0x33 /* 73: DDR3-800 and DDR3-1066: QxODT Control, enable for rank 1 */
+ 0x00 /* 74 */
+ 0x00 /* 75 */
+ 0x00 /* 76 */
+ 0x05 /* 77: MR1,2 for 800 & 1066: 60ohm Rtt_Nom, 34ohm drive */
+ 0x00 /* 78 */
+ 0x00 /* 79 */
+ 0x00 /* 80 */
+ 0x00 /* 81 */
+ 0x00 /* 82 */
+ 0x05 /* 83: MR1,2 for 1333 & 1600: 60ohm Rtt_Nom, 34ohm drive */
+ 0x84 /* 84 */
+ 0x85 /* 85 */
+ 0x86 /* 86 */
+ 0x87 /* 87 */
+ 0x88 /* 88 */
+ 0x05 /* 89: MR1,2 for 1866 & 2133: 60ohm Rtt_Nom, 34ohm drive */
+ 0x90
+ >;
+
+ rockchip,sdram-params = <
+ 0x1 /* ch0: rank */
+ 0xa /* ch0: col */
+ 0x3 /* ch0: bk */
+ 0x2 /* ch0: bw */
+ 0x1 /* ch0: dbw */
+ 0x0 /* ch0: row_3_4 */
+ 0xf /* ch0: cs0_row */
+ 0xf /* ch0: cs1_row */
+ 1 /* ch0: ddrconfig */
+ 0x80151015 /* ch0: ddrtiminga0 */
+ 0x14040902 /* ch0: ddrtimingb0 */
+ 0x00000002 /* ch0: ddrtimingc0 */
+ 0x00006346 /* ch0: devtodev0 */
+ 0x0000004c /* ch0: ddrmode */
+ 0x00000000 /* ch0: agingx0 */
0x1
0xa
0x3
@@ -35,1501 +130,11 @@
0x00006346
0x0000004c
0x00000000
- 800
- 3
- 2
- 9
- 1
- 0x00000600
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000008
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000008
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000008
- 0x00000000
- 0x00000000
- 0x01000000
- 0x00000000
- 0x00000101
- 0x00020100
- 0x00027100
- 0x00061a80
- 0x02000200
- 0x08160200
- 0x00081600
- 0x04000816
- 0x26050004
- 0x1c0b061c
- 0x1c260500
- 0x001c0b06
- 0x061c2605
- 0x06001c0b
- 0x00000c04
- 0x0400db60
- 0x0c040605
- 0x0400db60
- 0x0c040605
- 0x0400db60
- 0x02030005
- 0x0b0c0b00
- 0x000c0b0c
- 0x14000a0a
- 0x00000a0a
- 0x00010000
- 0x03171717
- 0x000b0b0b
- 0x00000000
- 0x03010000
- 0x18580118
- 0x18580118
- 0x18580118
- 0x00000000
- 0x00050005
- 0x00140005
- 0x00140014
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x02000000
- 0x02000120
- 0x02000120
- 0x00000120
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000301
- 0x00000001
- 0x00000000
- 0x00000000
- 0x01000000
- 0x80104002
- 0x00040003
- 0x00040005
- 0x00030000
- 0x00050004
- 0x00000004
- 0x00040003
- 0x00040005
- 0x61600000
- 0x000030b0
- 0x30b06160
- 0x61600000
- 0x000030b0
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x08080800
- 0x00080808
- 0x00030200
- 0x00040700
- 0x00000302
- 0x02000407
- 0x00000003
- 0x00030f04
- 0x00070004
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00010000
- 0x00010000
- 0x20040020
- 0x00200400
- 0x01000400
- 0x00000b80
- 0x00000000
- 0x00000001
- 0x00000002
- 0x0000000e
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00a00000
- 0x00c80050
- 0x00c80000
- 0x005000a0
- 0x000000c8
- 0x00a000c8
- 0x00c80050
- 0x00c80000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00420c70
- 0x0c700018
- 0x00180042
- 0x00420c70
- 0x00000018
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00420c70
- 0x0c700018
- 0x00180042
- 0x00420c70
- 0x00000018
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x01000000
- 0x00000000
- 0x00000000
- 0x18151100
- 0x0000000c
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00020003
- 0x00400100
- 0x00000000
- 0x01000200
- 0x00000040
- 0x00020000
- 0x00400100
- 0x00000000
- 0x00000000
- 0x00000000
- 0x01010100
- 0x00000202
- 0x0a000001
- 0x01000f0f
- 0x00000000
- 0x00000000
- 0x00010003
- 0x00000c03
- 0x00000000
- 0x00000000
- 0x01000000
- 0x00010000
- 0x00000001
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00010000
- 0x07070702
- 0x01010606
- 0x00000001
- 0x03030300
- 0x03080808
- 0x03050303
- 0x03050303
- 0x00050303
- 0x00020202
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x0d000001
- 0x00010028
- 0x00010000
- 0x00000003
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00010100
- 0x01000000
- 0x00000001
- 0x00000303
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x000556aa
- 0x000aaaaa
- 0x000aa955
- 0x00055555
- 0x000b3133
- 0x0004cd33
- 0x0004cecc
- 0x000b32cc
- 0x00010300
- 0x03000100
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00ffff00
- 0x15150000
- 0x08000015
- 0x000030b0
- 0x00000200
- 0x00000200
- 0x00000200
- 0x00000200
- 0x000030b0
- 0x0001e6e0
- 0x30b00709
- 0x00000200
- 0x00000200
- 0x00000200
- 0x00000200
- 0x000030b0
- 0x0001e6e0
- 0x30b00709
- 0x00000200
- 0x00000200
- 0x00000200
- 0x00000200
- 0x000030b0
- 0x0001e6e0
- 0x02020709
- 0x03030202
- 0x00000014
- 0x00000000
- 0x00000000
- 0x00001403
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00030000
- 0x00060018
- 0x00060018
- 0x00060018
- 0x00000000
- 0x00000000
- 0x01000000
- 0x02060206
- 0x00050206
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x01000100
- 0x01010101
- 0x01000101
- 0x01000100
- 0x00010001
- 0x00010002
- 0x00020100
- 0x00000002
- 0x00000600
- 0x00000000
- 0x00006160
- 0x000030b0
- 0x00006160
- 0x000030b0
- 0x00006160
- 0x30b030b0
- 0x00000200
- 0x00000200
- 0x00000200
- 0x00000200
- 0x000030b0
- 0x00000200
- 0x00000200
- 0x00000200
- 0x00000200
- 0x000030b0
- 0x00000200
- 0x00000200
- 0x00000200
- 0x00000200
- 0x00010000
- 0x00000007
- 0x110f0001
- 0x3c020000
- 0x3fffffff
- 0x3c030000
- 0x1dc0ffff
- 0x3c010000
- 0x1dc0ffff
- 0x3c000000
- 0x1dc0ffff
- 0x3c300400
- 0x1dc7ffff
- 0x3c000000
- 0x00000000
- 0x3c000000
- 0x00000000
- 0x3c000000
- 0x00000000
- 0x03000101
- 0x00242424
- 0x08160008
- 0x00081600
- 0x00000016
- 0x18580118
- 0x18580118
- 0x18580118
- 0x00000500
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x04040000
- 0x0d000004
- 0x00000128
- 0x00000000
- 0x00030003
- 0x00000014
- 0x00000000
- 0x00000000
- 0x07060002
- 0x07010701
- 0x00060601
- 0x00020001
- 0x00080004
- 0x00000000
- 0x00000000
- 0x03030300
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00030300
- 0x00000014
- 0x00000000
- 0x01010300
- 0x00000000
- 0x00000000
- 0x01000000
- 0x00000101
- 0x55555a5a
- 0x55555a5a
- 0x55555a5a
- 0x55555a5a
- 0x09090001
- 0x07070009
- 0x02020007
- 0x00000102
- 0x00030000
- 0x17030000
- 0x00060018
- 0x00060018
- 0x00060018
- 0x00000000
- 0x00000000
- 0x00000000
- 0x140a0000
- 0x000a000a
- 0x00000a00
- 0x010a000a
- 0x00000100
- 0x01000000
- 0x00000000
- 0x00000100
- 0x1e1a0000
- 0x10010204
- 0x07070705
- 0x20000202
- 0x00201000
- 0x00201000
- 0x04041000
- 0x10100100
- 0x00010110
- 0x004b004a
- 0x1a030000
- 0x0102041e
- 0x34000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00004200
- 0x00000018
- 0x004d4d00
- 0x00180042
- 0x4d000000
- 0x0000424d
- 0x00000018
- 0x004d4d00
- 0x00180042
- 0x4d000000
- 0x0000424d
- 0x00000018
- 0x004d4d00
- 0x00180042
- 0x4d000000
- 0x0042004d
- 0x00000018
- 0x004d4d00
- 0x00180042
- 0x4d000000
- 0x0000424d
- 0x00000018
- 0x004d4d00
- 0x00180042
- 0x4d000000
- 0x0000424d
- 0x00000018
- 0x004d4d00
- 0x00180042
- 0x4d000000
- 0x0000004d
- 0x00c800c8
- 0x060400c8
- 0x0c060b0b
- 0x1c00d92e
- 0x08042000
- 0x0b0b060c
- 0x00000c06
- 0x1c00d92e
- 0x08042000
- 0x0b0b060c
- 0x00000c06
- 0x1c00d92e
- 0x08042000
- 0x0200020c
- 0x02000200
- 0x02000200
- 0x02000200
- 0x02000200
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x01000300
- 0x0030b000
- 0x0001e6e0
- 0x000030b0
- 0x0001e6e0
- 0x000030b0
- 0x0001e6e0
- 0x08000000
- 0x00000100
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000001
- 0x76543210
- 0x0004c008
- 0x00000099
- 0x00000000
- 0x00000000
- 0x00010000
- 0x01665555
- 0x00665555
- 0x00010f00
- 0x05010200
- 0x00000001
- 0x001700c0
- 0x00cc0001
- 0x00000066
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x04080000
- 0x04080400
- 0x08000000
- 0x0c00c007
- 0x00000100
- 0x00000100
- 0x55555555
- 0xaaaaaaaa
- 0x55555555
- 0xaaaaaaaa
- 0x00005555
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00200000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x02800280
- 0x02800280
- 0x02800280
- 0x02800280
- 0x00000280
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00800000
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00990080
- 0x00000001
- 0x00000000
- 0x00000000
- 0x00000200
- 0x00000000
- 0x51313152
- 0x80013130
- 0x02000080
- 0x00100001
- 0x07054208
- 0x000f0c0f
- 0x01000140
- 0x00000c20
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x76543210
- 0x0004c008
- 0x00000099
- 0x00000000
- 0x00000000
- 0x00010000
- 0x01665555
- 0x00665555
- 0x00010f00
- 0x05010200
- 0x00000001
- 0x001700c0
- 0x00cc0001
- 0x00000066
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x04080000
- 0x04080400
- 0x08000000
- 0x0c00c007
- 0x00000100
- 0x00000100
- 0x55555555
- 0xaaaaaaaa
- 0x55555555
- 0xaaaaaaaa
- 0x00005555
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00200000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x02800280
- 0x02800280
- 0x02800280
- 0x02800280
- 0x00000280
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00800000
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00990080
- 0x00000001
- 0x00000000
- 0x00000000
- 0x00000200
- 0x00000000
- 0x51313152
- 0x80013130
- 0x02000080
- 0x00100001
- 0x07054208
- 0x000f0c0f
- 0x01000140
- 0x00000c20
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x76543210
- 0x0004c008
- 0x00000099
- 0x00000000
- 0x00000000
- 0x00010000
- 0x01665555
- 0x00665555
- 0x00010f00
- 0x05010200
- 0x00000001
- 0x001700c0
- 0x00cc0001
- 0x00000066
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x04080000
- 0x04080400
- 0x08000000
- 0x0c00c007
- 0x00000100
- 0x00000100
- 0x55555555
- 0xaaaaaaaa
- 0x55555555
- 0xaaaaaaaa
- 0x00005555
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00200000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x02800280
- 0x02800280
- 0x02800280
- 0x02800280
- 0x00000280
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00800000
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00990080
- 0x00000001
- 0x00000000
- 0x00000000
- 0x00000200
- 0x00000000
- 0x51313152
- 0x80013130
- 0x02000080
- 0x00100001
- 0x07054208
- 0x000f0c0f
- 0x01000140
- 0x00000c20
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x76543210
- 0x0004c008
- 0x00000099
- 0x00000000
- 0x00000000
- 0x00010000
- 0x01665555
- 0x00665555
- 0x00010f00
- 0x05010200
- 0x00000001
- 0x001700c0
- 0x00cc0001
- 0x00000066
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x04080000
- 0x04080400
- 0x08000000
- 0x0c00c007
- 0x00000100
- 0x00000100
- 0x55555555
- 0xaaaaaaaa
- 0x55555555
- 0xaaaaaaaa
- 0x00005555
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00200000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x02800280
- 0x02800280
- 0x02800280
- 0x02800280
- 0x00000280
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00800000
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00990080
- 0x00000001
- 0x00000000
- 0x00000000
- 0x00000200
- 0x00000000
- 0x51313152
- 0x80013130
- 0x02000080
- 0x00100001
- 0x07054208
- 0x000f0c0f
- 0x01000140
- 0x00000c20
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00800000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00400320
- 0x00000040
- 0x00dcba98
- 0x00000000
- 0x00dcba98
- 0x01000000
- 0x00020003
- 0x00000000
- 0x00000000
- 0x00000000
- 0x0000002a
- 0x00000015
- 0x00000015
- 0x0000002a
- 0x00000033
- 0x0000000c
- 0x0000000c
- 0x00000033
- 0x0a418820
- 0x103f0000
- 0x0000003f
- 0x00030055
- 0x03000300
- 0x03000300
- 0x00000300
- 0x42080010
- 0x00000003
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00800000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00400320
- 0x00000040
- 0x00000000
- 0x00000000
- 0x00000000
- 0x01000000
- 0x00020003
- 0x00000000
- 0x00000000
- 0x00000000
- 0x0000002a
- 0x00000015
- 0x00000015
- 0x0000002a
- 0x00000033
- 0x0000000c
- 0x0000000c
- 0x00000033
- 0x16a4a0e6
- 0x103f0000
- 0x0000003f
- 0x00030055
- 0x03000300
- 0x03000300
- 0x00000300
- 0x42080010
- 0x00000003
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00800000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00400320
- 0x00000040
- 0x00000000
- 0x00000000
- 0x00000000
- 0x01000000
- 0x00020003
- 0x00000000
- 0x00000000
- 0x00000000
- 0x0000002a
- 0x00000015
- 0x00000015
- 0x0000002a
- 0x00000033
- 0x0000000c
- 0x0000000c
- 0x00000033
- 0x1ee6b16a
- 0x103f0000
- 0x0000003f
- 0x00030055
- 0x03000300
- 0x03000300
- 0x00000300
- 0x42080010
- 0x00000003
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000001
- 0x00000000
- 0x01000005
- 0x04000f00
- 0x00020040
- 0x00020055
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00010100
- 0x00000601
- 0x00000000
- 0x00006400
- 0x01221102
- 0x00000000
- 0x00031f00
- 0x031f031f
- 0x031f031f
- 0x00030003
- 0x03000300
- 0x00000300
- 0x01221102
- 0x00000000
- 0x00000000
- 0x03020000
- 0x00000001
- 0x00008011
- 0x00000011
- 0x00000440
- 0x00000040
- 0x00004011
- 0x00004011
- 0x00004410
- 0x00004410
- 0x00004410
- 0x00004410
- 0x00004410
- 0x00004011
- 0x00004410
- 0x00004011
- 0x00004410
- 0x00004011
- 0x00004410
- 0x00000000
- 0x00000000
- 0x00000000
- 0x04000000
- 0x00000000
- 0x00000000
- 0x00000508
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0xe4000000
- 0x00000000
- 0x00000000
- 0x01010000
- 0x00000000
+ 800 /* base: ddr_freq */
+ 3 /* base: dramtype */
+ 2 /* base: num_channels */
+ 9 /* base: stride */
+ 1 /* base: odt */
>;
};
+
diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1866-4gb.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1866-4gb.dtsi
new file mode 100644
index 0000000000..8fdf514679
--- /dev/null
+++ b/arch/arm/dts/rk3399-sdram-ddr3-1866-4gb.dtsi
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) 2019 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+&dmc {
+ theobroma-systems,spd-data = /bits/ 8 <
+ 0x01 /* CRC covers 0~125, 128 bytes data */
+ 0x10 /* revision level 1.0 */
+ 0x0b /* DDR3 SDRAM */
+ 0x0b /* module-specific section (bytes 60 ~ 116): LRDIMM */
+ 0x35 /* 8 banks, 8 Gb devices */
+ 0x21 /* 16 rows, 10 columns */
+ 0x03 /* 1.35V and 1.5V operable */
+ 0x02 /* 1 rank, x16 device-width */
+ 0x02 /* 32 bit (primary) bus-width */
+ 0x11 /* fine timebase: 1/1 = 1ps */
+ 0x01 /* medium timebase dividend */
+ 0x08 /* medium timebase divisor */
+ 0x09 /* tCKmin(MTB) .. DDR-1866 */
+ 0x00 /* */
+ 0x54 /* CAS supported: CL=10, CL=8, CL=6 */
+ 0x02 /* CAS supported: CL=13 */
+ 0x70 /* tAAmin(MTB) */
+ 0x78 /* tWRmin(MTB) */
+ 0x70 /* tRCDmin(MTB) */
+ 0x30 /* tRRDmin(MTB): 6.0 ns */
+ 0x70 /* tRPmin(MTB) */
+ 0x11 /* upper nibble for tRC (bits 7~4) and tRAS bits (3~0) */
+ 0x10 /* tRASmin(MTB), LSB */
+ 0x80 /* tRCmin(MTB), LSB */
+ 0xF0 /* tRFCmin(MTB), LSB */
+ 0x0A /* tRFCmin(MTB), MSB */
+ 0x3C /* tWTRmin(MTB) */
+ 0x3C /* tRTPmin(MTB) */
+ 0x01 /* upper nibble for tFAWmin */
+ 0x18 /* tFAWmin(MTB), LSB */
+ 0x00 /* optional features: no DLL-Off, no RZQ/7, no RZQ/6 */
+ 0x05 /* thermal/refresh: ASR, 85-95 @ 2x refresh, 0-95 degC */
+ 0x00 /* no thermal sensor */
+ 0x10 /* stacking/signal-loading: not specified */
+ 0xca /* tCKmin(FTB) */
+ 0xa6 /* tAAmin(FTB) */
+ 0xa6 /* tRCDmin(FTB) */
+ 0xa6 /* tRPmin(FTB) */
+ 0xa6 /* tRCmin */
+ 0x00 /* MAC: tMAW = 8192*tREFI, untested MAC */
+ 0x00 /* reserved -- 39 */
+ 0x00 /* reserved -- 40 */
+ 0x00 /* reserved -- byte 42 */
+ 0x00 /* reserved -- byte 43 */
+ 0x00 /* reserved -- byte 44 */
+ 0x00 /* reserved -- byte 45 */
+ 0x00 /* reserved -- byte 46 */
+ 0x00 /* reserved -- byte 47 */
+ 0x00 /* reserved -- byte 48 */
+ 0x00 /* reserved -- byte 49 */
+ 0x00 /* reserved -- byte 50 */
+ 0x00 /* reserved -- byte 51 */
+ 0x00 /* reserved -- byte 52 */
+ 0x00 /* reserved -- byte 53 */
+ 0x00 /* reserved -- byte 54 */
+ 0x00 /* reserved -- byte 55 */
+ 0x00 /* reserved -- byte 56 */
+ 0x00 /* reserved -- byte 57 */
+ 0x00 /* reserved -- byte 58 */
+ 0x00 /* reserved -- byte 59 */
+ 0x00 /* 60 */
+ 0x00 /* 61 */
+ 0x1F /* not based on a JEDEC card reference design */
+ 0x00 /* 63 */
+ 0x00 /* 64 */
+ 0x00 /* 65 */
+ 0x00 /* 66 */
+ 0x00 /* 67 */
+ 0x00 /* 68 */
+ 0x00 /* 69 */
+ 0x00 /* 70 */
+ 0x00 /* 71 */
+ 0x16 /* 72: DDR3-800 and DDR3-1066: 34ohm drive-strength, 240ohm ODT */
+ 0x33 /* 73: DDR3-800 and DDR3-1066: QxODT Control, enable for rank 1 */
+ 0x00 /* 74 */
+ 0x00 /* 75 */
+ 0x00 /* 76 */
+ 0x05 /* 77: MR1,2 for 800 & 1066: 60ohm Rtt_Nom, 34ohm drive */
+ 0x00 /* 78 */
+ 0x00 /* 79 */
+ 0x00 /* 80 */
+ 0x00 /* 81 */
+ 0x00 /* 82 */
+ 0x05 /* 83: MR1,2 for 1333 & 1600: 60ohm Rtt_Nom, 34ohm drive */
+ 0x84 /* 84 */
+ 0x85 /* 85 */
+ 0x86 /* 86 */
+ 0x87 /* 87 */
+ 0x88 /* 88 */
+ 0x05 /* 89: MR1,2 for 1866 & 2133: 60ohm Rtt_Nom, 34ohm drive */
+ 0x90
+ >;
+
+ rockchip,sdram-params = <
+ 0x1 /* ch0: rank */
+ 0xa /* ch0: col */
+ 0x3 /* ch0: bk */
+ 0x2 /* ch0: bw */
+ 0x1 /* ch0: dbw */
+ 0x0 /* ch0: row_3_4 */
+ 0x10 /* ch0: cs0_row */
+ 0x10 /* ch0: cs1_row */
+ 1 /* ch0: ddrconfig */
+ 0x80181219 /* ch0: ddrtiminga0 */
+ 0x17050a03 /* ch0: ddrtimingb0 */
+ 0x00000002 /* ch0: ddrtimingc0 */
+ 0x00006456 /* ch0: devtodev0 */
+ 0x0000004c /* ch0: ddrmode */
+ 0x00000000 /* ch0: agingx0 */
+ 0x1
+ 0xa
+ 0x3
+ 0x2
+ 0x1
+ 0x0
+ 0x10
+ 0x10
+ 1
+ 0x80181219
+ 0x17050a03
+ 0x00000002
+ 0x00006456
+ 0x0000004c
+ 0x00000000
+ 933 /* base: ddr_freq */
+ 3 /* base: dramtype */
+ 2 /* base: num_channels */
+ 13 /* base: stride */
+ 1 /* base: odt */
+ >;
+};
+
diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi
index c46c1996be..f3c1039f87 100644
--- a/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi
+++ b/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi
@@ -1,25 +1,119 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * (C) 2017 Theobroma Systems Design und Consulting GmbH
+ * (C) 2019 Theobroma Systems Design und Consulting GmbH
*/
&dmc {
- rockchip,sdram-params = <
- 0x1
- 0xa
- 0x3
- 0x2
- 0x1
- 0x0
- 0xf
- 0xf
- 1
- 0x80181219
- 0x17050a03
- 0x00000002
- 0x00006456
- 0x0000004c
- 0x00000000
+ theobroma-systems,spd-data = /bits/ 8 <
+ 0x01 /* CRC covers 0~125, 128 bytes data */
+ 0x10 /* revision level 1.0 */
+ 0x0b /* DDR3 SDRAM */
+ 0x0b /* module-specific section (bytes 60 ~ 116): LRDIMM */
+ 0x34 /* 8 banks, 4 Gb devices */
+ 0x19 /* 15 rows, 10 columns */
+ 0x03 /* 1.35V and 1.5V operable */
+ 0x02 /* 1 rank, x16 device-width */
+ 0x02 /* 32 bit (primary) bus-width */
+ 0x11 /* fine timebase: 1/1 = 1ps */
+ 0x01 /* medium timebase dividend */
+ 0x08 /* medium timebase divisor */
+ 0x09 /* tCKmin(MTB) .. DDR-1866 */
+ 0x00 /* */
+ 0x54 /* CAS supported: CL=10, CL=8, CL=6 */
+ 0x02 /* CAS supported: CL=13 */
+ 0x70 /* tAAmin(MTB) */
+ 0x78 /* tWRmin(MTB) */
+ 0x70 /* tRCDmin(MTB) */
+ 0x30 /* tRRDmin(MTB): 6.0 ns */
+ 0x70 /* tRPmin(MTB) */
+ 0x11 /* upper nibble for tRC (bits 7~4) and tRAS bits (3~0) */
+ 0x10 /* tRASmin(MTB), LSB */
+ 0x80 /* tRCmin(MTB), LSB */
+ 0xF0 /* tRFCmin(MTB), LSB */
+ 0x0A /* tRFCmin(MTB), MSB */
+ 0x3C /* tWTRmin(MTB) */
+ 0x3C /* tRTPmin(MTB) */
+ 0x01 /* upper nibble for tFAWmin */
+ 0x18 /* tFAWmin(MTB), LSB */
+ 0x00 /* optional features: no DLL-Off, no RZQ/7, no RZQ/6 */
+ 0x05 /* thermal/refresh: ASR, 85-95 @ 2x refresh, 0-95 degC */
+ 0x00 /* no thermal sensor */
+ 0x10 /* stacking/signal-loading: not specified */
+ 0xca /* tCKmin(FTB) */
+ 0xa6 /* tAAmin(FTB) */
+ 0xa6 /* tRCDmin(FTB) */
+ 0xa6 /* tRPmin(FTB) */
+ 0xa6 /* tRCmin */
+ 0x00 /* MAC: tMAW = 8192*tREFI, untested MAC */
+ 0x00 /* reserved -- 39 */
+ 0x00 /* reserved -- 40 */
+ 0x00 /* reserved -- byte 42 */
+ 0x00 /* reserved -- byte 43 */
+ 0x00 /* reserved -- byte 44 */
+ 0x00 /* reserved -- byte 45 */
+ 0x00 /* reserved -- byte 46 */
+ 0x00 /* reserved -- byte 47 */
+ 0x00 /* reserved -- byte 48 */
+ 0x00 /* reserved -- byte 49 */
+ 0x00 /* reserved -- byte 50 */
+ 0x00 /* reserved -- byte 51 */
+ 0x00 /* reserved -- byte 52 */
+ 0x00 /* reserved -- byte 53 */
+ 0x00 /* reserved -- byte 54 */
+ 0x00 /* reserved -- byte 55 */
+ 0x00 /* reserved -- byte 56 */
+ 0x00 /* reserved -- byte 57 */
+ 0x00 /* reserved -- byte 58 */
+ 0x00 /* reserved -- byte 59 */
+ 0x00 /* 60 */
+ 0x00 /* 61 */
+ 0x1F /* not based on a JEDEC card reference design */
+ 0x00 /* 63 */
+ 0x00 /* 64 */
+ 0x00 /* 65 */
+ 0x00 /* 66 */
+ 0x00 /* 67 */
+ 0x00 /* 68 */
+ 0x00 /* 69 */
+ 0x00 /* 70 */
+ 0x00 /* 71 */
+ 0x16 /* 72: DDR3-800 and DDR3-1066: 34ohm drive-strength, 240ohm ODT */
+ 0x33 /* 73: DDR3-800 and DDR3-1066: QxODT Control, enable for rank 1 */
+ 0x00 /* 74 */
+ 0x00 /* 75 */
+ 0x00 /* 76 */
+ 0x05 /* 77: MR1,2 for 800 & 1066: 60ohm Rtt_Nom, 34ohm drive */
+ 0x00 /* 78 */
+ 0x00 /* 79 */
+ 0x00 /* 80 */
+ 0x00 /* 81 */
+ 0x00 /* 82 */
+ 0x05 /* 83: MR1,2 for 1333 & 1600: 60ohm Rtt_Nom, 34ohm drive */
+ 0x84 /* 84 */
+ 0x85 /* 85 */
+ 0x86 /* 86 */
+ 0x87 /* 87 */
+ 0x88 /* 88 */
+ 0x05 /* 89: MR1,2 for 1866 & 2133: 60ohm Rtt_Nom, 34ohm drive */
+ 0x90
+ >;
+
+ rockchip,sdram-params = <
+ 0x1 /* ch0: rank */
+ 0xa /* ch0: col */
+ 0x3 /* ch0: bk */
+ 0x2 /* ch0: bw */
+ 0x1 /* ch0: dbw */
+ 0x0 /* ch0: row_3_4 */
+ 0xf /* ch0: cs0_row */
+ 0xf /* ch0: cs1_row */
+ 1 /* ch0: ddrconfig */
+ 0x80181219 /* ch0: ddrtiminga0 */
+ 0x17050a03 /* ch0: ddrtimingb0 */
+ 0x00000002 /* ch0: ddrtimingc0 */
+ 0x00006456 /* ch0: devtodev0 */
+ 0x0000004c /* ch0: ddrmode */
+ 0x00000000 /* ch0: agingx0 */
0x1
0xa
0x3
@@ -35,1502 +129,11 @@
0x00006456
0x0000004c
0x00000000
- 933
- 3
- 2
- 9
- 1
- 0x00000600
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x0000000a
- 0x00000000
- 0x00000000
- 0x00000000
- 0x0000000a
- 0x00000000
- 0x00000000
- 0x00000000
- 0x0000000a
- 0x00000000
- 0x00000000
- 0x01000000
- 0x00000000
- 0x00000101
- 0x00020100
- 0x0002d976
- 0x00071fa6
- 0x02000200
- 0x091a0200
- 0x00091a00
- 0x0400091a
- 0x2c060004
- 0x210c0820
- 0x202c0600
- 0x00210c08
- 0x08202c06
- 0x0800210c
- 0x00000f04
- 0x0501000a
- 0x0f040805
- 0x0501000a
- 0x0f040805
- 0x0501000a
- 0x02030005
- 0x0c0f0c00
- 0x000f0c0f
- 0x14000a0a
- 0x00000a0a
- 0x00010000
- 0x031c1c1c
- 0x000c0c0c
- 0x00000000
- 0x03010000
- 0x1c6a0147
- 0x1c6a0147
- 0x1c6a0147
- 0x00000000
- 0x00060006
- 0x00170006
- 0x00170017
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x02000000
- 0x02000151
- 0x02000151
- 0x00000151
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000301
- 0x00000001
- 0x00000000
- 0x00000000
- 0x01000000
- 0x80104002
- 0x00040003
- 0x00040005
- 0x00030000
- 0x00050004
- 0x00000004
- 0x00040003
- 0x00040005
- 0x71a80000
- 0x000038d4
- 0x38d471a8
- 0x71a80000
- 0x000038d4
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x0a0a0a00
- 0x000a0a0a
- 0x00030200
- 0x00040700
- 0x00000302
- 0x02000407
- 0x00000003
- 0x00030f04
- 0x00070004
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00010000
- 0x00010000
- 0x20040020
- 0x00200400
- 0x01000400
- 0x00000b80
- 0x00000000
- 0x00000001
- 0x00000002
- 0x0000000e
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00bb0000
- 0x00ea005e
- 0x00ea0000
- 0x005e00bb
- 0x000000ea
- 0x00bb00ea
- 0x00ea005e
- 0x00ea0000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00420014
- 0x00140020
- 0x00200042
- 0x00420014
- 0x00000020
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00420014
- 0x00140020
- 0x00200042
- 0x00420014
- 0x00000020
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x01000000
- 0x00000000
- 0x00000000
- 0x18151100
- 0x0000000c
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00025603
- 0x004b012b
- 0x00000000
- 0x012b0256
- 0x0000004b
- 0x00025600
- 0x004b012b
- 0x00000000
- 0x00000000
- 0x00000000
- 0x01010100
- 0x00000202
- 0x0a000001
- 0x01000f0f
- 0x00000000
- 0x00000000
- 0x00010003
- 0x00000c03
- 0x00000000
- 0x00000000
- 0x01000000
- 0x00010000
- 0x00000001
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00010000
- 0x08080802
- 0x01010606
- 0x00000001
- 0x04040400
- 0x03080808
- 0x03050303
- 0x03050303
- 0x00050303
- 0x00020202
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x0d000001
- 0x00010028
- 0x00010000
- 0x00000003
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00010100
- 0x01000000
- 0x00000001
- 0x00000303
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x000556aa
- 0x000aaaaa
- 0x000aa955
- 0x00055555
- 0x000b3133
- 0x0004cd33
- 0x0004cecc
- 0x000b32cc
- 0x00010300
- 0x03000100
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00ffff00
- 0x15150000
- 0x08000015
- 0x000038d4
- 0x00000200
- 0x00000200
- 0x00000200
- 0x00000200
- 0x000038d4
- 0x00023848
- 0x38d4080b
- 0x00000200
- 0x00000200
- 0x00000200
- 0x00000200
- 0x000038d4
- 0x00023848
- 0x38d4080b
- 0x00000200
- 0x00000200
- 0x00000200
- 0x00000200
- 0x000038d4
- 0x00023848
- 0x0202080b
- 0x03030202
- 0x00000014
- 0x00000000
- 0x00000000
- 0x00001403
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00030000
- 0x00060018
- 0x00060018
- 0x00060018
- 0x00000000
- 0x00000000
- 0x01000000
- 0x03080308
- 0x00050308
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x01000100
- 0x01010101
- 0x01000101
- 0x01000100
- 0x00010001
- 0x00010002
- 0x00020100
- 0x00000002
- 0x00000600
- 0x00000000
- 0x000071a8
- 0x000038d4
- 0x000071a8
- 0x000038d4
- 0x000071a8
- 0x38d438d4
- 0x00000200
- 0x00000200
- 0x00000200
- 0x00000200
- 0x000038d4
- 0x00000200
- 0x00000200
- 0x00000200
- 0x00000200
- 0x000038d4
- 0x00000200
- 0x00000200
- 0x00000200
- 0x00000200
- 0x00010000
- 0x00000007
- 0x110f0001
- 0x3c020000
- 0x3fffffff
- 0x3c030000
- 0x1dc0ffff
- 0x3c010000
- 0x1dc0ffff
- 0x3c000000
- 0x1dc0ffff
- 0x3c300400
- 0x1dc7ffff
- 0x3c000000
- 0x00000000
- 0x3c000000
- 0x00000000
- 0x3c000000
- 0x00000000
- 0x03000101
- 0x00262626
- 0x091a0009
- 0x00091a00
- 0x0000001a
- 0x1c6a0147
- 0x1c6a0147
- 0x1c6a0147
- 0x00000500
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x04040000
- 0x0d000004
- 0x00000128
- 0x00000000
- 0x00030003
- 0x00000014
- 0x00000000
- 0x00000000
- 0x08060002
- 0x08010801
- 0x00060601
- 0x00020001
- 0x00080004
- 0x00000000
- 0x00000000
- 0x04040400
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00030300
- 0x00000014
- 0x00000000
- 0x01010300
- 0x00000000
- 0x00000000
- 0x01000000
- 0x00000101
- 0x55555a5a
- 0x55555a5a
- 0x55555a5a
- 0x55555a5a
- 0x0b0b0001
- 0x0808000b
- 0x03030008
- 0x00000103
- 0x00030000
- 0x17030000
- 0x00060018
- 0x00060018
- 0x00060018
- 0x00000000
- 0x00000000
- 0x00000000
- 0x140a0000
- 0x000a000a
- 0x00000a00
- 0x010a000a
- 0x00000100
- 0x01000000
- 0x00000000
- 0x00000100
- 0x1e1a0000
- 0x10010204
- 0x07070705
- 0x20000202
- 0x00201000
- 0x00201000
- 0x04041000
- 0x12120100
- 0x00010112
- 0x004b004a
- 0x1a030000
- 0x0102041e
- 0x34000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00004200
- 0x00000020
- 0x004d4d00
- 0x00200042
- 0x4d000000
- 0x0000424d
- 0x00000020
- 0x004d4d00
- 0x00200042
- 0x4d000000
- 0x0000424d
- 0x00000020
- 0x004d4d00
- 0x00200042
- 0x4d000000
- 0x0042004d
- 0x00000020
- 0x004d4d00
- 0x00200042
- 0x4d000000
- 0x0000424d
- 0x00000020
- 0x004d4d00
- 0x00200042
- 0x4d000000
- 0x0000424d
- 0x00000020
- 0x004d4d00
- 0x00200042
- 0x4d000000
- 0x0000004d
- 0x00ea00ea
- 0x080400ea
- 0x0f080c0c
- 0x2000fd7a
- 0x0a042000
- 0x0c0c080f
- 0x00000f08
- 0x2000fd7a
- 0x0a042000
- 0x0c0c080f
- 0x00000f08
- 0x2000fd7a
- 0x0a042000
- 0x0200020f
- 0x02000200
- 0x02000200
- 0x02000200
- 0x02000200
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x01000300
- 0x0038d400
- 0x00023848
- 0x000038d4
- 0x00023848
- 0x000038d4
- 0x00023848
- 0x08000000
- 0x00000100
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000001
- 0x76543210
- 0x0004c008
- 0x000000de
- 0x00000000
- 0x00000000
- 0x00010000
- 0x01665555
- 0x00665555
- 0x00010f00
- 0x06010200
- 0x00000001
- 0x001700c0
- 0x00cc0001
- 0x00000066
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x04080000
- 0x04080400
- 0x08000000
- 0x0c00c007
- 0x00000100
- 0x00000100
- 0x55555555
- 0xaaaaaaaa
- 0x55555555
- 0xaaaaaaaa
- 0x00005555
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00200000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x02800280
- 0x02800280
- 0x02800280
- 0x02800280
- 0x00000280
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00800000
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00de0080
- 0x00000001
- 0x00000000
- 0x00000000
- 0x00000200
- 0x00000000
- 0x51313152
- 0x80013130
- 0x02000080
- 0x00100001
- 0x07064208
- 0x000f0c0f
- 0x01000140
- 0x00000c20
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x76543210
- 0x0004c008
- 0x000000de
- 0x00000000
- 0x00000000
- 0x00010000
- 0x01665555
- 0x00665555
- 0x00010f00
- 0x06010200
- 0x00000001
- 0x001700c0
- 0x00cc0001
- 0x00000066
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x04080000
- 0x04080400
- 0x08000000
- 0x0c00c007
- 0x00000100
- 0x00000100
- 0x55555555
- 0xaaaaaaaa
- 0x55555555
- 0xaaaaaaaa
- 0x00005555
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00200000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x02800280
- 0x02800280
- 0x02800280
- 0x02800280
- 0x00000280
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00800000
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00de0080
- 0x00000001
- 0x00000000
- 0x00000000
- 0x00000200
- 0x00000000
- 0x51313152
- 0x80013130
- 0x02000080
- 0x00100001
- 0x07064208
- 0x000f0c0f
- 0x01000140
- 0x00000c20
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x76543210
- 0x0004c008
- 0x000000de
- 0x00000000
- 0x00000000
- 0x00010000
- 0x01665555
- 0x00665555
- 0x00010f00
- 0x06010200
- 0x00000001
- 0x001700c0
- 0x00cc0001
- 0x00000066
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x04080000
- 0x04080400
- 0x08000000
- 0x0c00c007
- 0x00000100
- 0x00000100
- 0x55555555
- 0xaaaaaaaa
- 0x55555555
- 0xaaaaaaaa
- 0x00005555
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00200000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x02800280
- 0x02800280
- 0x02800280
- 0x02800280
- 0x00000280
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00800000
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00de0080
- 0x00000001
- 0x00000000
- 0x00000000
- 0x00000200
- 0x00000000
- 0x51313152
- 0x80013130
- 0x02000080
- 0x00100001
- 0x07064208
- 0x000f0c0f
- 0x01000140
- 0x00000c20
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x76543210
- 0x0004c008
- 0x000000de
- 0x00000000
- 0x00000000
- 0x00010000
- 0x01665555
- 0x00665555
- 0x00010f00
- 0x06010200
- 0x00000001
- 0x001700c0
- 0x00cc0001
- 0x00000066
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x04080000
- 0x04080400
- 0x08000000
- 0x0c00c007
- 0x00000100
- 0x00000100
- 0x55555555
- 0xaaaaaaaa
- 0x55555555
- 0xaaaaaaaa
- 0x00005555
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00200000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x02800280
- 0x02800280
- 0x02800280
- 0x02800280
- 0x00000280
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00800000
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00800080
- 0x00de0080
- 0x00000001
- 0x00000000
- 0x00000000
- 0x00000200
- 0x00000000
- 0x51313152
- 0x80013130
- 0x02000080
- 0x00100001
- 0x07064208
- 0x000f0c0f
- 0x01000140
- 0x00000c20
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00800000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00400320
- 0x00000040
- 0x00dcba98
- 0x00000000
- 0x00dcba98
- 0x01000000
- 0x00020003
- 0x00000000
- 0x00000000
- 0x00000000
- 0x0000002a
- 0x00000015
- 0x00000015
- 0x0000002a
- 0x00000033
- 0x0000000c
- 0x0000000c
- 0x00000033
- 0x0a418820
- 0x103f0000
- 0x0000003f
- 0x00030055
- 0x03000300
- 0x03000300
- 0x00000300
- 0x42080010
- 0x00000003
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00800000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00400320
- 0x00000040
- 0x00000000
- 0x00000000
- 0x00000000
- 0x01000000
- 0x00020003
- 0x00000000
- 0x00000000
- 0x00000000
- 0x0000002a
- 0x00000015
- 0x00000015
- 0x0000002a
- 0x00000033
- 0x0000000c
- 0x0000000c
- 0x00000033
- 0x16a4a0e6
- 0x103f0000
- 0x0000003f
- 0x00030055
- 0x03000300
- 0x03000300
- 0x00000300
- 0x42080010
- 0x00000003
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00800000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00400320
- 0x00000040
- 0x00000000
- 0x00000000
- 0x00000000
- 0x01000000
- 0x00020003
- 0x00000000
- 0x00000000
- 0x00000000
- 0x0000002a
- 0x00000015
- 0x00000015
- 0x0000002a
- 0x00000033
- 0x0000000c
- 0x0000000c
- 0x00000033
- 0x1ee6b16a
- 0x103f0000
- 0x0000003f
- 0x00030055
- 0x03000300
- 0x03000300
- 0x00000300
- 0x42080010
- 0x00000003
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000001
- 0x00000000
- 0x01000005
- 0x04000f00
- 0x00020040
- 0x00020055
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00010100
- 0x00000601
- 0x00000000
- 0x00006400
- 0x01221102
- 0x00000000
- 0x00031f00
- 0x031f031f
- 0x031f031f
- 0x00030003
- 0x03000300
- 0x00000300
- 0x01221102
- 0x00000000
- 0x00000000
- 0x04020000
- 0x00000001
- 0x00008011
- 0x00000011
- 0x00000440
- 0x00000040
- 0x00004011
- 0x00004011
- 0x00004410
- 0x00004410
- 0x00004410
- 0x00004410
- 0x00004410
- 0x00004011
- 0x00004410
- 0x00004011
- 0x00004410
- 0x00004011
- 0x00004410
- 0x00000000
- 0x00000000
- 0x00000000
- 0x04000000
- 0x00000000
- 0x00000000
- 0x00000508
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000000
- 0xe4000000
- 0x00000000
- 0x00000000
- 0x01010000
- 0x00000000
+ 933 /* base: ddr_freq */
+ 3 /* base: dramtype */
+ 2 /* base: num_channels */
+ 9 /* base: stride */
+ 1 /* base: odt */
>;
};
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h b/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
index c6a260bad8..378bb20205 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
@@ -103,9 +103,11 @@ struct rk3399_base_params {
struct rk3399_sdram_params {
struct rk3399_sdram_channel ch[2];
struct rk3399_base_params base;
+#if 0 // TODO: revert, once completely split
struct rk3399_ddr_pctl_regs pctl_regs;
struct rk3399_ddr_pi_regs pi_regs;
struct rk3399_ddr_publ_regs phy_regs;
+#endif
};
#define PI_CA_TRAINING (1 << 0)
diff --git a/drivers/ram/rockchip/Makefile b/drivers/ram/rockchip/Makefile
index 5df196066d..bad18834a4 100644
--- a/drivers/ram/rockchip/Makefile
+++ b/drivers/ram/rockchip/Makefile
@@ -9,4 +9,4 @@ obj-$(CONFIG_ROCKCHIP_RK3188) = sdram_rk3188.o
obj-$(CONFIG_ROCKCHIP_RK322X) = sdram_rk322x.o
obj-$(CONFIG_ROCKCHIP_RK3288) = sdram_rk3288.o
obj-$(CONFIG_ROCKCHIP_RK3328) = sdram_rk3328.o
-obj-$(CONFIG_ROCKCHIP_RK3399) = sdram_rk3399.o
+obj-$(CONFIG_ROCKCHIP_RK3399) = sdram_rk3399.o dram_spec_timing.o
diff --git a/drivers/ram/rockchip/dram_spec_timing.c b/drivers/ram/rockchip/dram_spec_timing.c
new file mode 100644
index 0000000000..5c78ac1e26
--- /dev/null
+++ b/drivers/ram/rockchip/dram_spec_timing.c
@@ -0,0 +1,1327 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common.h>
+// #include <string.h>
+#include <asm/arch/sdram_common.h>
+#include <asm/arch/sdram_rk3399.h>
+#include <linux/kernel.h>
+// #include <stdint.h>
+// #include <dram.h>
+// #include <utils.h>
+#include "dram_spec_timing.h"
+
+static const uint8_t ddr3_cl_cwl[][7] = {
+ /*
+ * speed 0~330 331 ~ 400 401 ~ 533 534~666 667~800 801~933 934~1066
+ * tCK>3 2.5~3 1.875~2.5 1.5~1.875 1.25~1.5 1.07~1.25 0.938~1.07
+ * cl<<4, cwl cl<<4, cwl cl<<4, cwl
+ */
+ /* DDR3_800D (5-5-5) */
+ {((5 << 4) | 5), ((5 << 4) | 5), 0, 0, 0, 0, 0},
+ /* DDR3_800E (6-6-6) */
+ {((5 << 4) | 5), ((6 << 4) | 5), 0, 0, 0, 0, 0},
+ /* DDR3_1066E (6-6-6) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), 0, 0, 0, 0},
+ /* DDR3_1066F (7-7-7) */
+ {((5 << 4) | 5), ((6 << 4) | 5), ((7 << 4) | 6), 0, 0, 0, 0},
+ /* DDR3_1066G (8-8-8) */
+ {((5 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), 0, 0, 0, 0},
+ /* DDR3_1333F (7-7-7) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((7 << 4) | 7),
+ 0, 0, 0},
+ /* DDR3_1333G (8-8-8) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((7 << 4) | 6), ((8 << 4) | 7),
+ 0, 0, 0},
+ /* DDR3_1333H (9-9-9) */
+ {((5 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), ((9 << 4) | 7),
+ 0, 0, 0},
+ /* DDR3_1333J (10-10-10) */
+ {((5 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), ((10 << 4) | 7),
+ 0, 0, 0},
+ /* DDR3_1600G (8-8-8) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((7 << 4) | 7),
+ ((8 << 4) | 8), 0, 0},
+ /* DDR3_1600H (9-9-9) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((8 << 4) | 7),
+ ((9 << 4) | 8), 0, 0},
+ /* DDR3_1600J (10-10-10) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((7 << 4) | 6), ((9 << 4) | 7),
+ ((10 << 4) | 8), 0, 0},
+ /* DDR3_1600K (11-11-11) */
+ {((5 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), ((10 << 4) | 7),
+ ((11 << 4) | 8), 0, 0},
+ /* DDR3_1866J (10-10-10) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((8 << 4) | 7),
+ ((9 << 4) | 8), ((11 << 4) | 9), 0},
+ /* DDR3_1866K (11-11-11) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((7 << 4) | 6), ((8 << 4) | 7),
+ ((10 << 4) | 8), ((11 << 4) | 9), 0},
+ /* DDR3_1866L (12-12-12) */
+ {((6 << 4) | 5), ((6 << 4) | 5), ((7 << 4) | 6), ((9 << 4) | 7),
+ ((11 << 4) | 8), ((12 << 4) | 9), 0},
+ /* DDR3_1866M (13-13-13) */
+ {((6 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), ((10 << 4) | 7),
+ ((13 << 4) | 9), ((13 << 4) | 9), 0},
+ /* DDR3_2133K (11-11-11) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((7 << 4) | 7),
+ ((9 << 4) | 8), ((10 << 4) | 9), ((11 << 4) | 10)},
+ /* DDR3_2133L (12-12-12) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((8 << 4) | 7),
+ ((9 << 4) | 8), ((11 << 4) | 9), ((12 << 4) | 10)},
+ /* DDR3_2133M (13-13-13) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((7 << 4) | 6), ((9 << 4) | 7),
+ ((10 << 4) | 8), ((12 << 4) | 9), ((13 << 4) | 10)},
+ /* DDR3_2133N (14-14-14) */
+ {((6 << 4) | 5), ((6 << 4) | 5), ((7 << 4) | 6), ((9 << 4) | 7),
+ ((11 << 4) | 8), ((13 << 4) | 9), ((14 << 4) | 10)},
+ /* DDR3_DEFAULT */
+ {((6 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), ((10 << 4) | 7),
+ ((11 << 4) | 8), ((13 << 4) | 9), ((14 << 4) | 10)}
+};
+
+static const uint16_t ddr3_trc_tfaw[] = {
+ /* tRC tFAW */
+ ((50 << 8) | 50), /* DDR3_800D (5-5-5) */
+ ((53 << 8) | 50), /* DDR3_800E (6-6-6) */
+
+ ((49 << 8) | 50), /* DDR3_1066E (6-6-6) */
+ ((51 << 8) | 50), /* DDR3_1066F (7-7-7) */
+ ((53 << 8) | 50), /* DDR3_1066G (8-8-8) */
+
+ ((47 << 8) | 45), /* DDR3_1333F (7-7-7) */
+ ((48 << 8) | 45), /* DDR3_1333G (8-8-8) */
+ ((50 << 8) | 45), /* DDR3_1333H (9-9-9) */
+ ((51 << 8) | 45), /* DDR3_1333J (10-10-10) */
+
+ ((45 << 8) | 40), /* DDR3_1600G (8-8-8) */
+ ((47 << 8) | 40), /* DDR3_1600H (9-9-9)*/
+ ((48 << 8) | 40), /* DDR3_1600J (10-10-10) */
+ ((49 << 8) | 40), /* DDR3_1600K (11-11-11) */
+
+ ((45 << 8) | 35), /* DDR3_1866J (10-10-10) */
+ ((46 << 8) | 35), /* DDR3_1866K (11-11-11) */
+ ((47 << 8) | 35), /* DDR3_1866L (12-12-12) */
+ ((48 << 8) | 35), /* DDR3_1866M (13-13-13) */
+
+ ((44 << 8) | 35), /* DDR3_2133K (11-11-11) */
+ ((45 << 8) | 35), /* DDR3_2133L (12-12-12) */
+ ((46 << 8) | 35), /* DDR3_2133M (13-13-13) */
+ ((47 << 8) | 35), /* DDR3_2133N (14-14-14) */
+
+ ((53 << 8) | 50) /* DDR3_DEFAULT */
+};
+
+static uint32_t get_max_speed_rate(struct timing_related_config *timing_config)
+{
+ if (timing_config->ch_cnt > 1)
+ return max(timing_config->dram_info[0].speed_rate,
+ timing_config->dram_info[1].speed_rate);
+ else
+ return timing_config->dram_info[0].speed_rate;
+}
+
+static uint32_t
+get_max_die_capability(struct timing_related_config *timing_config)
+{
+ uint32_t die_cap = 0;
+ uint32_t cs, ch;
+
+ for (ch = 0; ch < timing_config->ch_cnt; ch++) {
+ for (cs = 0; cs < timing_config->dram_info[ch].cs_cnt; cs++) {
+ die_cap = max(die_cap,
+ timing_config->
+ dram_info[ch].per_die_capability[cs]);
+ }
+ }
+ return die_cap;
+}
+
+/* tRSTL, 200us */
+#define DDR3_TRSTL (200000)
+/* trsth, 500us */
+#define DDR3_TRSTH (500000)
+/* trefi, 7.8us */
+#define DDR3_TREFI_7_8_US (7800)
+/* tWR, 15ns */
+#define DDR3_TWR (15)
+/* tRTP, max(4 tCK,7.5ns) */
+#define DDR3_TRTP (7)
+/* tRRD = max(4nCK, 10ns) */
+#define DDR3_TRRD (10)
+/* tCK */
+#define DDR3_TCCD (4)
+/*tWTR, max(4 tCK,7.5ns)*/
+#define DDR3_TWTR (7)
+/* tCK */
+#define DDR3_TRTW (0)
+/* tRAS, 37.5ns(400MHz) 37.5ns(533MHz) */
+#define DDR3_TRAS (37)
+/* ns */
+#define DDR3_TRFC_512MBIT (90)
+/* ns */
+#define DDR3_TRFC_1GBIT (110)
+/* ns */
+#define DDR3_TRFC_2GBIT (160)
+/* ns */
+#define DDR3_TRFC_4GBIT (300)
+/* ns */
+#define DDR3_TRFC_8GBIT (350)
+
+/*pd and sr*/
+#define DDR3_TXP (7) /* tXP, max(3 tCK, 7.5ns)( < 933MHz) */
+#define DDR3_TXPDLL (24) /* tXPDLL, max(10 tCK, 24ns) */
+#define DDR3_TDLLK (512) /* tXSR, tDLLK=512 tCK */
+#define DDR3_TCKE_400MHZ (7) /* tCKE, max(3 tCK,7.5ns)(400MHz) */
+#define DDR3_TCKE_533MHZ (6) /* tCKE, max(3 tCK,5.625ns)(533MHz) */
+#define DDR3_TCKSRE (10) /* tCKSRX, max(5 tCK, 10ns) */
+
+/*mode register timing*/
+#define DDR3_TMOD (15) /* tMOD, max(12 tCK,15ns) */
+#define DDR3_TMRD (4) /* tMRD, 4 tCK */
+
+/* ZQ */
+#define DDR3_TZQINIT (640) /* tZQinit, max(512 tCK, 640ns) */
+#define DDR3_TZQCS (80) /* tZQCS, max(64 tCK, 80ns) */
+#define DDR3_TZQOPER (320) /* tZQoper, max(256 tCK, 320ns) */
+
+/* Write leveling */
+#define DDR3_TWLMRD (40) /* tCK */
+#define DDR3_TWLO (9) /* max 7.5ns */
+#define DDR3_TWLDQSEN (25) /* tCK */
+
+/*
+ * Description: depend on input parameter "timing_config",
+ * and calculate all ddr3
+ * spec timing to "pdram_timing"
+ * parameters:
+ * input: timing_config
+ * output: pdram_timing
+ */
+static void ddr3_get_parameter(struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ uint32_t nmhz = timing_config->freq;
+ uint32_t ddr_speed_bin = get_max_speed_rate(timing_config);
+ uint32_t ddr_capability_per_die = get_max_die_capability(timing_config);
+ uint32_t tmp;
+
+ // zeromem((void *)pdram_timing, sizeof(struct dram_timing_t));
+ pdram_timing->mhz = nmhz;
+ pdram_timing->al = 0;
+ pdram_timing->bl = timing_config->bl;
+ if (nmhz <= 330)
+ tmp = 0;
+ else if (nmhz <= 400)
+ tmp = 1;
+ else if (nmhz <= 533)
+ tmp = 2;
+ else if (nmhz <= 666)
+ tmp = 3;
+ else if (nmhz <= 800)
+ tmp = 4;
+ else if (nmhz <= 933)
+ tmp = 5;
+ else
+ tmp = 6;
+
+ /* when dll bypss cl = cwl = 6 */
+ if (nmhz < 300) {
+ pdram_timing->cl = 6;
+ pdram_timing->cwl = 6;
+ } else {
+ pdram_timing->cl = (ddr3_cl_cwl[ddr_speed_bin][tmp] >> 4) & 0xf;
+ pdram_timing->cwl = ddr3_cl_cwl[ddr_speed_bin][tmp] & 0xf;
+ }
+
+ switch (timing_config->dramds) {
+ case 40:
+ tmp = DDR3_DS_40;
+ break;
+ case 34:
+ default:
+ tmp = DDR3_DS_34;
+ break;
+ }
+
+ if (timing_config->odt)
+ switch (timing_config->dramodt) {
+ case 60:
+ pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_60;
+ break;
+ case 40:
+ pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_40;
+ break;
+ case 120:
+ pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_120;
+ break;
+ case 0:
+ default:
+ pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_DIS;
+ break;
+ }
+ else
+ pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_DIS;
+
+ pdram_timing->mr[2] = DDR3_MR2_CWL(pdram_timing->cwl);
+ pdram_timing->mr[3] = 0;
+
+ pdram_timing->trstl = ((DDR3_TRSTL * nmhz + 999) / 1000);
+ pdram_timing->trsth = ((DDR3_TRSTH * nmhz + 999) / 1000);
+ /* tREFI, average periodic refresh interval, 7.8us */
+ pdram_timing->trefi = ((DDR3_TREFI_7_8_US * nmhz + 999) / 1000);
+ /* base timing */
+ pdram_timing->trcd = pdram_timing->cl;
+ pdram_timing->trp = pdram_timing->cl;
+ pdram_timing->trppb = pdram_timing->cl;
+ tmp = ((DDR3_TWR * nmhz + 999) / 1000);
+ pdram_timing->twr = tmp;
+ pdram_timing->tdal = tmp + pdram_timing->trp;
+ if (tmp < 9) {
+ tmp = tmp - 4;
+ } else {
+ tmp += (tmp & 0x1) ? 1 : 0;
+ tmp = tmp >> 1;
+ }
+ if (pdram_timing->bl == 4)
+ pdram_timing->mr[0] = DDR3_BC4
+ | DDR3_CL(pdram_timing->cl)
+ | DDR3_WR(tmp);
+ else
+ pdram_timing->mr[0] = DDR3_BL8
+ | DDR3_CL(pdram_timing->cl)
+ | DDR3_WR(tmp);
+ tmp = ((DDR3_TRTP * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->trtp = max(4, tmp);
+ pdram_timing->trc =
+ (((ddr3_trc_tfaw[ddr_speed_bin] >> 8) * nmhz + 999) / 1000);
+ tmp = ((DDR3_TRRD * nmhz + 999) / 1000);
+ pdram_timing->trrd = max(4, tmp);
+ pdram_timing->tccd = DDR3_TCCD;
+ tmp = ((DDR3_TWTR * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->twtr = max(4, tmp);
+ pdram_timing->trtw = DDR3_TRTW;
+ pdram_timing->tras_max = 9 * pdram_timing->trefi;
+ pdram_timing->tras_min = ((DDR3_TRAS * nmhz + (nmhz >> 1) + 999)
+ / 1000);
+ pdram_timing->tfaw =
+ (((ddr3_trc_tfaw[ddr_speed_bin] & 0x0ff) * nmhz + 999)
+ / 1000);
+ /* tRFC, 90ns(512Mb),110ns(1Gb),160ns(2Gb),300ns(4Gb),350ns(8Gb) */
+ if (ddr_capability_per_die <= 0x4000000)
+ tmp = DDR3_TRFC_512MBIT;
+ else if (ddr_capability_per_die <= 0x8000000)
+ tmp = DDR3_TRFC_1GBIT;
+ else if (ddr_capability_per_die <= 0x10000000)
+ tmp = DDR3_TRFC_2GBIT;
+ else if (ddr_capability_per_die <= 0x20000000)
+ tmp = DDR3_TRFC_4GBIT;
+ else
+ tmp = DDR3_TRFC_8GBIT;
+ pdram_timing->trfc = (tmp * nmhz + 999) / 1000;
+ pdram_timing->txsnr = max(5, (((tmp + 10) * nmhz + 999) / 1000));
+ pdram_timing->tdqsck_max = 0;
+ /*pd and sr*/
+ pdram_timing->txsr = DDR3_TDLLK;
+ tmp = ((DDR3_TXP * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->txp = max(3, tmp);
+ tmp = ((DDR3_TXPDLL * nmhz + 999) / 1000);
+ pdram_timing->txpdll = max(10, tmp);
+ pdram_timing->tdllk = DDR3_TDLLK;
+ if (nmhz >= 533)
+ tmp = ((DDR3_TCKE_533MHZ * nmhz + 999) / 1000);
+ else
+ tmp = ((DDR3_TCKE_400MHZ * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->tcke = max(3, tmp);
+ pdram_timing->tckesr = (pdram_timing->tcke + 1);
+ tmp = ((DDR3_TCKSRE * nmhz + 999) / 1000);
+ pdram_timing->tcksre = max(5, tmp);
+ pdram_timing->tcksrx = max(5, tmp);
+ /*mode register timing*/
+ tmp = ((DDR3_TMOD * nmhz + 999) / 1000);
+ pdram_timing->tmod = max(12, tmp);
+ pdram_timing->tmrd = DDR3_TMRD;
+ pdram_timing->tmrr = 0;
+ /*ODT*/
+ pdram_timing->todton = pdram_timing->cwl - 2;
+ /*ZQ*/
+ tmp = ((DDR3_TZQINIT * nmhz + 999) / 1000);
+ pdram_timing->tzqinit = max(512, tmp);
+ tmp = ((DDR3_TZQCS * nmhz + 999) / 1000);
+ pdram_timing->tzqcs = max(64, tmp);
+ tmp = ((DDR3_TZQOPER * nmhz + 999) / 1000);
+ pdram_timing->tzqoper = max(256, tmp);
+ /* write leveling */
+ pdram_timing->twlmrd = DDR3_TWLMRD;
+ pdram_timing->twldqsen = DDR3_TWLDQSEN;
+ pdram_timing->twlo = ((DDR3_TWLO * nmhz + (nmhz >> 1) + 999) / 1000);
+}
+
+#if 0
+
+#define LPDDR2_TINIT1 (100) /* ns */
+#define LPDDR2_TINIT2 (5) /* tCK */
+#define LPDDR2_TINIT3 (200000) /* 200us */
+#define LPDDR2_TINIT4 (1000) /* 1us */
+#define LPDDR2_TINIT5 (10000) /* 10us */
+#define LPDDR2_TRSTL (0) /* tCK */
+#define LPDDR2_TRSTH (500000) /* 500us */
+#define LPDDR2_TREFI_3_9_US (3900) /* 3.9us */
+#define LPDDR2_TREFI_7_8_US (7800) /* 7.8us */
+
+/* base timing */
+#define LPDDR2_TRCD (24) /* tRCD,15ns(Fast)18ns(Typ)24ns(Slow) */
+#define LPDDR2_TRP_PB (18) /* tRPpb,15ns(Fast)18ns(Typ)24ns(Slow) */
+#define LPDDR2_TRP_AB_8_BANK (21) /* tRPab,18ns(Fast)21ns(Typ)27ns(Slow) */
+#define LPDDR2_TWR (15) /* tWR, max(3tCK,15ns) */
+#define LPDDR2_TRTP (7) /* tRTP, max(2tCK, 7.5ns) */
+#define LPDDR2_TRRD (10) /* tRRD, max(2tCK,10ns) */
+#define LPDDR2_TCCD (2) /* tCK */
+#define LPDDR2_TWTR_GREAT_200MHZ (7) /* ns */
+#define LPDDR2_TWTR_LITTLE_200MHZ (10) /* ns */
+#define LPDDR2_TRTW (0) /* tCK */
+#define LPDDR2_TRAS_MAX (70000) /* 70us */
+#define LPDDR2_TRAS (42) /* tRAS, max(3tCK,42ns) */
+#define LPDDR2_TFAW_GREAT_200MHZ (50) /* max(8tCK,50ns) */
+#define LPDDR2_TFAW_LITTLE_200MHZ (60) /* max(8tCK,60ns) */
+#define LPDDR2_TRFC_8GBIT (210) /* ns */
+#define LPDDR2_TRFC_4GBIT (130) /* ns */
+#define LPDDR2_TDQSCK_MIN (2) /* tDQSCKmin, 2.5ns */
+#define LPDDR2_TDQSCK_MAX (5) /* tDQSCKmax, 5.5ns */
+
+/*pd and sr*/
+#define LPDDR2_TXP (7) /* tXP, max(2tCK,7.5ns) */
+#define LPDDR2_TXPDLL (0)
+#define LPDDR2_TDLLK (0) /* tCK */
+#define LPDDR2_TCKE (3) /* tCK */
+#define LPDDR2_TCKESR (15) /* tCKESR, max(3tCK,15ns) */
+#define LPDDR2_TCKSRE (1) /* tCK */
+#define LPDDR2_TCKSRX (2) /* tCK */
+
+/*mode register timing*/
+#define LPDDR2_TMOD (0)
+#define LPDDR2_TMRD (5) /* tMRD, (=tMRW), 5 tCK */
+#define LPDDR2_TMRR (2) /* tCK */
+
+/*ZQ*/
+#define LPDDR2_TZQINIT (1000) /* ns */
+#define LPDDR2_TZQCS (90) /* tZQCS, max(6tCK,90ns) */
+#define LPDDR2_TZQCL (360) /* tZQCL, max(6tCK,360ns) */
+#define LPDDR2_TZQRESET (50) /* ZQreset, max(3tCK,50ns) */
+
+/*
+ * Description: depend on input parameter "timing_config",
+ * and calculate all lpddr2
+ * spec timing to "pdram_timing"
+ * parameters:
+ * input: timing_config
+ * output: pdram_timing
+ */
+static void lpddr2_get_parameter(struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ uint32_t nmhz = timing_config->freq;
+ uint32_t ddr_capability_per_die = get_max_die_capability(timing_config);
+ uint32_t tmp, trp_tmp, trppb_tmp, tras_tmp, twr_tmp, bl_tmp;
+
+ // zeromem((void *)pdram_timing, sizeof(struct dram_timing_t));
+ pdram_timing->mhz = nmhz;
+ pdram_timing->al = 0;
+ pdram_timing->bl = timing_config->bl;
+
+ /* 1066 933 800 667 533 400 333
+ * RL, 8 7 6 5 4 3 3
+ * WL, 4 4 3 2 2 1 1
+ */
+ if (nmhz <= 266) {
+ pdram_timing->cl = 4;
+ pdram_timing->cwl = 2;
+ pdram_timing->mr[2] = LPDDR2_RL4_WL2;
+ } else if (nmhz <= 333) {
+ pdram_timing->cl = 5;
+ pdram_timing->cwl = 2;
+ pdram_timing->mr[2] = LPDDR2_RL5_WL2;
+ } else if (nmhz <= 400) {
+ pdram_timing->cl = 6;
+ pdram_timing->cwl = 3;
+ pdram_timing->mr[2] = LPDDR2_RL6_WL3;
+ } else if (nmhz <= 466) {
+ pdram_timing->cl = 7;
+ pdram_timing->cwl = 4;
+ pdram_timing->mr[2] = LPDDR2_RL7_WL4;
+ } else {
+ pdram_timing->cl = 8;
+ pdram_timing->cwl = 4;
+ pdram_timing->mr[2] = LPDDR2_RL8_WL4;
+ }
+ switch (timing_config->dramds) {
+ case 120:
+ pdram_timing->mr[3] = LPDDR2_DS_120;
+ break;
+ case 80:
+ pdram_timing->mr[3] = LPDDR2_DS_80;
+ break;
+ case 60:
+ pdram_timing->mr[3] = LPDDR2_DS_60;
+ break;
+ case 48:
+ pdram_timing->mr[3] = LPDDR2_DS_48;
+ break;
+ case 40:
+ pdram_timing->mr[3] = LPDDR2_DS_40;
+ break;
+ case 34:
+ default:
+ pdram_timing->mr[3] = LPDDR2_DS_34;
+ break;
+ }
+ pdram_timing->mr[0] = 0;
+
+ pdram_timing->tinit1 = (LPDDR2_TINIT1 * nmhz + 999) / 1000;
+ pdram_timing->tinit2 = LPDDR2_TINIT2;
+ pdram_timing->tinit3 = (LPDDR2_TINIT3 * nmhz + 999) / 1000;
+ pdram_timing->tinit4 = (LPDDR2_TINIT4 * nmhz + 999) / 1000;
+ pdram_timing->tinit5 = (LPDDR2_TINIT5 * nmhz + 999) / 1000;
+ pdram_timing->trstl = LPDDR2_TRSTL;
+ pdram_timing->trsth = (LPDDR2_TRSTH * nmhz + 999) / 1000;
+ /*
+ * tREFI, average periodic refresh interval,
+ * 15.6us(<256Mb) 7.8us(256Mb-1Gb) 3.9us(2Gb-8Gb)
+ */
+ if (ddr_capability_per_die >= 0x10000000)
+ pdram_timing->trefi = (LPDDR2_TREFI_3_9_US * nmhz + 999)
+ / 1000;
+ else
+ pdram_timing->trefi = (LPDDR2_TREFI_7_8_US * nmhz + 999)
+ / 1000;
+ /* base timing */
+ tmp = ((LPDDR2_TRCD * nmhz + 999) / 1000);
+ pdram_timing->trcd = max(3, tmp);
+ /*
+ * tRPpb, max(3tCK, 15ns(Fast) 18ns(Typ) 24ns(Slow),
+ */
+ trppb_tmp = ((LPDDR2_TRP_PB * nmhz + 999) / 1000);
+ trppb_tmp = max(3, trppb_tmp);
+ pdram_timing->trppb = trppb_tmp;
+ /*
+ * tRPab, max(3tCK, 4-bank:15ns(Fast) 18ns(Typ) 24ns(Slow),
+ * 8-bank:18ns(Fast) 21ns(Typ) 27ns(Slow))
+ */
+ trp_tmp = ((LPDDR2_TRP_AB_8_BANK * nmhz + 999) / 1000);
+ trp_tmp = max(3, trp_tmp);
+ pdram_timing->trp = trp_tmp;
+ twr_tmp = ((LPDDR2_TWR * nmhz + 999) / 1000);
+ twr_tmp = max(3, twr_tmp);
+ pdram_timing->twr = twr_tmp;
+ bl_tmp = (pdram_timing->bl == 16) ? LPDDR2_BL16 :
+ ((pdram_timing->bl == 8) ? LPDDR2_BL8 : LPDDR2_BL4);
+ pdram_timing->mr[1] = bl_tmp | LPDDR2_N_WR(twr_tmp);
+ tmp = ((LPDDR2_TRTP * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->trtp = max(2, tmp);
+ tras_tmp = ((LPDDR2_TRAS * nmhz + 999) / 1000);
+ tras_tmp = max(3, tras_tmp);
+ pdram_timing->tras_min = tras_tmp;
+ pdram_timing->tras_max = ((LPDDR2_TRAS_MAX * nmhz + 999) / 1000);
+ pdram_timing->trc = (tras_tmp + trp_tmp);
+ tmp = ((LPDDR2_TRRD * nmhz + 999) / 1000);
+ pdram_timing->trrd = max(2, tmp);
+ pdram_timing->tccd = LPDDR2_TCCD;
+ /* tWTR, max(2tCK, 7.5ns(533-266MHz) 10ns(200-166MHz)) */
+ if (nmhz > 200)
+ tmp = ((LPDDR2_TWTR_GREAT_200MHZ * nmhz + (nmhz >> 1) +
+ 999) / 1000);
+ else
+ tmp = ((LPDDR2_TWTR_LITTLE_200MHZ * nmhz + 999) / 1000);
+ pdram_timing->twtr = max(2, tmp);
+ pdram_timing->trtw = LPDDR2_TRTW;
+ if (nmhz <= 200)
+ pdram_timing->tfaw = (LPDDR2_TFAW_LITTLE_200MHZ * nmhz + 999)
+ / 1000;
+ else
+ pdram_timing->tfaw = (LPDDR2_TFAW_GREAT_200MHZ * nmhz + 999)
+ / 1000;
+ /* tRFC, 90ns(<=512Mb) 130ns(1Gb-4Gb) 210ns(8Gb) */
+ if (ddr_capability_per_die >= 0x40000000) {
+ pdram_timing->trfc =
+ (LPDDR2_TRFC_8GBIT * nmhz + 999) / 1000;
+ tmp = (((LPDDR2_TRFC_8GBIT + 10) * nmhz + 999) / 1000);
+ } else {
+ pdram_timing->trfc =
+ (LPDDR2_TRFC_4GBIT * nmhz + 999) / 1000;
+ tmp = (((LPDDR2_TRFC_4GBIT + 10) * nmhz + 999) / 1000);
+ }
+ if (tmp < 2)
+ tmp = 2;
+ pdram_timing->txsr = tmp;
+ pdram_timing->txsnr = tmp;
+ /* tdqsck use rounded down */
+ pdram_timing->tdqsck = ((LPDDR2_TDQSCK_MIN * nmhz + (nmhz >> 1))
+ / 1000);
+ pdram_timing->tdqsck_max =
+ ((LPDDR2_TDQSCK_MAX * nmhz + (nmhz >> 1) + 999)
+ / 1000);
+ /* pd and sr */
+ tmp = ((LPDDR2_TXP * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->txp = max(2, tmp);
+ pdram_timing->txpdll = LPDDR2_TXPDLL;
+ pdram_timing->tdllk = LPDDR2_TDLLK;
+ pdram_timing->tcke = LPDDR2_TCKE;
+ tmp = ((LPDDR2_TCKESR * nmhz + 999) / 1000);
+ pdram_timing->tckesr = max(3, tmp);
+ pdram_timing->tcksre = LPDDR2_TCKSRE;
+ pdram_timing->tcksrx = LPDDR2_TCKSRX;
+ /* mode register timing */
+ pdram_timing->tmod = LPDDR2_TMOD;
+ pdram_timing->tmrd = LPDDR2_TMRD;
+ pdram_timing->tmrr = LPDDR2_TMRR;
+ /* ZQ */
+ pdram_timing->tzqinit = (LPDDR2_TZQINIT * nmhz + 999) / 1000;
+ tmp = ((LPDDR2_TZQCS * nmhz + 999) / 1000);
+ pdram_timing->tzqcs = max(6, tmp);
+ tmp = ((LPDDR2_TZQCL * nmhz + 999) / 1000);
+ pdram_timing->tzqoper = max(6, tmp);
+ tmp = ((LPDDR2_TZQRESET * nmhz + 999) / 1000);
+ pdram_timing->tzqreset = max(3, tmp);
+}
+
+#define LPDDR3_TINIT1 (100) /* ns */
+#define LPDDR3_TINIT2 (5) /* tCK */
+#define LPDDR3_TINIT3 (200000) /* 200us */
+#define LPDDR3_TINIT4 (1000) /* 1us */
+#define LPDDR3_TINIT5 (10000) /* 10us */
+#define LPDDR3_TRSTL (0)
+#define LPDDR3_TRSTH (0) /* 500us */
+#define LPDDR3_TREFI_3_9_US (3900) /* 3.9us */
+
+/* base timging */
+#define LPDDR3_TRCD (18) /* tRCD,15ns(Fast)18ns(Typ)24ns(Slow) */
+#define LPDDR3_TRP_PB (18) /* tRPpb, 15ns(Fast) 18ns(Typ) 24ns(Slow) */
+#define LPDDR3_TRP_AB (21) /* tRPab, 18ns(Fast) 21ns(Typ) 27ns(Slow) */
+#define LPDDR3_TWR (15) /* tWR, max(4tCK,15ns) */
+#define LPDDR3_TRTP (7) /* tRTP, max(4tCK, 7.5ns) */
+#define LPDDR3_TRRD (10) /* tRRD, max(2tCK,10ns) */
+#define LPDDR3_TCCD (4) /* tCK */
+#define LPDDR3_TWTR (7) /* tWTR, max(4tCK, 7.5ns) */
+#define LPDDR3_TRTW (0) /* tCK register min valid value */
+#define LPDDR3_TRAS_MAX (70000) /* 70us */
+#define LPDDR3_TRAS (42) /* tRAS, max(3tCK,42ns) */
+#define LPDDR3_TFAW (50) /* tFAW,max(8tCK, 50ns) */
+#define LPDDR3_TRFC_8GBIT (210) /* tRFC, 130ns(4Gb) 210ns(>4Gb) */
+#define LPDDR3_TRFC_4GBIT (130) /* ns */
+#define LPDDR3_TDQSCK_MIN (2) /* tDQSCKmin,2.5ns */
+#define LPDDR3_TDQSCK_MAX (5) /* tDQSCKmax,5.5ns */
+
+/* pd and sr */
+#define LPDDR3_TXP (7) /* tXP, max(3tCK,7.5ns) */
+#define LPDDR3_TXPDLL (0)
+#define LPDDR3_TCKE (7) /* tCKE, (max 7.5ns,3 tCK) */
+#define LPDDR3_TCKESR (15) /* tCKESR, max(3tCK,15ns) */
+#define LPDDR3_TCKSRE (2) /* tCKSRE=tCPDED, 2 tCK */
+#define LPDDR3_TCKSRX (2) /* tCKSRX, 2 tCK */
+
+/* mode register timing */
+#define LPDDR3_TMOD (0)
+#define LPDDR3_TMRD (14) /* tMRD, (=tMRW), max(14ns, 10 tCK) */
+#define LPDDR3_TMRR (4) /* tMRR, 4 tCK */
+#define LPDDR3_TMRRI LPDDR3_TRCD
+
+/* ODT */
+#define LPDDR3_TODTON (3) /* 3.5ns */
+
+/* ZQ */
+#define LPDDR3_TZQINIT (1000) /* 1us */
+#define LPDDR3_TZQCS (90) /* tZQCS, 90ns */
+#define LPDDR3_TZQCL (360) /* 360ns */
+#define LPDDR3_TZQRESET (50) /* ZQreset, max(3tCK,50ns) */
+/* write leveling */
+#define LPDDR3_TWLMRD (40) /* ns */
+#define LPDDR3_TWLO (20) /* ns */
+#define LPDDR3_TWLDQSEN (25) /* ns */
+/* CA training */
+#define LPDDR3_TCACKEL (10) /* tCK */
+#define LPDDR3_TCAENT (10) /* tCK */
+#define LPDDR3_TCAMRD (20) /* tCK */
+#define LPDDR3_TCACKEH (10) /* tCK */
+#define LPDDR3_TCAEXT (10) /* tCK */
+#define LPDDR3_TADR (20) /* ns */
+#define LPDDR3_TMRZ (3) /* ns */
+
+/* FSP */
+#define LPDDR3_TFC_LONG (250) /* ns */
+
+/*
+ * Description: depend on input parameter "timing_config",
+ * and calculate all lpddr3
+ * spec timing to "pdram_timing"
+ * parameters:
+ * input: timing_config
+ * output: pdram_timing
+ */
+static void lpddr3_get_parameter(struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ uint32_t nmhz = timing_config->freq;
+ uint32_t ddr_capability_per_die = get_max_die_capability(timing_config);
+ uint32_t tmp, trp_tmp, trppb_tmp, tras_tmp, twr_tmp, bl_tmp;
+
+ // zeromem((void *)pdram_timing, sizeof(struct dram_timing_t));
+ pdram_timing->mhz = nmhz;
+ pdram_timing->al = 0;
+ pdram_timing->bl = timing_config->bl;
+
+ /*
+ * Only support Write Latency Set A here
+ * 1066 933 800 733 667 600 533 400 166
+ * RL, 16 14 12 11 10 9 8 6 3
+ * WL, 8 8 6 6 6 5 4 3 1
+ */
+ if (nmhz <= 400) {
+ pdram_timing->cl = 6;
+ pdram_timing->cwl = 3;
+ pdram_timing->mr[2] = LPDDR3_RL6_WL3;
+ } else if (nmhz <= 533) {
+ pdram_timing->cl = 8;
+ pdram_timing->cwl = 4;
+ pdram_timing->mr[2] = LPDDR3_RL8_WL4;
+ } else if (nmhz <= 600) {
+ pdram_timing->cl = 9;
+ pdram_timing->cwl = 5;
+ pdram_timing->mr[2] = LPDDR3_RL9_WL5;
+ } else if (nmhz <= 667) {
+ pdram_timing->cl = 10;
+ pdram_timing->cwl = 6;
+ pdram_timing->mr[2] = LPDDR3_RL10_WL6;
+ } else if (nmhz <= 733) {
+ pdram_timing->cl = 11;
+ pdram_timing->cwl = 6;
+ pdram_timing->mr[2] = LPDDR3_RL11_WL6;
+ } else if (nmhz <= 800) {
+ pdram_timing->cl = 12;
+ pdram_timing->cwl = 6;
+ pdram_timing->mr[2] = LPDDR3_RL12_WL6;
+ } else if (nmhz <= 933) {
+ pdram_timing->cl = 14;
+ pdram_timing->cwl = 8;
+ pdram_timing->mr[2] = LPDDR3_RL14_WL8;
+ } else {
+ pdram_timing->cl = 16;
+ pdram_timing->cwl = 8;
+ pdram_timing->mr[2] = LPDDR3_RL16_WL8;
+ }
+ switch (timing_config->dramds) {
+ case 80:
+ pdram_timing->mr[3] = LPDDR3_DS_80;
+ break;
+ case 60:
+ pdram_timing->mr[3] = LPDDR3_DS_60;
+ break;
+ case 48:
+ pdram_timing->mr[3] = LPDDR3_DS_48;
+ break;
+ case 40:
+ pdram_timing->mr[3] = LPDDR3_DS_40;
+ break;
+ case 3440:
+ pdram_timing->mr[3] = LPDDR3_DS_34D_40U;
+ break;
+ case 4048:
+ pdram_timing->mr[3] = LPDDR3_DS_40D_48U;
+ break;
+ case 3448:
+ pdram_timing->mr[3] = LPDDR3_DS_34D_48U;
+ break;
+ case 34:
+ default:
+ pdram_timing->mr[3] = LPDDR3_DS_34;
+ break;
+ }
+ pdram_timing->mr[0] = 0;
+ if (timing_config->odt)
+ switch (timing_config->dramodt) {
+ case 60:
+ pdram_timing->mr11 = LPDDR3_ODT_60;
+ break;
+ case 120:
+ pdram_timing->mr11 = LPDDR3_ODT_120;
+ break;
+ case 240:
+ default:
+ pdram_timing->mr11 = LPDDR3_ODT_240;
+ break;
+ }
+ else
+ pdram_timing->mr11 = LPDDR3_ODT_DIS;
+
+ pdram_timing->tinit1 = (LPDDR3_TINIT1 * nmhz + 999) / 1000;
+ pdram_timing->tinit2 = LPDDR3_TINIT2;
+ pdram_timing->tinit3 = (LPDDR3_TINIT3 * nmhz + 999) / 1000;
+ pdram_timing->tinit4 = (LPDDR3_TINIT4 * nmhz + 999) / 1000;
+ pdram_timing->tinit5 = (LPDDR3_TINIT5 * nmhz + 999) / 1000;
+ pdram_timing->trstl = LPDDR3_TRSTL;
+ pdram_timing->trsth = (LPDDR3_TRSTH * nmhz + 999) / 1000;
+ /* tREFI, average periodic refresh interval, 3.9us(4Gb-16Gb) */
+ pdram_timing->trefi = (LPDDR3_TREFI_3_9_US * nmhz + 999) / 1000;
+ /* base timing */
+ tmp = ((LPDDR3_TRCD * nmhz + 999) / 1000);
+ pdram_timing->trcd = max(3, tmp);
+ trppb_tmp = ((LPDDR3_TRP_PB * nmhz + 999) / 1000);
+ trppb_tmp = max(3, trppb_tmp);
+ pdram_timing->trppb = trppb_tmp;
+ trp_tmp = ((LPDDR3_TRP_AB * nmhz + 999) / 1000);
+ trp_tmp = max(3, trp_tmp);
+ pdram_timing->trp = trp_tmp;
+ twr_tmp = ((LPDDR3_TWR * nmhz + 999) / 1000);
+ twr_tmp = max(4, twr_tmp);
+ pdram_timing->twr = twr_tmp;
+ if (twr_tmp <= 6)
+ twr_tmp = 6;
+ else if (twr_tmp <= 8)
+ twr_tmp = 8;
+ else if (twr_tmp <= 12)
+ twr_tmp = twr_tmp;
+ else if (twr_tmp <= 14)
+ twr_tmp = 14;
+ else
+ twr_tmp = 16;
+ if (twr_tmp > 9)
+ pdram_timing->mr[2] |= (1 << 4); /*enable nWR > 9*/
+ twr_tmp = (twr_tmp > 9) ? (twr_tmp - 10) : (twr_tmp - 2);
+ bl_tmp = LPDDR3_BL8;
+ pdram_timing->mr[1] = bl_tmp | LPDDR3_N_WR(twr_tmp);
+ tmp = ((LPDDR3_TRTP * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->trtp = max(4, tmp);
+ tras_tmp = ((LPDDR3_TRAS * nmhz + 999) / 1000);
+ tras_tmp = max(3, tras_tmp);
+ pdram_timing->tras_min = tras_tmp;
+ pdram_timing->trc = (tras_tmp + trp_tmp);
+ tmp = ((LPDDR3_TRRD * nmhz + 999) / 1000);
+ pdram_timing->trrd = max(2, tmp);
+ pdram_timing->tccd = LPDDR3_TCCD;
+ tmp = ((LPDDR3_TWTR * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->twtr = max(4, tmp);
+ pdram_timing->trtw = ((LPDDR3_TRTW * nmhz + 999) / 1000);
+ pdram_timing->tras_max = ((LPDDR3_TRAS_MAX * nmhz + 999) / 1000);
+ tmp = (LPDDR3_TFAW * nmhz + 999) / 1000;
+ pdram_timing->tfaw = max(8, tmp);
+ if (ddr_capability_per_die > 0x20000000) {
+ pdram_timing->trfc =
+ (LPDDR3_TRFC_8GBIT * nmhz + 999) / 1000;
+ tmp = (((LPDDR3_TRFC_8GBIT + 10) * nmhz + 999) / 1000);
+ } else {
+ pdram_timing->trfc =
+ (LPDDR3_TRFC_4GBIT * nmhz + 999) / 1000;
+ tmp = (((LPDDR3_TRFC_4GBIT + 10) * nmhz + 999) / 1000);
+ }
+ pdram_timing->txsr = max(2, tmp);
+ pdram_timing->txsnr = max(2, tmp);
+ /* tdqsck use rounded down */
+ pdram_timing->tdqsck =
+ ((LPDDR3_TDQSCK_MIN * nmhz + (nmhz >> 1))
+ / 1000);
+ pdram_timing->tdqsck_max =
+ ((LPDDR3_TDQSCK_MAX * nmhz + (nmhz >> 1) + 999)
+ / 1000);
+ /*pd and sr*/
+ tmp = ((LPDDR3_TXP * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->txp = max(3, tmp);
+ pdram_timing->txpdll = LPDDR3_TXPDLL;
+ tmp = ((LPDDR3_TCKE * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->tcke = max(3, tmp);
+ tmp = ((LPDDR3_TCKESR * nmhz + 999) / 1000);
+ pdram_timing->tckesr = max(3, tmp);
+ pdram_timing->tcksre = LPDDR3_TCKSRE;
+ pdram_timing->tcksrx = LPDDR3_TCKSRX;
+ /*mode register timing*/
+ pdram_timing->tmod = LPDDR3_TMOD;
+ tmp = ((LPDDR3_TMRD * nmhz + 999) / 1000);
+ pdram_timing->tmrd = max(10, tmp);
+ pdram_timing->tmrr = LPDDR3_TMRR;
+ tmp = ((LPDDR3_TRCD * nmhz + 999) / 1000);
+ pdram_timing->tmrri = max(3, tmp);
+ /* ODT */
+ pdram_timing->todton = (LPDDR3_TODTON * nmhz + (nmhz >> 1) + 999)
+ / 1000;
+ /* ZQ */
+ pdram_timing->tzqinit = (LPDDR3_TZQINIT * nmhz + 999) / 1000;
+ pdram_timing->tzqcs =
+ ((LPDDR3_TZQCS * nmhz + 999) / 1000);
+ pdram_timing->tzqoper =
+ ((LPDDR3_TZQCL * nmhz + 999) / 1000);
+ tmp = ((LPDDR3_TZQRESET * nmhz + 999) / 1000);
+ pdram_timing->tzqreset = max(3, tmp);
+ /* write leveling */
+ pdram_timing->twlmrd = (LPDDR3_TWLMRD * nmhz + 999) / 1000;
+ pdram_timing->twlo = (LPDDR3_TWLO * nmhz + 999) / 1000;
+ pdram_timing->twldqsen = (LPDDR3_TWLDQSEN * nmhz + 999) / 1000;
+ /* CA training */
+ pdram_timing->tcackel = LPDDR3_TCACKEL;
+ pdram_timing->tcaent = LPDDR3_TCAENT;
+ pdram_timing->tcamrd = LPDDR3_TCAMRD;
+ pdram_timing->tcackeh = LPDDR3_TCACKEH;
+ pdram_timing->tcaext = LPDDR3_TCAEXT;
+ pdram_timing->tadr = (LPDDR3_TADR * nmhz + 999) / 1000;
+ pdram_timing->tmrz = (LPDDR3_TMRZ * nmhz + 999) / 1000;
+ pdram_timing->tcacd = pdram_timing->tadr + 2;
+
+ /* FSP */
+ pdram_timing->tfc_long = (LPDDR3_TFC_LONG * nmhz + 999) / 1000;
+}
+
+#define LPDDR4_TINIT1 (200000) /* 200us */
+#define LPDDR4_TINIT2 (10) /* 10ns */
+#define LPDDR4_TINIT3 (2000000) /* 2ms */
+#define LPDDR4_TINIT4 (5) /* tCK */
+#define LPDDR4_TINIT5 (2000) /* 2us */
+#define LPDDR4_TRSTL LPDDR4_TINIT1
+#define LPDDR4_TRSTH LPDDR4_TINIT3
+#define LPDDR4_TREFI_3_9_US (3900) /* 3.9us */
+
+/* base timging */
+#define LPDDR4_TRCD (18) /* tRCD, max(18ns,4tCK) */
+#define LPDDR4_TRP_PB (18) /* tRPpb, max(18ns, 4tCK) */
+#define LPDDR4_TRP_AB (21) /* tRPab, max(21ns, 4tCK) */
+#define LPDDR4_TRRD (10) /* tRRD, max(4tCK,10ns) */
+#define LPDDR4_TCCD_BL16 (8) /* tCK */
+#define LPDDR4_TCCD_BL32 (16) /* tCK */
+#define LPDDR4_TWTR (10) /* tWTR, max(8tCK, 10ns) */
+#define LPDDR4_TRTW (0) /* tCK register min valid value */
+#define LPDDR4_TRAS_MAX (70000) /* 70us */
+#define LPDDR4_TRAS (42) /* tRAS, max(3tCK,42ns) */
+#define LPDDR4_TFAW (40) /* tFAW,min 40ns) */
+#define LPDDR4_TRFC_12GBIT (280) /* tRFC, 280ns(>=12Gb) */
+#define LPDDR4_TRFC_6GBIT (180) /* 6Gb/8Gb 180ns */
+#define LPDDR4_TRFC_4GBIT (130) /* 4Gb 130ns */
+#define LPDDR4_TDQSCK_MIN (1) /* tDQSCKmin,1.5ns */
+#define LPDDR4_TDQSCK_MAX (3) /* tDQSCKmax,3.5ns */
+#define LPDDR4_TPPD (4) /* tCK */
+
+/* pd and sr */
+#define LPDDR4_TXP (7) /* tXP, max(5tCK,7.5ns) */
+#define LPDDR4_TCKE (7) /* tCKE, max(7.5ns,4 tCK) */
+#define LPDDR4_TESCKE (1) /* tESCKE, max(1.75ns, 3tCK) */
+#define LPDDR4_TSR (15) /* tSR, max(15ns, 3tCK) */
+#define LPDDR4_TCMDCKE (1) /* max(1.75ns, 3tCK) */
+#define LPDDR4_TCSCKE (1) /* 1.75ns */
+#define LPDDR4_TCKELCS (5) /* max(5ns, 5tCK) */
+#define LPDDR4_TCSCKEH (1) /* 1.75ns */
+#define LPDDR4_TCKEHCS (7) /* max(7.5ns, 5tCK) */
+#define LPDDR4_TMRWCKEL (14) /* max(14ns, 10tCK) */
+#define LPDDR4_TCKELCMD (7) /* max(7.5ns, 3tCK) */
+#define LPDDR4_TCKEHCMD (7) /* max(7.5ns, 3tCK) */
+#define LPDDR4_TCKELPD (7) /* max(7.5ns, 3tCK) */
+#define LPDDR4_TCKCKEL (7) /* max(7.5ns, 3tCK) */
+
+/* mode register timing */
+#define LPDDR4_TMRD (14) /* tMRD, (=tMRW), max(14ns, 10 tCK) */
+#define LPDDR4_TMRR (8) /* tMRR, 8 tCK */
+
+/* ODT */
+#define LPDDR4_TODTON (3) /* 3.5ns */
+
+/* ZQ */
+#define LPDDR4_TZQCAL (1000) /* 1us */
+#define LPDDR4_TZQLAT (30) /* tZQLAT, max(30ns,8tCK) */
+#define LPDDR4_TZQRESET (50) /* ZQreset, max(3tCK,50ns) */
+#define LPDDR4_TZQCKE (1) /* tZQCKE, max(1.75ns, 3tCK) */
+
+/* write leveling */
+#define LPDDR4_TWLMRD (40) /* tCK */
+#define LPDDR4_TWLO (20) /* ns */
+#define LPDDR4_TWLDQSEN (20) /* tCK */
+
+/* CA training */
+#define LPDDR4_TCAENT (250) /* ns */
+#define LPDDR4_TADR (20) /* ns */
+#define LPDDR4_TMRZ (1) /* 1.5ns */
+#define LPDDR4_TVREF_LONG (250) /* ns */
+#define LPDDR4_TVREF_SHORT (100) /* ns */
+
+/* VRCG */
+#define LPDDR4_TVRCG_ENABLE (200) /* ns */
+#define LPDDR4_TVRCG_DISABLE (100) /* ns */
+
+/* FSP */
+#define LPDDR4_TFC_LONG (250) /* ns */
+#define LPDDR4_TCKFSPE (7) /* max(7.5ns, 4tCK) */
+#define LPDDR4_TCKFSPX (7) /* max(7.5ns, 4tCK) */
+
+/*
+ * Description: depend on input parameter "timing_config",
+ * and calculate all lpddr4
+ * spec timing to "pdram_timing"
+ * parameters:
+ * input: timing_config
+ * output: pdram_timing
+ */
+static void lpddr4_get_parameter(struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ uint32_t nmhz = timing_config->freq;
+ uint32_t ddr_capability_per_die = get_max_die_capability(timing_config);
+ uint32_t tmp, trp_tmp, trppb_tmp, tras_tmp;
+
+ // zeromem((void *)pdram_timing, sizeof(struct dram_timing_t));
+ pdram_timing->mhz = nmhz;
+ pdram_timing->al = 0;
+ pdram_timing->bl = timing_config->bl;
+
+ /*
+ * Only support Write Latency Set A here
+ * 2133 1866 1600 1333 1066 800 533 266
+ * RL, 36 32 28 24 20 14 10 6
+ * WL, 18 16 14 12 10 8 6 4
+ * nWR, 40 34 30 24 20 16 10 6
+ * nRTP,16 14 12 10 8 8 8 8
+ */
+ tmp = (timing_config->bl == 32) ? 1 : 0;
+
+ /*
+ * we always use WR preamble = 2tCK
+ * RD preamble = Static
+ */
+ tmp |= (1 << 2);
+ if (nmhz <= 266) {
+ pdram_timing->cl = 6;
+ pdram_timing->cwl = 4;
+ pdram_timing->twr = 6;
+ pdram_timing->trtp = 8;
+ pdram_timing->mr[2] = LPDDR4_RL6_NRTP8 | LPDDR4_A_WL4;
+ } else if (nmhz <= 533) {
+ if (timing_config->rdbi) {
+ pdram_timing->cl = 12;
+ pdram_timing->mr[2] = LPDDR4_RL12_NRTP8 | LPDDR4_A_WL6;
+ } else {
+ pdram_timing->cl = 10;
+ pdram_timing->mr[2] = LPDDR4_RL10_NRTP8 | LPDDR4_A_WL6;
+ }
+ pdram_timing->cwl = 6;
+ pdram_timing->twr = 10;
+ pdram_timing->trtp = 8;
+ tmp |= (1 << 4);
+ } else if (nmhz <= 800) {
+ if (timing_config->rdbi) {
+ pdram_timing->cl = 16;
+ pdram_timing->mr[2] = LPDDR4_RL16_NRTP8 | LPDDR4_A_WL8;
+ } else {
+ pdram_timing->cl = 14;
+ pdram_timing->mr[2] = LPDDR4_RL14_NRTP8 | LPDDR4_A_WL8;
+ }
+ pdram_timing->cwl = 8;
+ pdram_timing->twr = 16;
+ pdram_timing->trtp = 8;
+ tmp |= (2 << 4);
+ } else if (nmhz <= 1066) {
+ if (timing_config->rdbi) {
+ pdram_timing->cl = 22;
+ pdram_timing->mr[2] = LPDDR4_RL22_NRTP8 | LPDDR4_A_WL10;
+ } else {
+ pdram_timing->cl = 20;
+ pdram_timing->mr[2] = LPDDR4_RL20_NRTP8 | LPDDR4_A_WL10;
+ }
+ pdram_timing->cwl = 10;
+ pdram_timing->twr = 20;
+ pdram_timing->trtp = 8;
+ tmp |= (3 << 4);
+ } else if (nmhz <= 1333) {
+ if (timing_config->rdbi) {
+ pdram_timing->cl = 28;
+ pdram_timing->mr[2] = LPDDR4_RL28_NRTP10 |
+ LPDDR4_A_WL12;
+ } else {
+ pdram_timing->cl = 24;
+ pdram_timing->mr[2] = LPDDR4_RL24_NRTP10 |
+ LPDDR4_A_WL12;
+ }
+ pdram_timing->cwl = 12;
+ pdram_timing->twr = 24;
+ pdram_timing->trtp = 10;
+ tmp |= (4 << 4);
+ } else if (nmhz <= 1600) {
+ if (timing_config->rdbi) {
+ pdram_timing->cl = 32;
+ pdram_timing->mr[2] = LPDDR4_RL32_NRTP12 |
+ LPDDR4_A_WL14;
+ } else {
+ pdram_timing->cl = 28;
+ pdram_timing->mr[2] = LPDDR4_RL28_NRTP12 |
+ LPDDR4_A_WL14;
+ }
+ pdram_timing->cwl = 14;
+ pdram_timing->twr = 30;
+ pdram_timing->trtp = 12;
+ tmp |= (5 << 4);
+ } else if (nmhz <= 1866) {
+ if (timing_config->rdbi) {
+ pdram_timing->cl = 36;
+ pdram_timing->mr[2] = LPDDR4_RL36_NRTP14 |
+ LPDDR4_A_WL16;
+ } else {
+ pdram_timing->cl = 32;
+ pdram_timing->mr[2] = LPDDR4_RL32_NRTP14 |
+ LPDDR4_A_WL16;
+ }
+ pdram_timing->cwl = 16;
+ pdram_timing->twr = 34;
+ pdram_timing->trtp = 14;
+ tmp |= (6 << 4);
+ } else {
+ if (timing_config->rdbi) {
+ pdram_timing->cl = 40;
+ pdram_timing->mr[2] = LPDDR4_RL40_NRTP16 |
+ LPDDR4_A_WL18;
+ } else {
+ pdram_timing->cl = 36;
+ pdram_timing->mr[2] = LPDDR4_RL36_NRTP16 |
+ LPDDR4_A_WL18;
+ }
+ pdram_timing->cwl = 18;
+ pdram_timing->twr = 40;
+ pdram_timing->trtp = 16;
+ tmp |= (7 << 4);
+ }
+ pdram_timing->mr[1] = tmp;
+ tmp = (timing_config->rdbi ? LPDDR4_DBI_RD_EN : 0) |
+ (timing_config->wdbi ? LPDDR4_DBI_WR_EN : 0);
+ switch (timing_config->dramds) {
+ case 240:
+ pdram_timing->mr[3] = LPDDR4_PDDS_240 | tmp;
+ break;
+ case 120:
+ pdram_timing->mr[3] = LPDDR4_PDDS_120 | tmp;
+ break;
+ case 80:
+ pdram_timing->mr[3] = LPDDR4_PDDS_80 | tmp;
+ break;
+ case 60:
+ pdram_timing->mr[3] = LPDDR4_PDDS_60 | tmp;
+ break;
+ case 48:
+ pdram_timing->mr[3] = LPDDR4_PDDS_48 | tmp;
+ break;
+ case 40:
+ default:
+ pdram_timing->mr[3] = LPDDR4_PDDS_40 | tmp;
+ break;
+ }
+ pdram_timing->mr[0] = 0;
+ if (timing_config->odt) {
+ switch (timing_config->dramodt) {
+ case 240:
+ tmp = LPDDR4_DQODT_240;
+ break;
+ case 120:
+ tmp = LPDDR4_DQODT_120;
+ break;
+ case 80:
+ tmp = LPDDR4_DQODT_80;
+ break;
+ case 60:
+ tmp = LPDDR4_DQODT_60;
+ break;
+ case 48:
+ tmp = LPDDR4_DQODT_48;
+ break;
+ case 40:
+ default:
+ tmp = LPDDR4_DQODT_40;
+ break;
+ }
+
+ switch (timing_config->caodt) {
+ case 240:
+ pdram_timing->mr11 = LPDDR4_CAODT_240 | tmp;
+ break;
+ case 120:
+ pdram_timing->mr11 = LPDDR4_CAODT_120 | tmp;
+ break;
+ case 80:
+ pdram_timing->mr11 = LPDDR4_CAODT_80 | tmp;
+ break;
+ case 60:
+ pdram_timing->mr11 = LPDDR4_CAODT_60 | tmp;
+ break;
+ case 48:
+ pdram_timing->mr11 = LPDDR4_CAODT_48 | tmp;
+ break;
+ case 40:
+ default:
+ pdram_timing->mr11 = LPDDR4_CAODT_40 | tmp;
+ break;
+ }
+ } else {
+ pdram_timing->mr11 = LPDDR4_CAODT_DIS | tmp;
+ }
+
+ pdram_timing->tinit1 = (LPDDR4_TINIT1 * nmhz + 999) / 1000;
+ pdram_timing->tinit2 = (LPDDR4_TINIT2 * nmhz + 999) / 1000;
+ pdram_timing->tinit3 = (LPDDR4_TINIT3 * nmhz + 999) / 1000;
+ pdram_timing->tinit4 = (LPDDR4_TINIT4 * nmhz + 999) / 1000;
+ pdram_timing->tinit5 = (LPDDR4_TINIT5 * nmhz + 999) / 1000;
+ pdram_timing->trstl = (LPDDR4_TRSTL * nmhz + 999) / 1000;
+ pdram_timing->trsth = (LPDDR4_TRSTH * nmhz + 999) / 1000;
+ /* tREFI, average periodic refresh interval, 3.9us(4Gb-16Gb) */
+ pdram_timing->trefi = (LPDDR4_TREFI_3_9_US * nmhz + 999) / 1000;
+ /* base timing */
+ tmp = ((LPDDR4_TRCD * nmhz + 999) / 1000);
+ pdram_timing->trcd = max(4, tmp);
+ trppb_tmp = ((LPDDR4_TRP_PB * nmhz + 999) / 1000);
+ trppb_tmp = max(4, trppb_tmp);
+ pdram_timing->trppb = trppb_tmp;
+ trp_tmp = ((LPDDR4_TRP_AB * nmhz + 999) / 1000);
+ trp_tmp = max(4, trp_tmp);
+ pdram_timing->trp = trp_tmp;
+ tras_tmp = ((LPDDR4_TRAS * nmhz + 999) / 1000);
+ tras_tmp = max(3, tras_tmp);
+ pdram_timing->tras_min = tras_tmp;
+ pdram_timing->trc = (tras_tmp + trp_tmp);
+ tmp = ((LPDDR4_TRRD * nmhz + 999) / 1000);
+ pdram_timing->trrd = max(4, tmp);
+ if (timing_config->bl == 32)
+ pdram_timing->tccd = LPDDR4_TCCD_BL16;
+ else
+ pdram_timing->tccd = LPDDR4_TCCD_BL32;
+ pdram_timing->tccdmw = 4 * pdram_timing->tccd;
+ tmp = ((LPDDR4_TWTR * nmhz + 999) / 1000);
+ pdram_timing->twtr = max(8, tmp);
+ pdram_timing->trtw = ((LPDDR4_TRTW * nmhz + 999) / 1000);
+ pdram_timing->tras_max = ((LPDDR4_TRAS_MAX * nmhz + 999) / 1000);
+ pdram_timing->tfaw = (LPDDR4_TFAW * nmhz + 999) / 1000;
+ if (ddr_capability_per_die > 0x60000000) {
+ /* >= 12Gb */
+ pdram_timing->trfc =
+ (LPDDR4_TRFC_12GBIT * nmhz + 999) / 1000;
+ tmp = (((LPDDR4_TRFC_12GBIT + 7) * nmhz + (nmhz >> 1) +
+ 999) / 1000);
+ } else if (ddr_capability_per_die > 0x30000000) {
+ pdram_timing->trfc =
+ (LPDDR4_TRFC_6GBIT * nmhz + 999) / 1000;
+ tmp = (((LPDDR4_TRFC_6GBIT + 7) * nmhz + (nmhz >> 1) +
+ 999) / 1000);
+ } else {
+ pdram_timing->trfc =
+ (LPDDR4_TRFC_4GBIT * nmhz + 999) / 1000;
+ tmp = (((LPDDR4_TRFC_4GBIT + 7) * nmhz + (nmhz >> 1) +
+ 999) / 1000);
+ }
+ pdram_timing->txsr = max(2, tmp);
+ pdram_timing->txsnr = max(2, tmp);
+ /* tdqsck use rounded down */
+ pdram_timing->tdqsck = ((LPDDR4_TDQSCK_MIN * nmhz +
+ (nmhz >> 1)) / 1000);
+ pdram_timing->tdqsck_max = ((LPDDR4_TDQSCK_MAX * nmhz +
+ (nmhz >> 1) + 999) / 1000);
+ pdram_timing->tppd = LPDDR4_TPPD;
+ /* pd and sr */
+ tmp = ((LPDDR4_TXP * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->txp = max(5, tmp);
+ tmp = ((LPDDR4_TCKE * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->tcke = max(4, tmp);
+ tmp = ((LPDDR4_TESCKE * nmhz +
+ ((nmhz * 3) / 4) +
+ 999) / 1000);
+ pdram_timing->tescke = max(3, tmp);
+ tmp = ((LPDDR4_TSR * nmhz + 999) / 1000);
+ pdram_timing->tsr = max(3, tmp);
+ tmp = ((LPDDR4_TCMDCKE * nmhz +
+ ((nmhz * 3) / 4) +
+ 999) / 1000);
+ pdram_timing->tcmdcke = max(3, tmp);
+ pdram_timing->tcscke = ((LPDDR4_TCSCKE * nmhz +
+ ((nmhz * 3) / 4) +
+ 999) / 1000);
+ tmp = ((LPDDR4_TCKELCS * nmhz + 999) / 1000);
+ pdram_timing->tckelcs = max(5, tmp);
+ pdram_timing->tcsckeh = ((LPDDR4_TCSCKEH * nmhz +
+ ((nmhz * 3) / 4) +
+ 999) / 1000);
+ tmp = ((LPDDR4_TCKEHCS * nmhz +
+ (nmhz >> 1) + 999) / 1000);
+ pdram_timing->tckehcs = max(5, tmp);
+ tmp = ((LPDDR4_TMRWCKEL * nmhz + 999) / 1000);
+ pdram_timing->tmrwckel = max(10, tmp);
+ tmp = ((LPDDR4_TCKELCMD * nmhz + (nmhz >> 1) +
+ 999) / 1000);
+ pdram_timing->tckelcmd = max(3, tmp);
+ tmp = ((LPDDR4_TCKEHCMD * nmhz + (nmhz >> 1) +
+ 999) / 1000);
+ pdram_timing->tckehcmd = max(3, tmp);
+ tmp = ((LPDDR4_TCKELPD * nmhz + (nmhz >> 1) +
+ 999) / 1000);
+ pdram_timing->tckelpd = max(3, tmp);
+ tmp = ((LPDDR4_TCKCKEL * nmhz + (nmhz >> 1) +
+ 999) / 1000);
+ pdram_timing->tckckel = max(3, tmp);
+ /* mode register timing */
+ tmp = ((LPDDR4_TMRD * nmhz + 999) / 1000);
+ pdram_timing->tmrd = max(10, tmp);
+ pdram_timing->tmrr = LPDDR4_TMRR;
+ pdram_timing->tmrri = pdram_timing->trcd + 3;
+ /* ODT */
+ pdram_timing->todton = (LPDDR4_TODTON * nmhz + (nmhz >> 1) + 999)
+ / 1000;
+ /* ZQ */
+ pdram_timing->tzqcal = (LPDDR4_TZQCAL * nmhz + 999) / 1000;
+ tmp = ((LPDDR4_TZQLAT * nmhz + 999) / 1000);
+ pdram_timing->tzqlat = max(8, tmp);
+ tmp = ((LPDDR4_TZQRESET * nmhz + 999) / 1000);
+ pdram_timing->tzqreset = max(3, tmp);
+ tmp = ((LPDDR4_TZQCKE * nmhz +
+ ((nmhz * 3) / 4) +
+ 999) / 1000);
+ pdram_timing->tzqcke = max(3, tmp);
+ /* write leveling */
+ pdram_timing->twlmrd = LPDDR4_TWLMRD;
+ pdram_timing->twlo = (LPDDR4_TWLO * nmhz + 999) / 1000;
+ pdram_timing->twldqsen = LPDDR4_TWLDQSEN;
+ /* CA training */
+ pdram_timing->tcaent = (LPDDR4_TCAENT * nmhz + 999) / 1000;
+ pdram_timing->tadr = (LPDDR4_TADR * nmhz + 999) / 1000;
+ pdram_timing->tmrz = (LPDDR4_TMRZ * nmhz + (nmhz >> 1) + 999) / 1000;
+ pdram_timing->tvref_long = (LPDDR4_TVREF_LONG * nmhz + 999) / 1000;
+ pdram_timing->tvref_short = (LPDDR4_TVREF_SHORT * nmhz + 999) / 1000;
+ /* VRCG */
+ pdram_timing->tvrcg_enable = (LPDDR4_TVRCG_ENABLE * nmhz +
+ 999) / 1000;
+ pdram_timing->tvrcg_disable = (LPDDR4_TVRCG_DISABLE * nmhz +
+ 999) / 1000;
+ /* FSP */
+ pdram_timing->tfc_long = (LPDDR4_TFC_LONG * nmhz + 999) / 1000;
+ tmp = (LPDDR4_TCKFSPE * nmhz + (nmhz >> 1) + 999) / 1000;
+ pdram_timing->tckfspe = max(4, tmp);
+ tmp = (LPDDR4_TCKFSPX * nmhz + (nmhz >> 1) + 999) / 1000;
+ pdram_timing->tckfspx = max(4, tmp);
+}
+#endif
+
+/*
+ * Description: depend on input parameter "timing_config",
+ * and calculate correspond "dram_type"
+ * spec timing to "pdram_timing"
+ * parameters:
+ * input: timing_config
+ * output: pdram_timing
+ * NOTE: MR ODT is set, need to disable by controller
+ */
+void dram_get_parameter(struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ switch (timing_config->dram_type) {
+ case DDR3:
+ ddr3_get_parameter(timing_config, pdram_timing);
+ break;
+#if 0
+ case LPDDR2:
+ lpddr2_get_parameter(timing_config, pdram_timing);
+ break;
+ case LPDDR3:
+ lpddr3_get_parameter(timing_config, pdram_timing);
+ break;
+ case LPDDR4:
+ lpddr4_get_parameter(timing_config, pdram_timing);
+ break;
+#endif
+ }
+}
diff --git a/drivers/ram/rockchip/dram_spec_timing.h b/drivers/ram/rockchip/dram_spec_timing.h
new file mode 100644
index 0000000000..6eae4ca62b
--- /dev/null
+++ b/drivers/ram/rockchip/dram_spec_timing.h
@@ -0,0 +1,507 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _DRAM_SPEC_TIMING_HEAD_
+#define _DRAM_SPEC_TIMING_HEAD_
+// #include <stdint.h>
+
+enum ddr3_speed_rate {
+ /* 5-5-5 */
+ DDR3_800D = 0,
+ /* 6-6-6 */
+ DDR3_800E = 1,
+ /* 6-6-6 */
+ DDR3_1066E = 2,
+ /* 7-7-7 */
+ DDR3_1066F = 3,
+ /* 8-8-8 */
+ DDR3_1066G = 4,
+ /* 7-7-7 */
+ DDR3_1333F = 5,
+ /* 8-8-8 */
+ DDR3_1333G = 6,
+ /* 9-9-9 */
+ DDR3_1333H = 7,
+ /* 10-10-10 */
+ DDR3_1333J = 8,
+ /* 8-8-8 */
+ DDR3_1600G = 9,
+ /* 9-9-9 */
+ DDR3_1600H = 10,
+ /* 10-10-10 */
+ DDR3_1600J = 11,
+ /* 11-11-11 */
+ DDR3_1600K = 12,
+ /* 10-10-10 */
+ DDR3_1866J = 13,
+ /* 11-11-11 */
+ DDR3_1866K = 14,
+ /* 12-12-12 */
+ DDR3_1866L = 15,
+ /* 13-13-13 */
+ DDR3_1866M = 16,
+ /* 11-11-11 */
+ DDR3_2133K = 17,
+ /* 12-12-12 */
+ DDR3_2133L = 18,
+ /* 13-13-13 */
+ DDR3_2133M = 19,
+ /* 14-14-14 */
+ DDR3_2133N = 20,
+ DDR3_DEFAULT = 21,
+};
+
+#undef max
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+#define range(mi, val, ma) (((ma) > (val)) ? (max(mi, val)) : (ma))
+
+struct dram_timing_t {
+ /* unit MHz */
+ uint32_t mhz;
+ /* some timing unit is us */
+ uint32_t tinit1;
+ uint32_t tinit2;
+ uint32_t tinit3;
+ uint32_t tinit4;
+ uint32_t tinit5;
+ /* reset low, DDR3:200us */
+ uint32_t trstl;
+ /* reset high to CKE high, DDR3:500us */
+ uint32_t trsth;
+ uint32_t trefi;
+ /* base */
+ uint32_t trcd;
+ /* trp per bank */
+ uint32_t trppb;
+ /* trp all bank */
+ uint32_t trp;
+ uint32_t twr;
+ uint32_t tdal;
+ uint32_t trtp;
+ uint32_t trc;
+ uint32_t trrd;
+ uint32_t tccd;
+ uint32_t twtr;
+ uint32_t trtw;
+ uint32_t tras_max;
+ uint32_t tras_min;
+ uint32_t tfaw;
+ uint32_t trfc;
+ uint32_t tdqsck;
+ uint32_t tdqsck_max;
+ /* pd or sr */
+ uint32_t txsr;
+ uint32_t txsnr;
+ uint32_t txp;
+ uint32_t txpdll;
+ uint32_t tdllk;
+ uint32_t tcke;
+ uint32_t tckesr;
+ uint32_t tcksre;
+ uint32_t tcksrx;
+ uint32_t tdpd;
+ /* mode register timing */
+ uint32_t tmod;
+ uint32_t tmrd;
+ uint32_t tmrr;
+ uint32_t tmrri;
+ /* ODT */
+ uint32_t todton;
+ /* ZQ */
+ uint32_t tzqinit;
+ uint32_t tzqcs;
+ uint32_t tzqoper;
+ uint32_t tzqreset;
+ /* Write Leveling */
+ uint32_t twlmrd;
+ uint32_t twlo;
+ uint32_t twldqsen;
+ /* CA Training */
+ uint32_t tcackel;
+ uint32_t tcaent;
+ uint32_t tcamrd;
+ uint32_t tcackeh;
+ uint32_t tcaext;
+ uint32_t tadr;
+ uint32_t tmrz;
+ uint32_t tcacd;
+ /* mode register */
+ uint32_t mr[4];
+ uint32_t mr11;
+ /* lpddr4 spec */
+ uint32_t mr12;
+ uint32_t mr13;
+ uint32_t mr14;
+ uint32_t mr16;
+ uint32_t mr17;
+ uint32_t mr20;
+ uint32_t mr22;
+ uint32_t tccdmw;
+ uint32_t tppd;
+ uint32_t tescke;
+ uint32_t tsr;
+ uint32_t tcmdcke;
+ uint32_t tcscke;
+ uint32_t tckelcs;
+ uint32_t tcsckeh;
+ uint32_t tckehcs;
+ uint32_t tmrwckel;
+ uint32_t tzqcal;
+ uint32_t tzqlat;
+ uint32_t tzqcke;
+ uint32_t tvref_long;
+ uint32_t tvref_short;
+ uint32_t tvrcg_enable;
+ uint32_t tvrcg_disable;
+ uint32_t tfc_long;
+ uint32_t tckfspe;
+ uint32_t tckfspx;
+ uint32_t tckehcmd;
+ uint32_t tckelcmd;
+ uint32_t tckelpd;
+ uint32_t tckckel;
+ /* other */
+ uint32_t al;
+ uint32_t cl;
+ uint32_t cwl;
+ uint32_t bl;
+};
+
+struct dram_info_t {
+ /* speed_rate only used when DDR3 */
+ enum ddr3_speed_rate speed_rate;
+ /* 1: use CS0, 2: use CS0 and CS1 */
+ uint32_t cs_cnt;
+ /* give the max per-die capability on each rank/cs */
+ uint32_t per_die_capability[2];
+};
+
+struct timing_related_config {
+ struct dram_info_t dram_info[2];
+ uint32_t dram_type;
+ /* MHz */
+ uint32_t freq;
+ uint32_t ch_cnt;
+ uint32_t bl;
+ /* 1:auto precharge, 0:never auto precharge */
+ uint32_t ap;
+ /*
+ * 1:dll bypass, 0:dll normal
+ * dram and controller dll bypass at the same time
+ */
+ uint32_t dllbp;
+ /* 1:odt enable, 0:odt disable */
+ uint32_t odt;
+ /* 1:enable, 0:disabe */
+ uint32_t rdbi;
+ uint32_t wdbi;
+ /* dram driver strength */
+ uint32_t dramds;
+ /* dram ODT, if odt=0, this parameter invalid */
+ uint32_t dramodt;
+ /*
+ * ca ODT, if odt=0, this parameter invalid
+ * it only used by LPDDR4
+ */
+ uint32_t caodt;
+};
+
+/* mr0 for ddr3 */
+#define DDR3_BL8 (0)
+#define DDR3_BC4_8 (1)
+#define DDR3_BC4 (2)
+#define DDR3_CL(n) (((((n) - 4) & 0x7) << 4)\
+ | ((((n) - 4) & 0x8) >> 1))
+#define DDR3_WR(n) (((n) & 0x7) << 9)
+#define DDR3_DLL_RESET (1 << 8)
+#define DDR3_DLL_DERESET (0 << 8)
+
+/* mr1 for ddr3 */
+#define DDR3_DLL_ENABLE (0)
+#define DDR3_DLL_DISABLE (1)
+#define DDR3_MR1_AL(n) (((n) & 0x3) << 3)
+
+#define DDR3_DS_40 (0)
+#define DDR3_DS_34 (1 << 1)
+#define DDR3_RTT_NOM_DIS (0)
+#define DDR3_RTT_NOM_60 (1 << 2)
+#define DDR3_RTT_NOM_120 (1 << 6)
+#define DDR3_RTT_NOM_40 ((1 << 2) | (1 << 6))
+#define DDR3_TDQS (1 << 11)
+
+/* mr2 for ddr3 */
+#define DDR3_MR2_CWL(n) ((((n) - 5) & 0x7) << 3)
+#define DDR3_RTT_WR_DIS (0)
+#define DDR3_RTT_WR_60 (1 << 9)
+#define DDR3_RTT_WR_120 (2 << 9)
+
+/*
+ * MR0 (Device Information)
+ * 0:DAI complete, 1:DAI still in progress
+ */
+#define LPDDR2_DAI (0x1)
+/* 0:S2 or S4 SDRAM, 1:NVM */
+#define LPDDR2_DI (0x1 << 1)
+/* 0:DNV not supported, 1:DNV supported */
+#define LPDDR2_DNVI (0x1 << 2)
+#define LPDDR2_RZQI (0x3 << 3)
+
+/*
+ * 00:RZQ self test not supported,
+ * 01:ZQ-pin may connect to VDDCA or float
+ * 10:ZQ-pin may short to GND.
+ * 11:ZQ-pin self test completed, no error condition detected.
+ */
+
+/* MR1 (Device Feature) */
+#define LPDDR2_BL4 (0x2)
+#define LPDDR2_BL8 (0x3)
+#define LPDDR2_BL16 (0x4)
+#define LPDDR2_N_WR(n) (((n) - 2) << 5)
+
+/* MR2 (Device Feature 2) */
+#define LPDDR2_RL3_WL1 (0x1)
+#define LPDDR2_RL4_WL2 (0x2)
+#define LPDDR2_RL5_WL2 (0x3)
+#define LPDDR2_RL6_WL3 (0x4)
+#define LPDDR2_RL7_WL4 (0x5)
+#define LPDDR2_RL8_WL4 (0x6)
+
+/* MR3 (IO Configuration 1) */
+#define LPDDR2_DS_34 (0x1)
+#define LPDDR2_DS_40 (0x2)
+#define LPDDR2_DS_48 (0x3)
+#define LPDDR2_DS_60 (0x4)
+#define LPDDR2_DS_80 (0x6)
+/* optional */
+#define LPDDR2_DS_120 (0x7)
+
+/* MR4 (Device Temperature) */
+#define LPDDR2_TREF_MASK (0x7)
+#define LPDDR2_4_TREF (0x1)
+#define LPDDR2_2_TREF (0x2)
+#define LPDDR2_1_TREF (0x3)
+#define LPDDR2_025_TREF (0x5)
+#define LPDDR2_025_TREF_DERATE (0x6)
+
+#define LPDDR2_TUF (0x1 << 7)
+
+/* MR8 (Basic configuration 4) */
+#define LPDDR2_S4 (0x0)
+#define LPDDR2_S2 (0x1)
+#define LPDDR2_N (0x2)
+/* Unit:MB */
+#define LPDDR2_DENSITY(mr8) (8 << (((mr8) >> 2) & 0xf))
+#define LPDDR2_IO_WIDTH(mr8) (32 >> (((mr8) >> 6) & 0x3))
+
+/* MR10 (Calibration) */
+#define LPDDR2_ZQINIT (0xff)
+#define LPDDR2_ZQCL (0xab)
+#define LPDDR2_ZQCS (0x56)
+#define LPDDR2_ZQRESET (0xc3)
+
+/* MR16 (PASR Bank Mask), S2 SDRAM Only */
+#define LPDDR2_PASR_FULL (0x0)
+#define LPDDR2_PASR_1_2 (0x1)
+#define LPDDR2_PASR_1_4 (0x2)
+#define LPDDR2_PASR_1_8 (0x3)
+
+/*
+ * MR0 (Device Information)
+ * 0:DAI complete,
+ * 1:DAI still in progress
+ */
+#define LPDDR3_DAI (0x1)
+/*
+ * 00:RZQ self test not supported,
+ * 01:ZQ-pin may connect to VDDCA or float
+ * 10:ZQ-pin may short to GND.
+ * 11:ZQ-pin self test completed, no error condition detected.
+ */
+#define LPDDR3_RZQI (0x3 << 3)
+/*
+ * 0:DRAM does not support WL(Set B),
+ * 1:DRAM support WL(Set B)
+ */
+#define LPDDR3_WL_SUPOT (1 << 6)
+/*
+ * 0:DRAM does not support RL=3,nWR=3,WL=1;
+ * 1:DRAM supports RL=3,nWR=3,WL=1 for frequencies <=166
+ */
+#define LPDDR3_RL3_SUPOT (1 << 7)
+
+/* MR1 (Device Feature) */
+#define LPDDR3_BL8 (0x3)
+#define LPDDR3_N_WR(n) ((n) << 5)
+
+/* MR2 (Device Feature 2), WL Set A,default */
+/* <=166MHz,optional*/
+#define LPDDR3_RL3_WL1 (0x1)
+/* <=400MHz*/
+#define LPDDR3_RL6_WL3 (0x4)
+/* <=533MHz*/
+#define LPDDR3_RL8_WL4 (0x6)
+/* <=600MHz*/
+#define LPDDR3_RL9_WL5 (0x7)
+/* <=667MHz,default*/
+#define LPDDR3_RL10_WL6 (0x8)
+/* <=733MHz*/
+#define LPDDR3_RL11_WL6 (0x9)
+/* <=800MHz*/
+#define LPDDR3_RL12_WL6 (0xa)
+/* <=933MHz*/
+#define LPDDR3_RL14_WL8 (0xc)
+/* <=1066MHz*/
+#define LPDDR3_RL16_WL8 (0xe)
+
+/* WL Set B, optional */
+/* <=667MHz,default*/
+#define LPDDR3_RL10_WL8 (0x8)
+/* <=733MHz*/
+#define LPDDR3_RL11_WL9 (0x9)
+/* <=800MHz*/
+#define LPDDR3_RL12_WL9 (0xa)
+/* <=933MHz*/
+#define LPDDR3_RL14_WL11 (0xc)
+/* <=1066MHz*/
+#define LPDDR3_RL16_WL13 (0xe)
+
+/* 1:enable nWR programming > 9(default)*/
+#define LPDDR3_N_WRE (1 << 4)
+/* 1:Select WL Set B*/
+#define LPDDR3_WL_S (1 << 6)
+/* 1:enable*/
+#define LPDDR3_WR_LEVEL (1 << 7)
+
+/* MR3 (IO Configuration 1) */
+#define LPDDR3_DS_34 (0x1)
+#define LPDDR3_DS_40 (0x2)
+#define LPDDR3_DS_48 (0x3)
+#define LPDDR3_DS_60 (0x4)
+#define LPDDR3_DS_80 (0x6)
+#define LPDDR3_DS_34D_40U (0x9)
+#define LPDDR3_DS_40D_48U (0xa)
+#define LPDDR3_DS_34D_48U (0xb)
+
+/* MR4 (Device Temperature) */
+#define LPDDR3_TREF_MASK (0x7)
+/* SDRAM Low temperature operating limit exceeded */
+#define LPDDR3_LT_EXED (0x0)
+#define LPDDR3_4_TREF (0x1)
+#define LPDDR3_2_TREF (0x2)
+#define LPDDR3_1_TREF (0x3)
+#define LPDDR3_05_TREF (0x4)
+#define LPDDR3_025_TREF (0x5)
+#define LPDDR3_025_TREF_DERATE (0x6)
+/* SDRAM High temperature operating limit exceeded */
+#define LPDDR3_HT_EXED (0x7)
+
+/* 1:value has changed since last read of MR4 */
+#define LPDDR3_TUF (0x1 << 7)
+
+/* MR8 (Basic configuration 4) */
+#define LPDDR3_S8 (0x3)
+#define LPDDR3_DENSITY(mr8) (8 << (((mr8) >> 2) & 0xf))
+#define LPDDR3_IO_WIDTH(mr8) (32 >> (((mr8) >> 6) & 0x3))
+
+/* MR10 (Calibration) */
+#define LPDDR3_ZQINIT (0xff)
+#define LPDDR3_ZQCL (0xab)
+#define LPDDR3_ZQCS (0x56)
+#define LPDDR3_ZQRESET (0xc3)
+
+/* MR11 (ODT Control) */
+#define LPDDR3_ODT_60 (1)
+#define LPDDR3_ODT_120 (2)
+#define LPDDR3_ODT_240 (3)
+#define LPDDR3_ODT_DIS (0)
+
+/* MR2 (Device Feature 2) */
+/* RL & nRTP for DBI-RD Disabled */
+#define LPDDR4_RL6_NRTP8 (0x0)
+#define LPDDR4_RL10_NRTP8 (0x1)
+#define LPDDR4_RL14_NRTP8 (0x2)
+#define LPDDR4_RL20_NRTP8 (0x3)
+#define LPDDR4_RL24_NRTP10 (0x4)
+#define LPDDR4_RL28_NRTP12 (0x5)
+#define LPDDR4_RL32_NRTP14 (0x6)
+#define LPDDR4_RL36_NRTP16 (0x7)
+/* RL & nRTP for DBI-RD Disabled */
+#define LPDDR4_RL12_NRTP8 (0x1)
+#define LPDDR4_RL16_NRTP8 (0x2)
+#define LPDDR4_RL22_NRTP8 (0x3)
+#define LPDDR4_RL28_NRTP10 (0x4)
+#define LPDDR4_RL32_NRTP12 (0x5)
+#define LPDDR4_RL36_NRTP14 (0x6)
+#define LPDDR4_RL40_NRTP16 (0x7)
+/* WL Set A,default */
+#define LPDDR4_A_WL4 (0x0)
+#define LPDDR4_A_WL6 (0x1)
+#define LPDDR4_A_WL8 (0x2)
+#define LPDDR4_A_WL10 (0x3)
+#define LPDDR4_A_WL12 (0x4)
+#define LPDDR4_A_WL14 (0x5)
+#define LPDDR4_A_WL16 (0x6)
+#define LPDDR4_A_WL18 (0x7)
+/* WL Set B, optional */
+#define LPDDR4_B_WL4 (0x0 << 3)
+#define LPDDR4_B_WL8 (0x1 << 3)
+#define LPDDR4_B_WL12 (0x2 << 3)
+#define LPDDR4_B_WL18 (0x3 << 3)
+#define LPDDR4_B_WL22 (0x4 << 3)
+#define LPDDR4_B_WL26 (0x5 << 3)
+#define LPDDR4_B_WL30 (0x6 << 3)
+#define LPDDR4_B_WL34 (0x7 << 3)
+/* 1:Select WL Set B*/
+#define LPDDR4_WL_B (1 << 6)
+/* 1:enable*/
+#define LPDDR4_WR_LEVEL (1 << 7)
+
+/* MR3 */
+#define LPDDR4_VDDQ_2_5 (0)
+#define LPDDR4_VDDQ_3 (1)
+#define LPDDR4_WRPST_0_5_TCK (0 << 1)
+#define LPDDR4_WRPST_1_5_TCK (1 << 1)
+#define LPDDR4_PPR_EN (1 << 2)
+/* PDDS */
+#define LPDDR4_PDDS_240 (0x1 << 3)
+#define LPDDR4_PDDS_120 (0x2 << 3)
+#define LPDDR4_PDDS_80 (0x3 << 3)
+#define LPDDR4_PDDS_60 (0x4 << 3)
+#define LPDDR4_PDDS_48 (0x5 << 3)
+#define LPDDR4_PDDS_40 (0x6 << 3)
+#define LPDDR4_DBI_RD_EN (1 << 6)
+#define LPDDR4_DBI_WR_EN (1 << 7)
+
+/* MR11 (ODT Control) */
+#define LPDDR4_DQODT_240 (1)
+#define LPDDR4_DQODT_120 (2)
+#define LPDDR4_DQODT_80 (3)
+#define LPDDR4_DQODT_60 (4)
+#define LPDDR4_DQODT_48 (5)
+#define LPDDR4_DQODT_40 (6)
+#define LPDDR4_DQODT_DIS (0)
+#define LPDDR4_CAODT_240 (1 << 4)
+#define LPDDR4_CAODT_120 (2 << 4)
+#define LPDDR4_CAODT_80 (3 << 4)
+#define LPDDR4_CAODT_60 (4 << 4)
+#define LPDDR4_CAODT_48 (5 << 4)
+#define LPDDR4_CAODT_40 (6 << 4)
+#define LPDDR4_CAODT_DIS (0 << 4)
+
+/*
+ * Description: depend on input parameter "timing_config",
+ * and calculate correspond "dram_type"
+ * spec timing to "pdram_timing"
+ * parameters:
+ * input: timing_config
+ * output: pdram_timing
+ * NOTE: MR ODT is set, need to disable by controller
+ */
+void dram_get_parameter(struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing);
+
+#endif /* _DRAM_SPEC_TIMING_HEAD_ */
diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c
index 2a3c91d043..39975e16b6 100644
--- a/drivers/ram/rockchip/sdram_rk3399.c
+++ b/drivers/ram/rockchip/sdram_rk3399.c
@@ -20,7 +20,10 @@
#include <asm/arch/grf_rk3399.h>
#include <asm/arch/hardware.h>
#include <linux/err.h>
+//#include <linux/kernel.h>
#include <time.h>
+#include <i2c_eeprom.h>
+#include "dram_spec_timing.h"
struct chan_info {
struct rk3399_ddr_pctl_regs *pctl;
@@ -46,6 +49,15 @@ struct dram_info {
#define PRESET_GPIO0_HOLD(n) ((0x1 << (7 + 16)) | ((n) << 7))
#define PRESET_GPIO1_HOLD(n) ((0x1 << (8 + 16)) | ((n) << 8))
+/*
+ * Calculating back from the below drive-strength/ODT table,
+ * the following resistor array is used:
+ * 0b1000 = 120 ohm
+ * 0b0100 = 120 ohm
+ * 0b0010 = 120 ohm
+ * 0b0001 = 240 ohm
+ */
+
#define PHY_DRV_ODT_Hi_Z 0x0
#define PHY_DRV_ODT_240 0x1
#define PHY_DRV_ODT_120 0x8
@@ -55,57 +67,156 @@ struct dram_info {
#define PHY_DRV_ODT_40 0xe
#define PHY_DRV_ODT_34_3 0xf
+#define ENPER_CS_TRAINING_FREQ (666)
+#define TDFI_LAT_THRESHOLD_FREQ (933) /* TODO: actually 928 */
+#define PHY_DLL_BYPASS_FREQ (260)
+
+#define PI_REGS_DIMM_SUPPORT (0)
+#define PI_ADD_LATENCY (0)
+#define PI_DOUBLEFREEK (1)
+
+#define PI_PAD_DELAY_PS_VALUE (1000)
+#define PI_IE_ENABLE_VALUE (3000)
+#define PI_TSEL_ENABLE_VALUE (700)
+
#ifdef CONFIG_SPL_BUILD
+static int spd_decode_ddr3(const u8 *spd, const u32 freq, struct dram_timing_t *timing);
+
+#if 0
+
+#undef clrbits_le32
+#undef setbits_le32
+
+static inline void setbits_le32(u32 *addr, u32 set)
+{
+ *addr |= set;
+}
+
+static inline void clrbits_le32(u32 *addr, u32 clr)
+{
+ *addr &= ~clr;
+}
+
+#undef clrsetbits_le32
+static inline void clrsetbits_le32(u32 *addr, u32 clr, u32 set)
+{
+ *addr &= ~clr;
+ *addr |= set;
+}
+
+#undef writel
+#define writel writel_relaxed
+
+#endif
+
struct rockchip_dmc_plat {
#if CONFIG_IS_ENABLED(OF_PLATDATA)
struct dtd_rockchip_rk3399_dmc dtplat;
#else
struct rk3399_sdram_params sdram_params;
+ u8 spd[128];
#endif
struct regmap *map;
};
-static void 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++;
- }
-}
+static uint32_t wrdqs_delay_val[2][2][4];
+static uint32_t rddqs_delay_ps;
static void phy_dll_bypass_set(struct rk3399_ddr_publ_regs *ddr_publ_regs,
- u32 freq)
+ u32 freq, u32 ch, u32 index, u32 dram_type)
{
u32 *denali_phy = ddr_publ_regs->denali_phy;
+ u32 sw_master_mode = 0;
+ u32 rddqs_gate_delay, rddqs_latency, total_delay;
+ u32 i;
- /* From IP spec, only freq small than 125 can enter dll bypass mode */
- if (freq <= 125) {
- /* phy_sw_master_mode_X PHY_86/214/342/470 4bits offset_8 */
- setbits_le32(&denali_phy[86], (0x3 << 2) << 8);
- setbits_le32(&denali_phy[214], (0x3 << 2) << 8);
- setbits_le32(&denali_phy[342], (0x3 << 2) << 8);
- setbits_le32(&denali_phy[470], (0x3 << 2) << 8);
-
- /* phy_adrctl_sw_master_mode PHY_547/675/803 4bits offset_16 */
- setbits_le32(&denali_phy[547], (0x3 << 2) << 16);
- setbits_le32(&denali_phy[675], (0x3 << 2) << 16);
- setbits_le32(&denali_phy[803], (0x3 << 2) << 16);
- } else {
- /* phy_sw_master_mode_X PHY_86/214/342/470 4bits offset_8 */
- clrbits_le32(&denali_phy[86], (0x3 << 2) << 8);
- clrbits_le32(&denali_phy[214], (0x3 << 2) << 8);
- clrbits_le32(&denali_phy[342], (0x3 << 2) << 8);
- clrbits_le32(&denali_phy[470], (0x3 << 2) << 8);
+ debug("%s\n", __func__);
+
+ if (dram_type == DDR3)
+ total_delay = PI_PAD_DELAY_PS_VALUE;
+ else if (dram_type == LPDDR3)
+ total_delay = PI_PAD_DELAY_PS_VALUE + 2500;
+ else
+ total_delay = PI_PAD_DELAY_PS_VALUE + 1500;
+
+ /* total_delay + 0.55tck */
+ total_delay += (55 * 10000)/freq;
+ rddqs_latency = total_delay * freq / 1000000;
+ total_delay -= rddqs_latency * 1000000 / freq;
+ rddqs_gate_delay = total_delay * 0x200 * freq / 1000000;
+
+ if (freq <= PHY_DLL_BYPASS_FREQ) {
+ sw_master_mode = 0xc;
+
+ setbits_le32(&denali_phy[514], 1);
+ setbits_le32(&denali_phy[642], 1);
+ setbits_le32(&denali_phy[770], 1);
+
+ /* setting bypass mode slave delay */
+ for (i = 0; i < 4; i++) {
+ /* wr dq delay = -180deg + (0x60 / 4) * 20ps */
+ clrsetbits_le32(&denali_phy[1 + 128 * i],
+ 0x7ff << 8, 0x4a0 << 8);
+ /* rd dqs/dq delay = (0x60 / 4) * 20ps */
+ clrsetbits_le32(&denali_phy[11 + 128 * i],
+ 0x3ff, 0xa0);
+ /* rd rddqs_gate delay */
+ clrsetbits_le32(&denali_phy[2 + 128 * i],
+ 0x3ff, rddqs_gate_delay);
+ clrsetbits_le32(&denali_phy[78 + 128 * i],
+ 0xf, rddqs_latency);
+ }
- /* phy_adrctl_sw_master_mode PHY_547/675/803 4bits offset_16 */
- clrbits_le32(&denali_phy[547], (0x3 << 2) << 16);
- clrbits_le32(&denali_phy[675], (0x3 << 2) << 16);
- clrbits_le32(&denali_phy[803], (0x3 << 2) << 16);
+ /* adr delay */
+ for (i = 0; i < 3; i++)
+ clrsetbits_le32(&denali_phy[513 + 128 * i],
+ 0x7ff << 16, 0x80 << 16);
+
+ if ((readl(&denali_phy[86]) & 0xc00) == 0) {
+ /*
+ * old status is normal mode,
+ * and saving the wrdqs slave delay
+ */
+ for (i = 0; i < 4; i++) {
+ u32 reg = readl(&denali_phy[63 + i * 128]);
+
+ /* save and clear wr dqs slave delay */
+ wrdqs_delay_val[ch][index][i] =
+ 0x3ff &(reg >> 16);
+ clrsetbits_le32(&denali_phy[63 + i * 128],
+ 0x3ff << 16, 0 << 16);
+ /*
+ * in normal mode the cmd may delay 1cycle by
+ * wrlvl and in bypass mode making dqs also
+ * delay 1cycle.
+ */
+ clrsetbits_le32(&denali_phy[78 + i * 128],
+ 0x7 << 8, 0x1 << 8);
+ }
+ }
+ } else if (readl(&denali_phy[86]) & 0xc00) {
+ /* old status is bypass mode and restore wrlvl resume */
+ for (i = 0; i < 4; i++) {
+ clrsetbits_le32(&denali_phy[63 + i * 128],
+ 0x03ff << 16,
+ (wrdqs_delay_val[ch][index][i] &
+ 0x3ff) << 16);
+ /* resume phy_write_path_lat_add */
+ clrbits_le32(&denali_phy[78 + i * 128], 0x7 << 8);
+ }
}
+
+ /* phy_sw_master_mode_X PHY_86/214/342/470 4bits offset_8 */
+ clrsetbits_le32(&denali_phy[86], 0xf << 8, sw_master_mode << 8);
+ clrsetbits_le32(&denali_phy[214], 0xf << 8, sw_master_mode << 8);
+ clrsetbits_le32(&denali_phy[342], 0xf << 8, sw_master_mode << 8);
+ clrsetbits_le32(&denali_phy[470], 0xf << 8, sw_master_mode << 8);
+
+ /* phy_adrctl_sw_master_mode PHY_547/675/803 4bits offset_16 */
+ clrsetbits_le32(&denali_phy[547], 0xf << 16, sw_master_mode << 16);
+ clrsetbits_le32(&denali_phy[675], 0xf << 16, sw_master_mode << 16);
+ clrsetbits_le32(&denali_phy[803], 0xf << 16, sw_master_mode << 16);
}
static void set_memory_map(const struct chan_info *chan, u32 channel,
@@ -130,17 +241,26 @@ static void set_memory_map(const struct chan_info *chan, u32 channel,
cs_map = (sdram_ch->rank > 1) ? 3 : 1;
reduc = (sdram_ch->bw == 2) ? 0 : 1;
- /* Set the dram configuration to ctrl */
- clrsetbits_le32(&denali_ctl[191], 0xF, (12 - sdram_ch->col));
+ /* Set the dram configuration */
+ const u8 coldiff = 12 - sdram_ch->col;
+ clrsetbits_le32(&denali_ctl[191], 0xf, coldiff);
+ clrsetbits_le32(&denali_pi[199], 0xf, coldiff);
+
clrsetbits_le32(&denali_ctl[190], (0x3 << 16) | (0x7 << 24),
((3 - sdram_ch->bk) << 16) |
((16 - row) << 24));
- clrsetbits_le32(&denali_ctl[196], 0x3 | (1 << 16),
- cs_map | (reduc << 16));
+ /* Is this a 16bit wide bus? */
+ if (reduc) {
+ setbits_le32(&denali_ctl[196], BIT(16));
+ setbits_le32(&denali_pi[58], BIT(8));
+ } else {
+ clrbits_le32(&denali_ctl[196], BIT(16));
+ clrbits_le32(&denali_pi[58], BIT(8));
+ }
- /* PI_199 PI_COL_DIFF:RW:0:4 */
- clrsetbits_le32(&denali_pi[199], 0xF, (12 - sdram_ch->col));
+ /* active chip selects */
+ clrsetbits_le32(&denali_ctl[196], 0x3, cs_map);
/* PI_155 PI_ROW_DIFF:RW:24:3 PI_BANK_DIFF:RW:16:2 */
clrsetbits_le32(&denali_pi[155], (0x3 << 16) | (0x7 << 24),
@@ -193,6 +313,19 @@ static void set_ds_odt(const struct chan_info *chan,
tsel_wr_select_n = PHY_DRV_ODT_34_3;
ca_tsel_wr_select_n = PHY_DRV_ODT_34_3;
tsel_idle_select_n = PHY_DRV_ODT_240;
+
+#if 1
+ tsel_rd_select_p = PHY_DRV_ODT_60;
+ tsel_wr_select_p = PHY_DRV_ODT_34_3;
+ ca_tsel_wr_select_p = PHY_DRV_ODT_34_3;
+ tsel_idle_select_p = PHY_DRV_ODT_60;
+
+ tsel_rd_select_n = PHY_DRV_ODT_60;
+ tsel_wr_select_n = PHY_DRV_ODT_34_3;
+ ca_tsel_wr_select_n = PHY_DRV_ODT_34_3;
+ tsel_idle_select_n = PHY_DRV_ODT_60;
+
+#endif
}
if (sdram_params->base.odt == 1)
@@ -452,34 +585,1845 @@ static int phy_io_config(const struct chan_info *chan,
return 0;
}
-static int pctl_cfg(const struct chan_info *chan, u32 channel,
+static uint32_t get_pi_rdlat_adj(struct dram_timing_t *pdram_timing)
+{
+ /*[DLLSUBTYPE2] == "STD_DENALI_HS" */
+ uint32_t rdlat, delay_adder, ie_enable, hs_offset, tsel_adder,
+ extra_adder, tsel_enable;
+
+ ie_enable = PI_IE_ENABLE_VALUE;
+ tsel_enable = PI_TSEL_ENABLE_VALUE;
+
+ rdlat = pdram_timing->cl + PI_ADD_LATENCY;
+ delay_adder = ie_enable / (1000000 / pdram_timing->mhz);
+ if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0)
+ delay_adder++;
+ hs_offset = 0;
+ tsel_adder = 0;
+ extra_adder = 0;
+ /* rdlat = rdlat - (PREAMBLE_SUPPORT & 0x1); */
+ tsel_adder = tsel_enable / (1000000 / pdram_timing->mhz);
+ if ((tsel_enable % (1000000 / pdram_timing->mhz)) != 0)
+ tsel_adder++;
+ delay_adder = delay_adder - 1;
+ if (tsel_adder > delay_adder)
+ extra_adder = tsel_adder - delay_adder;
+ else
+ extra_adder = 0;
+ if (PI_REGS_DIMM_SUPPORT && PI_DOUBLEFREEK)
+ hs_offset = 2;
+ else
+ hs_offset = 1;
+
+ if (delay_adder > (rdlat - 1 - hs_offset)) {
+ rdlat = rdlat - tsel_adder;
+ } else {
+ if ((rdlat - delay_adder) < 2)
+ rdlat = 2;
+ else
+ rdlat = rdlat - delay_adder - extra_adder;
+ }
+
+ return rdlat;
+}
+
+static uint32_t get_pi_wrlat(struct dram_timing_t *pdram_timing,
+ struct timing_related_config *timing_config)
+{
+ uint32_t tmp;
+
+ if (timing_config->dram_type == LPDDR3) {
+ tmp = pdram_timing->cl;
+ if (tmp >= 14)
+ tmp = 8;
+ else if (tmp >= 10)
+ tmp = 6;
+ else if (tmp == 9)
+ tmp = 5;
+ else if (tmp == 8)
+ tmp = 4;
+ else if (tmp == 6)
+ tmp = 3;
+ else
+ tmp = 1;
+ } else {
+ tmp = 1;
+ }
+
+ return tmp;
+}
+
+static uint32_t get_pi_wrlat_adj(struct dram_timing_t *pdram_timing,
+ struct timing_related_config *timing_config)
+{
+ return get_pi_wrlat(pdram_timing, timing_config) + PI_ADD_LATENCY - 1;
+}
+
+static uint32_t get_pi_tdfi_phy_rdlat(struct dram_timing_t *pdram_timing,
+ struct timing_related_config *timing_config)
+{
+ /* [DLLSUBTYPE2] == "STD_DENALI_HS" */
+ uint32_t cas_lat, delay_adder, ie_enable, hs_offset, ie_delay_adder;
+ uint32_t mem_delay_ps, round_trip_ps;
+ uint32_t phy_internal_delay, lpddr_adder, dfi_adder, rdlat_delay;
+
+ ie_enable = PI_IE_ENABLE_VALUE;
+
+ delay_adder = ie_enable / (1000000 / pdram_timing->mhz);
+ if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0)
+ delay_adder++;
+ delay_adder = delay_adder - 1;
+ if (PI_REGS_DIMM_SUPPORT && PI_DOUBLEFREEK)
+ hs_offset = 2;
+ else
+ hs_offset = 1;
+
+ cas_lat = pdram_timing->cl + PI_ADD_LATENCY;
+
+ if (delay_adder > (cas_lat - 1 - hs_offset)) {
+ ie_delay_adder = 0;
+ } else {
+ ie_delay_adder = ie_enable / (1000000 / pdram_timing->mhz);
+ if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0)
+ ie_delay_adder++;
+ }
+
+ if (timing_config->dram_type == DDR3) {
+ mem_delay_ps = 0;
+ } else if (timing_config->dram_type == LPDDR4) {
+ mem_delay_ps = 3600;
+ } else if (timing_config->dram_type == LPDDR3) {
+ mem_delay_ps = 5500;
+ } else {
+ printf("get_pi_tdfi_phy_rdlat:dramtype unsupport\n");
+ return 0;
+ }
+ round_trip_ps = 1100 + 500 + mem_delay_ps + 500 + 600;
+ delay_adder = round_trip_ps / (1000000 / pdram_timing->mhz);
+ if ((round_trip_ps % (1000000 / pdram_timing->mhz)) != 0)
+ delay_adder++;
+
+ phy_internal_delay = 5 + 2 + 4;
+ lpddr_adder = mem_delay_ps / (1000000 / pdram_timing->mhz);
+ if ((mem_delay_ps % (1000000 / pdram_timing->mhz)) != 0)
+ lpddr_adder++;
+ dfi_adder = 0;
+ phy_internal_delay = phy_internal_delay + 2;
+ rdlat_delay = delay_adder + phy_internal_delay +
+ ie_delay_adder + lpddr_adder + dfi_adder;
+
+ rdlat_delay = rdlat_delay + 2;
+ return rdlat_delay;
+}
+
+static uint32_t get_pi_todtoff_min(struct dram_timing_t *pdram_timing,
+ struct timing_related_config *timing_config)
+{
+ uint32_t tmp, todtoff_min_ps;
+
+ if (timing_config->dram_type == LPDDR3)
+ todtoff_min_ps = 2500;
+ else if (timing_config->dram_type == LPDDR4)
+ todtoff_min_ps = 1500;
+ else
+ todtoff_min_ps = 0;
+ /* todtoff_min */
+ tmp = todtoff_min_ps / (1000000 / pdram_timing->mhz);
+ if ((todtoff_min_ps % (1000000 / pdram_timing->mhz)) != 0)
+ tmp++;
+ return tmp;
+}
+
+static uint32_t get_pi_todtoff_max(struct dram_timing_t *pdram_timing,
+ struct timing_related_config *timing_config)
+{
+ uint32_t tmp, todtoff_max_ps;
+
+ if ((timing_config->dram_type == LPDDR4)
+ || (timing_config->dram_type == LPDDR3))
+ todtoff_max_ps = 3500;
+ else
+ todtoff_max_ps = 0;
+
+ /* todtoff_max */
+ tmp = todtoff_max_ps / (1000000 / pdram_timing->mhz);
+ if ((todtoff_max_ps % (1000000 / pdram_timing->mhz)) != 0)
+ tmp++;
+ return tmp;
+}
+
+struct lat_adj_pair {
+ uint32_t cl;
+ uint32_t rdlat_adj;
+ uint32_t cwl;
+ uint32_t wrlat_adj;
+};
+
+const struct lat_adj_pair ddr3_lat_adj[] = {
+ {6, 5, 5, 4},
+ {8, 7, 6, 5},
+ {10, 9, 7, 6},
+ {11, 9, 8, 7},
+ {13, 0xb, 9, 8},
+ {14, 0xb, 0xa, 9}
+};
+
+static uint32_t get_rdlat_adj(uint32_t dram_type, uint32_t cl)
+{
+ const struct lat_adj_pair *p;
+ uint32_t cnt;
+ uint32_t i;
+
+ if (dram_type == DDR3) {
+ p = ddr3_lat_adj;
+ cnt = ARRAY_SIZE(ddr3_lat_adj);
+ }
+#if 0 // TODO
+ else if (dram_type == LPDDR3) {
+ p = lpddr3_lat_adj;
+ cnt = ARRAY_SIZE(lpddr3_lat_adj);
+ } else {
+ p = lpddr4_lat_adj;
+ cnt = ARRAY_SIZE(lpddr4_lat_adj);
+ }
+#endif
+
+ for (i = 0; i < cnt; i++) {
+ if (cl == p[i].cl)
+ return p[i].rdlat_adj;
+ }
+ /* fail */
+ return 0xff;
+}
+
+static uint32_t get_wrlat_adj(uint32_t dram_type, uint32_t cwl)
+{
+ const struct lat_adj_pair *p;
+ uint32_t cnt;
+ uint32_t i;
+
+ if (dram_type == DDR3) {
+ p = ddr3_lat_adj;
+ cnt = ARRAY_SIZE(ddr3_lat_adj);
+ }
+#if 0
+ else if (dram_type == LPDDR3) {
+ p = lpddr3_lat_adj;
+ cnt = ARRAY_SIZE(lpddr3_lat_adj);
+ } else {
+ p = lpddr4_lat_adj;
+ cnt = ARRAY_SIZE(lpddr4_lat_adj);
+ }
+#endif
+
+ for (i = 0; i < cnt; i++) {
+ if (cwl == p[i].cwl)
+ return p[i].wrlat_adj;
+ }
+ /* fail */
+ return 0xff;
+}
+
+static void gen_rk3399_ctl_params_f0(const struct chan_info *chan,
+ struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ u32 *denali_ctl = chan->pctl->denali_ctl;
+ // u32 *denali_pi = chan->pi->denali_pi;
+ // u32 *denali_phy = chan->publ->denali_phy;
+ uint32_t i;
+ uint32_t tmp, tmp1;
+
+ for (i = 0; i < timing_config->ch_cnt; i++) {
+ if (timing_config->dram_type == DDR3) {
+ tmp = (700000 * timing_config->freq + 999) / 1000;
+ tmp += pdram_timing->txsnr + (pdram_timing->tmrd * 3) +
+ pdram_timing->tmod + pdram_timing->tzqinit;
+ writel(tmp, &denali_ctl[5]);
+
+ clrsetbits_le32(&denali_ctl[22], 0xffff, pdram_timing->tdllk);
+
+ tmp = (pdram_timing->tmod << 8) | pdram_timing->tmrd;
+ writel(tmp, &denali_ctl[32]);
+
+ clrsetbits_le32(&denali_ctl[59], 0xffff << 16,
+ (pdram_timing->txsr - pdram_timing->trcd) << 16);
+#if 0
+ } else if (timing_config->dram_type == LPDDR4) {
+ mmio_write_32(CTL_REG(i, 5), pdram_timing->tinit1 +
+ pdram_timing->tinit3);
+ mmio_write_32(CTL_REG(i, 32),
+ (pdram_timing->tmrd << 8) |
+ pdram_timing->tmrd);
+ mmio_clrsetbits_32(CTL_REG(i, 59), 0xffff << 16,
+ pdram_timing->txsr << 16);
+ } else {
+ mmio_write_32(CTL_REG(i, 5), pdram_timing->tinit1);
+ mmio_write_32(CTL_REG(i, 7), pdram_timing->tinit4);
+ mmio_write_32(CTL_REG(i, 32),
+ (pdram_timing->tmrd << 8) |
+ pdram_timing->tmrd);
+ mmio_clrsetbits_32(CTL_REG(i, 59), 0xffff << 16,
+ pdram_timing->txsr << 16);
+#endif
+ }
+ writel(pdram_timing->tinit3, &denali_ctl[6]);
+ writel(pdram_timing->tinit5, &denali_ctl[8]);
+ clrsetbits_le32(&denali_ctl[23], (0x7f << 16),
+ ((pdram_timing->cl * 2) << 16));
+ clrsetbits_le32(&denali_ctl[23], (0x1f << 24),
+ (pdram_timing->cwl << 24));
+ clrsetbits_le32(&denali_ctl[24], 0x3f, pdram_timing->al);
+ clrsetbits_le32(&denali_ctl[26], 0xffff << 16,
+ (pdram_timing->trc << 24) |
+ (pdram_timing->trrd << 16));
+ writel(((pdram_timing->tfaw << 24) |
+ (pdram_timing->trppb << 16) |
+ (pdram_timing->twtr << 8) |
+ pdram_timing->tras_min),
+ &denali_ctl[27]);
+
+ clrsetbits_le32(&denali_ctl[31], 0xff << 24,
+ max(4, pdram_timing->trtp) << 24);
+ writel(((pdram_timing->tcke << 24) |
+ pdram_timing->tras_max),
+ &denali_ctl[33]);
+
+ clrsetbits_le32(&denali_ctl[34], 0xff,
+ max(1, pdram_timing->tckesr));
+ clrsetbits_le32(&denali_ctl[39],
+ (0x3f << 16) | (0xff << 8),
+ (pdram_timing->twr << 16) |
+ (pdram_timing->trcd << 8));
+ clrsetbits_le32(&denali_ctl[42], 0x1f << 16,
+ pdram_timing->tmrz << 16);
+ tmp = pdram_timing->tdal ? pdram_timing->tdal :
+ (pdram_timing->twr + pdram_timing->trp);
+ clrsetbits_le32(&denali_ctl[44], 0xff, tmp);
+ clrsetbits_le32(&denali_ctl[45], 0xff, pdram_timing->trp);
+ writel(((pdram_timing->trefi - 8) << 16) | pdram_timing->trfc,
+ &denali_ctl[48]);
+ clrsetbits_le32(&denali_ctl[52], 0xffff, pdram_timing->txp);
+ clrsetbits_le32(&denali_ctl[53], 0xffff << 16,
+ pdram_timing->txpdll << 16);
+ clrsetbits_le32(&denali_ctl[55], 0xf << 24,
+ pdram_timing->tcscke << 24);
+ clrsetbits_le32(&denali_ctl[55], 0xff,
+ pdram_timing->tmrri);
+ writel((pdram_timing->tzqcke << 24) |
+ (pdram_timing->tmrwckel << 16) |
+ (pdram_timing->tckehcs << 8) |
+ pdram_timing->tckelcs,
+ &denali_ctl[56]);
+ clrsetbits_le32(&denali_ctl[60], 0xffff, pdram_timing->txsnr);
+ clrsetbits_le32(&denali_ctl[62], 0xffff << 16,
+ (pdram_timing->tckehcmd << 24) |
+ (pdram_timing->tckelcmd << 16));
+ writel((pdram_timing->tckelpd << 24) |
+ (pdram_timing->tescke << 16) |
+ (pdram_timing->tsr << 8) |
+ pdram_timing->tckckel,
+ &denali_ctl[63]);
+
+ clrsetbits_le32(&denali_ctl[64], 0xfff,
+ (pdram_timing->tcmdcke << 8) |
+ pdram_timing->tcsckeh);
+ clrsetbits_le32(&denali_ctl[92], 0xffff << 8,
+ (pdram_timing->tcksrx << 16) |
+ (pdram_timing->tcksre << 8));
+ clrsetbits_le32(&denali_ctl[108], 0x1 << 24,
+ (timing_config->dllbp << 24));
+ clrsetbits_le32(&denali_ctl[122], 0x3ff << 16,
+ (pdram_timing->tvrcg_enable << 16));
+ writel((pdram_timing->tfc_long << 16) |
+ pdram_timing->tvrcg_disable,
+ &denali_ctl[123]);
+ writel((pdram_timing->tvref_long << 16) |
+ (pdram_timing->tckfspx << 8) |
+ pdram_timing->tckfspe,
+ &denali_ctl[124]);
+
+ writel((pdram_timing->mr[1] << 16) |
+ pdram_timing->mr[0], &denali_ctl[133]);
+ clrsetbits_le32(&denali_ctl[134], 0xffff,
+ pdram_timing->mr[2]);
+ clrsetbits_le32(&denali_ctl[138], 0xffff,
+ pdram_timing->mr[3]);
+ clrsetbits_le32(&denali_ctl[139], 0xff << 24,
+ pdram_timing->mr11 << 24);
+ writel((pdram_timing->mr[1] << 16) |
+ pdram_timing->mr[0],
+ &denali_ctl[147]);
+ clrsetbits_le32(&denali_ctl[148], 0xffff,
+ pdram_timing->mr[2]);
+ clrsetbits_le32(&denali_ctl[152], 0xffff,
+ pdram_timing->mr[3]);
+ clrsetbits_le32(&denali_ctl[153], 0xff << 24,
+ pdram_timing->mr11 << 24);
+ /*
+ if (timing_config->dram_type == LPDDR4) {
+ mmio_clrsetbits_32(CTL_REG(i, 140), 0xffff << 16,
+ pdram_timing->mr12 << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 142), 0xffff << 16,
+ pdram_timing->mr14 << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 145), 0xffff << 16,
+ pdram_timing->mr22 << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 154), 0xffff << 16,
+ pdram_timing->mr12 << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 156), 0xffff << 16,
+ pdram_timing->mr14 << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 159), 0xffff << 16,
+ pdram_timing->mr22 << 16);
+ }
+ */
+
+ clrsetbits_32(&denali_ctl[153], 0xfff << 8,
+ pdram_timing->tzqinit << 8);
+ writel((pdram_timing->tzqcs << 16) | (pdram_timing->tzqinit / 2),
+ &denali_ctl[180]);
+ writel((pdram_timing->tzqlat << 16) | pdram_timing->tzqcal,
+ &denali_ctl[181]);
+ clrsetbits_32(&denali_ctl[212], 0xff << 8,
+ pdram_timing->todton << 8);
+
+ if (timing_config->odt) {
+ setbits_le32(&denali_ctl[213], BIT(16));
+ if (timing_config->freq < 400)
+ tmp = 4;
+ else
+ tmp = 8;
+ } else {
+ clrbits_32(&denali_ctl[213], BIT(16));
+ tmp = 2;
+ }
+
+ /* Additional delay between reads to different chip selects */
+ clrsetbits_32(&denali_ctl[216], 0x1f << 24, tmp << 24);
+
+ clrsetbits_32(&denali_ctl[221], (0x3 << 16) | (0xf << 8),
+ (pdram_timing->tdqsck << 16) |
+ (pdram_timing->tdqsck_max << 8));
+
+ tmp =
+ (get_wrlat_adj(timing_config->dram_type, pdram_timing->cwl)
+ << 8) | get_rdlat_adj(timing_config->dram_type,
+ pdram_timing->cl);
+
+ clrsetbits_le32(&denali_ctl[284], 0xffff, tmp);
+
+ clrsetbits_le32(&denali_ctl[82], 0xffff << 16,
+ (4 * pdram_timing->trefi) << 16);
+
+ clrsetbits_le32(&denali_ctl[83], 0xffff,
+ (2 * pdram_timing->trefi) & 0xffff);
+
+ if ((timing_config->dram_type == LPDDR3) ||
+ (timing_config->dram_type == LPDDR4)) {
+ tmp = get_pi_wrlat(pdram_timing, timing_config);
+ tmp1 = get_pi_todtoff_max(pdram_timing, timing_config);
+ tmp = (tmp > tmp1) ? (tmp - tmp1) : 0;
+ } else {
+ tmp = 0;
+ }
+ clrsetbits_le32(&denali_ctl[214], 0x3f << 16,
+ (tmp & 0x3f) << 16);
+
+ if ((timing_config->dram_type == LPDDR3) ||
+ (timing_config->dram_type == LPDDR4)) {
+ /* min_rl_preamble = cl+TDQSCK_MIN -1 */
+ tmp = pdram_timing->cl +
+ get_pi_todtoff_min(pdram_timing, timing_config) - 1;
+ /* todtoff_max */
+ tmp1 = get_pi_todtoff_max(pdram_timing, timing_config);
+ tmp = (tmp > tmp1) ? (tmp - tmp1) : 0;
+ } else {
+ tmp = pdram_timing->cl - pdram_timing->cwl;
+ }
+ clrsetbits_le32(&denali_ctl[215], 0x3f << 8,
+ (tmp & 0x3f) << 8);
+
+ clrsetbits_le32(&denali_ctl[275], 0xff << 16,
+ (get_pi_tdfi_phy_rdlat(pdram_timing,
+ timing_config) &
+ 0xff) << 16);
+
+ clrsetbits_le32(&denali_ctl[277], 0xffff,
+ (2 * pdram_timing->trefi) & 0xffff);
+
+ clrsetbits_le32(&denali_ctl[282], 0xffff,
+ (2 * pdram_timing->trefi) & 0xffff);
+
+ writel(20 * pdram_timing->trefi,
+ &denali_ctl[283]);
+
+ /* CTL_308 TDFI_CALVL_CAPTURE_F0:RW:16:10 */
+ tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1;
+ if ((20000 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp1++;
+ tmp = (tmp1 >> 1) + (tmp1 % 2) + 5;
+ clrsetbits_le32(&denali_ctl[308], 0x3ff << 16, tmp << 16);
+
+ /* CTL_308 TDFI_CALVL_CC_F0:RW:0:10 */
+ tmp = tmp + 18;
+ clrsetbits_le32(&denali_ctl[308], 0x3ff, tmp);
+
+ /* CTL_314 TDFI_WRCSLAT_F0:RW:8:8 */
+ tmp1 = get_pi_wrlat_adj(pdram_timing, timing_config);
+ if (timing_config->freq <= TDFI_LAT_THRESHOLD_FREQ) {
+ if (tmp1 == 0)
+ tmp = 0;
+ else if (tmp1 < 5)
+ tmp = tmp1 - 1;
+ else
+ tmp = tmp1 - 5;
+ } else {
+ tmp = tmp1 - 2;
+ }
+ clrsetbits_le32(&denali_ctl[314], 0xff << 8, tmp << 8);
+
+ /* CTL_314 TDFI_RDCSLAT_F0:RW:0:8 */
+ if ((timing_config->freq <= TDFI_LAT_THRESHOLD_FREQ) &&
+ (pdram_timing->cl >= 5))
+ tmp = pdram_timing->cl - 5;
+ else
+ tmp = pdram_timing->cl - 2;
+ clrsetbits_le32(&denali_ctl[314], 0xff, tmp);
+ }
+}
+
+static void gen_rk3399_pi_params_f0(const struct chan_info *chan,
+ struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ u32 *denali_pi = chan->pi->denali_pi;
+ u32 tmp;
+
+ /* PI_02 PI_TDFI_PHYMSTR_MAX_F0:RW:0:32 */
+ tmp = 4 * pdram_timing->trefi;
+ writel(tmp, &denali_pi[2]);
+ /* PI_03 PI_TDFI_PHYMSTR_RESP_F0:RW:0:16 */
+ tmp = 2 * pdram_timing->trefi;
+ clrsetbits_le32(&denali_pi[3], 0xffff, tmp);
+ /* PI_07 PI_TDFI_PHYUPD_RESP_F0:RW:16:16 */
+ clrsetbits_le32(&denali_pi[7], 0xffff << 16, tmp << 16);
+
+ tmp = 0;
+ tmp += (pdram_timing->bl / 2) + 4 +
+ (get_pi_rdlat_adj(pdram_timing) - 2) +
+ get_pi_tdfi_phy_rdlat(pdram_timing, timing_config);
+ clrsetbits_le32(&denali_pi[42], 0xff, tmp);
+ clrsetbits_le32(&denali_pi[43], 0x7f << 16, (pdram_timing->cl * 2) << 16);
+
+ /* PI_46 PI_TREF_F0:RW:16:16 */
+ clrsetbits_le32(&denali_pi[46], 0xffff << 16,
+ pdram_timing->trefi << 16);
+ /* PI_46 PI_TRFC_F0:RW:0:10 */
+ clrsetbits_le32(&denali_pi[46], 0x3ff, pdram_timing->trfc);
+
+ /* PI_72 PI_WR_TO_ODTH_F0:RW:16:6 */
+#if 0
+ if ((timing_config->dram_type == LPDDR3) ||
+ (timing_config->dram_type == LPDDR4)) {
+ tmp1 = get_pi_wrlat(pdram_timing, timing_config);
+ tmp2 = get_pi_todtoff_max(pdram_timing, timing_config);
+ if (tmp1 > tmp2)
+ tmp = tmp1 - tmp2;
+ else
+ tmp = 0;
+ } else if (timing_config->dram_type == DDR3) {
+ tmp = 0;
+ }
+#endif
+ tmp = 0;
+ clrsetbits_le32(&denali_pi[72], 0x3f << 16, tmp << 16);
+ /* PI_73 PI_RD_TO_ODTH_F0:RW:8:6 */
+#if 0
+ if ((timing_config->dram_type == LPDDR3) ||
+ (timing_config->dram_type == LPDDR4)) {
+ /* min_rl_preamble = cl + TDQSCK_MIN - 1 */
+ tmp1 = pdram_timing->cl;
+ tmp1 += get_pi_todtoff_min(pdram_timing, timing_config);
+ tmp1--;
+ /* todtoff_max */
+ tmp2 = get_pi_todtoff_max(pdram_timing, timing_config);
+ if (tmp1 > tmp2)
+ tmp = tmp1 - tmp2;
+ else
+ tmp = 0;
+ } else if (timing_config->dram_type == DDR3) {
+ tmp = pdram_timing->cl - pdram_timing->cwl;
+ }
+#endif
+ tmp = pdram_timing->cl - pdram_timing->cwl;
+ clrsetbits_le32(&denali_pi[73], 0x3f << 8, tmp << 8);
+ /* PI_89 PI_RDLAT_ADJ_F0:RW:16:8 */
+ tmp = get_pi_rdlat_adj(pdram_timing);
+ clrsetbits_le32(&denali_pi[89], 0xff << 16, tmp << 16);
+ /* PI_90 PI_WRLAT_ADJ_F0:RW:16:8 */
+ tmp = get_pi_wrlat_adj(pdram_timing, timing_config);
+ clrsetbits_le32(&denali_pi[90], 0xff << 16, tmp << 16);
+ /* PI_125 PI_MR1_DATA_F0_0:RW+:8:16 */
+ clrsetbits_le32(&denali_pi[125], 0xffff << 8,
+ pdram_timing->mr[1] << 8);
+ /* PI_133 PI_MR1_DATA_F0_1:RW+:0:16 */
+ clrsetbits_le32(&denali_pi[133], 0xffff, pdram_timing->mr[1]);
+#if 0 // LPDDR4 only
+ /* PI_140 PI_MR1_DATA_F0_2:RW+:16:16 */
+ clrsetbits_le32(&denali_pi[140], 0xffff << 16,
+ pdram_timing->mr[1] << 16);
+ /* PI_148 PI_MR1_DATA_F0_3:RW+:0:16 */
+ clrsetbits_le32(&denali_pi[148], 0xffff, pdram_timing->mr[1]);
+#endif
+ /* PI_126 PI_MR2_DATA_F0_0:RW+:0:16 */
+ clrsetbits_le32(&denali_pi[126], 0xffff, pdram_timing->mr[2]);
+ /* PI_133 PI_MR2_DATA_F0_1:RW+:16:16 */
+ clrsetbits_le32(&denali_pi[133], 0xffff << 16,
+ pdram_timing->mr[2] << 16);
+#if 0 // LPDDR4
+ /* PI_141 PI_MR2_DATA_F0_2:RW+:0:16 */
+ clrsetbits_le32(&denali_pi[141], 0xffff, pdram_timing->mr[2]);
+ /* PI_148 PI_MR2_DATA_F0_3:RW+:16:16 */
+ clrsetbits_le32(&denali_pi[148], 0xffff << 16,
+ pdram_timing->mr[2] << 16);
+#endif
+ /* PI_156 PI_TFC_F0:RW:0:10 */
+ clrsetbits_le32(&denali_pi[156], 0x3ff,
+ pdram_timing->tfc_long);
+ /* PI_158 PI_TWR_F0:RW:24:6 */
+ clrsetbits_le32(&denali_pi[158], 0x3f << 24,
+ pdram_timing->twr << 24);
+
+ /* PI_158 PI_TWTR_F0:RW:16:6 */
+ clrsetbits_le32(&denali_pi[158], 0x3f << 16,
+ pdram_timing->twtr << 16);
+ /* PI_158 PI_TRCD_F0:RW:8:8 */
+ clrsetbits_le32(&denali_pi[158], 0xff << 8,
+ pdram_timing->trcd << 8);
+ /* PI_158 PI_TRP_F0:RW:0:8 */
+ clrsetbits_le32(&denali_pi[158], 0xff, pdram_timing->trp);
+ /* PI_157 PI_TRTP_F0:RW:24:8 */
+ clrsetbits_le32(&denali_pi[157], 0xff << 24,
+ pdram_timing->trtp << 24);
+ /* PI_159 PI_TRAS_MIN_F0:RW:24:8 */
+ clrsetbits_le32(&denali_pi[159], 0xff << 24,
+ pdram_timing->tras_min << 24);
+ /* PI_159 PI_TRAS_MAX_F0:RW:0:17 */
+ tmp = pdram_timing->tras_max * 99 / 100;
+ clrsetbits_le32(&denali_pi[159], 0x1ffff, tmp);
+ /* PI_160 PI_TMRD_F0:RW:16:6 */
+ clrsetbits_le32(&denali_pi[160], 0x3f << 16,
+ pdram_timing->tmrd << 16);
+ /*PI_160 PI_TDQSCK_MAX_F0:RW:0:4 */
+ clrsetbits_le32(&denali_pi[160], 0xf,
+ pdram_timing->tdqsck_max);
+ /* PI_187 PI_TDFI_CTRLUPD_MAX_F0:RW:8:16 */
+ clrsetbits_le32(&denali_pi[187], 0xffff << 8,
+ (2 * pdram_timing->trefi) << 8);
+ /* PI_188 PI_TDFI_CTRLUPD_INTERVAL_F0:RW:0:32 */
+ writel(20 * pdram_timing->trefi, &denali_pi[188]);
+
+#if 0
+ /* PI_43 PI_WRLAT_F0:RW:0:5 */
+ if (timing_config->dram_type == LPDDR3) {
+ tmp = get_pi_wrlat(pdram_timing, timing_config);
+ mmio_clrsetbits_32(PI_REG(i, 43), 0x1f, tmp);
+ }
+#endif
+
+ /* PI_43 PI_ADDITIVE_LAT_F0:RW:8:6 */
+ clrsetbits_le32(&denali_pi[43], 0x3f << 8,
+ PI_ADD_LATENCY << 8);
+ /* PI_43 PI_CASLAT_LIN_F0:RW:16:7 */
+ clrsetbits_le32(&denali_pi[43], 0x7f << 16,
+ (pdram_timing->cl * 2) << 16);
+
+#if 0
+ /* PI_66 PI_TODTL_2CMD_F0:RW:24:8 */
+ if (timing_config->dram_type == LPDDR3) {
+ tmp = get_pi_todtoff_max(pdram_timing, timing_config);
+ mmio_clrsetbits_32(PI_REG(i, 66), 0xff << 24,
+ tmp << 24);
+ }
+#endif
+
+ /* PI_91 PI_TDFI_WRCSLAT_F0:RW:16:8 */
+ tmp = get_pi_wrlat_adj(pdram_timing, timing_config);;
+ u32 tmp1 = tmp; // TODO: can be removed
+ if (tmp1 == 0)
+ tmp = 0;
+ else if (tmp1 < 5)
+ tmp = tmp1 - 1;
+ else
+ tmp = tmp1 - 5;
+ clrsetbits_le32(&denali_pi[91], 0xff << 16, tmp << 16);
+
+ /* PI_95 PI_TDFI_CALVL_CAPTURE_F0:RW:16:10 */
+ tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1;
+ if ((20000 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp1++;
+ tmp = (tmp1 >> 1) + (tmp1 % 2) + 5;
+ clrsetbits_le32(&denali_pi[95], 0x3ff << 16, tmp << 16);
+ /* PI_95 PI_TDFI_CALVL_CC_F0:RW:0:10 */
+ clrsetbits_le32(&denali_pi[95], 0x3ff, tmp + 18);
+
+ /* PI_102 PI_TMRZ_F0:RW:8:5 */
+ clrsetbits_le32(&denali_pi[102], 0x1f << 8,
+ pdram_timing->tmrz << 8);
+ /* PI_111 PI_TDFI_CALVL_STROBE_F0:RW:8:4 */
+ tmp1 = 2 * 1000 / (1000000 / pdram_timing->mhz);
+ if ((2 * 1000 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp1++;
+ /* pi_tdfi_calvl_strobe=tds_train+5 */
+ tmp = tmp1 + 5;
+ clrsetbits_le32(&denali_pi[111], 0xf << 8, tmp << 8);
+ /* PI_116 PI_TCKEHDQS_F0:RW:16:6 */
+ tmp = 10000 / (1000000 / pdram_timing->mhz);
+ if ((10000 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp++;
+ if (pdram_timing->mhz <= 100)
+ tmp = tmp + 1;
+ else
+ tmp = tmp + 8;
+ clrsetbits_le32(&denali_pi[116], 0x3f << 16, tmp << 16);
+
+}
+
+static void gen_rk3399_ctl_params_f1(const struct chan_info *chan,
+ struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ u32 *denali_ctl = chan->pctl->denali_ctl;
+ // u32 *denali_pi = chan->pi->denali_pi;
+ // u32 *denali_phy = chan->publ->denali_phy;
+ uint32_t i;
+ uint32_t tmp, tmp1;
+
+ // TODO: don't loop here?
+ for (i = 0; i < timing_config->ch_cnt; i++) {
+ if (timing_config->dram_type == DDR3) {
+ tmp = ((700000 + 10) * timing_config->freq +
+ 999) / 1000;
+ tmp += pdram_timing->txsnr + (pdram_timing->tmrd * 3) +
+ pdram_timing->tmod + pdram_timing->tzqinit;
+ writel(tmp, &denali_ctl[9]);
+
+ clrsetbits_le32(&denali_ctl[22], 0xffff << 16, pdram_timing->tdllk << 16);
+
+ tmp = (pdram_timing->tmod << 24) |
+ (pdram_timing->tmrd << 16) |
+ (pdram_timing->trtp << 8);
+ writel(tmp, &denali_ctl[34]);
+
+ clrsetbits_le32(&denali_ctl[60], 0xffff << 16,
+ (pdram_timing->txsr - pdram_timing->trcd) << 16);
+#if 0
+ } else if (timing_config->dram_type == LPDDR4) {
+ mmio_write_32(CTL_REG(i, 5), pdram_timing->tinit1 +
+ pdram_timing->tinit3);
+ mmio_write_32(CTL_REG(i, 32),
+ (pdram_timing->tmrd << 8) |
+ pdram_timing->tmrd);
+ mmio_clrsetbits_32(CTL_REG(i, 59), 0xffff << 16,
+ pdram_timing->txsr << 16);
+ } else {
+ mmio_write_32(CTL_REG(i, 5), pdram_timing->tinit1);
+ mmio_write_32(CTL_REG(i, 7), pdram_timing->tinit4);
+ mmio_write_32(CTL_REG(i, 32),
+ (pdram_timing->tmrd << 8) |
+ pdram_timing->tmrd);
+ mmio_clrsetbits_32(CTL_REG(i, 59), 0xffff << 16,
+ pdram_timing->txsr << 16);
+#endif
+ }
+ writel(pdram_timing->tinit3, &denali_ctl[10]);
+ writel(pdram_timing->tinit5, &denali_ctl[12]);
+ clrsetbits_le32(&denali_ctl[24], (0x7f << 8),
+ ((pdram_timing->cl * 2) << 8));
+ clrsetbits_le32(&denali_ctl[24], (0x1f << 16),
+ (pdram_timing->cwl << 16));
+ clrsetbits_le32(&denali_ctl[24], 0x3f << 24, pdram_timing->al << 24);
+ clrsetbits_le32(&denali_ctl[28], 0xffffff << 8,
+ (pdram_timing->tras_min << 24) |
+ (pdram_timing->trc << 16) |
+ (pdram_timing->trrd << 8));
+ clrsetbits_le32(&denali_ctl[29], 0xffffff,
+ (pdram_timing->tfaw << 16) |
+ (pdram_timing->trppb << 8) |
+ (pdram_timing->twtr));
+
+ writel(pdram_timing->tras_max | (pdram_timing->tcke << 24),
+ &denali_ctl[35]);
+
+ clrsetbits_le32(&denali_ctl[36], 0xff,
+ max(1, pdram_timing->tckesr));
+ clrsetbits_le32(&denali_ctl[39],
+ (0xff << 24),
+ (pdram_timing->trcd << 24));
+ clrsetbits_le32(&denali_ctl[40], 0x3f, pdram_timing->twr);
+ clrsetbits_le32(&denali_ctl[42], 0x1f << 24,
+ pdram_timing->tmrz << 24);
+ tmp = pdram_timing->tdal ? pdram_timing->tdal :
+ (pdram_timing->twr + pdram_timing->trp);
+ clrsetbits_le32(&denali_ctl[44], 0xff << 8, tmp << 8);
+ clrsetbits_le32(&denali_ctl[45], 0xff << 8, pdram_timing->trp << 8);
+ writel(((pdram_timing->trefi - 8) << 16) | pdram_timing->trfc,
+ &denali_ctl[49]);
+ clrsetbits_le32(&denali_ctl[52], 0xffff << 16, pdram_timing->txp << 16);
+ clrsetbits_le32(&denali_ctl[54], 0xffff, pdram_timing->txpdll);
+ // clrsetbits_le32(&denali_ctl[55], 0xf << 24,
+ // pdram_timing->tcscke << 24);
+ clrsetbits_le32(&denali_ctl[55], 0xff << 8,
+ pdram_timing->tmrri << 8);
+ writel((pdram_timing->tzqcke << 24) |
+ (pdram_timing->tmrwckel << 16) |
+ (pdram_timing->tckehcs << 8) |
+ pdram_timing->tckelcs,
+ &denali_ctl[57]);
+ //
+ clrsetbits_le32(&denali_ctl[61], 0xffff, pdram_timing->txsnr);
+ clrsetbits_le32(&denali_ctl[64], 0xffff << 16,
+ (pdram_timing->tckehcmd << 24) |
+ (pdram_timing->tckelcmd << 16));
+ writel((pdram_timing->tckelpd << 24) |
+ (pdram_timing->tescke << 16) |
+ (pdram_timing->tsr << 8) |
+ pdram_timing->tckckel,
+ &denali_ctl[65]);
+
+ clrsetbits_le32(&denali_ctl[66], 0xfff,
+ (pdram_timing->tcmdcke << 8) |
+ pdram_timing->tcsckeh);
+ clrsetbits_le32(&denali_ctl[92], 0xff << 24,
+ (pdram_timing->tcksre << 24));
+ clrsetbits_le32(&denali_ctl[93], 0xff, pdram_timing->tcksrx);
+ clrsetbits_le32(&denali_ctl[108], 0x1 << 25,
+ (timing_config->dllbp << 25));
+ clrsetbits_le32(&denali_ctl[125], 0x3ff << 16,
+ (pdram_timing->tvrcg_enable << 16));
+ writel(pdram_timing->tfc_long |
+ (pdram_timing->tckfspx << 24) |
+ (pdram_timing->tckfspe << 16),
+ &denali_ctl[126]);
+ clrsetbits_le32(&denali_ctl[127], 0xffff, pdram_timing->tvref_long);
+
+ clrsetbits_le32(&denali_ctl[134], 0xffff << 16,
+ pdram_timing->mr[0] << 16);
+ writel((pdram_timing->mr[2] << 16) |
+ pdram_timing->mr[1], &denali_ctl[135]);
+ clrsetbits_le32(&denali_ctl[138], 0xffff << 16,
+ pdram_timing->mr[3] << 16);
+ clrsetbits_le32(&denali_ctl[140], 0xff,
+ pdram_timing->mr11);
+ clrsetbits_le32(&denali_ctl[148], 0xffff << 16,
+ pdram_timing->mr[0] << 16);
+ writel((pdram_timing->mr[2] << 16) |
+ pdram_timing->mr[1],
+ &denali_ctl[149]);
+ clrsetbits_le32(&denali_ctl[152], 0xffff << 16,
+ pdram_timing->mr[3] << 16);
+ clrsetbits_le32(&denali_ctl[154], 0xff,
+ pdram_timing->mr11);
+ /*
+ if (timing_config->dram_type == LPDDR4) {
+ mmio_clrsetbits_32(CTL_REG(i, 140), 0xffff << 16,
+ pdram_timing->mr12 << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 142), 0xffff << 16,
+ pdram_timing->mr14 << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 145), 0xffff << 16,
+ pdram_timing->mr22 << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 154), 0xffff << 16,
+ pdram_timing->mr12 << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 156), 0xffff << 16,
+ pdram_timing->mr14 << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 159), 0xffff << 16,
+ pdram_timing->mr22 << 16);
+ }
+ */
+ writel(((pdram_timing->tzqinit / 2) << 16) |
+ pdram_timing->tzqinit,
+ &denali_ctl[182]);
+ writel((pdram_timing->tzqcal << 16) | pdram_timing->tzqcs,
+ &denali_ctl[183]);
+
+ clrsetbits_le32(&denali_ctl[184], 0x3f, pdram_timing->tzqlat);
+ clrsetbits_le32(&denali_ctl[188], 0xfff, pdram_timing->tzqreset);
+ clrsetbits_le32(&denali_ctl[212], 0xff << 16,
+ pdram_timing->todton << 16);
+
+ if (timing_config->odt) {
+ setbits_le32(&denali_ctl[213], BIT(24));
+ if (timing_config->freq < 400)
+ tmp = 4;
+ else
+ tmp = 8;
+ } else {
+ clrbits_le32(&denali_ctl[213], BIT(24));
+ tmp = 2;
+ }
+
+ /* Additional delay between reads to different chip selects */
+ clrsetbits_le32(&denali_ctl[217], 0x1f << 24, tmp << 24);
+
+ clrsetbits_le32(&denali_ctl[221], 0xf << 24,
+ (pdram_timing->tdqsck_max << 24));
+ clrsetbits_le32(&denali_ctl[222], 0x3, pdram_timing->tdqsck);
+
+ tmp =
+ (get_wrlat_adj(timing_config->dram_type, pdram_timing->cwl)
+ << 8) | get_rdlat_adj(timing_config->dram_type,
+ pdram_timing->cl);
+
+ clrsetbits_le32(&denali_ctl[291], 0xffff, tmp);
+
+ clrsetbits_le32(&denali_ctl[84], 0xffff,
+ (4 * pdram_timing->trefi));
+ clrsetbits_le32(&denali_ctl[84], 0xffff << 16,
+ ((2 * pdram_timing->trefi) & 0xffff) << 16);
+
+#if 0
+ if ((timing_config->dram_type == LPDDR3) ||
+ (timing_config->dram_type == LPDDR4)) {
+ tmp = get_pi_wrlat(pdram_timing, timing_config);
+ tmp1 = get_pi_todtoff_max(pdram_timing, timing_config);
+ tmp = (tmp > tmp1) ? (tmp - tmp1) : 0;
+ } else {
+ tmp = 0;
+ }
+#endif
+ tmp = 0;
+ clrsetbits_le32(&denali_ctl[214], 0x3f << 24,
+ (tmp & 0x3f) << 24);
+
+ if ((timing_config->dram_type == LPDDR3) ||
+ (timing_config->dram_type == LPDDR4)) {
+ /* min_rl_preamble = cl+TDQSCK_MIN -1 */
+ tmp = pdram_timing->cl +
+ get_pi_todtoff_min(pdram_timing, timing_config) - 1;
+ /* todtoff_max */
+ tmp1 = get_pi_todtoff_max(pdram_timing, timing_config);
+ tmp = (tmp > tmp1) ? (tmp - tmp1) : 0;
+ } else {
+ tmp = pdram_timing->cl - pdram_timing->cwl;
+ }
+ clrsetbits_le32(&denali_ctl[215], 0x3f << 24,
+ (tmp & 0x3f) << 24);
+
+ clrsetbits_le32(&denali_ctl[275], 0xff << 24,
+ (get_pi_tdfi_phy_rdlat(pdram_timing,
+ timing_config) &
+ 0xff) << 24);
+
+ clrsetbits_le32(&denali_ctl[284], 0xffff << 16,
+ ((2 * pdram_timing->trefi) & 0xffff) << 16);
+
+ clrsetbits_le32(&denali_ctl[289], 0xffff,
+ (2 * pdram_timing->trefi) & 0xffff);
+
+ writel(20 * pdram_timing->trefi,
+ &denali_ctl[290]);
+
+ /* CTL_308 TDFI_CALVL_CAPTURE_F0:RW:16:10 */
+ tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1;
+ if ((20000 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp1++;
+ tmp = (tmp1 >> 1) + (tmp1 % 2) + 5;
+ clrsetbits_le32(&denali_ctl[309], 0x3ff << 16, tmp << 16);
+
+ /* CTL_308 TDFI_CALVL_CC_F1:RW:0:10 */
+ tmp = tmp + 18;
+ clrsetbits_le32(&denali_ctl[309], 0x3ff, tmp);
+
+ // TODO: Merge w/ PI init
+ /* CTL_314 TDFI_WRCSLAT_F1:RW:24:8 */
+ tmp1 = get_pi_wrlat_adj(pdram_timing, timing_config);
+ if (timing_config->freq <= TDFI_LAT_THRESHOLD_FREQ) {
+ if (tmp1 == 0)
+ tmp = 0;
+ else if (tmp1 < 5)
+ tmp = tmp1 - 1;
+ else
+ tmp = tmp1 - 5;
+ } else {
+ tmp = tmp1 - 2;
+ }
+ clrsetbits_le32(&denali_ctl[314], 0xff << 24, tmp << 24);
+
+ /* CTL_314 TDFI_RDCSLAT_F1:RW:16:8 */
+ if ((timing_config->freq <= TDFI_LAT_THRESHOLD_FREQ) &&
+ (pdram_timing->cl >= 5))
+ tmp = pdram_timing->cl - 5;
+ else
+ tmp = pdram_timing->cl - 2;
+ clrsetbits_le32(&denali_ctl[314], 0xff << 16, tmp << 16);
+ }
+}
+
+static void gen_rk3399_pi_params_f1(const struct chan_info *chan,
+ struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ u32 *denali_pi = chan->pi->denali_pi;
+ u32 tmp;
+
+ /* PI_04 PI_TDFI_PHYMSTR_MAX_F1:RW:0:32 */
+ tmp = 4 * pdram_timing->trefi;
+ writel(tmp, &denali_pi[4]);
+ /* PI_05 PI_TDFI_PHYMSTR_RESP_F1:RW:0:16 */
+ tmp = 2 * pdram_timing->trefi;
+ clrsetbits_le32(&denali_pi[5], 0xffff, tmp);
+ /* PI_12 PI_TDFI_PHYUPD_RESP_F1:RW:0:16 */
+ clrsetbits_le32(&denali_pi[12], 0xffff, tmp);
+
+#if 0
+ /* PI_42 PI_TDELAY_RDWR_2_BUS_IDLE_F1:RW:8:8 */
+ if (timing_config->dram_type == LPDDR4)
+ tmp = 2;
+ else
+ tmp = 0;
+#endif
+ tmp = 0;
+ tmp += (pdram_timing->bl / 2) + 4 +
+ (get_pi_rdlat_adj(pdram_timing) - 2) +
+ get_pi_tdfi_phy_rdlat(pdram_timing, timing_config);
+ clrsetbits_le32(&denali_pi[42], 0xff << 8, tmp << 8);
+
+ /* PI_47 PI_TREF_F1:RW:16:16 */
+ clrsetbits_le32(&denali_pi[47], 0xffff << 16,
+ pdram_timing->trefi << 16);
+ /* PI_47 PI_TRFC_F1:RW:0:10 */
+ clrsetbits_le32(&denali_pi[47], 0x3ff, pdram_timing->trfc);
+
+ /* PI_72 PI_WR_TO_ODTH_F1:RW:24:6 */
+#if 0
+ if ((timing_config->dram_type == LPDDR3) ||
+ (timing_config->dram_type == LPDDR4)) {
+ tmp1 = get_pi_wrlat(pdram_timing, timing_config);
+ tmp2 = get_pi_todtoff_max(pdram_timing, timing_config);
+ if (tmp1 > tmp2)
+ tmp = tmp1 - tmp2;
+ else
+ tmp = 0;
+ } else if (timing_config->dram_type == DDR3) {
+ tmp = 0;
+ }
+#endif
+ tmp = 0;
+ clrsetbits_le32(&denali_pi[72], 0x3f << 24, tmp << 24);
+ /* PI_73 PI_RD_TO_ODTH_F1:RW:16:6 */
+#if 0
+ if ((timing_config->dram_type == LPDDR3) ||
+ (timing_config->dram_type == LPDDR4)) {
+ /* min_rl_preamble = cl + TDQSCK_MIN - 1 */
+ tmp1 = pdram_timing->cl +
+ get_pi_todtoff_min(pdram_timing, timing_config);
+ tmp1--;
+ /* todtoff_max */
+ tmp2 = get_pi_todtoff_max(pdram_timing, timing_config);
+ if (tmp1 > tmp2)
+ tmp = tmp1 - tmp2;
+ else
+ tmp = 0;
+ } else if (timing_config->dram_type == DDR3)
+ tmp = pdram_timing->cl - pdram_timing->cwl;
+#endif
+ tmp = pdram_timing->cl - pdram_timing->cwl;
+ clrsetbits_le32(&denali_pi[73], 0x3f << 16, tmp << 16);
+
+ /*P I_89 PI_RDLAT_ADJ_F1:RW:24:8 */
+ tmp = get_pi_rdlat_adj(pdram_timing);
+ clrsetbits_le32(&denali_pi[89], 0xff << 24, tmp << 24);
+ /* PI_90 PI_WRLAT_ADJ_F1:RW:24:8 */
+ tmp = get_pi_wrlat_adj(pdram_timing, timing_config);
+ clrsetbits_le32(&denali_pi[90], 0xff << 24, tmp << 24);
+
+ /* PI_128 PI_MR1_DATA_F1_0:RW+:0:16 */
+ clrsetbits_le32(&denali_pi[128], 0xffff, pdram_timing->mr[1]);
+ /* PI_135 PI_MR1_DATA_F1_1:RW+:8:16 */
+ clrsetbits_le32(&denali_pi[135], 0xffff << 8,
+ pdram_timing->mr[1] << 8);
+#if 0
+ /* PI_143 PI_MR1_DATA_F1_2:RW+:0:16 */
+ clrsetbits_le32(&denali_pi[143], 0xffff, pdram_timing->mr[1]);
+ /* PI_150 PI_MR1_DATA_F1_3:RW+:8:16 */
+ clrsetbits_le32(&denali_pi[150], 0xffff << 8,
+ pdram_timing->mr[1] << 8);
+#endif
+ /* PI_128 PI_MR2_DATA_F1_0:RW+:16:16 */
+ clrsetbits_le32(&denali_pi[128], 0xffff << 16,
+ pdram_timing->mr[2] << 16);
+ /* PI_136 PI_MR2_DATA_F1_1:RW+:0:16 */
+ clrsetbits_le32(&denali_pi[136], 0xffff, pdram_timing->mr[2]);
+#if 0
+ /* PI_143 PI_MR2_DATA_F1_2:RW+:16:16 */
+ clrsetbits_le32(&denali_pi[143], 0xffff << 16,
+ pdram_timing->mr[2] << 16);
+ /* PI_151 PI_MR2_DATA_F1_3:RW+:0:16 */
+ clrsetbits_le32(&denali_pi[151], 0xffff, pdram_timing->mr[2]);
+#endif
+ /* PI_156 PI_TFC_F1:RW:16:10 */
+ clrsetbits_le32(&denali_pi[156], 0x3ff << 16,
+ pdram_timing->tfc_long << 16);
+ /* PI_162 PI_TWR_F1:RW:8:6 */
+ clrsetbits_le32(&denali_pi[162], 0x3f << 8,
+ pdram_timing->twr << 8);
+ /* PI_162 PI_TWTR_F1:RW:0:6 */
+ clrsetbits_le32(&denali_pi[162], 0x3f, pdram_timing->twtr);
+ /* PI_161 PI_TRCD_F1:RW:24:8 */
+ clrsetbits_le32(&denali_pi[161], 0xff << 24,
+ pdram_timing->trcd << 24);
+ /* PI_161 PI_TRP_F1:RW:16:8 */
+ clrsetbits_le32(&denali_pi[161], 0xff << 16,
+ pdram_timing->trp << 16);
+ /* PI_161 PI_TRTP_F1:RW:8:8 */
+ clrsetbits_le32(&denali_pi[161], 0xff << 8,
+ pdram_timing->trtp << 8);
+ /* PI_163 PI_TRAS_MIN_F1:RW:24:8 */
+ clrsetbits_le32(&denali_pi[163], 0xff << 24,
+ pdram_timing->tras_min << 24);
+ /* PI_163 PI_TRAS_MAX_F1:RW:0:17 */
+ clrsetbits_le32(&denali_pi[163], 0x1ffff,
+ pdram_timing->tras_max * 99 / 100);
+ /* PI_164 PI_TMRD_F1:RW:16:6 */
+ clrsetbits_le32(&denali_pi[164], 0x3f << 16,
+ pdram_timing->tmrd << 16);
+ /* PI_164 PI_TDQSCK_MAX_F1:RW:0:4 */
+ clrsetbits_le32(&denali_pi[164], 0xf,
+ pdram_timing->tdqsck_max);
+ /* PI_189 PI_TDFI_CTRLUPD_MAX_F1:RW:0:16 */
+ clrsetbits_le32(&denali_pi[189], 0xffff,
+ 2 * pdram_timing->trefi);
+ /* PI_190 PI_TDFI_CTRLUPD_INTERVAL_F1:RW:0:32 */
+ writel(20 * pdram_timing->trefi, &denali_pi[190]);
+
+#if 0
+ /* PI_43 PI_WRLAT_F1:RW:24:5 */
+ if (timing_config->dram_type == LPDDR3) {
+ tmp = get_pi_wrlat(pdram_timing, timing_config);
+ mmio_clrsetbits_32(PI_REG(i, 43), 0x1f << 24,
+ tmp << 24);
+ }
+#endif
+ /* PI_44 PI_ADDITIVE_LAT_F1:RW:0:6 */
+ clrsetbits_le32(&denali_pi[44], 0x3f, PI_ADD_LATENCY);
+ /* PI_44 PI_CASLAT_LIN_F1:RW:8:7:=0x18 */
+ clrsetbits_le32(&denali_pi[44], 0x7f << 8,
+ (pdram_timing->cl * 2) << 8);
+#if 0
+ /* PI_67 PI_TODTL_2CMD_F1:RW:8:8 */
+ if (timing_config->dram_type == LPDDR3) {
+ tmp = get_pi_todtoff_max(pdram_timing, timing_config);
+ mmio_clrsetbits_32(PI_REG(i, 67), 0xff << 8, tmp << 8);
+ }
+#endif
+ /* PI_91 PI_TDFI_WRCSLAT_F1:RW:24:8 */
+ tmp = get_pi_wrlat_adj(pdram_timing, timing_config);
+ u32 tmp1 = tmp; // TODO: can be removed
+ if (tmp1 == 0)
+ tmp = 0;
+ else if (tmp1 < 5)
+ tmp = tmp1 - 1;
+ else
+ tmp = tmp1 - 5;
+ clrsetbits_le32(&denali_pi[91], 0xff << 24, tmp << 24);
+
+ /*PI_96 PI_TDFI_CALVL_CAPTURE_F1:RW:16:10 */
+ /* tadr=20ns */
+ tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1;
+ if ((20000 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp1++;
+ tmp = (tmp1 >> 1) + (tmp1 % 2) + 5;
+ clrsetbits_le32(&denali_pi[96], 0x3ff << 16, tmp << 16);
+ /* PI_96 PI_TDFI_CALVL_CC_F1:RW:0:10 */
+ tmp = tmp + 18;
+ clrsetbits_le32(&denali_pi[96], 0x3ff, tmp);
+ /*PI_103 PI_TMRZ_F1:RW:0:5 */
+ clrsetbits_le32(&denali_pi[103], 0x1f, pdram_timing->tmrz);
+ /*PI_111 PI_TDFI_CALVL_STROBE_F1:RW:16:4 */
+ /* tds_train=ceil(2/ns) */
+ tmp1 = 2 * 1000 / (1000000 / pdram_timing->mhz);
+ if ((2 * 1000 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp1++;
+ /* pi_tdfi_calvl_strobe=tds_train+5 */
+ tmp = tmp1 + 5;
+ clrsetbits_le32(&denali_pi[111], 0xf << 16,
+ tmp << 16);
+ /* PI_116 PI_TCKEHDQS_F1:RW:24:6 */
+ tmp = 10000 / (1000000 / pdram_timing->mhz);
+ if ((10000 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp++;
+ if (pdram_timing->mhz <= 100)
+ tmp = tmp + 1;
+ else
+ tmp = tmp + 8;
+ clrsetbits_le32(&denali_pi[116], 0x3f << 24,
+ tmp << 24);
+}
+
+static void gen_rk3399_phy_params(const struct chan_info *chan,
+ struct timing_related_config *timing_config,
+ /* struct drv_odt_lp_config *drv_config, */
+ struct dram_timing_t *pdram_timing,
+ uint32_t fn)
+{
+ uint32_t tmp, i, div, j;
+ uint32_t mem_delay_ps, pad_delay_ps, total_delay_ps, delay_frac_ps;
+ uint32_t trpre_min_ps, gate_delay_ps, gate_delay_frac_ps;
+ uint32_t ie_enable, tsel_enable, cas_lat, rddata_en_ie_dly, tsel_adder;
+ uint32_t extra_adder, delta, hs_offset;
+ // u32 fn = 0;
+ u32 *denali_phy = chan->publ->denali_phy;
+
+ for (i = 0; i < timing_config->ch_cnt; i++) {
+
+ pad_delay_ps = PI_PAD_DELAY_PS_VALUE;
+ ie_enable = PI_IE_ENABLE_VALUE;
+ tsel_enable = PI_TSEL_ENABLE_VALUE;
+
+ clrsetbits_le32(&denali_phy[896], (0x3 << 8) | 1, fn << 8);
+
+ /* PHY_LOW_FREQ_SEL */
+ /* DENALI_PHY_913 1bit offset_0 */
+ if (timing_config->freq > 400)
+ clrbits_le32(&denali_phy[913], 1);
+ else
+ setbits_le32(&denali_phy[913], 1);
+
+ /* PHY_RPTR_UPDATE_x */
+ /* DENALI_PHY_87/215/343/471 4bit offset_16 */
+ tmp = 2500 / (1000000 / pdram_timing->mhz) + 3;
+ if ((2500 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp++;
+ clrsetbits_le32(&denali_phy[87], 0xf << 16, tmp << 16);
+ clrsetbits_le32(&denali_phy[215], 0xf << 16, tmp << 16);
+ clrsetbits_le32(&denali_phy[343], 0xf << 16, tmp << 16);
+ clrsetbits_le32(&denali_phy[471], 0xf << 16, tmp << 16);
+
+ /* PHY_PLL_CTRL */
+ /* DENALI_PHY_911 13bits offset_0 */
+ /* PHY_LP4_BOOT_PLL_CTRL */
+ /* DENALI_PHY_919 13bits offset_0 */
+ tmp = (1 << 12) | (2 << 7) | (1 << 1);
+ clrsetbits_le32(&denali_phy[911], 0x1fff, tmp);
+ clrsetbits_le32(&denali_phy[919], 0x1fff, tmp);
+
+ /* PHY_PLL_CTRL_CA */
+ /* DENALI_PHY_911 13bits offset_16 */
+ /* PHY_LP4_BOOT_PLL_CTRL_CA */
+ /* DENALI_PHY_919 13bits offset_16 */
+ tmp = (2 << 7) | (1 << 5) | (1 << 1);
+ clrsetbits_le32(&denali_phy[911], 0x1fff << 16, tmp << 16);
+ clrsetbits_le32(&denali_phy[919], 0x1fff << 16, tmp << 16);
+
+ /* PHY_TCKSRE_WAIT */
+ /* DENALI_PHY_922 4bits offset_24 */
+ if (pdram_timing->mhz <= 400)
+ tmp = 1;
+ else if (pdram_timing->mhz <= 800)
+ tmp = 3;
+ else if (pdram_timing->mhz <= 1000)
+ tmp = 4;
+ else
+ tmp = 5;
+ clrsetbits_le32(&denali_phy[922], 0xf << 24, tmp << 24);
+ /* PHY_CAL_CLK_SELECT_0:RW8:3 */
+ div = pdram_timing->mhz / (2 * 20);
+ for (j = 2, tmp = 1; j <= 128; j <<= 1, tmp++) {
+ if (div < j)
+ break;
+ }
+ clrsetbits_le32(&denali_phy[947], 0x7 << 8, tmp << 8);
+
+ if (timing_config->dram_type == DDR3) {
+ mem_delay_ps = 0;
+ trpre_min_ps = 1000;
+ } else if (timing_config->dram_type == LPDDR4) {
+ mem_delay_ps = 1500;
+ trpre_min_ps = 900;
+ } else if (timing_config->dram_type == LPDDR3) {
+ mem_delay_ps = 2500;
+ trpre_min_ps = 900;
+ } else {
+ printf("gen_rk3399_phy_params:dramtype unsupport\n");
+ return;
+ }
+ total_delay_ps = mem_delay_ps + pad_delay_ps;
+ delay_frac_ps = 1000 * total_delay_ps /
+ (1000000 / pdram_timing->mhz);
+ gate_delay_ps = delay_frac_ps + 1000 - (trpre_min_ps / 2);
+ gate_delay_frac_ps = gate_delay_ps % 1000;
+ tmp = gate_delay_frac_ps * 0x200 / 1000;
+ /* PHY_RDDQS_GATE_SLAVE_DELAY */
+ /* DENALI_PHY_77/205/333/461 10bits offset_16 */
+ clrsetbits_le32(&denali_phy[77], 0x2ff << 16, tmp << 16);
+ clrsetbits_le32(&denali_phy[205], 0x2ff << 16, tmp << 16);
+ clrsetbits_le32(&denali_phy[333], 0x2ff << 16, tmp << 16);
+ clrsetbits_le32(&denali_phy[461], 0x2ff << 16, tmp << 16);
+
+ tmp = gate_delay_ps / 1000;
+ /* PHY_LP4_BOOT_RDDQS_LATENCY_ADJUST */
+ /* DENALI_PHY_10/138/266/394 4bit offset_0 */
+ clrsetbits_le32(&denali_phy[10], 0xf, tmp);
+ clrsetbits_le32(&denali_phy[138], 0xf, tmp);
+ clrsetbits_le32(&denali_phy[266], 0xf, tmp);
+ clrsetbits_le32(&denali_phy[394], 0xf, tmp);
+ /* PHY_GTLVL_LAT_ADJ_START */
+ /* DENALI_PHY_80/208/336/464 4bits offset_16 */
+ tmp = rddqs_delay_ps / (1000000 / pdram_timing->mhz) + 2;
+ clrsetbits_le32(&denali_phy[80], 0xf << 16, tmp << 16);
+ clrsetbits_le32(&denali_phy[208], 0xf << 16, tmp << 16);
+ clrsetbits_le32(&denali_phy[336], 0xf << 16, tmp << 16);
+ clrsetbits_le32(&denali_phy[464], 0xf << 16, tmp << 16);
+
+ cas_lat = pdram_timing->cl + PI_ADD_LATENCY;
+ rddata_en_ie_dly = ie_enable / (1000000 / pdram_timing->mhz);
+ if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0)
+ rddata_en_ie_dly++;
+ rddata_en_ie_dly = rddata_en_ie_dly - 1;
+ tsel_adder = tsel_enable / (1000000 / pdram_timing->mhz);
+ if ((tsel_enable % (1000000 / pdram_timing->mhz)) != 0)
+ tsel_adder++;
+ if (rddata_en_ie_dly > tsel_adder)
+ extra_adder = rddata_en_ie_dly - tsel_adder;
+ else
+ extra_adder = 0;
+ delta = cas_lat - rddata_en_ie_dly;
+ if (PI_REGS_DIMM_SUPPORT && PI_DOUBLEFREEK)
+ hs_offset = 2;
+ else
+ hs_offset = 1;
+ if (rddata_en_ie_dly > (cas_lat - 1 - hs_offset))
+ tmp = 0;
+ else if ((delta == 2) || (delta == 1))
+ tmp = rddata_en_ie_dly - 0 - extra_adder;
+ else
+ tmp = extra_adder;
+ /* PHY_LP4_BOOT_RDDATA_EN_TSEL_DLY */
+ /* DENALI_PHY_9/137/265/393 4bit offset_16 */
+ clrsetbits_le32(&denali_phy[9], 0xf << 16, tmp << 16);
+ clrsetbits_le32(&denali_phy[137], 0xf << 16, tmp << 16);
+ clrsetbits_le32(&denali_phy[265], 0xf << 16, tmp << 16);
+ clrsetbits_le32(&denali_phy[393], 0xf << 16, tmp << 16);
+ /* PHY_RDDATA_EN_TSEL_DLY */
+ /* DENALI_PHY_86/214/342/470 4bit offset_0 */
+ clrsetbits_le32(&denali_phy[86], 0xf, tmp);
+ clrsetbits_le32(&denali_phy[214], 0xf, tmp);
+ clrsetbits_le32(&denali_phy[342], 0xf, tmp);
+ clrsetbits_le32(&denali_phy[470], 0xf, tmp);
+
+ if (tsel_adder > rddata_en_ie_dly)
+ extra_adder = tsel_adder - rddata_en_ie_dly;
+ else
+ extra_adder = 0;
+ if (rddata_en_ie_dly > (cas_lat - 1 - hs_offset))
+ tmp = tsel_adder;
+ else
+ tmp = rddata_en_ie_dly - 0 + extra_adder;
+ /* PHY_LP4_BOOT_RDDATA_EN_DLY */
+ /* DENALI_PHY_9/137/265/393 4bit offset_8 */
+ clrsetbits_le32(&denali_phy[9], 0xf << 8, tmp << 8);
+ clrsetbits_le32(&denali_phy[137], 0xf << 8, tmp << 8);
+ clrsetbits_le32(&denali_phy[265], 0xf << 8, tmp << 8);
+ clrsetbits_le32(&denali_phy[393], 0xf << 8, tmp << 8);
+ /* PHY_RDDATA_EN_DLY */
+ /* DENALI_PHY_85/213/341/469 4bit offset_24 */
+ clrsetbits_le32(&denali_phy[85], 0xf << 24, tmp << 24);
+ clrsetbits_le32(&denali_phy[213], 0xf << 24, tmp << 24);
+ clrsetbits_le32(&denali_phy[341], 0xf << 24, tmp << 24);
+ clrsetbits_le32(&denali_phy[469], 0xf << 24, tmp << 24);
+
+ if (pdram_timing->mhz <= ENPER_CS_TRAINING_FREQ) {
+ /*
+ * Note:Per-CS Training is not compatible at speeds
+ * under 533 MHz. If the PHY is running at a speed
+ * less than 533MHz, all phy_per_cs_training_en_X
+ * parameters must be cleared to 0.
+ */
+
+ /*DENALI_PHY_84/212/340/468 1bit offset_16 */
+ clrbits_le32(&denali_phy[84], 0x1 << 16);
+ clrbits_le32(&denali_phy[212], 0x1 << 16);
+ clrbits_le32(&denali_phy[340], 0x1 << 16);
+ clrbits_le32(&denali_phy[468], 0x1 << 16);
+ } else {
+ setbits_le32(&denali_phy[84], 0x1 << 16);
+ setbits_le32(&denali_phy[212], 0x1 << 16);
+ setbits_le32(&denali_phy[340], 0x1 << 16);
+ setbits_le32(&denali_phy[468], 0x1 << 16);
+ }
+ // gen_rk3399_phy_dll_bypass(pdram_timing->mhz, i, fn,
+ // timing_config->dram_type);
+ phy_dll_bypass_set(chan->publ, pdram_timing->mhz, i, fn, timing_config->dram_type);
+ }
+}
+
+static void gen_rk3399_enable_training(u32 *denali_ctl, uint32_t nmhz)
+{
+ uint32_t tmp;
+
+ if (nmhz <= PHY_DLL_BYPASS_FREQ)
+ tmp = 0;
+ else
+ tmp = 1;
+
+ clrsetbits_le32(&denali_ctl[305], 1 << 16, tmp << 16);
+ clrsetbits_le32(&denali_ctl[71], 1, tmp);
+ clrsetbits_le32(&denali_ctl[70], 1 << 8, 1 << 8);
+}
+
+static int pctl_cfg(struct udevice *dev,
+ const struct chan_info *chan, u32 channel,
const struct rk3399_sdram_params *sdram_params)
{
+ /* const struct rk3399_sdram_channel *sdram_ch =
+ &sdram_params->ch[channel]; */
u32 *denali_ctl = chan->pctl->denali_ctl;
u32 *denali_pi = chan->pi->denali_pi;
u32 *denali_phy = chan->publ->denali_phy;
- const u32 *params_ctl = sdram_params->pctl_regs.denali_ctl;
- const u32 *params_phy = sdram_params->phy_regs.denali_phy;
u32 tmp, tmp1, tmp2;
u32 pwrup_srefresh_exit;
int ret;
const ulong timeout_ms = 200;
+ struct dram_timing_t dram_timing;
+ struct timing_related_config timing_config;
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+ struct rockchip_dmc_plat *plat = dev_get_platdata(dev);
+#endif
+
+ timing_config.dram_type = DDR3;
+ timing_config.dram_info[0].speed_rate = DDR3_1866M; //DDR3_1600K;
+ // timing_config.dram_info[0].speed_rate = DDR3_1600K;
+ timing_config.dram_info[0].cs_cnt = 1;
+ timing_config.dram_info[1].speed_rate = DDR3_1866M; //DDR3_1600K;
+ // timing_config.dram_info[1].speed_rate = DDR3_1600K;
+ timing_config.dram_info[1].cs_cnt = 1;
+ timing_config.ch_cnt = 1;
+ timing_config.odt = 1;
+ timing_config.freq = sdram_params->base.ddr_freq;
+ timing_config.bl = 8;
+ timing_config.ap = 0;
+ /*
+ if (mhz < 300)
+ rk3399_dram_status.timing_config.dllbp = 1;
+ else
+ rk3399_dram_status.timing_config.dllbp = 0;
+ */
+ timing_config.dllbp = 0;
+ timing_config.dramds = 34;
+ timing_config.dramodt = 60;
+ // timing_config.dramodt = 40;
+ /* timing_config.caodt = 120; */ /* NOT USED FOR DDR3 */
+
+ // dram_get_parameter(&timing_config, &dram_timing);
+ spd_decode_ddr3(&plat->spd[0], timing_config.freq, &dram_timing);
/*
* 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);
- writel(params_ctl[0], &denali_ctl[0]);
- copy_to_reg(denali_pi, &sdram_params->pi_regs.denali_pi[0],
- sizeof(struct rk3399_ddr_pi_regs));
- /* rank count need to set for init */
+ // 40: ok w/ spec
+ // 60: ok w/ spec(gcc)
+ // 130: ok w/ spec(gcc)
+ // 182: ok w/ spec(gcc)
+ // 201: ok w/ spec(gcc)
+ // 225: ok w/ spec(gcc)
+ // 284
+ // 299
+ // 300
+ //
+
+#if 1
+ /* initialize PCTL */
+
+ /*
+ * Disable MRR commands during initialization.
+ * Set to 1 to disable.
+ */
+ /* DENALI_CTL_16 */
+ const u32 NO_AUTO_MRR_INIT = BIT(24);
+
+ /* DENALI_CTL_18 */
+ /*
+ * Enable PHY independent training mode commands during initialization.
+ * Set to 1 to enable.
+ */
+ const u32 PHY_INDEP_TRAIN_MODE = BIT(8);
+ /*
+ * Disable PHY Independent Training during initialization.
+ * Set to 1 to disable.
+ */
+ const u32 NO_PHY_IND_TRAIN_INIT = BIT(0);
+
+ setbits_le32(&denali_ctl[16], NO_AUTO_MRR_INIT);
+ dmb();
+
+ setbits_le32(&denali_ctl[18], PHY_INDEP_TRAIN_MODE |
+ NO_PHY_IND_TRAIN_INIT);
+
+ /* 1:1 mapping for DFIBUS frequencies at F0..F2 */
+ clrsetbits_le32(&denali_ctl[19], 0x1f1f1f, 0x020100);
+
+ /* for ddr3 */
+ /* tRST_PWRON */
+ writel(dram_timing.trstl, &denali_ctl[20]);
+ /* CKE-inactive */
+ writel(dram_timing.trsth, &denali_ctl[21]);
+
+ /* LPC_SR_ZQ_EN */
+ const u32 LPC_SR_ZQ_EN = BIT(16);
+ const u32 LPC_SR_PHYMSTR_EN = BIT(0);
+ setbits_le32(&denali_ctl[107], LPC_SR_ZQ_EN | LPC_SR_PHYMSTR_EN);
+
+ /* TBST_INT_INTERVAL */
+ clrsetbits_le32(&denali_ctl[25], 0x7 << 24, 0x4 << 24);
+ /* BST_LEN */
+ /*
+ * Encoded burst length sent to DRAMs during initialization.
+ * Program to 1 for BL2, program to 2 for BL4, or program to 3 for BL8.
+ */
+ clrsetbits_le32(&denali_ctl[44], 0x1f << 24, 3 << 24);
+
+ /* TREF_ENABLE - start refreshes */
+ const u32 TREF_ENABLE = BIT(16);
+ setbits_le32(&denali_ctl[47], TREF_ENABLE);
+ // CHECK: [47] := 0x03 << 24;
+
+ /* CONCURRENTAP */
+ const u32 CONCURRENTAP = BIT(16);
+ setbits_le32(&denali_ctl[43], CONCURRENTAP);
+
+ /* Basic settings for DFS and DFI */
+ const u32 DFS_ENABLE = BIT(16);
+ setbits_le32(&denali_ctl[108], DFS_ENABLE);
+ /* */
+ const u32 TDFI_INIT_START_F0 = 0x20;
+ const u32 TDFI_INIT_START_F1 = 0x20;
+ const u32 TDFI_INIT_START_F2 = 0x20;
+ const u32 TDFI_INIT_COMPLETE_F0 = 0x400;
+ const u32 TDFI_INIT_COMPLETE_F1 = 0x400;
+ const u32 TDFI_INIT_COMPLETE_F2 = 0x400;
+ const u32 DFS_PHY_REG_WRITE_EN = BIT(24);
+
+ writel((TDFI_INIT_START_F1 << 24) |
+ (TDFI_INIT_COMPLETE_F0 << 8) |
+ TDFI_INIT_START_F0, &denali_ctl[109]);
+ writel((TDFI_INIT_START_F2 << 16) | TDFI_INIT_COMPLETE_F1,
+ &denali_ctl[110]);
+ clrsetbits_le32(&denali_ctl[111], 0x0100ffff,
+ DFS_PHY_REG_WRITE_EN | TDFI_INIT_COMPLETE_F2);
+
+ writel(0xb80, &denali_ctl[112]); /* DFS_PHY_REG_WRITE_ADDR */
+ writel(0x0, &denali_ctl[113]); /* DFS_PHY_REG_WRITE_DATA_F0 */
+ writel(0x1, &denali_ctl[114]); /* DFS_PHY_REG_WRITE_DATA_F1 */
+ writel(0x2, &denali_ctl[115]); /* DFS_PHY_REG_WRITE_DATA_F2 */
+ writel(0xe, &denali_ctl[116]); /* DFS_PHY_REG_WRITE_MASK */
+
+ /* AREF_MAX_DEFICIT, AREF_HIGH_THRESHOLD, AREF_NORM_THRESHOLD */
+ writel(0x18151100, &denali_ctl[164]);
+ /* AREF_MAX_CREDIT */
+ clrsetbits_le32(&denali_ctl[165], 0x1f, 0xc);
+
+ const u32 ZQCS_ROTATE = BIT(8);
+ setbits_le32(&denali_ctl[189], ZQCS_ROTATE); /* TODO: via DTS */
+
+ // const u32 COL_DIFF = (12 - sdram_ch->col); // was: 2
+ // clrsetbits_le32(&denali_ctl[191], 0xf, COL_DIFF);
+ // TODO: collocate w/ pi[199]
+
+ /* COMMAND_AGE_COUNT and AGE_COUNT */
+ // TODO - configurable
+ const u32 COMMAND_AGE_COUNT = 0x7;
+ const u32 AGE_COUNT = 0x7;
+ clrsetbits_le32(&denali_ctl[192], 0x0f0f,
+ (COMMAND_AGE_COUNT << 8) | AGE_COUNT);
+ // CHECK:
+ setbits_le32(&denali_ctl[192], BIT(24));
+
+ /* configurable command queuing */
+ // TODO - make configurable
+ const u32 RW_SAME_EN = BIT(24);
+ const u32 PRIORITY_EN = BIT(16);
+ const u32 PLACEMENT_EN = BIT(8);
+ const u32 BANK_SPLIT_EN = BIT(0);
+ clrbits_le32(&denali_ctl[193],
+ RW_SAME_EN | PRIORITY_EN |
+ PLACEMENT_EN | BANK_SPLIT_EN);
+
+ /* TODO: more command queuing policy in #194 */
+ // TODO - make configurable
+ const u32 DISABLE_RD_INTERLEAVE = BIT(16);
+ clrsetbits_le32(&denali_ctl[195], 0x7, DISABLE_RD_INTERLEAVE | 0x3); /* NUM_Q_ENTRIES_ACT_DISABLE */
+
+ /* BC# is A12 for DDR3 */
+ clrsetbits_le32(&denali_ctl[196], 0xf << 8, 12 << 8);
+
+ /* TODO: Programm MEMDATA_RATIO_0 for dual-rank */
+ // clrsetbits_le32(&denali_ctl[197], 7, 1);
+
+ /*
+ * Force the controller to accept commands in the order that
+ * they are placed in the command queue.
+ */
+ // TODO: make configurable
+ const u32 IN_ORDER_ACCEPT = BIT(24);
+ setbits_le32(&denali_ctl[199], IN_ORDER_ACCEPT);
+
+ /*
+ * Enable Enable an automatic controller-initiated update
+ * (dfi_ctrlupd_req) after every refresh.
+ */
+ const u32 CTRLUPD_REQ_PER_AREF_EN = BIT(16);
+ setbits_le32(&denali_ctl[200], CTRLUPD_REQ_PER_AREF_EN);
+
+ const u32 RD_PREAMBLE_TRAINING_EN = BIT(0);
+ setbits_le32(&denali_ctl[201], RD_PREAMBLE_TRAINING_EN);
+
+ /* Enable ODT on writes */
+ // TODO: sync/colocate w/ pi_odt_wr_map_cs1, pi_odt_wr_map_cs0
+ // CHECK THESE:
+ setbits_le32(&denali_ctl[211], BIT(16)); /* on CS0 for writes to CS0 */
+ setbits_le32(&denali_ctl[212], BIT(1)); /* on CS1 for writes to CS1 */
+
+ /* TODTL_2CMD_F{0,1,2} */
+ // CHECK THESE AGAINST JEDEC:
+ // TODO: should this be ODTLoff (WL-2) ???
+ // clrsetbits_le32(&denali_ctl[212], 0xffffff << 8, 0x070707 << 8);
+
+ /* ODT high time*/
+ // TODO
+ // This is true for DDR3 w/ BL8 only
+ /* const u32 tODTH4 = 4; */
+ const u32 tODTH8 = 6;
+ clrsetbits_le32(&denali_ctl[213], 0xf << 8, tODTH8 << 8); // TODTH_RD
+ clrsetbits_le32(&denali_ctl[213], 0xf << 0, tODTH8 << 0); // TODTH_WR
+
+ /* TODO: Make this DTS-configurable */
+ const u32 EN_ODT_ASSERT_EXCEPT_RD = BIT(8);
+ clrbits_le32(&denali_ctl[214], EN_ODT_ASSERT_EXCEPT_RD);
+
+ /* RD_TO_ODTH_F{0,1,2} */
+ // TODO: This doesn't match up with anything in JESD-79 for me ... */
+ // TODO: 040404 for 933, 030303 ok for 800
+ clrsetbits_le32(&denali_ctl[215], 0xffffff << 8, 0x040404 << 8);
+
+ /* CTL_217: {W2W,W2R,R2W}_DIFFCS_DLY_F0 */
+ // TODO: Check againstt JESD-79
+ clrsetbits_le32(&denali_ctl[217], 0xffffff, 0x050303); // TODO: F0
+ /* CTL_217: {W2W,W2R,R2W}_DIFFCS_DLY_F1 */
+ clrsetbits_le32(&denali_ctl[218], 0xffffff, 0x050303); // TODO: F1
+
+ /* WLDQSEN --- DDR3: 28 nCK */
+ const u32 PHYUPD_APPEND_EN = BIT(0);
+ clrsetbits_le32(&denali_ctl[225], 0x3f << 24, 28 << 24);
+ setbits_le32(&denali_ctl[225], PHYUPD_APPEND_EN);
+
+ /* WLMRD --- DDR3: 40 nCK */
+ const u32 DFI_PHY_WRLVL_MODE = BIT(16);
+ clrsetbits_le32(&denali_ctl[226], 0x3f, 40);
+ setbits_le32(&denali_ctl[226], DFI_PHY_WRLVL_MODE);
+
+ /* WRLVL_CS_MAP */
+ // TODO: check number of ranks/chip-selects
+ clrsetbits_le32(&denali_ctl[227], 0x3, 0x3);
+
+ const u32 DFI_PHY_RDLVL_GATE_MODE = BIT(16);
+ const u32 DFI_PHY_RDLVL_MODE = BIT(8);
+ setbits_le32(&denali_ctl[237], DFI_PHY_RDLVL_GATE_MODE |
+ DFI_PHY_RDLVL_MODE);
+
+ const u32 RDLVL_AREF_EN = BIT(24);
+ setbits_le32(&denali_ctl[238], RDLVL_AREF_EN);
+
+ const u32 RDLVL_GATE_AREF_EN = BIT(0);
+ setbits_le32(&denali_ctl[239], RDLVL_GATE_AREF_EN);
+
+ /* RDLVL_GATE_CS_MAP and RDLVL_CS_MAP */
+ // TODO: match up against single-rank vs. dual-rank
+ clrsetbits_le32(&denali_ctl[240], 0x303, 0x303);
+
+ /* CA training patterns */
+ clrsetbits_le32(&denali_ctl[256], 0xfffff, 0x556aa);
+ clrsetbits_le32(&denali_ctl[257], 0xfffff, 0xaaaaa);
+ clrsetbits_le32(&denali_ctl[258], 0xfffff, 0xaa955);
+ clrsetbits_le32(&denali_ctl[259], 0xfffff, 0x55555);
+ clrsetbits_le32(&denali_ctl[260], 0xfffff, 0xb3133);
+ clrsetbits_le32(&denali_ctl[261], 0xfffff, 0x4cd33);
+ clrsetbits_le32(&denali_ctl[262], 0xfffff, 0x4cecc);
+ clrsetbits_le32(&denali_ctl[263], 0xfffff, 0xb32cc);
+
+ const u32 CALVL_SEQ_EN = BIT(16);
+ const u32 CALVL_SEQ_ALL_PATTERNS = 3 << 8;
+ setbits_le32(&denali_ctl[264], CALVL_SEQ_EN | CALVL_SEQ_ALL_PATTERNS);
+
+ const u32 CALVL_CS_MAP = 3 << 24;
+ const u32 CALVL_AREF_EN = BIT(8);
+ setbits_le32(&denali_ctl[265], CALVL_CS_MAP | CALVL_AREF_EN);
+
+ /* DLL_RST_ADJ_DLY */
+ // TODO: why?
+ clrsetbits_le32(&denali_ctl[274], 0xffff << 8, 0xffff);
+
+ /* tPHY_WRLAT -- calculated by HW? */
+ // clrsetbits_le32(&denali_ctl[275], 0xff, 6);
+ // clrsetbits_le32(&denali_ctl[275], 0xff, 2);
+
+ // TODO: 298: tCTRL_DELAY_F0, tCTRL_DELAY_F1: 2 vs 3
+
+ /* TDFI_WRLVL_WW */
+ clrsetbits_le32(&denali_ctl[303], 0x3ff, 20);
+ /* TDFI_RDLVL_RR - minimum # cycles between read commands; tunable? */
+ // TODO: verify that 0 is ok; also check pi[78]
+ /* TDFI_RDLVL_EN */
+ clrsetbits_le32(&denali_ctl[303], 0x3ffff, 20 << 8 | 3);
+ /* TDFI_CALVL_EN */
+ clrsetbits_le32(&denali_ctl[307], 0xff << 16, 3 << 16);
+ /* TDFI_PHY_WRDATA */
+ clrsetbits_le32(&denali_ctl[313], 0x07 << 24, 1 << 24);
+ /* TDFI_WRDATA_DELAY */
+ clrsetbits_le32(&denali_ctl[315], 0xff << 16, 5 << 16);
+
+ /* DENALI_CTL324 */
+ const u32 MULTI_CHANNEL_ZQ_CAL_MASTER = BIT(24);
+ /* const u32 BL_ON_FLY_ENABLE = BIT(16); */
+ const u32 DISABLE_MEMORY_MASKED_WRITE = BIT(8);
+ /* const u32 EN_1T_TIMING = BIT(0); */
+
+ // TODO: make 2t-timing an option via DTS
+ setbits_le32(&denali_ctl[324], /* EN_1T_TIMING | */
+ MULTI_CHANNEL_ZQ_CAL_MASTER |
+ DISABLE_MEMORY_MASKED_WRITE);
+
+ /* reg 325 is missing from the documentation */
+ // writel(&denali_ctl[325], 0x01010101); // breaks 933mhz
+
+#endif
+
+ /* TODO: rank count need to set for init */
+
+ gen_rk3399_ctl_params_f0(chan, &timing_config, &dram_timing);
+ gen_rk3399_ctl_params_f1(chan, &timing_config, &dram_timing);
+
+ /* common for f0..f2 */
+ clrsetbits_le32(&denali_ctl[26], 0x1f, dram_timing.tccd);
+
+ /* DRAM class */
+ enum {
+ DDR3 = 6,
+ LPDDR3 = 7,
+ LPDDR4 = 11,
+ };
+
+ clrsetbits_le32(&denali_ctl[0], 0xf << 8, DDR3 << 8);
+ clrsetbits_le32(&denali_pi[0], 0xf << 8, DDR3 << 8);
+
+#if 0
+ if (channel == 0) {
+ printf ("/* PI - preinit */\n");
+ for (int i = 0; i < sizeof(struct rk3399_ddr_pi_regs) / 4; ++i)
+ printf("PI_%d = 0x%08x\n", i, readl(&denali_pi[i]));
+ }
+#endif
+
+ gen_rk3399_pi_params_f0(chan, &timing_config, &dram_timing);
+ gen_rk3399_pi_params_f1(chan, &timing_config, &dram_timing);
set_memory_map(chan, channel, sdram_params);
- writel(sdram_params->phy_regs.denali_phy[910], &denali_phy[910]);
- writel(sdram_params->phy_regs.denali_phy[911], &denali_phy[911]);
- writel(sdram_params->phy_regs.denali_phy[912], &denali_phy[912]);
+ // PI_23: TODO
+ setbits_le32(&denali_pi[23], 7);
+ // for DDR3:
+ writel(0x110f0000, &denali_pi[24]);
+ // writel(0x1f0f0000, &denali_pi[24]);
+ writel(0x3c020000 | dram_timing.mr[2], &denali_pi[25]);
+ // CS0 + CS1; write MRS2
+ writel(0x3fffffff, &denali_pi[26]);
+ writel(0x3c030000 | dram_timing.mr[3], &denali_pi[27]);
+ // CS0 + CS1; write MRS3
+ writel(0x3fffffff, &denali_pi[28]);
+ writel(0x3c010000 | dram_timing.mr[1], &denali_pi[29]);
+ // CS0 + CS1; write MRS1
+ writel(0x3fffffff, &denali_pi[30]);
+ writel(0x3c010000 | dram_timing.mr[0], &denali_pi[31]);
+ // CS0 + CS1; write MRS0
+ writel(0x3fffffff, &denali_pi[32]);
+ writel(0x3c300400, &denali_pi[33]); // CS0 + C1; ZQCL
+
+ // PI_49: pi_tref_interval -- cycles between ref to different CS
+ // TODO: sync with DIFFCS_DLY ?? (e.g. ctl[217] and ctl[218]?
+ clrsetbits_le32(&denali_pi[49], 0xffff << 8, 5 << 8);
+
+ // pi_tdfi_ctrl_delay_f0,f1
+ // TODO: match up with CTL[298]
+ clrsetbits_le32(&denali_pi[58], 0x1f << 24, 4 << 24);
+ clrsetbits_le32(&denali_pi[58], 0x1f << 16, 4 << 16);
+
+ // pi_wldqsen PI_59
+ // TODO: match up with ctl[225]
+ // TODO: collocate w/ ctl[225]
+ clrsetbits_le32(&denali_pi[59], 0x3f << 24, 28 << 24);
+
+ // pi_wlmrd
+ // TODO: match up with ctl[226] and collocate
+ clrsetbits_le32(&denali_pi[60], 0x3f, 40);
+
+ // tDFI_WRLVL_EN ctl[299] match up
+ clrsetbits_le32(&denali_pi[62], 0xff << 16, 0);
+ // pi_wrlvl_cs_map ctl[???] match up
+ clrsetbits_le32(&denali_pi[62], 3, 3);
+
+ // TDFI_WRLVL_WW
+ // TODO: ctl[303]
+ clrsetbits_le32(&denali_pi[63], 0x3ff, 20);
+
+ // TODO: pi_wrlvl_strobe_num (LPDDR4 only): can't be 0 even for DDR3
+ setbits_le32(&denali_pi[66], 2);
+
+ // pi_odt_en_f1 and pi_odt_en_f0
+ // TODO: ctl[213]
+ if (timing_config.odt) {
+ setbits_le32(&denali_pi[67], BIT(16)); // pi_odt_en_f1
+ setbits_le32(&denali_pi[67], BIT(0)); // pi_odt_en_f0
+ }
+
+ // TODO: ctl[211] and ctl[212]
+ setbits_le32(&denali_pi[69], BIT(17)); // pi_odt_wr_map_cs1
+ setbits_le32(&denali_pi[69], BIT(0)); // pi_odt_wr_map_cs0
+
+ // pi_rdlvl_gate_cs_map, pi_rdlvl_cs_map
+ // TODO: ctl[240]
+ clrsetbits_le32(&denali_pi[77], 0x303 << 8, 0x303 << 8);
+
+ // pi_tdfi_rdlvl_rr
+ // TODO: ctl[303]
+ clrsetbits_le32(&denali_pi[78], 0x3ff, 20);
+
+ // pi_tdfi_rdlvl_en
+ // TODO: ctl[303]
+ // CHECK: read-leveling is LPDDR4 only, right?
+ clrsetbits_le32(&denali_pi[80], 0xff << 8, 3 << 8);
+
+ // pi_rd_preamble_training_en
+ // TODO: ctl[201]
+ setbits_le32(&denali_pi[89], BIT(0));
+
+ // pi_calvl_seq_en (matches up w/ CALVL_SEQ_ALL_PATTERNS)
+ // TODO: ctl[264]
+ clrsetbits_le32(&denali_pi[93], 3 << 16, 3 << 16);
+
+ // pi_calvl_cs_map (matches up w/ CALVL_CS_MAP)
+ // TODO: ctl[264]
+ clrsetbits_le32(&denali_pi[94], 3 << 16, 3 << 16);
+
+#if 0
+ if (channel == 0) {
+ printf ("/* PI - postinit */\n");
+ for (int i = 0; i < sizeof(struct rk3399_ddr_pi_regs) / 4; ++i)
+ printf("PI_%d = 0x%08x\n", i, readl(&denali_pi[i]));
+ }
+#endif
+
+ /* PHY PLL params */
+ writel(0x64 << 8, &denali_phy[910]); // PHY_PLL_WAIT
+ writel(0x01121102, &denali_phy[911]);
+ clrbits_le32(&denali_phy[912], 0xf); // clear PHY_PLL_BYPASS
pwrup_srefresh_exit = readl(&denali_ctl[68]) & PWRUP_SREFRESH_EXIT;
clrbits_le32(&denali_ctl[68], PWRUP_SREFRESH_EXIT);
@@ -487,8 +2431,11 @@ static int pctl_cfg(const struct chan_info *chan, u32 channel,
/* PHY_DLL_RST_EN */
clrsetbits_le32(&denali_phy[957], 0x3 << 24, 1 << 24);
+ dmb();
setbits_le32(&denali_pi[0], START);
+ dmb();
setbits_le32(&denali_ctl[0], START);
+ dmb();
/* Wating for phy DLL lock */
while (1) {
@@ -502,49 +2449,190 @@ static int pctl_cfg(const struct chan_info *chan, u32 channel,
break;
}
- 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, sdram_params);
+ for (int i = 0; i < 4; ++i) {
+ /* Establish a 1:1 mapping for DM/DQ bits */
+ writel(0x76543210, &denali_phy[0 + i * 128]);
+ writel(0x00000008, &denali_phy[1 + i * 128]);
+ setbits_le32(&denali_phy[6 + i * 128], BIT(24)); // tsel during read
+
+ // TODO: PHY_CLK_WR_BYPASS_SLAVE_DELAY_0
+ // clrsetbits(&denali_phy[1], 0x7ff << 8, 0x4c0);
+
+ // PHY_PER_CS_TRAINING_MULTICAST_E
+ setbits_le32(&denali_phy[8 + i * 128], BIT(16));
+ setbits_le32(&denali_phy[8 + i * 128], 3 << 8); // TODO: cs_map;
+
+ // PHY_LPDDR_TYPE_0 // TODO
+ // clrsetbits_le32(&denali_phy[12], 3 << 8, 0); // DDR3
+ // PHY_LPDDR_0 - even though 'LPDDR', required for DDR3
+ setbits_le32(&denali_phy[12 + i * 128], 1);
+ // PHY_GATE_ERROR_DELAY_SELECT_0
+ clrsetbits_le32(&denali_phy[11 + i * 128], 0x1f << 16, 0x1f);
+ // PHY_GATE_SMPL1_SLAVE_DELAY_0
+ clrsetbits_le32(&denali_phy[12 + i * 128], 0x1ff << 16, 0xcc << 16);
+ // PHY_GATE_SMPL2_SLAVE_DELAY_0
+ clrsetbits_le32(&denali_phy[13 + i * 128], 0x1ff, 0x66);
+
+ // PHY_WRLVL_UPDT_WAIT_CNT_0, PHY_WRLVL_CAPTURE_CNT_0
+ clrsetbits_le32(&denali_phy[22 + i * 128], 0x0f3f << 16, 0x408 << 16);
+ // PHY_RDLVL_UPDT_WAIT_CNT_0, PHY_RDLVL_CAPTURE_CNT_0
+ clrsetbits_le32(&denali_phy[23 + i * 128], 0x0f3f << 16, 0x408 << 16);
+ // PHY_GTLVL_UPDT_WAIT_CNT_0
+ clrsetbits_le32(&denali_phy[23 + i * 128], 0xf << 8, 4 << 8);
+ // PHY_WDQLVL_BURST_CNT_0 (TODO: should this be burst-length?)
+ clrsetbits_le32(&denali_phy[24 + i * 128], 0x3f << 24, 8 << 24);
+
+ // PHY_WDQLVL_UPDT_WAIT_CNT_0
+ clrsetbits_le32(&denali_phy[25 + i * 128], 0xf << 24, 0xc << 24);
+ // PHY_WDQLVL_DQDM_SLV_DLY_JUMP_OFFSET_0
+ clrsetbits_le32(&denali_phy[25 + i * 128], 0x7ff << 8, 0xc0 << 8);
+ // PHY_WDQLVL_PATT_0
+ setbits_le32(&denali_phy[25 + i * 128], 7); // TODO: all patterns
+ // PHY_WDQLVL_QTR_DLY_STEP_0
+ clrsetbits_le32(&denali_phy[26 + i * 128], 0xf << 8, 1 << 8);
+
+ /* We have only 8bits in DM (i.e. no ECC), so mask bit 8 */
+ setbits_le32(&denali_phy[27 + i * 128], BIT(8));
+
+ // PHY_USER_PATT0_0
+ writel(0x55555555, &denali_phy[28 + i * 128]);
+ writel(0xaaaaaaaa, &denali_phy[29 + i * 128]);
+ writel(0x55555555, &denali_phy[30 + i * 128]);
+ writel(0xaaaaaaaa, &denali_phy[31 + i * 128]);
+ writel(0x00005555, &denali_phy[32 + i * 128]);
+
+ /* clock slave delays */
+ // TODO: write as a series ox 0x270 writes
+ // TODO/CHECK: 270 on lpddr3, 280 on ddr3
+ writel(0x2800280, &denali_phy[59 + i * 128]);
+ writel(0x2800280, &denali_phy[60 + i * 128]);
+ writel(0x2800280, &denali_phy[61 + i * 128]);
+ writel(0x2800280, &denali_phy[62 + i * 128]);
+ writel(0x280, &denali_phy[63 + i * 128]);
+
+#if 1
+ // CHECK: this should not be needed
+ writel(0x0080000, &denali_phy[68 + i * 128]);
+ for (int j = 69; j < 76; ++j)
+ writel(0x0080080, &denali_phy[j + i * 128]);
+ writel(0x0080, &denali_phy[77 + i * 128]);
+#endif
- /*
- * 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);
+ // PHY_RDDQS_LATENCY_ADJUST_0
+ clrsetbits_le32(&denali_phy[78 + i * 128], 0xf, 1);
- /*
- * 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);
+ // timings -- TODO: clean up
+ writel(0x51413152, &denali_phy[83 + i * 128]); // includes the "add half-cycle"
+ writel(0x80004130, &denali_phy[84 + i * 128]); // note: per-cs training set elsewhere (i.e. not here)
+ writel(0x80, &denali_phy[85 + i * 128]);
+
+ writel(0x100001, &denali_phy[86 + i * 128]);
+ writel(0x07004208, &denali_phy[87 + i * 128]); // PHY_RPTR_UPDATE_0 will be generated later
+ writel(0x000f0c0f, &denali_phy[88 + i * 128]); // TODO: split into fields
+ writel(0x01000140, &denali_phy[89 + i * 128]);
+ writel(0x00000c20, &denali_phy[90 + i * 128]);
+ }
+
+ writel(0x0a418820, &denali_phy[541]); // LPDDR4, but required?
+ writel(0x16a4a0e6, &denali_phy[669]); // LPDDR4, but required?
+ writel(0x1ee6b16a, &denali_phy[797]);
+ for (int i = 0; i < 3; ++i) {
+ writel(0x103f0000, &denali_phy[542 + i * 128]); //
+
+ /* Delay lines */ // TODO: 0x380 on LPDDR3, 0x300 on DDR3
+ const u32 slave_delay = 0x380;
+ clrsetbits_le32(&denali_phy[544 + i * 128],
+ 0x7ff << 8, slave_delay << 8);
+ clrsetbits_le32(&denali_phy[545 + i * 128],
+ 0x7ff << 16, slave_delay << 16);
+ clrsetbits_le32(&denali_phy[545 + i * 128],
+ 0x7ff, slave_delay);
+ clrsetbits_le32(&denali_phy[546 + i * 128],
+ 0x7ff << 16, slave_delay << 16);
+ clrsetbits_le32(&denali_phy[546 + i * 128],
+ 0x7ff, slave_delay);
+ clrsetbits_le32(&denali_phy[547 + i * 128],
+ 0x7ff, slave_delay);
+
+ writel(0x42080010, &denali_phy[548 + i * 128]);
+ writel(3, &denali_phy[549 + i * 128]); // no CALVL, but required?
+ }
+
+ // PHY_DFI_PHYUPD_TYPE, PHY_ADRCTL_LPDDR
+ // TODO: same as PHY_LPDDR_0 ??
+ writel(0x10100, &denali_phy[907]);
+
+ /* Delay lines */
+ const u32 slave_delay = 0x380;
+ clrsetbits_le32(&denali_phy[916],
+ 0x7ff << 8, slave_delay << 8);
+ clrsetbits_le32(&denali_phy[917],
+ 0x7ff << 16, slave_delay << 16);
+ clrsetbits_le32(&denali_phy[917],
+ 0x7ff, slave_delay);
+ clrsetbits_le32(&denali_phy[918],
+ 0x7ff, slave_delay);
+
+ // PHY_TCKSRE_WAIT (CHECK: rockchip has 3, 0xf seems a safe default
+ clrsetbits_le32(&denali_phy[922], 0xf << 24, 0xf);
+
+ // TODO: check?
+ clrsetbits_le32(&denali_phy[944], 0xff << 24, 0x6 << 24);
+ writel(0x508, &denali_phy[947]); // TODO: more pad-calibration
+
+ writel(0xe4 << 24, &denali_phy[954]); // data-slice byte-swap
+ setbits_le32(&denali_phy[957], BIT(16) | BIT(24));
+
+ set_ds_odt(chan, sdram_params);
ret = phy_io_config(chan, sdram_params);
+
+ gen_rk3399_phy_params(chan, &timing_config, &dram_timing, 0);
+ gen_rk3399_phy_params(chan, &timing_config, &dram_timing, 1);
+
if (ret)
return ret;
+#if defined(DEBUG)
+ {
+ u32 trefi0 = (readl(&denali_ctl[48]) >> 16) + 8;
+ u32 trefi1 = (readl(&denali_ctl[49]) >> 16) + 8;
+
+ printf("trefi0 %08x\n", trefi0);
+ printf("trefi1 %08x\n", trefi1);
+ printf("tinit1+2 %08x (txsnr, 3*mrd, tmod, tzqinit)) ... 700us\n",
+ readl(&denali_ctl[5]));
+ printf("tinit3 %08x\n", readl(&denali_ctl[6]));
+ printf("tinit5 %08x\n", readl(&denali_ctl[8]));
+ printf("tCL * 2 %08x (%d)\n",
+ ((readl(&denali_ctl[23]) >> 16) & 0x7f),
+ ((readl(&denali_ctl[23]) >> 16) & 0x7f));
+ printf("timing.CL %d CWL %d\n", dram_timing.cl, dram_timing.cwl);
+ printf("tCWL %d\n", ((readl(&denali_ctl[23]) >> 24) & 0x1f));
+ printf("tAL %d\n", (readl(&denali_ctl[24]) & 0x3f));
+ printf("tRC %d\n", (readl(&denali_ctl[26]) >> 24) & 0xff);
+ printf("tRRD %d\n", (readl(&denali_ctl[26]) >> 16) & 0xff);
+ printf("tMOD %d\n", (readl(&denali_ctl[32]) >> 8) & 0xff);
+ printf("tMRD %d\n", (readl(&denali_ctl[32]) >> 0) & 0xff);
+ printf("MR[0] %04x (tCL, tWR)\n",
+ (readl(&denali_ctl[133]) >> 0) & 0xffff);
+ printf("MR[1] %04x\n", (readl(&denali_ctl[133]) >> 16) & 0xffff);
+ printf("MR[2] %04x (tCWL)\n",
+ (readl(&denali_ctl[134]) >> 0) & 0xffff);
+ printf("MR[3] %04x\n", (readl(&denali_ctl[138]) >> 0) & 0xffff);
+ // printf("
+ printf("CTL284: wrlat_adj %d rdlat_adj %d (depends on CWL, CL)\n",
+ (readl(&denali_ctl[284]) >> 8) & 0xff,
+ (readl(&denali_ctl[284]) >> 0) & 0xff);
+
+ }
+#endif
+
/* PHY_DLL_RST_EN */
clrsetbits_le32(&denali_phy[957], 0x3 << 24, 0x2 << 24);
+ gen_rk3399_enable_training(denali_ctl, timing_config.freq);
+
/* Wating for PHY and DRAM init complete */
tmp = get_timer(0);
do {
@@ -558,6 +2646,21 @@ static int pctl_cfg(const struct chan_info *chan, u32 channel,
clrsetbits_le32(&denali_ctl[68], PWRUP_SREFRESH_EXIT,
pwrup_srefresh_exit);
+
+#if 0
+ printf ("/* PCTL */\n");
+ for (int i = 0; i < sizeof(struct rk3399_ddr_pctl_regs) / 4; ++i)
+ printf("\t\t0x%08x\n", readl(&denali_ctl[i]));
+
+ printf ("/* PI */\n");
+ for (int i = 0; i < sizeof(struct rk3399_ddr_pi_regs) / 4; ++i)
+ printf("\t\t0x%08x\n", readl(&denali_pi[i]));
+
+ printf ("/* PHY */\n");
+ for (int i = 0; i < 958; ++i)
+ printf("\t\t0x%08x\n", readl(&denali_phy[i]));
+#endif
+
return 0;
}
@@ -668,14 +2771,21 @@ static int data_training_wl(const struct chan_info *chan, u32 channel,
u32 rank = sdram_params->ch[channel].rank;
for (i = 0; i < rank; i++) {
- select_per_cs_training_index(chan, i);
+#if 0
+ // TODO: remove => this was needed due to a bug in RK template
/* PI_60 PI_WRLVL_EN:RW:8:2 */
- clrsetbits_le32(&denali_pi[60], 0x3 << 8, 0x2 << 8);
+ clrsetbits_le32(&denali_pi[59], 0xff << 24, 0xff << 24);
+ debug("denali_pi[59] %08x\n", readl(&denali_pi[59]));
+ debug("denali_pi[60] %08x\n", readl(&denali_pi[60]));
+#endif
+ clrsetbits_le32(&denali_pi[60], 0x3 << 8, 0x3 << 8);
/* PI_59 PI_WRLVL_REQ:WR:8:1,PI_WRLVL_CS:RW:16:2 */
clrsetbits_le32(&denali_pi[59],
(0x1 << 8) | (0x3 << 16),
(0x1 << 8) | (i << 16));
+ select_per_cs_training_index(chan, i);
+
/* Waiting for training complete */
while (1) {
/* PI_174 PI_INT_STATUS:RD:8:18 */
@@ -701,8 +2811,10 @@ static int data_training_wl(const struct chan_info *chan, u32 channel,
(obs_err == 0))
break;
else if ((((tmp >> 4) & 0x1) == 0x1) ||
- (obs_err == 1))
+ (obs_err == 1)) {
+ printf("%s: -EIO\n", __func__);
return -EIO;
+ }
}
/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
writel(0x00003f7c, (&denali_pi[175]));
@@ -710,6 +2822,7 @@ static int data_training_wl(const struct chan_info *chan, u32 channel,
override_write_leveling_value(chan);
clrbits_le32(&denali_pi[60], 0x3 << 8);
+ // TODO/CHECK: should this not remain enabled for non-init?
return 0;
}
@@ -988,8 +3101,9 @@ static void dram_all_config(struct dram_info *dram,
clrsetbits_le32(&dram->cru->glb_rst_con, 0x3, 0x3);
}
-static int switch_to_phy_index1(struct dram_info *dram,
- const struct rk3399_sdram_params *sdram_params)
+static int switch_to_phy_index(struct dram_info *dram,
+ const struct rk3399_sdram_params *sdram_params,
+ u32 index)
{
u32 channel;
u32 *denali_phy;
@@ -998,7 +3112,7 @@ static int switch_to_phy_index1(struct dram_info *dram,
int i = 0;
writel(RK_CLRSETBITS(0x03 << 4 | 1 << 2 | 1,
- 1 << 4 | 1 << 2 | 1),
+ (index & 0x3) << 4 | 1 << 2 | 1),
&dram->cic->cic_ctrl0);
while (!(readl(&dram->cic->cic_status0) & (1 << 2))) {
mdelay(10);
@@ -1022,9 +3136,10 @@ static int switch_to_phy_index1(struct dram_info *dram,
for (channel = 0; channel < ch_count; channel++) {
denali_phy = dram->chan[channel].publ->denali_phy;
- clrsetbits_le32(&denali_phy[896], (0x3 << 8) | 1, 1 << 8);
+ clrsetbits_le32(&denali_phy[896], (0x3 << 8) | 1, (index & 3) << 8);
+ debug("data training\n");
ret = data_training(&dram->chan[channel], channel,
- sdram_params, PI_FULL_TRAINING);
+ sdram_params, PI_FULL_TRAINING);
if (ret) {
debug("index1 training failed\n");
return ret;
@@ -1034,7 +3149,7 @@ static int switch_to_phy_index1(struct dram_info *dram,
return 0;
}
-static int sdram_init(struct dram_info *dram,
+static int sdram_init(struct udevice *dev, struct dram_info *dram,
const struct rk3399_sdram_params *sdram_params)
{
unsigned char dramtype = sdram_params->base.dramtype;
@@ -1054,12 +3169,13 @@ static int sdram_init(struct dram_info *dram,
const struct chan_info *chan = &dram->chan[channel];
struct rk3399_ddr_publ_regs *publ = chan->publ;
- phy_dll_bypass_set(publ, ddr_freq);
+ phy_dll_bypass_set(publ, ddr_freq, channel, 0, dramtype);
+ phy_dll_bypass_set(publ, ddr_freq, channel, 1, dramtype);
if (channel >= sdram_params->base.num_channels)
continue;
- if (pctl_cfg(chan, channel, sdram_params) != 0) {
+ if (pctl_cfg(dev, chan, channel, sdram_params) != 0) {
printf("pctl_cfg fail, reset\n");
return -EIO;
}
@@ -1078,18 +3194,493 @@ static int sdram_init(struct dram_info *dram,
sdram_params->ch[channel].ddrconfig);
}
dram_all_config(dram, sdram_params);
- switch_to_phy_index1(dram, sdram_params);
+ switch_to_phy_index(dram, sdram_params, 1);
debug("Finish SDRAM initialization...\n");
return 0;
}
+static inline u16 crc16(const u8 *ptr, int count)
+{
+ int crc = 0;
+ int i;
+
+ while (--count >= 0) {
+ crc = crc ^ (int)*ptr++ << 8;
+ for (i = 0; i < 8; ++i)
+ if (crc & 0x8000)
+ crc = crc << 1 ^ 0x1021;
+ else
+ crc = crc << 1;
+ }
+
+ return crc;
+}
+
+/*
+ * CAS Latency Calculation (as per "Annex K")
+ * -----------------------
+ * CAS latency is not a purely analog value as DDR3 SDRAMs use the DLL
+ * to synchronize data and strobe outputs with the clock. All possible
+ * frequencies may not be tested, therefore an application should use
+ * the next smaller JEDEC standard tCKmin value (2.5, 1.875, 1.5,
+ * 1.25, 1.071, and 0.938 ns for DDR3 SDRAMs) when calculating CAS
+ * Latency. This section shows how the BIOS may calculate CAS latency
+ * based on Bytes 12 ~ 16, 34, and 35.
+ *
+ * Step 1: Determine the common set of supported CAS Latency values
+ * for all modules on the memory channel using the CAS
+ * Latencies Supported in SPD bytes 14 and 15.
+ *
+ * Step 2: Determine tAAmin(all) which is the largest tAAmin value for
+ * all modules on the memory channel (SPD bytes 16 and 35).
+ *
+ * Step 3: Determine tCKmin(all) which is the largest tCKmin value for
+ * all modules on the memory channel (SPD bytes 12 and 34).
+ *
+ * Step 4: For a proposed tCK value (tCKproposed) between tCKmin(all)
+ * and tCKmax, determine the desired CAS Latency. If
+ * tCKproposed is not a standard JEDEC value (2.5, 1.875, 1.5,
+ * 1.25, 1.071, or 0.938 ns) then tCKproposed must be adjusted
+ * to the next lower standard tCK value for calculating
+ * CLdesired.
+ *
+ * CLdesired = ceiling (tAAmin(all) / tCKproposed)
+ * where tAAmin is defined in Byte 16 and Byte 35.
+ *
+ * The ceiling function requires that the quotient be rounded
+ * up always.
+ *
+ * Step 5: Chose an actual CAS Latency (CLactual) that is greater than
+ * or equal to CLdesired and is supported by all modules on
+ * the memory channel as determined in step 1. If no such
+ * value exists, choose a higher tCKproposed value and repeat
+ * steps 4 and 5 until a solution is found.
+ *
+ * Step 6: Once the calculation of CLactual is completed, the BIOS
+ * must also verify that this CAS Latency value does not
+ * exceed tAAmax, which is 20 ns for all DDR3 speed grades, by
+ * multiplying CLactual times tCKproposed. If not, choose a
+ * lower CL value and repeat steps 5 and 6 until a solution is
+ * found.
+ */
+
+static inline u32 subps_to_cycles(const u32 subps, const u32 tck)
+{
+ return DIV_ROUND_UP(subps, tck);
+}
+
+static inline u32 ns_to_cycles(const u16 ns, const u32 tck)
+{
+ const u32 ns_as_subps = ns * 10000;
+ return subps_to_cycles(ns_as_subps, tck);
+}
+
+static int spd_decode_ddr3(const u8 *spd, const u32 freq, struct dram_timing_t *timing)
+{
+ int n_crc = 126;
+ /* u32 val; */
+
+ /* u32 capacity_shift; */
+ /* u32 banks_shift; */
+ u32 capacity, banks;
+ u32 rows, cols;
+ u32 width, bus_width;
+ u32 ranks;
+ /* u32 dramds; */
+ /* u32 dramodt; */
+
+#if defined(DEBUG)
+ const u8 SPD_VDD_1_25V = (1 << 2);
+ const u8 SPD_VDD_1_35V = (1 << 1);
+ const u8 SPD_VDD_1_50V = (1 << 0);
+ bool supports_1_25V = false;
+ bool supports_1_35V = false;
+ bool supports_1_50V = false;
+#endif
+
+ /* Check if the CRC covers only 0~116 instead of 0~125 */
+ if (spd[0] & 0x80)
+ n_crc = 117;
+
+ debug("\nCRC expected: 0x%04x\n", crc16(spd, n_crc));
+
+ /* Number of memory banks */
+ banks = 1 << ((spd[4] >> 4) & 0x07);
+ if (banks > 8) {
+ debug(" Invalid number of memory banks\n");
+ // ret = SPD_STATUS_INVALID_FIELD;
+ }
+
+ /* SDRAM capacity */
+ capacity = 256 << (spd[4] & 0x0f);
+ if (capacity > 8192) {
+ debug(" Invalid module capacity\n");
+ // ret = SPD_STATUS_INVALID_FIELD;
+ }
+
+ /* Row address bits */
+ rows = 12 + ((spd[5] >> 3) & 0x07);
+ if (rows > 16) {
+ debug(" Invalid row address bits\n");
+ // ret = SPD_STATUS_INVALID_FIELD;
+ }
+
+ /* Column address bits */
+ cols = 9 + (spd[5] & 0x07);
+ if (cols > 12) {
+ debug(" Invalid column address bits\n");
+ // ret = SPD_STATUS_INVALID_FIELD;
+ }
+
+#if defined(DEBUG)
+ /* Module nominal voltage */
+ if (spd[6] & SPD_VDD_1_25V)
+ supports_1_25V = true;
+
+ if (spd[6] & SPD_VDD_1_35V)
+ supports_1_35V = true;
+
+ if (spd[6] & SPD_VDD_1_50V)
+ supports_1_50V = true;
+#endif
+
+ /* Number of ranks */
+ ranks = 1 + ((spd[7] >> 3) & 0x07);
+ if (ranks > 2) {
+ debug(" Unsupported number of ranks\n");
+ // ret = SPD_STATUS_INVALID_FIELD;
+ }
+
+ /* SDRAM device width */
+ width = 4 << (spd[7] & 0x07);
+ if (width > 32) {
+ debug(" Invalid SDRAM width\n");
+ // ret = SPD_STATUS_INVALID_FIELD;
+ }
+ // dimm->width = (4 << val);
+ // printram(" SDRAM width : %u\n", dimm->width);
+
+ /* Bus extension */
+ /* --> ECC not implemented on the RK3399 */
+
+ /* Bus width */
+ bus_width = 8 << (spd[8] & 0x07);
+ if (bus_width > 32) {
+ printf(" Unsupported bus width\n");
+ // ret = SPD_STATUS_INVALID_FIELD;
+ }
+
+#if defined(DEBUG)
+ u32 size_mb = (capacity / 8) * (bus_width / width) * ranks;
+#endif
+
+ /* Fine Timebase (FTB) Dividend/Divisor */
+ const u32 ftb_dividend = (spd[9] >> 4) & 0x0f;
+ const u32 ftb_divisor = spd[9] & 0x0f;
+ const u32 ftb = (ftb_dividend * 10) / ftb_divisor;
+
+ /* Medium Timebase (MTB) */
+ const u32 mtb = (((u32) spd[10]) * 10000) / spd[11];
+
+ /* tXX = tXX(MTB) * MTB + tXX(FTB) * FTB */
+ const u32 tCKmin = spd[12] * mtb + (s8)spd[34] * ftb;
+ const u32 tAAmin = spd[16] * mtb + (s8)spd[35] * ftb;
+ const u32 tWRmin = spd[17] * mtb;
+ const u32 tRCDmin = spd[18] * mtb + (s8)spd[36] * ftb;
+ const u32 tRRDmin = spd[19] * mtb;
+#if defined(DEBUG)
+ const u32 tRPmin = spd[20] * mtb + (s8)spd[37] * ftb;
+#endif
+ const u32 tRASmin = (((spd[21] & 0x0f) << 8) + spd[22]) * mtb;
+ const u32 tRCmin = (((spd[21] >> 4) << 8) + spd[23]) * mtb + (s8)spd[38] * ftb;
+ const u32 tRFCmin = (spd[24] + (spd[25] << 8)) * mtb;
+ const u32 tWTRmin = spd[26] * mtb;
+ const u32 tRTPmin = spd[27] * mtb;
+ const u32 tFAWmin = (((spd[28] & 0x0f) << 8) + spd[29]) * mtb;
+ /*
+ * Supported CAS latencies are encoded in a bitmap to be
+ * tested as
+ * BIT(CL - 4)
+ */
+ const u16 CL_supported = (spd[15] << 8) | spd[14];
+
+ const u32 tCK = 10000000 / freq;
+
+#if defined(DEBUG)
+ printf(" tCK : %u ps (@ %u MHz)\n", tCK / 10, freq);
+ if (tCK < tCKmin) {
+ printf(" => violates tCKmin\n");
+ // ret = ...
+ }
+ printf(" tAAmin (cycles) : %u tCK\n", (tAAmin + tCK - 1) / tCK);
+ printf(" tCKmin : %u ps\n", tCKmin / 10);
+ printf(" tAAmin : %u ps\n", tAAmin / 10);
+ printf(" tWRmin : %u ps\n", tWRmin / 10);
+ printf(" tRCDmin : %u ps\n", tRCDmin / 10);
+ printf(" tRRDmin : %u ps\n", tRRDmin / 10);
+ printf(" tRPmin : %u ps\n", tRPmin / 10);
+ printf(" tRCmin : %u ps\n", tRCmin / 10);
+
+ printf(" Banks : %u\n", banks);
+ printf(" Number of ranks : %u\n", ranks);
+ printf(" Capacity : %u Mib\n", capacity);
+ printf(" Supported voltages : ");
+ if (supports_1_25V)
+ printf("1.25V ");
+ if (supports_1_35V)
+ printf("1.35V ");
+ if (supports_1_50V)
+ printf("1.50V ");
+ printf("\n");
+ printf(" Device width : %u\n", width);
+ printf(" Bus width : %u\n", bus_width);
+ printf(" Row addr bits : %u\n", rows);
+ printf(" Column addr bits : %u\n", cols);
+ printf(" Channel Capacity : %u MiB\n", size_mb);
+#endif
+
+ /* Calculate the CAS latency to be used */
+ const u32 CLdesired = DIV_ROUND_UP(tAAmin, tCK);
+ debug("CLdesired %d\n", CLdesired);
+ /* TODO: find the smallest CL greater-equal CLdesired */
+ u32 CLactual;
+ for (CLactual = CLdesired; CLactual < 19; ++CLactual)
+ if (CL_supported & BIT(CLactual - 4))
+ break;
+
+ if (CLactual == 19) {
+ debug("no CAS latency found\n");
+ return -1;
+ }
+
+ u32 tCL = CLactual * tCK;
+ debug("-- tCL: %u ps (must be <= 20ns)\n", tCL / 10);
+ debug(" CL: %d\n", CLactual);
+
+ /*
+ * In DDR3, only one CWL is valid for a given clock frequency
+ * range. For this reason, there is no entry encoding the CWL
+ * values in the SPD.
+ * The valid CWL values (in respect to the corresponding tCK
+ * values) are:
+ * - CWL = 5, for tCKavg in [2.5ns; 3.3ns)
+ * - CWL = 6, for tCKavg in [1.875ns; 2.5ns)
+ * - CWL = 7, for tCKavg in [1.5ns; 1.875ns)
+ * - CWL = 8, for tCKavg in [1.25ns; 1.5ns)
+ * - CWL = 9, for tCKavg in [1.07ns; 1.25ns)
+ * - CWL = 10, for tCKavg in [0.938ns; 1.07ns)
+ */
+
+ u8 CWL = 0;
+ if (tCK >= 25000) /* 2500.0ps */
+ CWL = 5;
+ else if (tCK >= 18750) /* 1875.0ps */
+ CWL = 6;
+ else if (tCK >= 15000) /* 1500.0ps */
+ CWL = 7;
+ else if (tCK >= 12500) /* 1250.0ps */
+ CWL = 8;
+ else if (tCK >= 10700) /* 1070.0ps */
+ CWL = 9;
+ else if (tCK >= 9380) /* 938.0ps */
+ CWL = 10;
+
+ debug(" CWL: %d\n", CWL);
+ if (!CWL) {
+ printf("could not find a valid CWL\n");
+ // handle error
+ }
+
+ timing->mhz = freq;
+
+ timing->trefi = ns_to_cycles(7800, tCK); /* 7.8us */
+ timing->al = 0;
+ timing->bl = 8;
+
+ timing->cl = CLactual;
+ timing->cwl = CWL;
+
+ timing->trstl = ns_to_cycles(100, tCK); /* 100 ns */
+ timing->trsth = DIV_ROUND_UP(500000 * freq, 1000); /* 500 us */
+
+ timing->trcd = max(4, subps_to_cycles(tRCDmin, tCK));
+ timing->trp = timing->cl;
+ timing->trppb = timing->cl;
+ timing->twr = subps_to_cycles(tWRmin, tCK);
+ timing->tdal = timing->twr + timing->trp;
+ timing->trtp = max(4, subps_to_cycles(tRTPmin, tCK));
+ timing->trc = max(4, subps_to_cycles(tRCmin, tCK));
+ timing->trrd = max(4, subps_to_cycles(tRRDmin, tCK));
+ timing->tccd = 4;
+ timing->twtr = max(4, subps_to_cycles(tWTRmin, tCK));
+ timing->trtw = 0;
+ timing->tras_max = 9 * timing->trefi;
+ timing->tras_min = subps_to_cycles(tRASmin, tCK);
+ timing->tfaw = subps_to_cycles(tFAWmin, tCK);
+ timing->trfc = subps_to_cycles(tRFCmin, tCK);
+ timing->txsnr = max(5, subps_to_cycles(tRFCmin + 10000, tCK));
+ timing->tdqsck_max = 0;
+
+ /* pd and sr */
+ timing->tdllk = 512; /* always 512 cycles for DDR3 */
+ timing->txsr = timing->tdllk;
+ timing->txp = max(3, ns_to_cycles(7, tCK));
+ timing->txpdll = max(10, ns_to_cycles(10, tCK));
+
+ if (tCKmin > 18750) /* DDR-800 or slower */
+ timing->tcke = max(3, subps_to_cycles(75000, tCK)); /* 7.5ns */
+ else if (tCKmin > 12500) /* DDR-1066 */
+ timing->tcke = max(3, subps_to_cycles(56250, tCK)); /* 5.625ns */
+ else
+ timing->tcke = max(3, subps_to_cycles(50000, tCK)); /* 5ns */
+
+ timing->tckesr = timing->tcke + 1; // CHECK
+ timing->tcksre = max(5, ns_to_cycles(10, tCK));
+ timing->tcksrx = timing->tcksre;
+
+ /* mode register timing */
+ timing->tmod = max(12, ns_to_cycles(15, tCK));
+ timing->tmrd = 4; /* always 4 cycles for DDR3 */
+ timing->tmrr = 0;
+
+ /* ODT */
+ timing->todton = timing->cwl - 2;
+
+ /* ZQ */
+ timing->tzqinit = max(512, ns_to_cycles(640, tCK));
+ timing->tzqcs = max(64, ns_to_cycles(80, tCK));
+ timing->tzqoper = max(256, ns_to_cycles(320, tCK));
+
+ /* write leveling */
+ timing->twlmrd = 40;
+ timing->twldqsen = 25;
+ timing->twlo = ns_to_cycles(9, tCK);
+
+ timing->mr[0] =
+ ((timing->bl == 8) ? DDR3_BL8 : DDR3_BC4) |
+ DDR3_CL(timing->cl) |
+ DDR3_WR(timing->twr);
+ timing->mr[1] = 0;
+
+ /* TODO: set timing->odt = */
+
+ u8 odt_offset = 72;
+ /* extract ODT settings from SPD */
+ if (tCK >= 18750) /* 533MHz and less */
+ odt_offset = 72;
+ // 72, 73, 77
+ else if (tCK >= 12500) /* (533MHz; 800Mhz] */
+ // 78, 79, 83
+ odt_offset = 78;
+ else if (tCK >= 9380) /* (800MHz, 1066MHz] */
+ // 84, 85, 89
+ odt_offset = 84;
+
+ debug("MR12 byte (spd[%d]): 0x%02x\n", odt_offset + 5, spd[odt_offset + 5]);
+
+ switch (spd[odt_offset + 5] & 3) {
+ case 0:
+ /* dramds = 40; */
+ timing->mr[1] = DDR3_DS_40;
+ break;
+ case 1:
+ /* dramds = 34; */
+ timing->mr[1] = DDR3_DS_34;
+ break;
+ default:
+ // err
+ break;
+ }
+
+ switch ((spd[odt_offset + 5] >> 2) & 0x7) {
+ case 0:
+ /* dramodt = 0; */ /* disabled */
+ timing->mr[1] |= DDR3_RTT_NOM_DIS;
+ break;
+ case 1:
+ /* dramodt = 60; */ /* RZQ/4 */
+ timing->mr[1] |= DDR3_RTT_NOM_60;
+ break;
+ case 2:
+ /* dramodt = 120; */ /* RZQ/2 */
+ timing->mr[1] |= DDR3_RTT_NOM_120;
+ break;
+ case 3:
+ /* dramodt = 40; */ /* RZQ/6 */
+ timing->mr[1] |= DDR3_RTT_NOM_40;
+ break;
+ default:
+ // err
+ break;
+ }
+
+ /* mode register settings */
+ timing->mr[2] = DDR3_MR2_CWL(timing->cwl);
+ timing->mr[3] = 0;
+
+ return 0;
+}
+
static int rk3399_dmc_ofdata_to_platdata(struct udevice *dev)
{
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
struct rockchip_dmc_plat *plat = dev_get_platdata(dev);
int ret;
+ const void *spd_data;
+ int spd_len;
+
+ /*
+ * To support a single design with multiple different DRAM
+ * configurations (i.e. memory capacity and speed-grades) with
+ * a single U-Boot binary, the contents of a DDR3 SPD (based
+ * JEDEC document "Annex K: Serial Presence Detect (SPD) for
+ * DDR3 SDRAM Modules") can be retrieved from an EEPROM
+ * referenced by 'theobroma-systems,spd-eeprom'. If SPD data
+ * is present, it is used to auto-configure the DRAM busses.
+ *
+ * Note the following RK3399-specific usage/subset of the SPD
+ * specification:
+ * - The "key byte" (byte 3), indicating the encoding of
+ * 'module specific section' (bytes 60~116) and the physical
+ * dimensions should always be 0x00 (undefined).
+ * However, the 'module specific section' should use the
+ * encoding specified for an LRDIMM module for bytes 67~89
+ * to store drive strength parameters, ODT control and MR1
+ * and MR2 setting for various operating points using the
+ * encodings defined for LRDIMM modules.
+ * - RK3399-specific data should be stored in bytes 150~175.
+ */
+
+ struct udevice *spd_eeprom = NULL;
+ /* get rockchip grf syscon phandle */
+ ret = uclass_get_device_by_phandle(UCLASS_I2C_EEPROM, dev,
+ "theobroma-systems,spd-eeprom",
+ &spd_eeprom);
+ if (ret)
+ debug("unable to find theobroma-systems,spd-eeprom (%d)\n", ret);
+ if (spd_eeprom) {
+ i2c_eeprom_read(spd_eeprom, 0, &plat->spd[0], 128);
+#if defined(DEBUG)
+ print_buffer(0, &plat->spd[0], 1, 128, 16);
+#endif
+ }
+
+ /*
+ * If we don't have a SPD EEPROM on board, try to retrieve SPD
+ * data (from a 'theobroma-systems,spd-data' property) from
+ * the DTS. This fallback may also be used during factory
+ * programming, when the SPD has not yet been programmed.
+ */
+ spd_data = dev_read_prop(dev, "theobroma-systems,spd-data", &spd_len);
+ if (spd_data)
+ memcpy(&plat->spd[0], spd_data, spd_len);
+
+ /*
+ * And if all else fails, fall back to the (full) register-dump stored
+ * as 'rockchip,sdram-params'.
+ */
ret = dev_read_u32_array(dev, "rockchip,sdram-params",
(u32 *)&plat->sdram_params,
sizeof(plat->sdram_params) / sizeof(u32));
@@ -1101,7 +3692,6 @@ static int rk3399_dmc_ofdata_to_platdata(struct udevice *dev)
ret = regmap_init_mem(dev_ofnode(dev), &plat->map);
if (ret)
printf("%s: regmap failed %d\n", __func__, ret);
-
#endif
return 0;
}
@@ -1170,17 +3760,25 @@ static int rk3399_dmc_init(struct udevice *dev)
printf("%s clk get failed %d\n", __func__, ret);
return ret;
}
+ debug("base.ddr_freq %d\n", params->base.ddr_freq);
ret = clk_set_rate(&priv->ddr_clk, params->base.ddr_freq * MHz);
if (ret < 0) {
printf("%s clk set failed %d\n", __func__, ret);
return ret;
}
- ret = sdram_init(priv, params);
+ ret = sdram_init(dev, priv, params);
if (ret < 0) {
printf("%s DRAM init failed%d\n", __func__, ret);
return ret;
}
+#if defined(DEBUG)
+ {
+ *(volatile u64*)0 = 0x0123456789abcdef;
+ printf("%08x %08x\n", *(volatile u32*)0, *(volatile u32*)4);
+ }
+#endif
+
return 0;
}
#endif