From 85f6551b230771849c959f67779d719794be7e49 Mon Sep 17 00:00:00 2001 From: Christoph Muellner Date: Wed, 24 Apr 2019 14:39:44 +0200 Subject: 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 --- arch/arm/dts/Makefile | 2 + arch/arm/dts/rk3399-puma-ddr1600-4gb.dts | 10 + arch/arm/dts/rk3399-puma-ddr1866-4gb.dts | 11 + arch/arm/dts/rk3399-sdram-ddr3-1600-4gb.dtsi | 140 ++ arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi | 1631 +----------- arch/arm/dts/rk3399-sdram-ddr3-1866-4gb.dtsi | 141 ++ arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi | 1629 +----------- arch/arm/include/asm/arch-rockchip/sdram_rk3399.h | 2 + drivers/ram/rockchip/Makefile | 2 +- drivers/ram/rockchip/dram_spec_timing.c | 1327 ++++++++++ drivers/ram/rockchip/dram_spec_timing.h | 507 ++++ drivers/ram/rockchip/sdram_rk3399.c | 2794 ++++++++++++++++++++- 12 files changed, 5071 insertions(+), 3125 deletions(-) create mode 100644 arch/arm/dts/rk3399-puma-ddr1600-4gb.dts create mode 100644 arch/arm/dts/rk3399-puma-ddr1866-4gb.dts create mode 100644 arch/arm/dts/rk3399-sdram-ddr3-1600-4gb.dtsi create mode 100644 arch/arm/dts/rk3399-sdram-ddr3-1866-4gb.dtsi create mode 100644 drivers/ram/rockchip/dram_spec_timing.c create mode 100644 drivers/ram/rockchip/dram_spec_timing.h 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 +// #include +#include +#include +#include +// #include +// #include +// #include +#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 + +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 #include #include +//#include #include +#include +#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], ¶ms_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], ¶ms_phy[896], (958 - 895) * 4); - copy_to_reg(&denali_phy[0], ¶ms_phy[0], (90 - 0 + 1) * 4); - copy_to_reg(&denali_phy[128], ¶ms_phy[128], (218 - 128 + 1) * 4); - copy_to_reg(&denali_phy[256], ¶ms_phy[256], (346 - 256 + 1) * 4); - copy_to_reg(&denali_phy[384], ¶ms_phy[384], (474 - 384 + 1) * 4); - copy_to_reg(&denali_phy[512], ¶ms_phy[512], (549 - 512 + 1) * 4); - copy_to_reg(&denali_phy[640], ¶ms_phy[640], (677 - 640 + 1) * 4); - copy_to_reg(&denali_phy[768], ¶ms_phy[768], (805 - 768 + 1) * 4); - set_ds_odt(chan, 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 -- cgit v1.2.3