All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/6] rk3399: enable SPL driver
@ 2017-01-18 12:16 Kever Yang
  2017-01-18 12:16 ` [U-Boot] [PATCH 1/6] arm64: rk3399: add ddr controller driver Kever Yang
                   ` (6 more replies)
  0 siblings, 7 replies; 21+ messages in thread
From: Kever Yang @ 2017-01-18 12:16 UTC (permalink / raw)
  To: u-boot


This series patch enable basic driver for rk3399 SPL, the ATF support
has been split as a separate patch.

SPL_OF_PLATDATA is consider to be must because the dram driver has much
configuration parameter from dts, but we don't want to do the copy.

Other driver like clock, pinctrl, sdhci has update to support
OF-PLATDATA.



Kever Yang (6):
  arm64: rk3399: add ddr controller driver
  arm64: rk3399: move grf register definitions to grf_rk3399.h
  clk: rk3399: update driver for spl
  sdhci: rk3399: update driver to support of-platdata
  pinctrl: rk3399: add the of-platdata support
  arm64: rk3399: add SPL support

 arch/arm/Kconfig                                  |    1 +
 arch/arm/dts/rk3399-evb.dts                       |    2 +
 arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi    | 1536 +++++++++++++++++++++
 arch/arm/dts/rk3399.dtsi                          |   44 +
 arch/arm/include/asm/arch-rockchip/clock.h        |   10 +
 arch/arm/include/asm/arch-rockchip/cru_rk3399.h   |    5 +
 arch/arm/include/asm/arch-rockchip/grf_rk3399.h   |  118 ++
 arch/arm/include/asm/arch-rockchip/sdram_rk3399.h |  120 ++
 arch/arm/mach-rockchip/Kconfig                    |    2 +
 arch/arm/mach-rockchip/Makefile                   |    1 +
 arch/arm/mach-rockchip/rk3399-board-spl.c         |  158 +++
 arch/arm/mach-rockchip/rk3399/Makefile            |    1 +
 arch/arm/mach-rockchip/rk3399/clk_rk3399.c        |   21 +
 arch/arm/mach-rockchip/rk3399/sdram_rk3399.c      | 1243 +++++++++++++++++
 arch/arm/mach-rockchip/rk3399/syscon_rk3399.c     |   40 +
 configs/evb-rk3399_defconfig                      |   18 +
 drivers/clk/rockchip/clk_rk3399.c                 |   89 +-
 drivers/mmc/rockchip_sdhci.c                      |   17 +-
 drivers/pinctrl/rockchip/pinctrl_rk3399.c         |  111 +-
 include/configs/rk3399_common.h                   |   11 +
 include/dt-bindings/clock/rk3399-cru.h            |   16 +-
 21 files changed, 3441 insertions(+), 123 deletions(-)
 create mode 100644 arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
 create mode 100644 arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
 create mode 100644 arch/arm/mach-rockchip/rk3399-board-spl.c
 create mode 100644 arch/arm/mach-rockchip/rk3399/sdram_rk3399.c

-- 
1.9.1

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 1/6] arm64: rk3399: add ddr controller driver
  2017-01-18 12:16 [U-Boot] [PATCH 0/6] rk3399: enable SPL driver Kever Yang
@ 2017-01-18 12:16 ` Kever Yang
  2017-01-26 14:23   ` Simon Glass
  2017-01-18 12:16 ` [U-Boot] [PATCH 2/6] arm64: rk3399: move grf register definitions to grf_rk3399.h Kever Yang
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Kever Yang @ 2017-01-18 12:16 UTC (permalink / raw)
  To: u-boot

RK3399 support DDR3, LPDDR3, DDR4 sdram, this patch is porting from
coreboot, support 4GB lpddr3 in this version.

Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
---

 arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi    | 1536 +++++++++++++++++++++
 arch/arm/include/asm/arch-rockchip/sdram_rk3399.h |  120 ++
 arch/arm/mach-rockchip/rk3399/Makefile            |    1 +
 arch/arm/mach-rockchip/rk3399/sdram_rk3399.c      | 1243 +++++++++++++++++
 4 files changed, 2900 insertions(+)
 create mode 100644 arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
 create mode 100644 arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
 create mode 100644 arch/arm/mach-rockchip/rk3399/sdram_rk3399.c

diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
new file mode 100644
index 0000000..5568be2
--- /dev/null
+++ b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
@@ -0,0 +1,1536 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+&dmc {
+	rockchip,sdram-params = <
+		0x2
+		0xA
+		0x3
+		0x2
+		0x2
+		0x0
+		0xF
+		0xF
+		1
+		0x1d191519
+		0x14040808
+		0x00000002
+		0x00006226
+		0x00000054
+		0x00000000
+		0x2
+		0xA
+		0x3
+		0x2
+		0x2
+		0x0
+		0xF
+		0xF
+		1
+		0x1d191519
+		0x14040808
+		0x00000002
+		0x00006226
+		0x00000054
+		0x00000000
+		800
+		6
+		2
+		13
+		1
+		0x00000700
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000050
+		0x00027100
+		0x00000320
+		0x00001f40
+		0x00000050
+		0x00027100
+		0x00000320
+		0x00001f40
+		0x00000050
+		0x00027100
+		0x00000320
+		0x01001f40
+		0x00000000
+		0x00000101
+		0x00020100
+		0x000000a0
+		0x00000190
+		0x00000000
+		0x06180000
+		0x00061800
+		0x04000618
+		0x33080004
+		0x280f0622
+		0x22330800
+		0x00280f06
+		0x06223308
+		0x0600280f
+		0x00000a0a
+		0x0600dac0
+		0x0a0a060c
+		0x0600dac0
+		0x0a0a060c
+		0x0600dac0
+		0x0203000c
+		0x0f0c0f00
+		0x040c0f0c
+		0x14000a0a
+		0x03030a0a
+		0x00010003
+		0x031b1b1b
+		0x00111111
+		0x00000000
+		0x03010000
+		0x0c2800a8
+		0x0c2800a8
+		0x0c2800a8
+		0x00000000
+		0x00060006
+		0x00140006
+		0x00140014
+		0x000f0f0f
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00b00000
+		0x00b000b0
+		0x00b000b0
+		0x000000b0
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000301
+		0x00000001
+		0x00000000
+		0x00000000
+		0x01000000
+		0x80104002
+		0x00040003
+		0x00040005
+		0x00030000
+		0x00050004
+		0x00000004
+		0x00040003
+		0x00040005
+		0x30a00000
+		0x00001850
+		0x185030a0
+		0x30a00000
+		0x00001850
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x02020200
+		0x00020202
+		0x00030200
+		0x00040700
+		0x00000302
+		0x02000407
+		0x00000003
+		0x00030f04
+		0x00070004
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		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
+		0x00430000
+		0x0000001a
+		0x001a0043
+		0x00430000
+		0x0000001a
+		0x00010001
+		0x07000001
+		0x00000707
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00430000
+		0x0000001a
+		0x001a0043
+		0x00430000
+		0x0000001a
+		0x00010001
+		0x07000001
+		0x00000707
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x01000000
+		0x00000000
+		0x00000000
+		0x18151100
+		0x0000000c
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00032003
+		0x00480120
+		0x00000000
+		0x01200320
+		0x00000048
+		0x00032000
+		0x00480120
+		0x00000000
+		0x00280000
+		0x00280028
+		0x01010100
+		0x01000202
+		0x0a000002
+		0x01000f0f
+		0x00000000
+		0x00000000
+		0x00010003
+		0x00000c03
+		0x00000100
+		0x00010000
+		0x01000000
+		0x00010000
+		0x00000001
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00010000
+		0x03030301
+		0x01010808
+		0x03030001
+		0x0a0a0a03
+		0x02080808
+		0x02050103
+		0x02050103
+		0x00050103
+		0x00020202
+		0x05020500
+		0x00020502
+		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
+		0x1e1e0000
+		0x0800001e
+		0x00001850
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00001850
+		0x0000f320
+		0x1850050a
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00001850
+		0x0000f320
+		0x1850050a
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00001850
+		0x0000f320
+		0x0202050a
+		0x03030202
+		0x00000018
+		0x00000000
+		0x00000000
+		0x00001403
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00030000
+		0x000e0020
+		0x000e0020
+		0x000e0020
+		0x00000000
+		0x00000000
+		0x01000000
+		0x00070007
+		0x00050007
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x01000101
+		0x01010101
+		0x01000101
+		0x01000100
+		0x00010001
+		0x00010002
+		0x00020100
+		0x00000002
+		0x00000700
+		0x00000000
+		0x000030a0
+		0x00001850
+		0x000030a0
+		0x00001850
+		0x000030a0
+		0x18501850
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00001850
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00001850
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00010000
+		0x00000007
+		0x81000001
+		0x0f0003f0
+		0x3fffffff
+		0x0f0000a0
+		0x377ff000
+		0x0f000020
+		0x377ff000
+		0x0f000030
+		0x377ff000
+		0x0f0000b0
+		0x377ff000
+		0x0f000100
+		0x377ff000
+		0x0f000110
+		0x377ff000
+		0x0f000010
+		0x377ff000
+		0x03000101
+		0x042e2e2e
+		0x06180006
+		0x00061800
+		0x00000018
+		0x0c2800a8
+		0x0c2800a8
+		0x0c2800a8
+		0x00000500
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x04040000
+		0x0d000004
+		0x00000128
+		0x00000000
+		0x00030003
+		0x00000018
+		0x00000000
+		0x00000000
+		0x03060002
+		0x03010301
+		0x01080801
+		0x04020201
+		0x01080804
+		0x00000000
+		0x03030000
+		0x0a0a0a03
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00030300
+		0x00000014
+		0x00000000
+		0x01010300
+		0x00000000
+		0x00000000
+		0x01000000
+		0x00000101
+		0x55555a5a
+		0x55555a5a
+		0x55555a5a
+		0x55555a5a
+		0x0a0a0001
+		0x0505000a
+		0x00000005
+		0x00000100
+		0x00030000
+		0x17030000
+		0x000e0020
+		0x000e0020
+		0x000e0020
+		0x00000000
+		0x00000000
+		0x00000100
+		0x140a0000
+		0x000a030a
+		0x03000a03
+		0x010a000a
+		0x00000100
+		0x01000000
+		0x00000000
+		0x00000100
+		0x1e1a0000
+		0x10010204
+		0x07070705
+		0x20000202
+		0x00201000
+		0x00201000
+		0x04041000
+		0x10100100
+		0x00010110
+		0x004b004a
+		0x1a030000
+		0x0102041e
+		0x34000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00004300
+		0x0001001a
+		0x004d4d07
+		0x001a0043
+		0x4d070001
+		0x0000434d
+		0x0001001a
+		0x004d4d07
+		0x001a0043
+		0x4d070001
+		0x0000434d
+		0x0001001a
+		0x004d4d07
+		0x001a0043
+		0x4d070001
+		0x0043004d
+		0x0001001a
+		0x004d4d07
+		0x001a0043
+		0x4d070001
+		0x0000434d
+		0x0001001a
+		0x004d4d07
+		0x001a0043
+		0x4d070001
+		0x0000434d
+		0x0001001a
+		0x004d4d07
+		0x001a0043
+		0x4d070001
+		0x0100004d
+		0x00c800c8
+		0x060400c8
+		0x0c060f11
+		0x2200d890
+		0x0a0c2005
+		0x0f11060a
+		0x00000c06
+		0x2200d890
+		0x0a0c2005
+		0x0f11060a
+		0x00000c06
+		0x2200d890
+		0x0a0c2005
+		0x0200020a
+		0x02000200
+		0x02000200
+		0x02000200
+		0x02000200
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x01000300
+		0x00185000
+		0x0000f320
+		0x00001850
+		0x0000f320
+		0x00001850
+		0x0000f320
+		0x08000000
+		0x00000100
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000002
+		0x76543210
+		0x0004c008
+		0x000000b3
+		0x00000000
+		0x00000000
+		0x00010000
+		0x01665555
+		0x00665555
+		0x00010f00
+		0x05010200
+		0x00000003
+		0x001700c0
+		0x00cc0101
+		0x00030066
+		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
+		0x02700270
+		0x02700270
+		0x02700270
+		0x02700270
+		0x00000270
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00800000
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00b30080
+		0x00000003
+		0x00000000
+		0x00020000
+		0x00000200
+		0x00000000
+		0x51315152
+		0xc0013150
+		0x020000c0
+		0x00100001
+		0x07054208
+		0x000f0c18
+		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
+		0x000000b3
+		0x00000000
+		0x00000000
+		0x00010000
+		0x01665555
+		0x00665555
+		0x00010f00
+		0x05010200
+		0x00000003
+		0x001700c0
+		0x00cc0101
+		0x00030066
+		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
+		0x02700270
+		0x02700270
+		0x02700270
+		0x02700270
+		0x00000270
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00800000
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00b30080
+		0x00000003
+		0x00000000
+		0x00020000
+		0x00000200
+		0x00000000
+		0x51315152
+		0xc0013150
+		0x020000c0
+		0x00100001
+		0x07054208
+		0x000f0c18
+		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
+		0x000000b3
+		0x00000000
+		0x00000000
+		0x00010000
+		0x01665555
+		0x00665555
+		0x00010f00
+		0x05010200
+		0x00000003
+		0x001700c0
+		0x00cc0101
+		0x00030066
+		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
+		0x02700270
+		0x02700270
+		0x02700270
+		0x02700270
+		0x00000270
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00800000
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00b30080
+		0x00000003
+		0x00000000
+		0x00020000
+		0x00000200
+		0x00000000
+		0x51315152
+		0xc0013150
+		0x020000c0
+		0x00100001
+		0x07054208
+		0x000f0c18
+		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
+		0x000000b3
+		0x00000000
+		0x00000000
+		0x00010000
+		0x01665555
+		0x00665555
+		0x00010f00
+		0x05010200
+		0x00000003
+		0x001700c0
+		0x00cc0101
+		0x00030066
+		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
+		0x02700270
+		0x02700270
+		0x02700270
+		0x02700270
+		0x00000270
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00800000
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00b30080
+		0x00000003
+		0x00000000
+		0x00020000
+		0x00000200
+		0x00000000
+		0x51315152
+		0xc0013150
+		0x020000c0
+		0x00100001
+		0x07054208
+		0x000f0c18
+		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
+		0x00000001
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00400320
+		0x00000040
+		0x00806420
+		0x00917531
+		0x00806420
+		0x01917531
+		0x00020003
+		0x00000000
+		0x00000000
+		0x00000000
+		0x000556aa
+		0x000aaaaa
+		0x000aa955
+		0x00055555
+		0x000b3133
+		0x0004cd33
+		0x0004cecc
+		0x000b32cc
+		0x0a418820
+		0x103f0000
+		0x0000003f
+		0x00038055
+		0x03800380
+		0x03800380
+		0x00000380
+		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
+		0x00000001
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00400320
+		0x00000040
+		0x00008eca
+		0x00009fdb
+		0x00008eca
+		0x01009fdb
+		0x00020003
+		0x00000000
+		0x00000000
+		0x00000000
+		0x000556aa
+		0x000aaaaa
+		0x000aa955
+		0x00055555
+		0x000b3133
+		0x0004cd33
+		0x0004cecc
+		0x000b32cc
+		0x0004a0e6
+		0x080f0000
+		0x0000000f
+		0x00038055
+		0x03800380
+		0x03800380
+		0x00000380
+		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
+		0x00000001
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00400320
+		0x00000040
+		0x00008eca
+		0x00009fdb
+		0x00008eca
+		0x01009fdb
+		0x00020003
+		0x00000000
+		0x00000000
+		0x00000000
+		0x000556aa
+		0x000aaaaa
+		0x000aa955
+		0x00055555
+		0x000b3133
+		0x0004cd33
+		0x0004cecc
+		0x000b32cc
+		0x1ee6b16a
+		0x10000000
+		0x00000000
+		0x00038055
+		0x03800380
+		0x03800380
+		0x00000380
+		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
+		0x00000050
+		0x00000000
+		0x00010100
+		0x00000601
+		0x00000000
+		0x00006400
+		0x01221102
+		0x00000000
+		0x00051f00
+		0x051f051f
+		0x051f051f
+		0x00030003
+		0x03000300
+		0x00000300
+		0x01221102
+		0x00000000
+		0x00000000
+		0x03020000
+		0x00000001
+		0x00000011
+		0x00000011
+		0x00000400
+		0x00000000
+		0x00000011
+		0x00000011
+		0x00004410
+		0x00004410
+		0x00004410
+		0x00004410
+		0x00004410
+		0x00000011
+		0x00004410
+		0x00000011
+		0x00004410
+		0x00000011
+		0x00004410
+		0x00000000
+		0x00000000
+		0x00000000
+		0x04000000
+		0x00000000
+		0x00000000
+		0x00000508
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0xe4000000
+		0x00000000
+		0x00000000
+		0x01010000
+		0x00000000
+	>;
+};
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h b/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
new file mode 100644
index 0000000..3edccb5
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2015 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef _ASM_ARCH_SDRAM_RK3399_H
+#define _ASM_ARCH_SDRAM_RK3399_H
+
+enum {
+	DDR3 = 0x3,
+	LPDDR2 = 0x5,
+	LPDDR3 = 0x6,
+	LPDDR4 = 0x7,
+	UNUSED = 0xFF
+};
+
+struct rk3399_ddr_pctl_regs {
+	u32 denali_ctl[332];
+};
+
+struct rk3399_ddr_publ_regs {
+	u32 denali_phy[959];
+};
+
+struct rk3399_ddr_pi_regs {
+	u32 denali_pi[200];
+};
+
+struct rk3399_msch_regs {
+	u32 coreid;
+	u32 revisionid;
+	u32 ddrconf;
+	u32 ddrsize;
+	u32 ddrtiminga0;
+	u32 ddrtimingb0;
+	u32 ddrtimingc0;
+	u32 devtodev0;
+	u32 reserved0[(0x110 - 0x20) / 4];
+	u32 ddrmode;
+	u32 reserved1[(0x1000 - 0x114) / 4];
+	u32 agingx0;
+};
+
+struct rk3399_msch_timings {
+	u32 ddrtiminga0;
+	u32 ddrtimingb0;
+	u32 ddrtimingc0;
+	u32 devtodev0;
+	u32 ddrmode;
+	u32 agingx0;
+};
+
+struct rk3399_ddr_cic_regs {
+	u32 cic_ctrl0;
+	u32 cic_ctrl1;
+	u32 cic_idle_th;
+	u32 cic_cg_wait_th;
+	u32 cic_status0;
+	u32 cic_status1;
+	u32 cic_ctrl2;
+	u32 cic_ctrl3;
+	u32 cic_ctrl4;
+};
+
+/* DENALI_CTL_00 */
+#define START		1
+
+/* DENALI_CTL_68 */
+#define PWRUP_SREFRESH_EXIT	(1 << 16)
+
+/* DENALI_CTL_274 */
+#define MEM_RST_VALID	1
+
+struct rk3399_sdram_channel {
+	unsigned int rank;
+	/* dram column number, 0 means this channel is invalid */
+	unsigned int col;
+	/* dram bank number, 3:8bank, 2:4bank */
+	unsigned int bk;
+	/* channel buswidth, 2:32bit, 1:16bit, 0:8bit */
+	unsigned int bw;
+	/* die buswidth, 2:32bit, 1:16bit, 0:8bit */
+	unsigned int dbw;
+	/*
+	 * row_3_4 = 1: 6Gb or 12Gb die
+	 * row_3_4 = 0: normal die, power of 2
+	 */
+	unsigned int row_3_4;
+	unsigned int cs0_row;
+	unsigned int cs1_row;
+	unsigned int ddrconfig;
+	struct rk3399_msch_timings noc_timings;
+};
+
+struct rk3399_sdram_params {
+	struct rk3399_sdram_channel ch[2];
+	unsigned int ddr_freq;
+	unsigned int dramtype;
+	unsigned int num_channels;
+	unsigned int stride;
+	unsigned int odt;
+	/* align 8 byte */
+	struct rk3399_ddr_pctl_regs pctl_regs;
+	/* align 8 byte */
+	struct rk3399_ddr_pi_regs pi_regs;
+	/* align 8 byte */
+	struct rk3399_ddr_publ_regs phy_regs;
+	/* used for align 8byte for next struct */
+	unsigned int align_8;
+};
+
+#define PI_CA_TRAINING	(1 << 0)
+#define PI_WRITE_LEVELING	(1 << 1)
+#define PI_READ_GATE_TRAINING	(1 << 2)
+#define PI_READ_LEVELING	(1 << 3)
+#define PI_WDQ_LEVELING	(1 << 4)
+#define PI_FULL_TRAINING	(0xff)
+
+#endif
diff --git a/arch/arm/mach-rockchip/rk3399/Makefile b/arch/arm/mach-rockchip/rk3399/Makefile
index 98ebeac..437d851 100644
--- a/arch/arm/mach-rockchip/rk3399/Makefile
+++ b/arch/arm/mach-rockchip/rk3399/Makefile
@@ -7,3 +7,4 @@
 obj-y += clk_rk3399.o
 obj-y += rk3399.o
 obj-y += syscon_rk3399.o
+obj-y += sdram_rk3399.o
diff --git a/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c b/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c
new file mode 100644
index 0000000..2670a67
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c
@@ -0,0 +1,1243 @@
+/*
+ * (C) Copyright 2016 Rockchip Inc.
+ *
+ * SPDX-License-Identifier:     GPL-2.0
+ *
+ * Adapted from coreboot.
+ */
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <ram.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sdram_rk3399.h>
+#include <asm/arch/cru_rk3399.h>
+#include <asm/arch/grf_rk3399.h>
+#include <asm/arch/hardware.h>
+#include <linux/err.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+struct chan_info {
+	struct rk3399_ddr_pctl_regs *pctl;
+	struct rk3399_ddr_pi_regs *pi;
+	struct rk3399_ddr_publ_regs *publ;
+	struct rk3399_msch_regs *msch;
+};
+
+struct dram_info {
+#ifdef CONFIG_SPL_BUILD
+	struct chan_info chan[2];
+	struct clk ddr_clk;
+	struct rk3399_cru *cru;
+	struct rk3399_pmucru *pmucru;
+	struct rk3399_pmusgrf_regs *pmusgrf;
+	struct rk3399_ddr_cic_regs *cic;
+#endif
+	struct ram_info info;
+	struct rk3399_pmugrf_regs *pmugrf;
+};
+
+/*
+ * sys_reg bitfield struct
+ * [31]		row_3_4_ch1
+ * [30]		row_3_4_ch0
+ * [29:28]	chinfo
+ * [27]		rank_ch1
+ * [26:25]	col_ch1
+ * [24]		bk_ch1
+ * [23:22]	cs0_row_ch1
+ * [21:20]	cs1_row_ch1
+ * [19:18]	bw_ch1
+ * [17:16]	dbw_ch1;
+ * [15:13]	ddrtype
+ * [12]		channelnum
+ * [11]		rank_ch0
+ * [10:9]	col_ch0
+ * [8]		bk_ch0
+ * [7:6]	cs0_row_ch0
+ * [5:4]	cs1_row_ch0
+ * [3:2]	bw_ch0
+ * [1:0]	dbw_ch0
+*/
+#define SYS_REG_ENC_ROW_3_4(n, ch)	((n) << (30 + (ch)))
+#define SYS_REG_DEC_ROW_3_4(n, ch)	((n >> (30 + ch)) & 0x1)
+#define SYS_REG_ENC_CHINFO(ch)		(1 << (28 + (ch)))
+#define SYS_REG_ENC_DDRTYPE(n)		((n) << 13)
+#define SYS_REG_ENC_NUM_CH(n)		(((n) - 1) << 12)
+#define SYS_REG_DEC_NUM_CH(n)		(1 + ((n >> 12) & 0x1))
+#define SYS_REG_ENC_RANK(n, ch)		(((n) - 1) << (11 + ((ch) * 16)))
+#define SYS_REG_DEC_RANK(n, ch)		(1 + ((n >> (11 + 16 * ch)) & 0x1))
+#define SYS_REG_ENC_COL(n, ch)		(((n) - 9) << (9 + ((ch) * 16)))
+#define SYS_REG_DEC_COL(n, ch)		(9 + ((n >> (9 + 16 * ch)) & 0x3))
+#define SYS_REG_ENC_BK(n, ch)		(((n) == 3 ? 0 : 1) \
+						<< (8 + ((ch) * 16)))
+#define SYS_REG_DEC_BK(n, ch)		(3 - ((n >> (8 + 16 * ch)) & 0x1))
+#define SYS_REG_ENC_CS0_ROW(n, ch)	(((n) - 13) << (6 + ((ch) * 16)))
+#define SYS_REG_DEC_CS0_ROW(n, ch)	(13 + ((n >> (6 + 16 * ch)) & 0x3))
+#define SYS_REG_ENC_CS1_ROW(n, ch)	(((n) - 13) << (4 + ((ch) * 16)))
+#define SYS_REG_DEC_CS1_ROW(n, ch)	(13 + ((n >> (4 + 16 * ch)) & 0x3))
+#define SYS_REG_ENC_BW(n, ch)		((2 >> (n)) << (2 + ((ch) * 16)))
+#define SYS_REG_DEC_BW(n, ch)		(2 >> ((n >> (2 + 16 * ch)) & 0x3))
+#define SYS_REG_ENC_DBW(n, ch)		((2 >> (n)) << (0 + ((ch) * 16)))
+#define SYS_REG_DEC_DBW(n, ch)		(2 >> ((n >> (0 + 16 * ch)) & 0x3))
+
+#define DDR_STRIDE(n, r)		writel((0x1F << (10 + 16)) \
+					       | (n << 10), r)
+
+#define PRESET_SGRF_HOLD(n)	((0x1 << (6+16)) | ((n) << 6))
+#define PRESET_GPIO0_HOLD(n)	((0x1 << (7+16)) | ((n) << 7))
+#define PRESET_GPIO1_HOLD(n)	((0x1 << (8+16)) | ((n) << 8))
+
+#define PHY_DRV_ODT_Hi_Z	(0x0)
+#define PHY_DRV_ODT_240		(0x1)
+#define PHY_DRV_ODT_120		(0x8)
+#define PHY_DRV_ODT_80		(0x9)
+#define PHY_DRV_ODT_60		(0xc)
+#define PHY_DRV_ODT_48		(0xd)
+#define PHY_DRV_ODT_40		(0xe)
+#define PHY_DRV_ODT_34_3	(0xf)
+
+#ifdef CONFIG_SPL_BUILD
+
+struct rockchip_dmc_plat {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_rockchip_rk3399_dmc dtplat;
+#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 void phy_dll_bypass_set(struct rk3399_ddr_publ_regs *ddr_publ_regs,
+			       u32 freq)
+{
+	u32 *denali_phy = ddr_publ_regs->denali_phy;
+
+	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);
+
+		/* 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);
+	}
+}
+
+static void set_memory_map(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 cs_map;
+	u32 reduc;
+	u32 row;
+
+	/* Get row number from ddrconfig setting */
+	if ((sdram_ch->ddrconfig < 2) || (sdram_ch->ddrconfig == 4))
+		row = 16;
+	else if (sdram_ch->ddrconfig == 3)
+		row = 14;
+	else
+		row = 15;
+
+	cs_map = (sdram_ch->rank > 1) ? 3 : 1;
+	reduc = (sdram_ch->bw == 2) ? 0 : 1;
+
+	clrsetbits_le32(&denali_ctl[191], 0xF, (12 - sdram_ch->col));
+	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));
+
+	/* PI_199 PI_COL_DIFF:RW:0:4 */
+	clrsetbits_le32(&denali_pi[199], 0xF, (12 - sdram_ch->col));
+
+	/* PI_155 PI_ROW_DIFF:RW:24:3 PI_BANK_DIFF:RW:16:2 */
+	clrsetbits_le32(&denali_pi[155], (0x3 << 16) | (0x7 << 24),
+			((3 - sdram_ch->bk) << 16) |
+			((16 - row) << 24));
+	/* PI_41 PI_CS_MAP:RW:24:4 */
+	clrsetbits_le32(&denali_pi[41], 0xf << 24, cs_map << 24);
+	if ((sdram_ch->rank == 1) && (sdram_params->dramtype == DDR3))
+		writel(0x2EC7FFFF, &denali_pi[34]);
+}
+
+static void set_ds_odt(const struct chan_info *chan,
+		       const struct rk3399_sdram_params *sdram_params)
+{
+	u32 *denali_phy = chan->publ->denali_phy;
+
+	u32 tsel_idle_en, tsel_wr_en, tsel_rd_en;
+	u32 tsel_idle_select_p, tsel_wr_select_p, tsel_rd_select_p;
+	u32 ca_tsel_wr_select_p, ca_tsel_wr_select_n;
+	u32 tsel_idle_select_n, tsel_wr_select_n, tsel_rd_select_n;
+	u32 reg_value;
+
+	if (sdram_params->dramtype == LPDDR4) {
+		tsel_rd_select_p = PHY_DRV_ODT_Hi_Z;
+		tsel_wr_select_p = PHY_DRV_ODT_40;
+		ca_tsel_wr_select_p = PHY_DRV_ODT_40;
+		tsel_idle_select_p = PHY_DRV_ODT_Hi_Z;
+
+		tsel_rd_select_n = PHY_DRV_ODT_240;
+		tsel_wr_select_n = PHY_DRV_ODT_40;
+		ca_tsel_wr_select_n = PHY_DRV_ODT_40;
+		tsel_idle_select_n = PHY_DRV_ODT_240;
+	} else if (sdram_params->dramtype == LPDDR3) {
+		tsel_rd_select_p = PHY_DRV_ODT_240;
+		tsel_wr_select_p = PHY_DRV_ODT_34_3;
+		ca_tsel_wr_select_p = PHY_DRV_ODT_48;
+		tsel_idle_select_p = PHY_DRV_ODT_240;
+
+		tsel_rd_select_n = PHY_DRV_ODT_Hi_Z;
+		tsel_wr_select_n = PHY_DRV_ODT_34_3;
+		ca_tsel_wr_select_n = PHY_DRV_ODT_48;
+		tsel_idle_select_n = PHY_DRV_ODT_Hi_Z;
+	} else {
+		tsel_rd_select_p = PHY_DRV_ODT_240;
+		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_240;
+
+		tsel_rd_select_n = PHY_DRV_ODT_240;
+		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 (sdram_params->odt == 1)
+		tsel_rd_en = 1;
+	else
+		tsel_rd_en = 0;
+
+	tsel_wr_en = 0;
+	tsel_idle_en = 0;
+
+	/*
+	 * phy_dq_tsel_select_X 24bits DENALI_PHY_6/134/262/390 offset_0
+	 * sets termination values for read/idle cycles and drive strength
+	 * for write cycles for DQ/DM
+	 */
+	reg_value = tsel_rd_select_n | (tsel_rd_select_p << 0x4) |
+		    (tsel_wr_select_n << 8) | (tsel_wr_select_p << 12) |
+		    (tsel_idle_select_n << 16) | (tsel_idle_select_p << 20);
+	clrsetbits_le32(&denali_phy[6], 0xffffff, reg_value);
+	clrsetbits_le32(&denali_phy[134], 0xffffff, reg_value);
+	clrsetbits_le32(&denali_phy[262], 0xffffff, reg_value);
+	clrsetbits_le32(&denali_phy[390], 0xffffff, reg_value);
+
+	/*
+	 * phy_dqs_tsel_select_X 24bits DENALI_PHY_7/135/263/391 offset_0
+	 * sets termination values for read/idle cycles and drive strength
+	 * for write cycles for DQS
+	 */
+	clrsetbits_le32(&denali_phy[7], 0xffffff, reg_value);
+	clrsetbits_le32(&denali_phy[135], 0xffffff, reg_value);
+	clrsetbits_le32(&denali_phy[263], 0xffffff, reg_value);
+	clrsetbits_le32(&denali_phy[391], 0xffffff, reg_value);
+
+	/* phy_adr_tsel_select_ 8bits DENALI_PHY_544/672/800 offset_0 */
+	reg_value = ca_tsel_wr_select_n | (ca_tsel_wr_select_p << 0x4);
+	clrsetbits_le32(&denali_phy[544], 0xff, reg_value);
+	clrsetbits_le32(&denali_phy[672], 0xff, reg_value);
+	clrsetbits_le32(&denali_phy[800], 0xff, reg_value);
+
+	/* phy_pad_addr_drive 8bits DENALI_PHY_928 offset_0 */
+	clrsetbits_le32(&denali_phy[928], 0xff, reg_value);
+
+	/* phy_pad_rst_drive 8bits DENALI_PHY_937 offset_0 */
+	clrsetbits_le32(&denali_phy[937], 0xff, reg_value);
+
+	/* phy_pad_cke_drive 8bits DENALI_PHY_935 offset_0 */
+	clrsetbits_le32(&denali_phy[935], 0xff, reg_value);
+
+	/* phy_pad_cs_drive 8bits DENALI_PHY_939 offset_0 */
+	clrsetbits_le32(&denali_phy[939], 0xff, reg_value);
+
+	/* phy_pad_clk_drive 8bits DENALI_PHY_929 offset_0 */
+	clrsetbits_le32(&denali_phy[929], 0xff, reg_value);
+
+	/* phy_pad_fdbk_drive 23bit DENALI_PHY_924/925 */
+	clrsetbits_le32(&denali_phy[924], 0xff,
+			tsel_wr_select_n | (tsel_wr_select_p << 4));
+	clrsetbits_le32(&denali_phy[925], 0xff,
+			tsel_rd_select_n | (tsel_rd_select_p << 4));
+
+	/* phy_dq_tsel_enable_X 3bits DENALI_PHY_5/133/261/389 offset_16 */
+	reg_value = (tsel_rd_en | (tsel_wr_en << 1) | (tsel_idle_en << 2))
+		<< 16;
+	clrsetbits_le32(&denali_phy[5], 0x7 << 16, reg_value);
+	clrsetbits_le32(&denali_phy[133], 0x7 << 16, reg_value);
+	clrsetbits_le32(&denali_phy[261], 0x7 << 16, reg_value);
+	clrsetbits_le32(&denali_phy[389], 0x7 << 16, reg_value);
+
+	/* phy_dqs_tsel_enable_X 3bits DENALI_PHY_6/134/262/390 offset_24 */
+	reg_value = (tsel_rd_en | (tsel_wr_en << 1) | (tsel_idle_en << 2))
+		<< 24;
+	clrsetbits_le32(&denali_phy[6], 0x7 << 24, reg_value);
+	clrsetbits_le32(&denali_phy[134], 0x7 << 24, reg_value);
+	clrsetbits_le32(&denali_phy[262], 0x7 << 24, reg_value);
+	clrsetbits_le32(&denali_phy[390], 0x7 << 24, reg_value);
+
+	/* phy_adr_tsel_enable_ 1bit DENALI_PHY_518/646/774 offset_8 */
+	reg_value = tsel_wr_en << 8;
+	clrsetbits_le32(&denali_phy[518], 0x1 << 8, reg_value);
+	clrsetbits_le32(&denali_phy[646], 0x1 << 8, reg_value);
+	clrsetbits_le32(&denali_phy[774], 0x1 << 8, reg_value);
+
+	/* phy_pad_addr_term tsel 1bit DENALI_PHY_933 offset_17 */
+	reg_value = tsel_wr_en << 17;
+	clrsetbits_le32(&denali_phy[933], 0x1 << 17, reg_value);
+	/*
+	 * pad_rst/cke/cs/clk_term tsel 1bits
+	 * DENALI_PHY_938/936/940/934 offset_17
+	 */
+	clrsetbits_le32(&denali_phy[938], 0x1 << 17, reg_value);
+	clrsetbits_le32(&denali_phy[936], 0x1 << 17, reg_value);
+	clrsetbits_le32(&denali_phy[940], 0x1 << 17, reg_value);
+	clrsetbits_le32(&denali_phy[934], 0x1 << 17, reg_value);
+
+	/* phy_pad_fdbk_term 1bit DENALI_PHY_930 offset_17 */
+	clrsetbits_le32(&denali_phy[930], 0x1 << 17, reg_value);
+}
+
+static int phy_io_config(const struct chan_info *chan,
+			  const struct rk3399_sdram_params *sdram_params)
+{
+	u32 *denali_phy = chan->publ->denali_phy;
+	u32 vref_mode_dq, vref_value_dq, vref_mode_ac, vref_value_ac;
+	u32 mode_sel;
+	u32 reg_value;
+	u32 drv_value, odt_value;
+	u32 speed;
+
+	/* vref setting */
+	if (sdram_params->dramtype == LPDDR4) {
+		/* LPDDR4 */
+		vref_mode_dq = 0x6;
+		vref_value_dq = 0x1f;
+		vref_mode_ac = 0x6;
+		vref_value_ac = 0x1f;
+	} else if (sdram_params->dramtype == LPDDR3) {
+		if (sdram_params->odt == 1) {
+			vref_mode_dq = 0x5;  /* LPDDR3 ODT */
+			drv_value = (readl(&denali_phy[6]) >> 12) & 0xf;
+			odt_value = (readl(&denali_phy[6]) >> 4) & 0xf;
+			if (drv_value == PHY_DRV_ODT_48) {
+				switch (odt_value) {
+				case PHY_DRV_ODT_240:
+					vref_value_dq = 0x16;
+					break;
+				case PHY_DRV_ODT_120:
+					vref_value_dq = 0x26;
+					break;
+				case PHY_DRV_ODT_60:
+					vref_value_dq = 0x36;
+					break;
+				default:
+					debug("Halting: Invalid ODT value.\n");
+					return -EINVAL;
+				}
+			} else if (drv_value == PHY_DRV_ODT_40) {
+				switch (odt_value) {
+				case PHY_DRV_ODT_240:
+					vref_value_dq = 0x19;
+					break;
+				case PHY_DRV_ODT_120:
+					vref_value_dq = 0x23;
+					break;
+				case PHY_DRV_ODT_60:
+					vref_value_dq = 0x31;
+					break;
+				default:
+					debug("Halting: Invalid ODT value.\n");
+					return -EINVAL;
+				}
+			} else if (drv_value == PHY_DRV_ODT_34_3) {
+				switch (odt_value) {
+				case PHY_DRV_ODT_240:
+					vref_value_dq = 0x17;
+					break;
+				case PHY_DRV_ODT_120:
+					vref_value_dq = 0x20;
+					break;
+				case PHY_DRV_ODT_60:
+					vref_value_dq = 0x2e;
+					break;
+				default:
+					debug("Halting: Invalid ODT value.\n");
+					return -EINVAL;
+				}
+			} else {
+				debug("Halting: Invalid DRV value.\n");
+				return -EINVAL;
+			}
+		} else {
+			vref_mode_dq = 0x2;  /* LPDDR3 */
+			vref_value_dq = 0x1f;
+		}
+		vref_mode_ac = 0x2;
+		vref_value_ac = 0x1f;
+	} else if (sdram_params->dramtype == DDR3) {
+		/* DDR3L */
+		vref_mode_dq = 0x1;
+		vref_value_dq = 0x1f;
+		vref_mode_ac = 0x1;
+		vref_value_ac = 0x1f;
+	} else {
+		debug("Halting: Unknown DRAM type.\n");
+		return -ENODEV;
+	}
+
+	reg_value = (vref_mode_dq << 9) | (0x1 << 8) | vref_value_dq;
+
+	/* PHY_913 PHY_PAD_VREF_CTRL_DQ_0 12bits offset_8 */
+	clrsetbits_le32(&denali_phy[913], 0xfff << 8, reg_value << 8);
+	/* PHY_914 PHY_PAD_VREF_CTRL_DQ_1 12bits offset_0 */
+	clrsetbits_le32(&denali_phy[914], 0xfff, reg_value);
+	/* PHY_914 PHY_PAD_VREF_CTRL_DQ_2 12bits offset_16 */
+	clrsetbits_le32(&denali_phy[914], 0xfff << 16, reg_value << 16);
+	/* PHY_915 PHY_PAD_VREF_CTRL_DQ_3 12bits offset_0 */
+	clrsetbits_le32(&denali_phy[915], 0xfff, reg_value);
+
+	reg_value = (vref_mode_ac << 9) | (0x1 << 8) | vref_value_ac;
+
+	/* PHY_915 PHY_PAD_VREF_CTRL_AC 12bits offset_16 */
+	clrsetbits_le32(&denali_phy[915], 0xfff << 16, reg_value << 16);
+
+	if (sdram_params->dramtype == LPDDR4)
+		mode_sel = 0x6;
+	else if (sdram_params->dramtype == LPDDR3)
+		mode_sel = 0x0;
+	else if (sdram_params->dramtype == DDR3)
+		mode_sel = 0x1;
+
+	/* PHY_924 PHY_PAD_FDBK_DRIVE */
+	clrsetbits_le32(&denali_phy[924], 0x7 << 15, mode_sel << 15);
+	/* PHY_926 PHY_PAD_DATA_DRIVE */
+	clrsetbits_le32(&denali_phy[926], 0x7 << 6, mode_sel << 6);
+	/* PHY_927 PHY_PAD_DQS_DRIVE */
+	clrsetbits_le32(&denali_phy[927], 0x7 << 6, mode_sel << 6);
+	/* PHY_928 PHY_PAD_ADDR_DRIVE */
+	clrsetbits_le32(&denali_phy[928], 0x7 << 14, mode_sel << 14);
+	/* PHY_929 PHY_PAD_CLK_DRIVE */
+	clrsetbits_le32(&denali_phy[929], 0x7 << 14, mode_sel << 14);
+	/* PHY_935 PHY_PAD_CKE_DRIVE */
+	clrsetbits_le32(&denali_phy[935], 0x7 << 14, mode_sel << 14);
+	/* PHY_937 PHY_PAD_RST_DRIVE */
+	clrsetbits_le32(&denali_phy[937], 0x7 << 14, mode_sel << 14);
+	/* PHY_939 PHY_PAD_CS_DRIVE */
+	clrsetbits_le32(&denali_phy[939], 0x7 << 14, mode_sel << 14);
+
+
+	/* speed setting */
+	if (sdram_params->ddr_freq < 400)
+		speed = 0x0;
+	else if (sdram_params->ddr_freq < 800)
+		speed = 0x1;
+	else if (sdram_params->ddr_freq < 1200)
+		speed = 0x2;
+	else
+		speed = 0x3;
+
+	/* PHY_924 PHY_PAD_FDBK_DRIVE */
+	clrsetbits_le32(&denali_phy[924], 0x3 << 21, speed << 21);
+	/* PHY_926 PHY_PAD_DATA_DRIVE */
+	clrsetbits_le32(&denali_phy[926], 0x3 << 9, speed << 9);
+	/* PHY_927 PHY_PAD_DQS_DRIVE */
+	clrsetbits_le32(&denali_phy[927], 0x3 << 9, speed << 9);
+	/* PHY_928 PHY_PAD_ADDR_DRIVE */
+	clrsetbits_le32(&denali_phy[928], 0x3 << 17, speed << 17);
+	/* PHY_929 PHY_PAD_CLK_DRIVE */
+	clrsetbits_le32(&denali_phy[929], 0x3 << 17, speed << 17);
+	/* PHY_935 PHY_PAD_CKE_DRIVE */
+	clrsetbits_le32(&denali_phy[935], 0x3 << 17, speed << 17);
+	/* PHY_937 PHY_PAD_RST_DRIVE */
+	clrsetbits_le32(&denali_phy[937], 0x3 << 17, speed << 17);
+	/* PHY_939 PHY_PAD_CS_DRIVE */
+	clrsetbits_le32(&denali_phy[939], 0x3 << 17, speed << 17);
+
+	return 0;
+}
+
+static int pctl_cfg(const struct chan_info *chan, u32 channel,
+		    const struct rk3399_sdram_params *sdram_params)
+{
+	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;
+
+	/*
+	 * work around controller bug:
+	 * Do not program DRAM_CLASS until NO_PHY_IND_TRAIN_INT is programmed
+	 */
+	copy_to_reg(&denali_ctl[1], &params_ctl[1],
+		    sizeof(struct rk3399_ddr_pctl_regs) - 4);
+	writel(params_ctl[0], &denali_ctl[0]);
+	copy_to_reg(denali_pi, &sdram_params->pi_regs.denali_pi[0],
+		    sizeof(struct rk3399_ddr_pi_regs));
+	/* rank count need to set for init */
+	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]);
+
+	pwrup_srefresh_exit = readl(&denali_ctl[68]) & PWRUP_SREFRESH_EXIT;
+	clrbits_le32(&denali_ctl[68], PWRUP_SREFRESH_EXIT);
+
+	/* PHY_DLL_RST_EN */
+	clrsetbits_le32(&denali_phy[957], 0x3 << 24, 1 << 24);
+
+	setbits_le32(&denali_pi[0], START);
+	setbits_le32(&denali_ctl[0], START);
+
+	/* Wating for phy DLL lock */
+	while (1) {
+		tmp = readl(&denali_phy[920]);
+		tmp1 = readl(&denali_phy[921]);
+		tmp2 = readl(&denali_phy[922]);
+		if ((((tmp >> 16) & 0x1) == 0x1) &&
+		    (((tmp1 >> 16) & 0x1) == 0x1) &&
+		    (((tmp1 >> 0) & 0x1) == 0x1) &&
+		    (((tmp2 >> 0) & 0x1) == 0x1))
+			break;
+	}
+
+	copy_to_reg(&denali_phy[896], &params_phy[896], (958 - 895) * 4);
+	copy_to_reg(&denali_phy[0], &params_phy[0], (90 - 0 + 1) * 4);
+	copy_to_reg(&denali_phy[128], &params_phy[128], (218 - 128 + 1) * 4);
+	copy_to_reg(&denali_phy[256], &params_phy[256], (346 - 256 + 1) * 4);
+	copy_to_reg(&denali_phy[384], &params_phy[384], (474 - 384 + 1) * 4);
+	copy_to_reg(&denali_phy[512], &params_phy[512], (549 - 512 + 1) * 4);
+	copy_to_reg(&denali_phy[640], &params_phy[640], (677 - 640 + 1) * 4);
+	copy_to_reg(&denali_phy[768], &params_phy[768], (805 - 768 + 1) * 4);
+	set_ds_odt(chan, sdram_params);
+
+	/*
+	 * 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_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);
+
+	ret = phy_io_config(chan, sdram_params);
+	if (ret)
+		return ret;
+
+	/* PHY_DLL_RST_EN */
+	clrsetbits_le32(&denali_phy[957], 0x3 << 24, 0x2 << 24);
+
+	/* Wating for PHY and DRAM init complete */
+	tmp = 0;
+	while (!(readl(&denali_ctl[203]) & (1 << 3))) {
+		mdelay(10);
+		tmp++;
+		if (tmp > 10)
+			return -ETIME;
+	}
+
+	clrsetbits_le32(&denali_ctl[68], PWRUP_SREFRESH_EXIT,
+			pwrup_srefresh_exit);
+	return 0;
+}
+
+static void select_per_cs_training_index(const struct chan_info *chan,
+					 u32 rank)
+{
+	u32 *denali_phy = chan->publ->denali_phy;
+
+	/* PHY_84 PHY_PER_CS_TRAINING_EN_0 1bit offset_16 */
+	if ((readl(&denali_phy[84])>>16) & 1) {
+		/*
+		 * PHY_8/136/264/392
+		 * phy_per_cs_training_index_X 1bit offset_24
+		 */
+		clrsetbits_le32(&denali_phy[8], 0x1 << 24, rank << 24);
+		clrsetbits_le32(&denali_phy[136], 0x1 << 24, rank << 24);
+		clrsetbits_le32(&denali_phy[264], 0x1 << 24, rank << 24);
+		clrsetbits_le32(&denali_phy[392], 0x1 << 24, rank << 24);
+	}
+}
+
+static void override_write_leveling_value(const struct chan_info *chan)
+{
+	u32 *denali_ctl = chan->pctl->denali_ctl;
+	u32 *denali_phy = chan->publ->denali_phy;
+	u32 byte;
+
+	/* PHY_896 PHY_FREQ_SEL_MULTICAST_EN 1bit offset_0 */
+	setbits_le32(&denali_phy[896], 1);
+
+	/*
+	 * PHY_8/136/264/392
+	 * phy_per_cs_training_multicast_en_X 1bit offset_16
+	 */
+	clrsetbits_le32(&denali_phy[8], 0x1 << 16, 1 << 16);
+	clrsetbits_le32(&denali_phy[136], 0x1 << 16, 1 << 16);
+	clrsetbits_le32(&denali_phy[264], 0x1 << 16, 1 << 16);
+	clrsetbits_le32(&denali_phy[392], 0x1 << 16, 1 << 16);
+
+	for (byte = 0; byte < 4; byte++)
+		clrsetbits_le32(&denali_phy[63 + (128 * byte)], 0xffff << 16,
+				0x200 << 16);
+
+	/* PHY_896 PHY_FREQ_SEL_MULTICAST_EN 1bit offset_0 */
+	clrbits_le32(&denali_phy[896], 1);
+
+	/* CTL_200 ctrlupd_req 1bit offset_8 */
+	clrsetbits_le32(&denali_ctl[200], 0x1 << 8, 0x1 << 8);
+}
+
+static int data_training_ca(const struct chan_info *chan, u32 channel,
+			    const struct rk3399_sdram_params *sdram_params)
+{
+	u32 *denali_pi = chan->pi->denali_pi;
+	u32 *denali_phy = chan->publ->denali_phy;
+	u32 i, tmp;
+	u32 obs_0, obs_1, obs_2, obs_err = 0;
+	u32 rank = sdram_params->ch[channel].rank;
+
+	for (i = 0; i < rank; i++) {
+		select_per_cs_training_index(chan, i);
+		/* PI_100 PI_CALVL_EN:RW:8:2 */
+		clrsetbits_le32(&denali_pi[100], 0x3 << 8, 0x2 << 8);
+		/* PI_92 PI_CALVL_REQ:WR:16:1,PI_CALVL_CS:RW:24:2 */
+		clrsetbits_le32(&denali_pi[92],
+				(0x1 << 16) | (0x3 << 24),
+				(0x1 << 16) | (i << 24));
+
+		/* Waiting for training complete */
+		while (1) {
+			/* PI_174 PI_INT_STATUS:RD:8:18 */
+			tmp = readl(&denali_pi[174]) >> 8;
+			/*
+			 * check status obs
+			 * PHY_532/660/789 phy_adr_calvl_obs1_:0:32
+			 */
+			obs_0 = readl(&denali_phy[532]);
+			obs_1 = readl(&denali_phy[660]);
+			obs_2 = readl(&denali_phy[788]);
+			if (((obs_0 >> 30) & 0x3) ||
+			    ((obs_1 >> 30) & 0x3) ||
+			    ((obs_2 >> 30) & 0x3))
+				obs_err = 1;
+			if ((((tmp >> 11) & 0x1) == 0x1) &&
+			    (((tmp >> 13) & 0x1) == 0x1) &&
+			    (((tmp >> 5) & 0x1) == 0x0) &&
+			    (obs_err == 0))
+				break;
+			else if ((((tmp >> 5) & 0x1) == 0x1) ||
+				 (obs_err == 1))
+				return -EIO;
+		}
+		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
+		writel(0x00003f7c, (&denali_pi[175]));
+	}
+	clrbits_le32(&denali_pi[100], 0x3 << 8);
+
+	return 0;
+}
+
+static int data_training_wl(const struct chan_info *chan, u32 channel,
+			    const struct rk3399_sdram_params *sdram_params)
+{
+	u32 *denali_pi = chan->pi->denali_pi;
+	u32 *denali_phy = chan->publ->denali_phy;
+	u32 i, tmp;
+	u32 obs_0, obs_1, obs_2, obs_3, obs_err = 0;
+	u32 rank = sdram_params->ch[channel].rank;
+
+	for (i = 0; i < rank; i++) {
+		select_per_cs_training_index(chan, i);
+		/* PI_60 PI_WRLVL_EN:RW:8:2 */
+		clrsetbits_le32(&denali_pi[60], 0x3 << 8, 0x2 << 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));
+
+		/* Waiting for training complete */
+		while (1) {
+			/* PI_174 PI_INT_STATUS:RD:8:18 */
+			tmp = readl(&denali_pi[174]) >> 8;
+
+			/*
+			 * check status obs, if error maybe can not
+			 * get leveling done PHY_40/168/296/424
+			 * phy_wrlvl_status_obs_X:0:13
+			 */
+			obs_0 = readl(&denali_phy[40]);
+			obs_1 = readl(&denali_phy[168]);
+			obs_2 = readl(&denali_phy[296]);
+			obs_3 = readl(&denali_phy[424]);
+			if (((obs_0 >> 12) & 0x1) ||
+			    ((obs_1 >> 12) & 0x1) ||
+			    ((obs_2 >> 12) & 0x1) ||
+			    ((obs_3 >> 12) & 0x1))
+				obs_err = 1;
+			if ((((tmp >> 10) & 0x1) == 0x1) &&
+			    (((tmp >> 13) & 0x1) == 0x1) &&
+			    (((tmp >> 4) & 0x1) == 0x0) &&
+			    (obs_err == 0))
+				break;
+			else if ((((tmp >> 4) & 0x1) == 0x1) ||
+				 (obs_err == 1))
+				return -EIO;
+		}
+		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
+		writel(0x00003f7c, (&denali_pi[175]));
+	}
+
+	override_write_leveling_value(chan);
+	clrbits_le32(&denali_pi[60], 0x3 << 8);
+
+	return 0;
+}
+
+static int data_training_rg(const struct chan_info *chan, u32 channel,
+			    const struct rk3399_sdram_params *sdram_params)
+{
+	u32 *denali_pi = chan->pi->denali_pi;
+	u32 *denali_phy = chan->publ->denali_phy;
+	u32 i, tmp;
+	u32 obs_0, obs_1, obs_2, obs_3, obs_err = 0;
+	u32 rank = sdram_params->ch[channel].rank;
+
+	for (i = 0; i < rank; i++) {
+		select_per_cs_training_index(chan, i);
+		/* PI_80 PI_RDLVL_GATE_EN:RW:24:2 */
+		clrsetbits_le32(&denali_pi[80], 0x3 << 24, 0x2 << 24);
+		/*
+		 * PI_74 PI_RDLVL_GATE_REQ:WR:16:1
+		 * PI_RDLVL_CS:RW:24:2
+		 */
+		clrsetbits_le32(&denali_pi[74],
+				(0x1 << 16) | (0x3 << 24),
+				(0x1 << 16) | (i << 24));
+
+		/* Waiting for training complete */
+		while (1) {
+			/* PI_174 PI_INT_STATUS:RD:8:18 */
+			tmp = readl(&denali_pi[174]) >> 8;
+
+			/*
+			 * check status obs
+			 * PHY_43/171/299/427
+			 *     PHY_GTLVL_STATUS_OBS_x:16:8
+			 */
+			obs_0 = readl(&denali_phy[43]);
+			obs_1 = readl(&denali_phy[171]);
+			obs_2 = readl(&denali_phy[299]);
+			obs_3 = readl(&denali_phy[427]);
+			if (((obs_0 >> (16 + 6)) & 0x3) ||
+			    ((obs_1 >> (16 + 6)) & 0x3) ||
+			    ((obs_2 >> (16 + 6)) & 0x3) ||
+			    ((obs_3 >> (16 + 6)) & 0x3))
+				obs_err = 1;
+			if ((((tmp >> 9) & 0x1) == 0x1) &&
+			    (((tmp >> 13) & 0x1) == 0x1) &&
+			    (((tmp >> 3) & 0x1) == 0x0) &&
+			    (obs_err == 0))
+				break;
+			else if ((((tmp >> 3) & 0x1) == 0x1) ||
+				 (obs_err == 1))
+				return -EIO;
+		}
+		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
+		writel(0x00003f7c, (&denali_pi[175]));
+	}
+	clrbits_le32(&denali_pi[80], 0x3 << 24);
+
+	return 0;
+}
+
+static int data_training_rl(const struct chan_info *chan, u32 channel,
+			    const struct rk3399_sdram_params *sdram_params)
+{
+	u32 *denali_pi = chan->pi->denali_pi;
+	u32 i, tmp;
+	u32 rank = sdram_params->ch[channel].rank;
+
+	for (i = 0; i < rank; i++) {
+		select_per_cs_training_index(chan, i);
+		/* PI_80 PI_RDLVL_EN:RW:16:2 */
+		clrsetbits_le32(&denali_pi[80], 0x3 << 16, 0x2 << 16);
+		/* PI_74 PI_RDLVL_REQ:WR:8:1,PI_RDLVL_CS:RW:24:2 */
+		clrsetbits_le32(&denali_pi[74],
+				(0x1 << 8) | (0x3 << 24),
+				(0x1 << 8) | (i << 24));
+
+		/* Waiting for training complete */
+		while (1) {
+			/* PI_174 PI_INT_STATUS:RD:8:18 */
+			tmp = readl(&denali_pi[174]) >> 8;
+
+			/*
+			 * make sure status obs not report error bit
+			 * PHY_46/174/302/430
+			 *     phy_rdlvl_status_obs_X:16:8
+			 */
+			if ((((tmp >> 8) & 0x1) == 0x1) &&
+			    (((tmp >> 13) & 0x1) == 0x1) &&
+			    (((tmp >> 2) & 0x1) == 0x0))
+				break;
+			else if (((tmp >> 2) & 0x1) == 0x1)
+				return -EIO;
+		}
+		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
+		writel(0x00003f7c, (&denali_pi[175]));
+	}
+	clrbits_le32(&denali_pi[80], 0x3 << 16);
+
+	return 0;
+}
+
+static int data_training_wdql(const struct chan_info *chan, u32 channel,
+			      const struct rk3399_sdram_params *sdram_params)
+{
+	u32 *denali_pi = chan->pi->denali_pi;
+	u32 i, tmp;
+	u32 rank = sdram_params->ch[channel].rank;
+
+	for (i = 0; i < rank; i++) {
+		select_per_cs_training_index(chan, i);
+		/*
+		 * disable PI_WDQLVL_VREF_EN before wdq leveling?
+		 * PI_181 PI_WDQLVL_VREF_EN:RW:8:1
+		 */
+		clrbits_le32(&denali_pi[181], 0x1 << 8);
+		/* PI_124 PI_WDQLVL_EN:RW:16:2 */
+		clrsetbits_le32(&denali_pi[124], 0x3 << 16, 0x2 << 16);
+		/* PI_121 PI_WDQLVL_REQ:WR:8:1,PI_WDQLVL_CS:RW:16:2 */
+		clrsetbits_le32(&denali_pi[121],
+				(0x1 << 8) | (0x3 << 16),
+				(0x1 << 8) | (i << 16));
+
+		/* Waiting for training complete */
+		while (1) {
+			/* PI_174 PI_INT_STATUS:RD:8:18 */
+			tmp = readl(&denali_pi[174]) >> 8;
+			if ((((tmp >> 12) & 0x1) == 0x1) &&
+			    (((tmp >> 13) & 0x1) == 0x1) &&
+			    (((tmp >> 6) & 0x1) == 0x0))
+				break;
+			else if (((tmp >> 6) & 0x1) == 0x1)
+				return -EIO;
+		}
+		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
+		writel(0x00003f7c, (&denali_pi[175]));
+	}
+	clrbits_le32(&denali_pi[124], 0x3 << 16);
+
+	return 0;
+}
+
+static int data_training(const struct chan_info *chan, u32 channel,
+			 const struct rk3399_sdram_params *sdram_params,
+			 u32 training_flag)
+{
+	u32 *denali_phy = chan->publ->denali_phy;
+
+	/* PHY_927 PHY_PAD_DQS_DRIVE  RPULL offset_22 */
+	setbits_le32(&denali_phy[927], (1 << 22));
+
+	if (training_flag == PI_FULL_TRAINING) {
+		if (sdram_params->dramtype == LPDDR4) {
+			training_flag = PI_CA_TRAINING | PI_WRITE_LEVELING |
+					PI_READ_GATE_TRAINING |
+					PI_READ_LEVELING | PI_WDQ_LEVELING;
+		} else if (sdram_params->dramtype == LPDDR3) {
+			training_flag = PI_CA_TRAINING | PI_WRITE_LEVELING |
+					PI_READ_GATE_TRAINING;
+		} else if (sdram_params->dramtype == DDR3) {
+			training_flag = PI_WRITE_LEVELING |
+					PI_READ_GATE_TRAINING |
+					PI_READ_LEVELING;
+		}
+	}
+
+	/* ca training(LPDDR4,LPDDR3 support) */
+	if ((training_flag & PI_CA_TRAINING) == PI_CA_TRAINING)
+		data_training_ca(chan, channel, sdram_params);
+
+	/* write leveling(LPDDR4,LPDDR3,DDR3 support) */
+	if ((training_flag & PI_WRITE_LEVELING) == PI_WRITE_LEVELING)
+		data_training_wl(chan, channel, sdram_params);
+
+	/* read gate training(LPDDR4,LPDDR3,DDR3 support) */
+	if ((training_flag & PI_READ_GATE_TRAINING) == PI_READ_GATE_TRAINING)
+		data_training_rg(chan, channel, sdram_params);
+
+	/* read leveling(LPDDR4,LPDDR3,DDR3 support) */
+	if ((training_flag & PI_READ_LEVELING) == PI_READ_LEVELING)
+		data_training_rl(chan, channel, sdram_params);
+
+	/* wdq leveling(LPDDR4 support) */
+	if ((training_flag & PI_WDQ_LEVELING) == PI_WDQ_LEVELING)
+		data_training_wdql(chan, channel, sdram_params);
+
+	/* PHY_927 PHY_PAD_DQS_DRIVE  RPULL offset_22 */
+	clrbits_le32(&denali_phy[927], (1 << 22));
+
+	return 0;
+}
+
+static void set_ddrconfig(const struct chan_info *chan,
+			  const struct rk3399_sdram_params *sdram_params,
+			  unsigned char channel, u32 ddrconfig)
+{
+	/* only need to set ddrconfig */
+	struct rk3399_msch_regs *ddr_msch_regs = chan->msch;
+	unsigned int cs0_cap = 0;
+	unsigned int cs1_cap = 0;
+
+	cs0_cap = (1 << (sdram_params->ch[channel].cs0_row
+			+ sdram_params->ch[channel].col
+			+ sdram_params->ch[channel].bk
+			+ sdram_params->ch[channel].bw - 20));
+	if (sdram_params->ch[channel].rank > 1)
+		cs1_cap = cs0_cap >> (sdram_params->ch[channel].cs0_row
+				- sdram_params->ch[channel].cs1_row);
+	if (sdram_params->ch[channel].row_3_4) {
+		cs0_cap = cs0_cap * 3 / 4;
+		cs1_cap = cs1_cap * 3 / 4;
+	}
+
+	writel(ddrconfig | (ddrconfig << 8), &ddr_msch_regs->ddrconf);
+	writel(((cs0_cap / 32) & 0xff) | (((cs1_cap / 32) & 0xff) << 8),
+	       &ddr_msch_regs->ddrsize);
+}
+
+static void dram_all_config(struct dram_info *dram,
+			    const struct rk3399_sdram_params *sdram_params)
+{
+	u32 sys_reg = 0;
+	unsigned int channel, idx;
+
+	sys_reg |= SYS_REG_ENC_DDRTYPE(sdram_params->dramtype);
+	sys_reg |= SYS_REG_ENC_NUM_CH(sdram_params->num_channels);
+	for (channel = 0, idx = 0;
+	     (idx < sdram_params->num_channels) && (channel < 2); channel++) {
+		const struct rk3399_sdram_channel *info =
+			&sdram_params->ch[channel];
+		struct rk3399_msch_regs *ddr_msch_regs;
+		const struct rk3399_msch_timings *noc_timing;
+
+		if (sdram_params->ch[channel].col == 0)
+			continue;
+		idx++;
+		sys_reg |= SYS_REG_ENC_ROW_3_4(info->row_3_4, channel);
+		sys_reg |= SYS_REG_ENC_CHINFO(channel);
+		sys_reg |= SYS_REG_ENC_RANK(info->rank, channel);
+		sys_reg |= SYS_REG_ENC_COL(info->col, channel);
+		sys_reg |= SYS_REG_ENC_BK(info->bk, channel);
+		sys_reg |= SYS_REG_ENC_CS0_ROW(info->cs0_row, channel);
+		if (sdram_params->ch[channel].rank > 1)
+			sys_reg |= SYS_REG_ENC_CS1_ROW(info->cs1_row, channel);
+		sys_reg |= SYS_REG_ENC_BW(info->bw, channel);
+		sys_reg |= SYS_REG_ENC_DBW(info->dbw, channel);
+
+		ddr_msch_regs = dram->chan[channel].msch;
+		noc_timing = &sdram_params->ch[channel].noc_timings;
+		writel(noc_timing->ddrtiminga0,
+		       &ddr_msch_regs->ddrtiminga0);
+		writel(noc_timing->ddrtimingb0,
+		       &ddr_msch_regs->ddrtimingb0);
+		writel(noc_timing->ddrtimingc0,
+		       &ddr_msch_regs->ddrtimingc0);
+		writel(noc_timing->devtodev0,
+		       &ddr_msch_regs->devtodev0);
+		writel(noc_timing->ddrmode,
+		       &ddr_msch_regs->ddrmode);
+
+		/* rank 1 memory clock disable (dfi_dram_clk_disable = 1) */
+		if (sdram_params->ch[channel].rank == 1)
+			setbits_le32(&dram->chan[channel].pctl->denali_ctl[276],
+				     1 << 17);
+	}
+
+	writel(sys_reg, &dram->pmugrf->os_reg2);
+	DDR_STRIDE(sdram_params->stride, &dram->pmusgrf->soc_con4);
+
+	/* reboot hold register set */
+	writel(PRESET_SGRF_HOLD(0) | PRESET_GPIO0_HOLD(1) |
+		PRESET_GPIO1_HOLD(1),
+		&dram->pmucru->pmucru_rstnhold_con[1]);
+	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)
+{
+	u32 channel;
+	u32 *denali_phy;
+	u32 ch_count = sdram_params->num_channels;
+	int i = 0;
+
+	writel(RK_CLRSETBITS(0x03 << 4 | 1 << 2 | 1,
+			     1 << 4 | 1 << 2 | 1),
+			&dram->cic->cic_ctrl0);
+	while (!(readl(&dram->cic->cic_status0) & (1 << 2))) {
+		mdelay(10);
+		i++;
+		if (i > 10) {
+			debug("index1 frequency change overtime, reset\n");
+			return -ETIME;
+		}
+	}
+
+	i = 0;
+	writel(RK_CLRSETBITS(1 << 1, 1 << 1), &dram->cic->cic_ctrl0);
+	while (!(readl(&dram->cic->cic_status0) & (1 << 0))) {
+		mdelay(10);
+		if (i > 10) {
+			debug("index1 frequency done overtime, reset\n");
+			return -ETIME;
+		}
+	}
+
+	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);
+		if (data_training(&dram->chan[channel], channel,
+				  sdram_params, PI_FULL_TRAINING)) {
+			debug("index1 training failed, reset\n");
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+static int sdram_init(struct dram_info *dram,
+		      const struct rk3399_sdram_params *sdram_params)
+{
+	unsigned char dramtype = sdram_params->dramtype;
+	unsigned int ddr_freq = sdram_params->ddr_freq;
+	int channel;
+
+	printf("Starting SDRAM initialization...\n");
+
+	if ((dramtype == DDR3 && ddr_freq > 800) ||
+	    (dramtype == LPDDR3 && ddr_freq > 933) ||
+	    (dramtype == LPDDR4 && ddr_freq > 800)) {
+		debug("SDRAM frequency is to high!");
+		return -E2BIG;
+	}
+
+
+	for (channel = 0; channel < 2; channel++) {
+		const struct chan_info *chan = &dram->chan[channel];
+		struct rk3399_ddr_publ_regs *publ = chan->publ;
+
+		phy_dll_bypass_set(publ, ddr_freq);
+
+		if (channel >= sdram_params->num_channels)
+			continue;
+
+		if (pctl_cfg(chan, channel, sdram_params) != 0) {
+			printf("pctl_cfg fail, reset\n");
+			return -EIO;
+		}
+
+		/* LPDDR2/LPDDR3 need to wait DAI complete, max 10us */
+		if (dramtype == LPDDR3)
+			udelay(10);
+
+		if (data_training(chan, channel,
+				  sdram_params, PI_FULL_TRAINING)) {
+			printf("SDRAM initialization failed, reset\n");
+			return -EIO;
+		}
+
+		set_ddrconfig(chan, sdram_params, channel,
+			      sdram_params->ch[channel].ddrconfig);
+	}
+	dram_all_config(dram, sdram_params);
+	switch_to_phy_index1(dram, sdram_params);
+
+	printf("Finish SDRAM initialization...\n");
+	return 0;
+}
+#endif
+
+size_t sdram_size_mb(struct dram_info *dram)
+{
+	u32 rank, col, bk, cs0_row, cs1_row, bw, row_3_4;
+	size_t chipsize_mb = 0;
+	size_t size_mb = 0;
+	u32 ch;
+
+	u32 sys_reg = readl(&dram->pmugrf->os_reg2);
+	u32 ch_num = SYS_REG_DEC_NUM_CH(sys_reg);
+
+	for (ch = 0; ch < ch_num; ch++) {
+		rank = SYS_REG_DEC_RANK(sys_reg, ch);
+		col = SYS_REG_DEC_COL(sys_reg, ch);
+		bk = SYS_REG_DEC_BK(sys_reg, ch);
+		cs0_row = SYS_REG_DEC_CS0_ROW(sys_reg, ch);
+		cs1_row = SYS_REG_DEC_CS1_ROW(sys_reg, ch);
+		bw = SYS_REG_DEC_BW(sys_reg, ch);
+		row_3_4 = SYS_REG_DEC_ROW_3_4(sys_reg, ch);
+
+		chipsize_mb = (1 << (cs0_row + col + bk + bw - 20));
+
+		if (rank > 1)
+			chipsize_mb += chipsize_mb >> (cs0_row - cs1_row);
+		if (row_3_4)
+			chipsize_mb = chipsize_mb * 3 / 4;
+		size_mb += chipsize_mb;
+	}
+
+	/*
+	 * we use the 0x00000000~0xf7ffffff space
+	 * since 0xf8000000~0xffffffff is soc register space
+	 * so we reserve it
+	 */
+	size_mb = min_t(size_t, size_mb, 0xf8000000/(1<<20));
+
+	return size_mb;
+}
+
+static int rk3399_dmc_probe(struct udevice *dev)
+{
+	struct dram_info *priv = dev_get_priv(dev);
+#ifdef CONFIG_SPL_BUILD
+	struct rockchip_dmc_plat *plat = dev_get_platdata(dev);
+	struct dtd_rockchip_rk3399_dmc *dtplat = &plat->dtplat;
+	struct rk3399_sdram_params *params =
+					(void *)dtplat->rockchip_sdram_params;
+	int ret;
+
+	priv->cic = syscon_get_first_range(ROCKCHIP_SYSCON_CIC);
+	priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
+	priv->pmusgrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUSGRF);
+	priv->pmucru = syscon_get_first_range(ROCKCHIP_SYSCON_PMUCRU);
+	ret = regmap_init_mem_platdata(dev, dtplat->reg,
+				       ARRAY_SIZE(dtplat->reg) / 4,
+				       &plat->map);
+	if (ret)
+		return ret;
+
+	priv->chan[0].pctl = regmap_get_range(plat->map, 0);
+	priv->chan[0].pi = regmap_get_range(plat->map, 1);
+	priv->chan[0].publ = regmap_get_range(plat->map, 2);
+	priv->chan[0].msch = regmap_get_range(plat->map, 3);
+	priv->chan[1].pctl = regmap_get_range(plat->map, 4);
+	priv->chan[1].pi = regmap_get_range(plat->map, 5);
+	priv->chan[1].publ = regmap_get_range(plat->map, 6);
+	priv->chan[1].msch = regmap_get_range(plat->map, 7);
+	priv->cru = rockchip_get_cru();
+	if (IS_ERR(priv->cru))
+		return PTR_ERR(priv->cru);
+
+	ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->ddr_clk);
+	if (ret) {
+		printf("%s clk get failed %d\n", __func__, ret);
+		return ret;
+	}
+	ret = clk_set_rate(&priv->ddr_clk, params->ddr_freq*MHz);
+	if (ret < 0) {
+		printf("%s clk set failed %d\n", __func__, ret);
+		return ret;
+	}
+	ret = sdram_init(priv, params);
+	if (ret < 0) {
+		printf("%s DRAM init failed%d\n", __func__, ret);
+		return ret;
+	}
+#else
+	priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
+	debug("%s: pmugrf=%p\n", __func__, priv->pmugrf);
+#endif
+	return 0;
+}
+
+static int rk3399_dmc_get_info(struct udevice *dev, struct ram_info *info)
+{
+	struct dram_info *priv = dev_get_priv(dev);
+
+	info = &priv->info;
+	priv->info.base = 0;
+	priv->info.size = sdram_size_mb(priv) << 20;
+
+	return 0;
+}
+
+static struct ram_ops rk3399_dmc_ops = {
+	.get_info = rk3399_dmc_get_info,
+};
+
+
+static const struct udevice_id rk3399_dmc_ids[] = {
+	{ .compatible = "rockchip,rk3399-dmc" },
+	{ }
+};
+
+U_BOOT_DRIVER(dmc_rk3399) = {
+	.name = "rockchip_rk3399_dmc",
+	.id = UCLASS_RAM,
+	.of_match = rk3399_dmc_ids,
+	.ops = &rk3399_dmc_ops,
+	.probe = rk3399_dmc_probe,
+#ifdef CONFIG_SPL_BUILD
+	.priv_auto_alloc_size = sizeof(struct dram_info),
+	.platdata_auto_alloc_size = sizeof(struct rockchip_dmc_plat),
+#endif
+};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 2/6] arm64: rk3399: move grf register definitions to grf_rk3399.h
  2017-01-18 12:16 [U-Boot] [PATCH 0/6] rk3399: enable SPL driver Kever Yang
  2017-01-18 12:16 ` [U-Boot] [PATCH 1/6] arm64: rk3399: add ddr controller driver Kever Yang
@ 2017-01-18 12:16 ` Kever Yang
  2017-01-25  4:09   ` Simon Glass
  2017-01-18 12:16 ` [U-Boot] [PATCH 3/6] clk: rk3399: update driver for spl Kever Yang
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Kever Yang @ 2017-01-18 12:16 UTC (permalink / raw)
  To: u-boot

rk3399 grf register bit defenitions should locate in header
file, so that not only pinctrl can use it.

Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
---

 arch/arm/include/asm/arch-rockchip/grf_rk3399.h | 118 ++++++++++++++++++++++++
 drivers/pinctrl/rockchip/pinctrl_rk3399.c       | 106 ---------------------
 2 files changed, 118 insertions(+), 106 deletions(-)

diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk3399.h b/arch/arm/include/asm/arch-rockchip/grf_rk3399.h
index d3d1467..62d8496 100644
--- a/arch/arm/include/asm/arch-rockchip/grf_rk3399.h
+++ b/arch/arm/include/asm/arch-rockchip/grf_rk3399.h
@@ -318,4 +318,122 @@ struct rk3399_pmusgrf_regs {
 };
 check_member(rk3399_pmusgrf_regs, slv_secure_con4, 0xe3d4);
 
+enum {
+	/* GRF_GPIO2B_IOMUX */
+	GRF_GPIO2B1_SEL_SHIFT	= 0,
+	GRF_GPIO2B1_SEL_MASK	= 3 << GRF_GPIO2B1_SEL_SHIFT,
+	GRF_SPI2TPM_RXD		= 1,
+	GRF_GPIO2B2_SEL_SHIFT	= 2,
+	GRF_GPIO2B2_SEL_MASK	= 3 << GRF_GPIO2B2_SEL_SHIFT,
+	GRF_SPI2TPM_TXD		= 1,
+	GRF_GPIO2B3_SEL_SHIFT	= 6,
+	GRF_GPIO2B3_SEL_MASK	= 3 << GRF_GPIO2B3_SEL_SHIFT,
+	GRF_SPI2TPM_CLK		= 1,
+	GRF_GPIO2B4_SEL_SHIFT	= 8,
+	GRF_GPIO2B4_SEL_MASK	= 3 << GRF_GPIO2B4_SEL_SHIFT,
+	GRF_SPI2TPM_CSN0	= 1,
+
+	/* GRF_GPIO3A_IOMUX */
+	GRF_GPIO3A4_SEL_SHIFT	= 8,
+	GRF_GPIO3A4_SEL_MASK	= 3 << GRF_GPIO3A4_SEL_SHIFT,
+	GRF_SPI0NORCODEC_RXD	= 2,
+	GRF_GPIO3A5_SEL_SHIFT	= 10,
+	GRF_GPIO3A5_SEL_MASK	= 3 << GRF_GPIO3A5_SEL_SHIFT,
+	GRF_SPI0NORCODEC_TXD	= 2,
+	GRF_GPIO3A6_SEL_SHIFT	= 12,
+	GRF_GPIO3A6_SEL_MASK	= 3 << GRF_GPIO3A6_SEL_SHIFT,
+	GRF_SPI0NORCODEC_CLK	= 2,
+	GRF_GPIO3A7_SEL_SHIFT	= 14,
+	GRF_GPIO3A7_SEL_MASK	= 3 << GRF_GPIO3A7_SEL_SHIFT,
+	GRF_SPI0NORCODEC_CSN0	= 2,
+
+	/* GRF_GPIO3B_IOMUX */
+	GRF_GPIO3B0_SEL_SHIFT	= 0,
+	GRF_GPIO3B0_SEL_MASK	= 3 << GRF_GPIO3B0_SEL_SHIFT,
+	GRF_SPI0NORCODEC_CSN1	= 2,
+
+	/* GRF_GPIO4B_IOMUX */
+	GRF_GPIO4B0_SEL_SHIFT	= 0,
+	GRF_GPIO4B0_SEL_MASK	= 3 << GRF_GPIO4B0_SEL_SHIFT,
+	GRF_SDMMC_DATA0		= 1,
+	GRF_UART2DBGA_SIN	= 2,
+	GRF_GPIO4B1_SEL_SHIFT	= 2,
+	GRF_GPIO4B1_SEL_MASK	= 3 << GRF_GPIO4B1_SEL_SHIFT,
+	GRF_SDMMC_DATA1		= 1,
+	GRF_UART2DBGA_SOUT	= 2,
+	GRF_GPIO4B2_SEL_SHIFT	= 4,
+	GRF_GPIO4B2_SEL_MASK	= 3 << GRF_GPIO4B2_SEL_SHIFT,
+	GRF_SDMMC_DATA2		= 1,
+	GRF_GPIO4B3_SEL_SHIFT	= 6,
+	GRF_GPIO4B3_SEL_MASK	= 3 << GRF_GPIO4B3_SEL_SHIFT,
+	GRF_SDMMC_DATA3		= 1,
+	GRF_GPIO4B4_SEL_SHIFT	= 8,
+	GRF_GPIO4B4_SEL_MASK    = 3 << GRF_GPIO4B4_SEL_SHIFT,
+	GRF_SDMMC_CLKOUT        = 1,
+	GRF_GPIO4B5_SEL_SHIFT   = 10,
+	GRF_GPIO4B5_SEL_MASK    = 3 << GRF_GPIO4B5_SEL_SHIFT,
+	GRF_SDMMC_CMD           = 1,
+
+	/*  GRF_GPIO4C_IOMUX */
+	GRF_GPIO4C0_SEL_SHIFT   = 0,
+	GRF_GPIO4C0_SEL_MASK    = 3 << GRF_GPIO4C0_SEL_SHIFT,
+	GRF_UART2DGBB_SIN       = 2,
+	GRF_GPIO4C1_SEL_SHIFT   = 2,
+	GRF_GPIO4C1_SEL_MASK    = 3 << GRF_GPIO4C1_SEL_SHIFT,
+	GRF_UART2DGBB_SOUT      = 2,
+	GRF_GPIO4C2_SEL_SHIFT   = 4,
+	GRF_GPIO4C2_SEL_MASK    = 3 << GRF_GPIO4C2_SEL_SHIFT,
+	GRF_PWM_0               = 1,
+	GRF_GPIO4C3_SEL_SHIFT   = 6,
+	GRF_GPIO4C3_SEL_MASK    = 3 << GRF_GPIO4C3_SEL_SHIFT,
+	GRF_UART2DGBC_SIN       = 1,
+	GRF_GPIO4C4_SEL_SHIFT   = 8,
+	GRF_GPIO4C4_SEL_MASK    = 3 << GRF_GPIO4C4_SEL_SHIFT,
+	GRF_UART2DBGC_SOUT      = 1,
+	GRF_GPIO4C6_SEL_SHIFT   = 12,
+	GRF_GPIO4C6_SEL_MASK    = 3 << GRF_GPIO4C6_SEL_SHIFT,
+	GRF_PWM_1               = 1,
+
+	/* GRF_SOC_CON7 */
+	GRF_UART_DBG_SEL_SHIFT	= 10,
+	GRF_UART_DBG_SEL_MASK	= 3 << GRF_UART_DBG_SEL_SHIFT,
+	GRF_UART_DBG_SEL_C	= 2,
+
+	/*  PMUGRF_GPIO0A_IOMUX */
+	PMUGRF_GPIO0A6_SEL_SHIFT        = 12,
+	PMUGRF_GPIO0A6_SEL_MASK = 3 << PMUGRF_GPIO0A6_SEL_SHIFT,
+	PMUGRF_PWM_3A           = 1,
+
+	/*  PMUGRF_GPIO1A_IOMUX */
+	PMUGRF_GPIO1A7_SEL_SHIFT        = 14,
+	PMUGRF_GPIO1A7_SEL_MASK = 3 << PMUGRF_GPIO1A7_SEL_SHIFT,
+	PMUGRF_SPI1EC_RXD       = 2,
+
+	/*  PMUGRF_GPIO1B_IOMUX */
+	PMUGRF_GPIO1B0_SEL_SHIFT        = 0,
+	PMUGRF_GPIO1B0_SEL_MASK = 3 << PMUGRF_GPIO1B0_SEL_SHIFT,
+	PMUGRF_SPI1EC_TXD       = 2,
+	PMUGRF_GPIO1B1_SEL_SHIFT        = 2,
+	PMUGRF_GPIO1B1_SEL_MASK = 3 << PMUGRF_GPIO1B1_SEL_SHIFT,
+	PMUGRF_SPI1EC_CLK       = 2,
+	PMUGRF_GPIO1B2_SEL_SHIFT        = 4,
+	PMUGRF_GPIO1B2_SEL_MASK = 3 << PMUGRF_GPIO1B2_SEL_SHIFT,
+	PMUGRF_SPI1EC_CSN0      = 2,
+	PMUGRF_GPIO1B6_SEL_SHIFT        = 12,
+	PMUGRF_GPIO1B6_SEL_MASK = 3 << PMUGRF_GPIO1B6_SEL_SHIFT,
+	PMUGRF_PWM_3B           = 1,
+	PMUGRF_GPIO1B7_SEL_SHIFT        = 14,
+	PMUGRF_GPIO1B7_SEL_MASK = 3 << PMUGRF_GPIO1B7_SEL_SHIFT,
+	PMUGRF_I2C0PMU_SDA      = 2,
+
+	/*  PMUGRF_GPIO1C_IOMUX */
+	PMUGRF_GPIO1C0_SEL_SHIFT        = 0,
+	PMUGRF_GPIO1C0_SEL_MASK = 3 << PMUGRF_GPIO1C0_SEL_SHIFT,
+	PMUGRF_I2C0PMU_SCL      = 2,
+	PMUGRF_GPIO1C3_SEL_SHIFT        = 6,
+	PMUGRF_GPIO1C3_SEL_MASK = 3 << PMUGRF_GPIO1C3_SEL_SHIFT,
+	PMUGRF_PWM_2            = 1,
+
+};
+
 #endif	/* __SOC_ROCKCHIP_RK3399_GRF_H__ */
diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3399.c b/drivers/pinctrl/rockchip/pinctrl_rk3399.c
index 17ea165..2f8aa64 100644
--- a/drivers/pinctrl/rockchip/pinctrl_rk3399.c
+++ b/drivers/pinctrl/rockchip/pinctrl_rk3399.c
@@ -22,112 +22,6 @@ struct rk3399_pinctrl_priv {
 	struct rk3399_pmugrf_regs *pmugrf;
 };
 
-enum {
-	/* GRF_GPIO2B_IOMUX */
-	GRF_GPIO2B1_SEL_SHIFT	= 0,
-	GRF_GPIO2B1_SEL_MASK	= 3 << GRF_GPIO2B1_SEL_SHIFT,
-	GRF_SPI2TPM_RXD		= 1,
-	GRF_GPIO2B2_SEL_SHIFT	= 2,
-	GRF_GPIO2B2_SEL_MASK	= 3 << GRF_GPIO2B2_SEL_SHIFT,
-	GRF_SPI2TPM_TXD		= 1,
-	GRF_GPIO2B3_SEL_SHIFT	= 6,
-	GRF_GPIO2B3_SEL_MASK	= 3 << GRF_GPIO2B3_SEL_SHIFT,
-	GRF_SPI2TPM_CLK		= 1,
-	GRF_GPIO2B4_SEL_SHIFT	= 8,
-	GRF_GPIO2B4_SEL_MASK	= 3 << GRF_GPIO2B4_SEL_SHIFT,
-	GRF_SPI2TPM_CSN0	= 1,
-
-	/* GRF_GPIO3A_IOMUX */
-	GRF_GPIO3A4_SEL_SHIFT	= 8,
-	GRF_GPIO3A4_SEL_MASK	= 3 << GRF_GPIO3A4_SEL_SHIFT,
-	GRF_SPI0NORCODEC_RXD	= 2,
-	GRF_GPIO3A5_SEL_SHIFT	= 10,
-	GRF_GPIO3A5_SEL_MASK	= 3 << GRF_GPIO3A5_SEL_SHIFT,
-	GRF_SPI0NORCODEC_TXD	= 2,
-	GRF_GPIO3A6_SEL_SHIFT	= 12,
-	GRF_GPIO3A6_SEL_MASK	= 3 << GRF_GPIO3A6_SEL_SHIFT,
-	GRF_SPI0NORCODEC_CLK	= 2,
-	GRF_GPIO3A7_SEL_SHIFT	= 14,
-	GRF_GPIO3A7_SEL_MASK	= 3 << GRF_GPIO3A7_SEL_SHIFT,
-	GRF_SPI0NORCODEC_CSN0	= 2,
-
-	/* GRF_GPIO3B_IOMUX */
-	GRF_GPIO3B0_SEL_SHIFT	= 0,
-	GRF_GPIO3B0_SEL_MASK	= 3 << GRF_GPIO3B0_SEL_SHIFT,
-	GRF_SPI0NORCODEC_CSN1	= 2,
-
-	/* GRF_GPIO4B_IOMUX */
-	GRF_GPIO4B0_SEL_SHIFT	= 0,
-	GRF_GPIO4B0_SEL_MASK	= 3 << GRF_GPIO4B0_SEL_SHIFT,
-	GRF_SDMMC_DATA0		= 1,
-	GRF_UART2DBGA_SIN	= 2,
-	GRF_GPIO4B1_SEL_SHIFT	= 2,
-	GRF_GPIO4B1_SEL_MASK	= 3 << GRF_GPIO4B1_SEL_SHIFT,
-	GRF_SDMMC_DATA1		= 1,
-	GRF_UART2DBGA_SOUT	= 2,
-	GRF_GPIO4B2_SEL_SHIFT	= 4,
-	GRF_GPIO4B2_SEL_MASK	= 3 << GRF_GPIO4B2_SEL_SHIFT,
-	GRF_SDMMC_DATA2		= 1,
-	GRF_GPIO4B3_SEL_SHIFT	= 6,
-	GRF_GPIO4B3_SEL_MASK	= 3 << GRF_GPIO4B3_SEL_SHIFT,
-	GRF_SDMMC_DATA3		= 1,
-	GRF_GPIO4B4_SEL_SHIFT	= 8,
-	GRF_GPIO4B4_SEL_MASK	= 3 << GRF_GPIO4B4_SEL_SHIFT,
-	GRF_SDMMC_CLKOUT	= 1,
-	GRF_GPIO4B5_SEL_SHIFT	= 10,
-	GRF_GPIO4B5_SEL_MASK	= 3 << GRF_GPIO4B5_SEL_SHIFT,
-	GRF_SDMMC_CMD		= 1,
-
-	/* GRF_GPIO4C_IOMUX */
-	GRF_GPIO4C2_SEL_SHIFT	= 4,
-	GRF_GPIO4C2_SEL_MASK	= 3 << GRF_GPIO4C2_SEL_SHIFT,
-	GRF_PWM_0		= 1,
-	GRF_GPIO4C3_SEL_SHIFT	= 6,
-	GRF_GPIO4C3_SEL_MASK	= 3 << GRF_GPIO4C3_SEL_SHIFT,
-	GRF_UART2DGBC_SIN	= 1,
-	GRF_GPIO4C4_SEL_SHIFT	= 8,
-	GRF_GPIO4C4_SEL_MASK	= 3 << GRF_GPIO4C4_SEL_SHIFT,
-	GRF_UART2DBGC_SOUT	= 1,
-	GRF_GPIO4C6_SEL_SHIFT	= 12,
-	GRF_GPIO4C6_SEL_MASK	= 3 << GRF_GPIO4C6_SEL_SHIFT,
-	GRF_PWM_1		= 1,
-
-	/* PMUGRF_GPIO0A_IOMUX */
-	PMUGRF_GPIO0A6_SEL_SHIFT	= 12,
-	PMUGRF_GPIO0A6_SEL_MASK	= 3 << PMUGRF_GPIO0A6_SEL_SHIFT,
-	PMUGRF_PWM_3A		= 1,
-
-	/* PMUGRF_GPIO1A_IOMUX */
-	PMUGRF_GPIO1A7_SEL_SHIFT	= 14,
-	PMUGRF_GPIO1A7_SEL_MASK	= 3 << PMUGRF_GPIO1A7_SEL_SHIFT,
-	PMUGRF_SPI1EC_RXD	= 2,
-
-	/* PMUGRF_GPIO1B_IOMUX */
-	PMUGRF_GPIO1B0_SEL_SHIFT	= 0,
-	PMUGRF_GPIO1B0_SEL_MASK = 3 << PMUGRF_GPIO1B0_SEL_SHIFT,
-	PMUGRF_SPI1EC_TXD	= 2,
-	PMUGRF_GPIO1B1_SEL_SHIFT	= 2,
-	PMUGRF_GPIO1B1_SEL_MASK = 3 << PMUGRF_GPIO1B1_SEL_SHIFT,
-	PMUGRF_SPI1EC_CLK	= 2,
-	PMUGRF_GPIO1B2_SEL_SHIFT	= 4,
-	PMUGRF_GPIO1B2_SEL_MASK = 3 << PMUGRF_GPIO1B2_SEL_SHIFT,
-	PMUGRF_SPI1EC_CSN0	= 2,
-	PMUGRF_GPIO1B6_SEL_SHIFT	= 12,
-	PMUGRF_GPIO1B6_SEL_MASK	= 3 << PMUGRF_GPIO1B6_SEL_SHIFT,
-	PMUGRF_PWM_3B		= 1,
-	PMUGRF_GPIO1B7_SEL_SHIFT	= 14,
-	PMUGRF_GPIO1B7_SEL_MASK	= 3 << PMUGRF_GPIO1B7_SEL_SHIFT,
-	PMUGRF_I2C0PMU_SDA	= 2,
-
-	/* PMUGRF_GPIO1C_IOMUX */
-	PMUGRF_GPIO1C0_SEL_SHIFT	= 0,
-	PMUGRF_GPIO1C0_SEL_MASK	= 3 << PMUGRF_GPIO1C0_SEL_SHIFT,
-	PMUGRF_I2C0PMU_SCL	= 2,
-	PMUGRF_GPIO1C3_SEL_SHIFT	= 6,
-	PMUGRF_GPIO1C3_SEL_MASK	= 3 << PMUGRF_GPIO1C3_SEL_SHIFT,
-	PMUGRF_PWM_2		= 1,
-
-};
 static void pinctrl_rk3399_pwm_config(struct rk3399_grf_regs *grf,
 		struct rk3399_pmugrf_regs *pmugrf, int pwm_id)
 {
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 3/6] clk: rk3399: update driver for spl
  2017-01-18 12:16 [U-Boot] [PATCH 0/6] rk3399: enable SPL driver Kever Yang
  2017-01-18 12:16 ` [U-Boot] [PATCH 1/6] arm64: rk3399: add ddr controller driver Kever Yang
  2017-01-18 12:16 ` [U-Boot] [PATCH 2/6] arm64: rk3399: move grf register definitions to grf_rk3399.h Kever Yang
@ 2017-01-18 12:16 ` Kever Yang
  2017-01-26 14:23   ` Simon Glass
  2017-01-18 12:16 ` [U-Boot] [PATCH 4/6] sdhci: rk3399: update driver to support of-platdata Kever Yang
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Kever Yang @ 2017-01-18 12:16 UTC (permalink / raw)
  To: u-boot

Add ddr clock setting, add rockchip_get_pmucru API,
and enable of-platdata support.

Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
---

 arch/arm/include/asm/arch-rockchip/clock.h      |  7 ++
 arch/arm/include/asm/arch-rockchip/cru_rk3399.h |  5 ++
 arch/arm/mach-rockchip/rk3399/clk_rk3399.c      | 21 ++++++
 drivers/clk/rockchip/clk_rk3399.c               | 89 ++++++++++++++++++++++---
 include/dt-bindings/clock/rk3399-cru.h          | 16 +++--
 5 files changed, 123 insertions(+), 15 deletions(-)

diff --git a/arch/arm/include/asm/arch-rockchip/clock.h b/arch/arm/include/asm/arch-rockchip/clock.h
index 804c77b..6f7e755 100644
--- a/arch/arm/include/asm/arch-rockchip/clock.h
+++ b/arch/arm/include/asm/arch-rockchip/clock.h
@@ -63,6 +63,13 @@ static inline u32 clk_get_divisor(ulong input_rate, uint output_rate)
  */
 void *rockchip_get_cru(void);
 
+/**
+ * rockchip_get_pmucru() - get a pointer to the clock/reset unit registers
+ *
+ * @return pointer to registers, or -ve error on error
+ */
+void *rockchip_get_pmucru(void);
+
 struct rk3288_cru;
 struct rk3288_grf;
 
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3399.h b/arch/arm/include/asm/arch-rockchip/cru_rk3399.h
index 98fba2b..cf830d0 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3399.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3399.h
@@ -15,6 +15,11 @@ struct rk3399_clk_priv {
 	ulong rate;
 };
 
+struct rk3399_pmuclk_priv {
+	struct rk3399_pmucru *pmucru;
+	ulong rate;
+};
+
 struct rk3399_pmucru {
 	u32 ppll_con[6];
 	u32 reserved[0x1a];
diff --git a/arch/arm/mach-rockchip/rk3399/clk_rk3399.c b/arch/arm/mach-rockchip/rk3399/clk_rk3399.c
index ce706a6..cf5b8c9 100644
--- a/arch/arm/mach-rockchip/rk3399/clk_rk3399.c
+++ b/arch/arm/mach-rockchip/rk3399/clk_rk3399.c
@@ -31,3 +31,24 @@ void *rockchip_get_cru(void)
 
 	return priv->cru;
 }
+
+static int rockchip_get_pmucruclk(struct udevice **devp)
+{
+	return uclass_get_device_by_driver(UCLASS_CLK,
+			DM_GET_DRIVER(rockchip_rk3399_pmuclk), devp);
+}
+
+void *rockchip_get_pmucru(void)
+{
+	struct rk3399_pmuclk_priv *priv;
+	struct udevice *dev;
+	int ret;
+
+	ret = rockchip_get_pmucruclk(&dev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	priv = dev_get_priv(dev);
+
+	return priv->pmucru;
+}
diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c
index 2e87e4b..8e3860b 100644
--- a/drivers/clk/rockchip/clk_rk3399.c
+++ b/drivers/clk/rockchip/clk_rk3399.c
@@ -7,7 +7,9 @@
 #include <common.h>
 #include <clk-uclass.h>
 #include <dm.h>
+#include <dt-structs.h>
 #include <errno.h>
+#include <mapmem.h>
 #include <syscon.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
@@ -18,10 +20,16 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-struct rk3399_pmuclk_priv {
-	struct rk3399_pmucru *pmucru;
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+struct rk3399_clk_plat {
+	struct dtd_rockchip_rk3399_cru dtd;
 };
 
+struct rk3399_pmuclk_plat {
+	struct dtd_rockchip_rk3399_pmucru dtd;
+};
+#endif
+
 struct pll_div {
 	u32 refdiv;
 	u32 fbdiv;
@@ -381,6 +389,7 @@ static int pll_para_config(u32 freq_hz, struct pll_div *div)
 	return 0;
 }
 
+#ifdef CONFIG_SPL_BUILD
 static void rkclk_init(struct rk3399_cru *cru)
 {
 	u32 aclk_div;
@@ -456,6 +465,7 @@ static void rkclk_init(struct rk3399_cru *cru)
 		     hclk_div << HCLK_PERILP1_DIV_CON_SHIFT |
 		     HCLK_PERILP1_PLL_SEL_GPLL << HCLK_PERILP1_PLL_SEL_SHIFT);
 }
+#endif
 
 void rk3399_configure_cpu(struct rk3399_cru *cru,
 			  enum apll_l_frequencies apll_l_freq)
@@ -709,6 +719,44 @@ static ulong rk3399_mmc_set_clk(struct rk3399_cru *cru,
 	return rk3399_mmc_get_clk(cru, clk_id);
 }
 
+#define PMUSGRF_DDR_RGN_CON16 0xff330040
+static ulong rk3399_ddr_set_clk(struct rk3399_cru *cru,
+				ulong set_rate)
+{
+	struct pll_div dpll_cfg;
+
+	/*  IC ECO bug, need to set this register */
+	writel(0xc000c000, PMUSGRF_DDR_RGN_CON16);
+
+	/*  clk_ddrc == DPLL = 24MHz / refdiv * fbdiv / postdiv1 / postdiv2 */
+	switch (set_rate) {
+	case 200*MHz:
+		dpll_cfg = (struct pll_div)
+		{.refdiv = 1, .fbdiv = 50, .postdiv1 = 6, .postdiv2 = 1};
+		break;
+	case 300*MHz:
+		dpll_cfg = (struct pll_div)
+		{.refdiv = 2, .fbdiv = 100, .postdiv1 = 4, .postdiv2 = 1};
+		break;
+	case 666*MHz:
+		dpll_cfg = (struct pll_div)
+		{.refdiv = 2, .fbdiv = 111, .postdiv1 = 2, .postdiv2 = 1};
+		break;
+	case 800*MHz:
+		dpll_cfg = (struct pll_div)
+		{.refdiv = 1, .fbdiv = 100, .postdiv1 = 3, .postdiv2 = 1};
+		break;
+	case 933*MHz:
+		dpll_cfg = (struct pll_div)
+		{.refdiv = 1, .fbdiv = 116, .postdiv1 = 3, .postdiv2 = 1};
+		break;
+	default:
+		error("Unsupported SDRAM frequency!,%ld\n", set_rate);
+	}
+	rkclk_set_pll(&cru->dpll_con[0], &dpll_cfg);
+
+	return set_rate;
+}
 static ulong rk3399_clk_get_rate(struct clk *clk)
 {
 	struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
@@ -763,6 +811,9 @@ static ulong rk3399_clk_set_rate(struct clk *clk, ulong rate)
 	case DCLK_VOP1:
 		ret = rk3399_vop_set_clk(priv->cru, clk->id, rate);
 		break;
+	case SCLK_DDRCLK:
+		ret = rk3399_ddr_set_clk(priv->cru, rate);
+		break;
 	default:
 		return -ENOENT;
 	}
@@ -777,19 +828,26 @@ static struct clk_ops rk3399_clk_ops = {
 
 static int rk3399_clk_probe(struct udevice *dev)
 {
+#ifdef CONFIG_SPL_BUILD
 	struct rk3399_clk_priv *priv = dev_get_priv(dev);
 
-	rkclk_init(priv->cru);
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct rk3399_clk_plat *plat = dev_get_platdata(dev);
 
+	priv->cru = map_sysmem(plat->dtd.reg[1], plat->dtd.reg[3]);
+#endif
+	rkclk_init(priv->cru);
+#endif
 	return 0;
 }
 
 static int rk3399_clk_ofdata_to_platdata(struct udevice *dev)
 {
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	struct rk3399_clk_priv *priv = dev_get_priv(dev);
 
 	priv->cru = (struct rk3399_cru *)dev_get_addr(dev);
-
+#endif
 	return 0;
 }
 
@@ -811,7 +869,7 @@ static const struct udevice_id rk3399_clk_ids[] = {
 };
 
 U_BOOT_DRIVER(clk_rk3399) = {
-	.name		= "clk_rk3399",
+	.name		= "rockchip_rk3399_cru",
 	.id		= UCLASS_CLK,
 	.of_match	= rk3399_clk_ids,
 	.priv_auto_alloc_size = sizeof(struct rk3399_clk_priv),
@@ -819,6 +877,9 @@ U_BOOT_DRIVER(clk_rk3399) = {
 	.ops		= &rk3399_clk_ops,
 	.bind		= rk3399_clk_bind,
 	.probe		= rk3399_clk_probe,
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	.platdata_auto_alloc_size = sizeof(struct rk3399_clk_plat),
+#endif
 };
 
 static ulong rk3399_i2c_get_pmuclk(struct rk3399_pmucru *pmucru, ulong clk_id)
@@ -939,7 +1000,6 @@ static void pmuclk_init(struct rk3399_pmucru *pmucru)
 
 	/*  configure pmu pclk */
 	pclk_div = PPLL_HZ / PMU_PCLK_HZ - 1;
-	assert((pclk_div + 1) * PMU_PCLK_HZ == PPLL_HZ && pclk_div < 0x1f);
 	rk_clrsetreg(&pmucru->pmucru_clksel[0],
 		     PMU_PCLK_DIV_CON_MASK,
 		     pclk_div << PMU_PCLK_DIV_CON_SHIFT);
@@ -949,17 +1009,25 @@ static int rk3399_pmuclk_probe(struct udevice *dev)
 {
 	struct rk3399_pmuclk_priv *priv = dev_get_priv(dev);
 
-	pmuclk_init(priv->pmucru);
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct rk3399_pmuclk_plat *plat = dev_get_platdata(dev);
+
+	priv->pmucru = map_sysmem(plat->dtd.reg[1], plat->dtd.reg[3]);
+#endif
 
+#ifndef CONFIG_SPL_BUILD
+	pmuclk_init(priv->pmucru);
+#endif
 	return 0;
 }
 
 static int rk3399_pmuclk_ofdata_to_platdata(struct udevice *dev)
 {
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	struct rk3399_pmuclk_priv *priv = dev_get_priv(dev);
 
 	priv->pmucru = (struct rk3399_pmucru *)dev_get_addr(dev);
-
+#endif
 	return 0;
 }
 
@@ -969,11 +1037,14 @@ static const struct udevice_id rk3399_pmuclk_ids[] = {
 };
 
 U_BOOT_DRIVER(rockchip_rk3399_pmuclk) = {
-	.name		= "pmuclk_rk3399",
+	.name		= "rockchip_rk3399_pmucru",
 	.id		= UCLASS_CLK,
 	.of_match	= rk3399_pmuclk_ids,
 	.priv_auto_alloc_size = sizeof(struct rk3399_pmuclk_priv),
 	.ofdata_to_platdata = rk3399_pmuclk_ofdata_to_platdata,
 	.ops		= &rk3399_pmuclk_ops,
 	.probe		= rk3399_pmuclk_probe,
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	.platdata_auto_alloc_size = sizeof(struct rk3399_pmuclk_plat),
+#endif
 };
diff --git a/include/dt-bindings/clock/rk3399-cru.h b/include/dt-bindings/clock/rk3399-cru.h
index 0a86aec..d4bdcc6 100644
--- a/include/dt-bindings/clock/rk3399-cru.h
+++ b/include/dt-bindings/clock/rk3399-cru.h
@@ -122,6 +122,10 @@
 #define SCLK_DPHY_RX0_CFG		165
 #define SCLK_RMII_SRC			166
 #define SCLK_PCIEPHY_REF100M		167
+#define SCLK_USBPHY0_480M_SRC		168
+#define SCLK_USBPHY1_480M_SRC		169
+#define SCLK_DDRCLK			170
+#define SCLK_TESTOUT2			171
 
 #define DCLK_VOP0			180
 #define DCLK_VOP1			181
@@ -589,13 +593,13 @@
 #define SRST_P_SPI0			214
 #define SRST_P_SPI1			215
 #define SRST_P_SPI2			216
-#define SRST_P_SPI3			217
-#define SRST_P_SPI4			218
+#define SRST_P_SPI4			217
+#define SRST_P_SPI5			218
 #define SRST_SPI0			219
 #define SRST_SPI1			220
 #define SRST_SPI2			221
-#define SRST_SPI3			222
-#define SRST_SPI4			223
+#define SRST_SPI4			222
+#define SRST_SPI5			223
 
 /* cru_softrst_con14 */
 #define SRST_I2S0_8CH			224
@@ -717,8 +721,8 @@
 #define SRST_H_CM0S_NOC			3
 #define SRST_DBG_CM0S			4
 #define SRST_PO_CM0S			5
-#define SRST_P_SPI6			6
-#define SRST_SPI6			7
+#define SRST_P_SPI3			6
+#define SRST_SPI3			7
 #define SRST_P_TIMER_0_1		8
 #define SRST_P_TIMER_0			9
 #define SRST_P_TIMER_1			10
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 4/6] sdhci: rk3399: update driver to support of-platdata
  2017-01-18 12:16 [U-Boot] [PATCH 0/6] rk3399: enable SPL driver Kever Yang
                   ` (2 preceding siblings ...)
  2017-01-18 12:16 ` [U-Boot] [PATCH 3/6] clk: rk3399: update driver for spl Kever Yang
@ 2017-01-18 12:16 ` Kever Yang
  2017-01-26 14:23   ` Simon Glass
  2017-01-18 12:16 ` [U-Boot] [PATCH 5/6] pinctrl: rk3399: add the of-platdata support Kever Yang
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Kever Yang @ 2017-01-18 12:16 UTC (permalink / raw)
  To: u-boot

Change some API in order to enable of-platdata.

Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
---

 drivers/mmc/rockchip_sdhci.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index e33e35e..1ea5db4 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -8,9 +8,11 @@
 
 #include <common.h>
 #include <dm.h>
+#include <dt-structs.h>
 #include <fdtdec.h>
 #include <libfdt.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <sdhci.h>
 #include <clk.h>
 
@@ -19,6 +21,9 @@ DECLARE_GLOBAL_DATA_PTR;
 #define EMMC_MIN_FREQ	400000
 
 struct rockchip_sdhc_plat {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_rockchip_rk3399_sdhci_5_1 dtplat;
+#endif
 	struct mmc_config cfg;
 	struct mmc mmc;
 };
@@ -37,10 +42,18 @@ static int arasan_sdhci_probe(struct udevice *dev)
 	int max_frequency, ret;
 	struct clk clk;
 
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_rockchip_rk3399_sdhci_5_1 *dtplat = &plat->dtplat;
 
+	host->name = dev->name;
+	host->ioaddr = map_sysmem(dtplat->reg[1], dtplat->reg[3]);
+	max_frequency = dtplat->max_frequency;
+	ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &clk);
+#else
 	max_frequency = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
 			"max-frequency", 0);
 	ret = clk_get_by_index(dev, 0, &clk);
+#endif
 	if (!ret) {
 		ret = clk_set_rate(&clk, max_frequency);
 		if (IS_ERR_VALUE(ret))
@@ -66,10 +79,12 @@ static int arasan_sdhci_probe(struct udevice *dev)
 
 static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
 {
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	struct sdhci_host *host = dev_get_priv(dev);
 
 	host->name = dev->name;
 	host->ioaddr = dev_get_addr_ptr(dev);
+#endif
 
 	return 0;
 }
@@ -87,7 +102,7 @@ static const struct udevice_id arasan_sdhci_ids[] = {
 };
 
 U_BOOT_DRIVER(arasan_sdhci_drv) = {
-	.name		= "arasan_sdhci",
+	.name		= "rockchip_rk3399_sdhci_5_1",
 	.id		= UCLASS_MMC,
 	.of_match	= arasan_sdhci_ids,
 	.ofdata_to_platdata = arasan_sdhci_ofdata_to_platdata,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 5/6] pinctrl: rk3399: add the of-platdata support
  2017-01-18 12:16 [U-Boot] [PATCH 0/6] rk3399: enable SPL driver Kever Yang
                   ` (3 preceding siblings ...)
  2017-01-18 12:16 ` [U-Boot] [PATCH 4/6] sdhci: rk3399: update driver to support of-platdata Kever Yang
@ 2017-01-18 12:16 ` Kever Yang
  2017-01-26 14:23   ` Simon Glass
  2017-01-18 12:16 ` [U-Boot] [PATCH 6/6] arm64: rk3399: add SPL support Kever Yang
  2017-01-24 13:51 ` [U-Boot] [PATCH 0/6] rk3399: enable SPL driver Simon Glass
  6 siblings, 1 reply; 21+ messages in thread
From: Kever Yang @ 2017-01-18 12:16 UTC (permalink / raw)
  To: u-boot

Do not use the API which of-platdata not support.

Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
---

 drivers/pinctrl/rockchip/pinctrl_rk3399.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3399.c b/drivers/pinctrl/rockchip/pinctrl_rk3399.c
index 2f8aa64..f7417d5 100644
--- a/drivers/pinctrl/rockchip/pinctrl_rk3399.c
+++ b/drivers/pinctrl/rockchip/pinctrl_rk3399.c
@@ -253,6 +253,7 @@ static int rk3399_pinctrl_request(struct udevice *dev, int func, int flags)
 static int rk3399_pinctrl_get_periph_id(struct udevice *dev,
 					struct udevice *periph)
 {
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	u32 cell[3];
 	int ret;
 
@@ -283,7 +284,7 @@ static int rk3399_pinctrl_get_periph_id(struct udevice *dev,
 	case 65:
 		return PERIPH_ID_SDMMC1;
 	}
-
+#endif
 	return -ENOENT;
 }
 
@@ -328,6 +329,8 @@ U_BOOT_DRIVER(pinctrl_rk3399) = {
 	.of_match	= rk3399_pinctrl_ids,
 	.priv_auto_alloc_size = sizeof(struct rk3399_pinctrl_priv),
 	.ops		= &rk3399_pinctrl_ops,
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	.bind		= dm_scan_fdt_dev,
+#endif
 	.probe		= rk3399_pinctrl_probe,
 };
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 6/6] arm64: rk3399: add SPL support
  2017-01-18 12:16 [U-Boot] [PATCH 0/6] rk3399: enable SPL driver Kever Yang
                   ` (4 preceding siblings ...)
  2017-01-18 12:16 ` [U-Boot] [PATCH 5/6] pinctrl: rk3399: add the of-platdata support Kever Yang
@ 2017-01-18 12:16 ` Kever Yang
  2017-01-26 14:23   ` Simon Glass
  2017-01-24 13:51 ` [U-Boot] [PATCH 0/6] rk3399: enable SPL driver Simon Glass
  6 siblings, 1 reply; 21+ messages in thread
From: Kever Yang @ 2017-01-18 12:16 UTC (permalink / raw)
  To: u-boot

Add spl support for rk3399, default with of-platdata enabled.

Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
---

 arch/arm/Kconfig                              |   1 +
 arch/arm/dts/rk3399-evb.dts                   |   2 +
 arch/arm/dts/rk3399.dtsi                      |  44 +++++++
 arch/arm/include/asm/arch-rockchip/clock.h    |   3 +
 arch/arm/mach-rockchip/Kconfig                |   2 +
 arch/arm/mach-rockchip/Makefile               |   1 +
 arch/arm/mach-rockchip/rk3399-board-spl.c     | 158 ++++++++++++++++++++++++++
 arch/arm/mach-rockchip/rk3399/syscon_rk3399.c |  40 +++++++
 configs/evb-rk3399_defconfig                  |  18 +++
 include/configs/rk3399_common.h               |  11 ++
 10 files changed, 280 insertions(+)
 create mode 100644 arch/arm/mach-rockchip/rk3399-board-spl.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d871a45..9a0efe4 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -882,6 +882,7 @@ config ARCH_ROCKCHIP
 	select DM
 	select SPL_DM if SPL
 	select SYS_MALLOC_F
+	select SPL_SEPARATE_BSS if SPL
 	select SPL_SYS_MALLOC_SIMPLE if SPL
 	select DM_GPIO
 	select DM_I2C
diff --git a/arch/arm/dts/rk3399-evb.dts b/arch/arm/dts/rk3399-evb.dts
index fa60e19..a959989 100644
--- a/arch/arm/dts/rk3399-evb.dts
+++ b/arch/arm/dts/rk3399-evb.dts
@@ -7,6 +7,7 @@
 /dts-v1/;
 #include <dt-bindings/pwm/pwm.h>
 #include "rk3399.dtsi"
+#include "rk3399-sdram-lpddr3-4GB-1600.dtsi"
 
 / {
 	model = "Rockchip RK3399 Evaluation Board";
@@ -69,6 +70,7 @@
 };
 
 &sdmmc {
+	bus-width = <4>;
 	status = "okay";
 };
 
diff --git a/arch/arm/dts/rk3399.dtsi b/arch/arm/dts/rk3399.dtsi
index 22277ff..379e04b 100644
--- a/arch/arm/dts/rk3399.dtsi
+++ b/arch/arm/dts/rk3399.dtsi
@@ -183,6 +183,7 @@
 	};
 
 	sdhci: sdhci at fe330000 {
+		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1";
 		reg = <0x0 0xfe330000 0x0 0x10000>;
 		interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
@@ -416,6 +417,7 @@
 	};
 
 	pmugrf: syscon at ff320000 {
+		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-pmugrf", "syscon", "simple-mfd";
 		reg = <0x0 0xff320000 0x0 0x1000>;
 		#address-cells = <1>;
@@ -427,6 +429,12 @@
 		};
 	};
 
+	pmusgrf: syscon at ff330000 {
+		u-boot,dm-pre-reloc;
+		compatible = "rockchip,rk3399-pmusgrf", "syscon";
+		reg = <0x0 0xff330000 0x0 0xe3d4>;
+	};
+
 	spi3: spi at ff350000 {
 		compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi";
 		reg = <0x0 0xff350000 0x0 0x1000>;
@@ -497,7 +505,40 @@
 		status = "disabled";
 	};
 
+	cic: syscon at ff620000 {
+		u-boot,dm-pre-reloc;
+		compatible = "rockchip,rk3399-cic", "syscon";
+		reg = <0x0 0xff620000 0x0 0x100>;
+	};
+
+	dfi: dfi at ff630000 {
+		reg = <0x00 0xff630000 0x00 0x4000>;
+		compatible = "rockchip,rk3399-dfi";
+		rockchip,pmu = <&pmugrf>;
+		clocks = <&cru PCLK_DDR_MON>;
+		clock-names = "pclk_ddr_mon";
+		status = "disabled";
+	};
+
+	dmc: dmc {
+		u-boot,dm-pre-reloc;
+		compatible = "rockchip,rk3399-dmc";
+		devfreq-events = <&dfi>;
+		interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH 0>;
+		clocks = <&cru SCLK_DDRCLK>;
+		clock-names = "dmc_clk";
+		reg = <0x0 0xffa80000 0x0 0x0800
+		       0x0 0xffa80800 0x0 0x1800
+		       0x0 0xffa82000 0x0 0x2000
+		       0x0 0xffa84000 0x0 0x1000
+		       0x0 0xffa88000 0x0 0x0800
+		       0x0 0xffa88800 0x0 0x1800
+		       0x0 0xffa8a000 0x0 0x2000
+		       0x0 0xffa8c000 0x0 0x1000>;
+	};
+
 	pmucru: pmu-clock-controller at ff750000 {
+		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-pmucru";
 		reg = <0x0 0xff750000 0x0 0x1000>;
 		#clock-cells = <1>;
@@ -507,6 +548,7 @@
 	};
 
 	cru: clock-controller at ff760000 {
+		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-cru";
 		reg = <0x0 0xff760000 0x0 0x1000>;
 		#clock-cells = <1>;
@@ -530,6 +572,7 @@
 	};
 
 	grf: syscon at ff770000 {
+		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-grf", "syscon", "simple-mfd";
 		reg = <0x0 0xff770000 0x0 0x10000>;
 		#address-cells = <1>;
@@ -607,6 +650,7 @@
 	};
 
 	pinctrl: pinctrl {
+		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-pinctrl";
 		rockchip,grf = <&grf>;
 		rockchip,pmu = <&pmugrf>;
diff --git a/arch/arm/include/asm/arch-rockchip/clock.h b/arch/arm/include/asm/arch-rockchip/clock.h
index 6f7e755..9dfbb43 100644
--- a/arch/arm/include/asm/arch-rockchip/clock.h
+++ b/arch/arm/include/asm/arch-rockchip/clock.h
@@ -17,6 +17,9 @@ enum {
 	ROCKCHIP_SYSCON_SGRF,
 	ROCKCHIP_SYSCON_PMU,
 	ROCKCHIP_SYSCON_PMUGRF,
+	ROCKCHIP_SYSCON_PMUSGRF,
+	ROCKCHIP_SYSCON_PMUCRU,
+	ROCKCHIP_SYSCON_CIC,
 };
 
 /* Standard Rockchip clock numbers */
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 5c4a4c2..cd8fef8 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -26,6 +26,8 @@ config ROCKCHIP_RK3288
 config ROCKCHIP_RK3399
 	bool "Support Rockchip RK3399"
 	select ARM64
+	select SUPPORT_SPL
+	select SPL
 	help
 	  The Rockchip RK3399 is a ARM-based SoC with a dual-core Cortex-A72
 	  and quad-core Cortex-A53.
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 6e79fed..b58c02d 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -7,6 +7,7 @@
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board-spl.o
 obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-spl.o
+obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399-board-spl.o
 obj-$(CONFIG_ROCKCHIP_SPL_BACK_TO_BROM) += save_boot_param.o
 else
 obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board.o
diff --git a/arch/arm/mach-rockchip/rk3399-board-spl.c b/arch/arm/mach-rockchip/rk3399-board-spl.c
new file mode 100644
index 0000000..8ae3055
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3399-board-spl.c
@@ -0,0 +1,158 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <led.h>
+#include <malloc.h>
+#include <ram.h>
+#include <spl.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/periph.h>
+#include <asm/arch/sdram.h>
+#include <asm/arch/timer.h>
+#include <dm/pinctrl.h>
+#include <dm/root.h>
+#include <dm/test.h>
+#include <dm/util.h>
+#include <power/regulator.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+u32 spl_boot_device(void)
+{
+	return BOOT_DEVICE_MMC1;
+}
+
+u32 spl_boot_mode(const u32 boot_device)
+{
+	return MMCSD_MODE_RAW;
+}
+
+#define TIMER_CHN10_BASE	0xff8680a0
+#define TIMER_END_COUNT_L	0x00
+#define TIMER_END_COUNT_H	0x04
+#define TIMER_INIT_COUNT_L	0x10
+#define TIMER_INIT_COUNT_H	0x14
+#define TIMER_CONTROL_REG	0x1c
+
+#define TIMER_EN	0x1
+#define	TIMER_FMODE	(0 << 1)
+#define	TIMER_RMODE	(1 << 1)
+
+void secure_timer_init(void)
+{
+	writel(0xffffffff, TIMER_CHN10_BASE + TIMER_END_COUNT_L);
+	writel(0xffffffff, TIMER_CHN10_BASE + TIMER_END_COUNT_H);
+	writel(0, TIMER_CHN10_BASE + TIMER_INIT_COUNT_L);
+	writel(0, TIMER_CHN10_BASE + TIMER_INIT_COUNT_H);
+	writel(TIMER_EN | TIMER_FMODE, TIMER_CHN10_BASE + TIMER_CONTROL_REG);
+}
+
+#define GRF_EMMCCORE_CON11 0xff77f02c
+void board_init_f(ulong dummy)
+{
+	struct udevice *pinctrl;
+	struct udevice *dev;
+	int ret;
+
+	/* Example code showing how to enable the debug UART on RK3288 */
+#include <asm/arch/grf_rk3399.h>
+	/* Enable early UART2 channel C on the RK3399 */
+#define GRF_BASE	0xff770000
+	struct rk3399_grf_regs * const grf = (void *)GRF_BASE;
+
+	rk_clrsetreg(&grf->gpio4c_iomux,
+		     GRF_GPIO4C3_SEL_MASK,
+		     GRF_UART2DGBC_SIN << GRF_GPIO4C3_SEL_SHIFT);
+	rk_clrsetreg(&grf->gpio4c_iomux,
+		     GRF_GPIO4C4_SEL_MASK,
+		     GRF_UART2DBGC_SOUT << GRF_GPIO4C4_SEL_SHIFT);
+	/* Set channel C as UART2 input */
+	rk_clrsetreg(&grf->soc_con7,
+		     GRF_UART_DBG_SEL_MASK,
+		     GRF_UART_DBG_SEL_C << GRF_UART_DBG_SEL_SHIFT);
+#define EARLY_UART
+#ifdef EARLY_UART
+	/*
+	 * Debug UART can be used from here if required:
+	 *
+	 * debug_uart_init();
+	 * printch('a');
+	 * printhex8(0x1234);
+	 * printascii("string");
+	 */
+	debug_uart_init();
+	printascii("U-Boot SPL board init");
+#endif
+	/*  Emmc clock generator: disable the clock multipilier */
+	rk_clrreg(GRF_EMMCCORE_CON11, 0x0ff);
+
+	ret = spl_init();
+	if (ret) {
+		debug("spl_init() failed: %d\n", ret);
+		hang();
+	}
+
+	secure_timer_init();
+
+	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
+	if (ret) {
+		debug("Pinctrl init failed: %d\n", ret);
+		return;
+	}
+
+	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+	if (ret) {
+		debug("DRAM init failed: %d\n", ret);
+		return;
+	}
+}
+
+void spl_board_init(void)
+{
+	struct udevice *pinctrl;
+	int ret;
+
+	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
+	if (ret) {
+		debug("%s: Cannot find pinctrl device\n", __func__);
+		goto err;
+	}
+
+	/* Enable debug UART */
+	ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART_DBG);
+	if (ret) {
+		debug("%s: Failed to set up console UART\n", __func__);
+		goto err;
+	}
+
+	preloader_console_init();
+#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+	back_to_bootrom();
+#endif
+	return;
+err:
+	printf("spl_board_init: Error %d\n", ret);
+
+	/* No way to report error here */
+	hang();
+}
+
+#ifdef CONFIG_SPL_LOAD_FIT
+int board_fit_config_name_match(const char *name)
+{
+	/* Just empty function now - can't decide what to choose */
+	debug("%s: %s\n", __func__, name);
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/mach-rockchip/rk3399/syscon_rk3399.c b/arch/arm/mach-rockchip/rk3399/syscon_rk3399.c
index 2cef68b..d32985b 100644
--- a/arch/arm/mach-rockchip/rk3399/syscon_rk3399.c
+++ b/arch/arm/mach-rockchip/rk3399/syscon_rk3399.c
@@ -12,6 +12,8 @@
 static const struct udevice_id rk3399_syscon_ids[] = {
 	{ .compatible = "rockchip,rk3399-grf", .data = ROCKCHIP_SYSCON_GRF },
 	{ .compatible = "rockchip,rk3399-pmugrf", .data = ROCKCHIP_SYSCON_PMUGRF },
+	{ .compatible = "rockchip,rk3399-pmusgrf", .data = ROCKCHIP_SYSCON_PMUSGRF },
+	{ .compatible = "rockchip,rk3399-cic", .data = ROCKCHIP_SYSCON_CIC },
 };
 
 U_BOOT_DRIVER(syscon_rk3399) = {
@@ -19,3 +21,41 @@ U_BOOT_DRIVER(syscon_rk3399) = {
 	.id = UCLASS_SYSCON,
 	.of_match = rk3399_syscon_ids,
 };
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+static int rk3399_syscon_bind_of_platdata(struct udevice *dev)
+{
+	dev->driver_data = dev->driver->of_match->data;
+	debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(rockchip_rk3399_grf) = {
+	.name = "rockchip_rk3399_grf",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3399_syscon_ids,
+	.bind = rk3399_syscon_bind_of_platdata,
+};
+
+U_BOOT_DRIVER(rockchip_rk3399_pmugrf) = {
+	.name = "rockchip_rk3399_pmugrf",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3399_syscon_ids + 1,
+	.bind = rk3399_syscon_bind_of_platdata,
+};
+
+U_BOOT_DRIVER(rockchip_rk3399_pmusgrf) = {
+	.name = "rockchip_rk3399_pmusgrf",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3399_syscon_ids + 2,
+	.bind = rk3399_syscon_bind_of_platdata,
+};
+
+U_BOOT_DRIVER(rockchip_rk3399_cic) = {
+	.name = "rockchip_rk3399_cic",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3399_syscon_ids + 3,
+	.bind = rk3399_syscon_bind_of_platdata,
+};
+#endif
diff --git a/configs/evb-rk3399_defconfig b/configs/evb-rk3399_defconfig
index 40a8295..abfabc5 100644
--- a/configs/evb-rk3399_defconfig
+++ b/configs/evb-rk3399_defconfig
@@ -3,7 +3,16 @@ CONFIG_ARCH_ROCKCHIP=y
 CONFIG_ROCKCHIP_RK3399=y
 CONFIG_DEFAULT_DEVICE_TREE="rk3399-evb"
 CONFIG_FIT=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_SPL_OF_LIBFDT=y
+CONFIG_SPL_ATF_SUPPORT=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x200
+CONFIG_SPL_ATF_TEXT_BASE=0x00010000
 # CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_ADDR=0x80000
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x4000
+CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
@@ -16,18 +25,27 @@ CONFIG_CMD_EXT2=y
 CONFIG_CMD_EXT4=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_CMD_PXE=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_SPL_OF_PLATDATA=y
 CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
 CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
 CONFIG_CLK=y
+CONFIG_SPL_CLK=y
 CONFIG_ROCKCHIP_GPIO=y
 CONFIG_ROCKCHIP_DWMMC=y
 CONFIG_ROCKCHIP_SDHCI=y
 CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
 CONFIG_ROCKCHIP_RK3399_PINCTRL=y
 CONFIG_PWM_ROCKCHIP=y
 CONFIG_REGULATOR_PWM=y
 CONFIG_DM_REGULATOR_FIXED=y
 CONFIG_RAM=y
+CONFIG_SPL_RAM=y
 CONFIG_DEBUG_UART=y
 CONFIG_DEBUG_UART_BASE=0xFF1A0000
 CONFIG_DEBUG_UART_CLOCK=24000000
diff --git a/include/configs/rk3399_common.h b/include/configs/rk3399_common.h
index aa646c6..3699a9d 100644
--- a/include/configs/rk3399_common.h
+++ b/include/configs/rk3399_common.h
@@ -17,12 +17,23 @@
 #define CONFIG_SYS_MALLOC_LEN		(32 << 20)
 #define CONFIG_SYS_CBSIZE		1024
 #define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_DRIVERS_MISC_SUPPORT
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
 
 #define CONFIG_SYS_NS16550_MEM32
 
 #define CONFIG_SYS_TEXT_BASE		0x00200000
 #define CONFIG_SYS_INIT_SP_ADDR		0x00300000
 #define CONFIG_SYS_LOAD_ADDR		0x00800800
+#define CONFIG_SPL_STACK		0xff8effff
+#define CONFIG_SPL_TEXT_BASE		0xff8c2008
+#define CONFIG_SPL_MAX_SIZE		0x30000
+/*  BSS setup */
+#define CONFIG_SPL_BSS_START_ADDR       0xff8e0000
+#define CONFIG_SPL_BSS_MAX_SIZE         0x10000
 
 #define CONFIG_SYS_BOOTM_LEN	(64 << 20)	/* 64M */
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 0/6] rk3399: enable SPL driver
  2017-01-18 12:16 [U-Boot] [PATCH 0/6] rk3399: enable SPL driver Kever Yang
                   ` (5 preceding siblings ...)
  2017-01-18 12:16 ` [U-Boot] [PATCH 6/6] arm64: rk3399: add SPL support Kever Yang
@ 2017-01-24 13:51 ` Simon Glass
  2017-02-05  1:41   ` Kever Yang
  6 siblings, 1 reply; 21+ messages in thread
From: Simon Glass @ 2017-01-24 13:51 UTC (permalink / raw)
  To: u-boot

Hi Kever,

On 18 January 2017 at 05:16, Kever Yang <kever.yang@rock-chips.com> wrote:
> This series patch enable basic driver for rk3399 SPL, the ATF support
> has been split as a separate patch.
>
> SPL_OF_PLATDATA is consider to be must because the dram driver has much
> configuration parameter from dts, but we don't want to do the copy.
>
> Other driver like clock, pinctrl, sdhci has update to support
> OF-PLATDATA.
>
>
>
> Kever Yang (6):
> arm64: rk3399: add ddr controller driver
> arm64: rk3399: move grf register definitions to grf_rk3399.h
> clk: rk3399: update driver for spl
> sdhci: rk3399: update driver to support of-platdata
> pinctrl: rk3399: add the of-platdata support
> arm64: rk3399: add SPL support

What is the limit in SPL size on rk3399?

Regards,
Simon

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 2/6] arm64: rk3399: move grf register definitions to grf_rk3399.h
  2017-01-18 12:16 ` [U-Boot] [PATCH 2/6] arm64: rk3399: move grf register definitions to grf_rk3399.h Kever Yang
@ 2017-01-25  4:09   ` Simon Glass
  0 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2017-01-25  4:09 UTC (permalink / raw)
  To: u-boot

On 18 January 2017 at 05:16, Kever Yang <kever.yang@rock-chips.com> wrote:
> rk3399 grf register bit defenitions should locate in header
> file, so that not only pinctrl can use it.
>
> Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
> ---
>
>  arch/arm/include/asm/arch-rockchip/grf_rk3399.h | 118 ++++++++++++++++++++++++
>  drivers/pinctrl/rockchip/pinctrl_rk3399.c       | 106 ---------------------
>  2 files changed, 118 insertions(+), 106 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 1/6] arm64: rk3399: add ddr controller driver
  2017-01-18 12:16 ` [U-Boot] [PATCH 1/6] arm64: rk3399: add ddr controller driver Kever Yang
@ 2017-01-26 14:23   ` Simon Glass
  2017-02-05  2:45     ` Kever Yang
  0 siblings, 1 reply; 21+ messages in thread
From: Simon Glass @ 2017-01-26 14:23 UTC (permalink / raw)
  To: u-boot

Hi Kever,

On 18 January 2017 at 05:16, Kever Yang <kever.yang@rock-chips.com> wrote:
> RK3399 support DDR3, LPDDR3, DDR4 sdram, this patch is porting from
> coreboot, support 4GB lpddr3 in this version.
>
> Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
> ---
>
>  arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi    | 1536 +++++++++++++++++++++
>  arch/arm/include/asm/arch-rockchip/sdram_rk3399.h |  120 ++
>  arch/arm/mach-rockchip/rk3399/Makefile            |    1 +
>  arch/arm/mach-rockchip/rk3399/sdram_rk3399.c      | 1243 +++++++++++++++++
>  4 files changed, 2900 insertions(+)
>  create mode 100644 arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
>  create mode 100644 arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
>  create mode 100644 arch/arm/mach-rockchip/rk3399/sdram_rk3399.c
>

Change log?

Re your comments about MASK/SHIFT and register definitions, I'm not
convinced. In my case I set up a Python script to create the registers
(with the MASK set incorrectly unfortunately) and did something like
this:

pdftotext -layout  -f 130 -l 350 rk3288-fs.pdf /tmp/asc
tools/rkmux.py /tmp/asc GRF_GPIO4C_IOMUX

to generate the definitions. Does that help?

My concern is that if we don't write a good quality driver now, when
will it be updated/fixed? It seems better to do it now. Is it really a
lot of work?

> diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
> new file mode 100644
> index 0000000..5568be2
> --- /dev/null
> +++ b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
> @@ -0,0 +1,1536 @@
> +/*
> + * (C) Copyright 2016 Rockchip Electronics Co., Ltd
> + *
> + * SPDX-License-Identifier:     GPL-2.0+
> + */
> +
> +&dmc {
> +       rockchip,sdram-params = <
> +               0x2
> +               0xA

Can you use lower-case hex please?

> +               0x3
> +               0x2
> +               0x2
> +               0x0

...

> +#define SYS_REG_ENC_ROW_3_4(n, ch)     ((n) << (30 + (ch)))
> +#define SYS_REG_DEC_ROW_3_4(n, ch)     ((n >> (30 + ch)) & 0x1)
> +#define SYS_REG_ENC_CHINFO(ch)         (1 << (28 + (ch)))
> +#define SYS_REG_ENC_DDRTYPE(n)         ((n) << 13)
> +#define SYS_REG_ENC_NUM_CH(n)          (((n) - 1) << 12)
> +#define SYS_REG_DEC_NUM_CH(n)          (1 + ((n >> 12) & 0x1))
> +#define SYS_REG_ENC_RANK(n, ch)                (((n) - 1) << (11 + ((ch) * 16)))
> +#define SYS_REG_DEC_RANK(n, ch)                (1 + ((n >> (11 + 16 * ch)) & 0x1))
> +#define SYS_REG_ENC_COL(n, ch)         (((n) - 9) << (9 + ((ch) * 16)))
> +#define SYS_REG_DEC_COL(n, ch)         (9 + ((n >> (9 + 16 * ch)) & 0x3))
> +#define SYS_REG_ENC_BK(n, ch)          (((n) == 3 ? 0 : 1) \
> +                                               << (8 + ((ch) * 16)))
> +#define SYS_REG_DEC_BK(n, ch)          (3 - ((n >> (8 + 16 * ch)) & 0x1))
> +#define SYS_REG_ENC_CS0_ROW(n, ch)     (((n) - 13) << (6 + ((ch) * 16)))
> +#define SYS_REG_DEC_CS0_ROW(n, ch)     (13 + ((n >> (6 + 16 * ch)) & 0x3))
> +#define SYS_REG_ENC_CS1_ROW(n, ch)     (((n) - 13) << (4 + ((ch) * 16)))
> +#define SYS_REG_DEC_CS1_ROW(n, ch)     (13 + ((n >> (4 + 16 * ch)) & 0x3))
> +#define SYS_REG_ENC_BW(n, ch)          ((2 >> (n)) << (2 + ((ch) * 16)))
> +#define SYS_REG_DEC_BW(n, ch)          (2 >> ((n >> (2 + 16 * ch)) & 0x3))
> +#define SYS_REG_ENC_DBW(n, ch)         ((2 >> (n)) << (0 + ((ch) * 16)))
> +#define SYS_REG_DEC_DBW(n, ch)         (2 >> ((n >> (0 + 16 * ch)) & 0x3))

These seem impenetrable to me :-( Is this the coreboot code standard?

> +
> +#define DDR_STRIDE(n, r)               writel((0x1F << (10 + 16)) \
> +                                              | (n << 10), r)

This is only used one, so can you just inline it?

> +
> +#define PRESET_SGRF_HOLD(n)    ((0x1 << (6+16)) | ((n) << 6))
> +#define PRESET_GPIO0_HOLD(n)   ((0x1 << (7+16)) | ((n) << 7))
> +#define PRESET_GPIO1_HOLD(n)   ((0x1 << (8+16)) | ((n) << 8))
> +
> +#define PHY_DRV_ODT_Hi_Z       (0x0)

Drop () on these simple constants.

> +#define PHY_DRV_ODT_240                (0x1)
> +#define PHY_DRV_ODT_120                (0x8)
> +#define PHY_DRV_ODT_80         (0x9)
> +#define PHY_DRV_ODT_60         (0xc)
> +#define PHY_DRV_ODT_48         (0xd)
> +#define PHY_DRV_ODT_40         (0xe)
> +#define PHY_DRV_ODT_34_3       (0xf)
> +
> +#ifdef CONFIG_SPL_BUILD
> +
> +struct rockchip_dmc_plat {
> +#if CONFIG_IS_ENABLED(OF_PLATDATA)
> +       struct dtd_rockchip_rk3399_dmc dtplat;
> +#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 void phy_dll_bypass_set(struct rk3399_ddr_publ_regs *ddr_publ_regs,
> +                              u32 freq)
> +{
> +       u32 *denali_phy = ddr_publ_regs->denali_phy;
> +
> +       if (freq <= 125) {

Please add a comment as to why 125 is the magic number.

> +               /* 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);
> +
> +               /* 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);
> +       }
> +}
> +
> +static void set_memory_map(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 cs_map;
> +       u32 reduc;
> +       u32 row;
> +
> +       /* Get row number from ddrconfig setting */
> +       if ((sdram_ch->ddrconfig < 2) || (sdram_ch->ddrconfig == 4))

nit: too many brackets

> +               row = 16;
> +       else if (sdram_ch->ddrconfig == 3)
> +               row = 14;
> +       else
> +               row = 15;
> +
> +       cs_map = (sdram_ch->rank > 1) ? 3 : 1;
> +       reduc = (sdram_ch->bw == 2) ? 0 : 1;
> +
> +       clrsetbits_le32(&denali_ctl[191], 0xF, (12 - sdram_ch->col));
> +       clrsetbits_le32(&denali_ctl[190], (0x3 << 16) | (0x7 << 24),
> +                       ((3 - sdram_ch->bk) << 16) |
> +                       ((16 - row) << 24));

What are all these magic numbers? Shouldn't there be register names in
denali_ctl, i.e have it as a struct instead of 191, 190?

> +       clrsetbits_le32(&denali_phy[6], 0xffffff, reg_value);
> +       clrsetbits_le32(&denali_phy[134], 0xffffff, reg_value);
> +       clrsetbits_le32(&denali_phy[262], 0xffffff, reg_value);
> +       clrsetbits_le32(&denali_phy[390], 0xffffff, reg_value);
> +
> +       /*
> +        * phy_dqs_tsel_select_X 24bits DENALI_PHY_7/135/263/391 offset_0
> +        * sets termination values for read/idle cycles and drive strength
> +        * for write cycles for DQS
> +        */

...

Regards,
Simon

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 3/6] clk: rk3399: update driver for spl
  2017-01-18 12:16 ` [U-Boot] [PATCH 3/6] clk: rk3399: update driver for spl Kever Yang
@ 2017-01-26 14:23   ` Simon Glass
  0 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2017-01-26 14:23 UTC (permalink / raw)
  To: u-boot

On 18 January 2017 at 05:16, Kever Yang <kever.yang@rock-chips.com> wrote:
> Add ddr clock setting, add rockchip_get_pmucru API,
> and enable of-platdata support.
>
> Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
> ---
>
>  arch/arm/include/asm/arch-rockchip/clock.h      |  7 ++
>  arch/arm/include/asm/arch-rockchip/cru_rk3399.h |  5 ++
>  arch/arm/mach-rockchip/rk3399/clk_rk3399.c      | 21 ++++++
>  drivers/clk/rockchip/clk_rk3399.c               | 89 ++++++++++++++++++++++---
>  include/dt-bindings/clock/rk3399-cru.h          | 16 +++--
>  5 files changed, 123 insertions(+), 15 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 4/6] sdhci: rk3399: update driver to support of-platdata
  2017-01-18 12:16 ` [U-Boot] [PATCH 4/6] sdhci: rk3399: update driver to support of-platdata Kever Yang
@ 2017-01-26 14:23   ` Simon Glass
  0 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2017-01-26 14:23 UTC (permalink / raw)
  To: u-boot

On 18 January 2017 at 05:16, Kever Yang <kever.yang@rock-chips.com> wrote:
> Change some API in order to enable of-platdata.
>
> Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
> ---
>
>  drivers/mmc/rockchip_sdhci.c | 17 ++++++++++++++++-
>  1 file changed, 16 insertions(+), 1 deletion(-)

Assuming we need this patch and must use of-platdata:

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 5/6] pinctrl: rk3399: add the of-platdata support
  2017-01-18 12:16 ` [U-Boot] [PATCH 5/6] pinctrl: rk3399: add the of-platdata support Kever Yang
@ 2017-01-26 14:23   ` Simon Glass
  0 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2017-01-26 14:23 UTC (permalink / raw)
  To: u-boot

On 18 January 2017 at 05:16, Kever Yang <kever.yang@rock-chips.com> wrote:
> Do not use the API which of-platdata not support.
>
> Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
> ---
>
>  drivers/pinctrl/rockchip/pinctrl_rk3399.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 6/6] arm64: rk3399: add SPL support
  2017-01-18 12:16 ` [U-Boot] [PATCH 6/6] arm64: rk3399: add SPL support Kever Yang
@ 2017-01-26 14:23   ` Simon Glass
  2017-02-05  3:01     ` Kever Yang
  0 siblings, 1 reply; 21+ messages in thread
From: Simon Glass @ 2017-01-26 14:23 UTC (permalink / raw)
  To: u-boot

Hi Kever,

On 18 January 2017 at 05:16, Kever Yang <kever.yang@rock-chips.com> wrote:
> Add spl support for rk3399, default with of-platdata enabled.
>
> Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
> ---
>
>  arch/arm/Kconfig                              |   1 +
>  arch/arm/dts/rk3399-evb.dts                   |   2 +
>  arch/arm/dts/rk3399.dtsi                      |  44 +++++++
>  arch/arm/include/asm/arch-rockchip/clock.h    |   3 +
>  arch/arm/mach-rockchip/Kconfig                |   2 +
>  arch/arm/mach-rockchip/Makefile               |   1 +
>  arch/arm/mach-rockchip/rk3399-board-spl.c     | 158 ++++++++++++++++++++++++++
>  arch/arm/mach-rockchip/rk3399/syscon_rk3399.c |  40 +++++++
>  configs/evb-rk3399_defconfig                  |  18 +++
>  include/configs/rk3399_common.h               |  11 ++
>  10 files changed, 280 insertions(+)
>  create mode 100644 arch/arm/mach-rockchip/rk3399-board-spl.c

Reviewed-by: Simon Glass <sjg@chromium.org>

But there is too much in this patch. Please split out the patches. My
suggestion:

- syscon additions
- dts/dtsi additions
- arch/arm/Kconfig and include/configs changes
- board-spl.c stuff
- defconfig changes to enable everything

So it should be possible to enable/disable SPL just in the final patch.

Regards,
Simon

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 0/6] rk3399: enable SPL driver
  2017-01-24 13:51 ` [U-Boot] [PATCH 0/6] rk3399: enable SPL driver Simon Glass
@ 2017-02-05  1:41   ` Kever Yang
  2017-02-08  5:10     ` Simon Glass
  0 siblings, 1 reply; 21+ messages in thread
From: Kever Yang @ 2017-02-05  1:41 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 01/24/2017 09:51 PM, Simon Glass wrote:
> Hi Kever,
>
> On 18 January 2017 at 05:16, Kever Yang <kever.yang@rock-chips.com 
> <mailto:kever.yang@rock-chips.com>> wrote:
> > This series patch enable basic driver for rk3399 SPL, the ATF support
> > has been split as a separate patch.
> >
> > SPL_OF_PLATDATA is consider to be must because the dram driver has much
> > configuration parameter from dts, but we don't want to do the copy.
> >
> > Other driver like clock, pinctrl, sdhci has update to support
> > OF-PLATDATA.
> >
> >
> >
> > Kever Yang (6):
> > arm64: rk3399: add ddr controller driver
> > arm64: rk3399: move grf register definitions to grf_rk3399.h
> > clk: rk3399: update driver for spl
> > sdhci: rk3399: update driver to support of-platdata
> > pinctrl: rk3399: add the of-platdata support
> > arm64: rk3399: add SPL support
>
> What is the limit in SPL size on rk3399?

rk3399 has 192KB internal SRAM, the bootrom use the first 8K,
so the SPL size limit should be 184KB.

Thanks,
- Kever
>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 1/6] arm64: rk3399: add ddr controller driver
  2017-01-26 14:23   ` Simon Glass
@ 2017-02-05  2:45     ` Kever Yang
  2017-02-08  5:10       ` Simon Glass
  0 siblings, 1 reply; 21+ messages in thread
From: Kever Yang @ 2017-02-05  2:45 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 01/26/2017 10:23 PM, Simon Glass wrote:
> Hi Kever,
>
> On 18 January 2017 at 05:16, Kever Yang <kever.yang@rock-chips.com> wrote:
>> RK3399 support DDR3, LPDDR3, DDR4 sdram, this patch is porting from
>> coreboot, support 4GB lpddr3 in this version.
>>
>> Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
>> ---
>>
>>   arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi    | 1536 +++++++++++++++++++++
>>   arch/arm/include/asm/arch-rockchip/sdram_rk3399.h |  120 ++
>>   arch/arm/mach-rockchip/rk3399/Makefile            |    1 +
>>   arch/arm/mach-rockchip/rk3399/sdram_rk3399.c      | 1243 +++++++++++++++++
>>   4 files changed, 2900 insertions(+)
>>   create mode 100644 arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
>>   create mode 100644 arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
>>   create mode 100644 arch/arm/mach-rockchip/rk3399/sdram_rk3399.c
>>
> Change log?

Sorry for missing change log, basically, I apply all the comments from 
you but
MASK/SHIFT.

>
> Re your comments about MASK/SHIFT and register definitions, I'm not
> convinced. In my case I set up a Python script to create the registers
> (with the MASK set incorrectly unfortunately) and did something like
> this:
>
> pdftotext -layout  -f 130 -l 350 rk3288-fs.pdf /tmp/asc
> tools/rkmux.py /tmp/asc GRF_GPIO4C_IOMUX
>
> to generate the definitions. Does that help?

Is not only header file need to update, but also almost all the register
operation in C source code.
>
> My concern is that if we don't write a good quality driver now, when
> will it be updated/fixed? It seems better to do it now. Is it really a
> lot of work?

I agree that we should write a good quality driver, but it does not mean
the quality is not good if I don't include SHIFT in MASK, right?
I would like to include the SHIFT in MASK if this is the first time for
the driver commit to public as the requirement from maintainer,
but this is porting from coreboot which has prove to be a good quality 
driver
with a lot of test.
Another point is that in order to make it easier to maintain the source 
code,
we have already sync our internal source code to the copy on coreboot, it's
really not convenient for the driver owner(not me, there are other guys 
focus
on dram drivers) to maintain all these drivers in different platform.
And here comes another question, what should we do for next SoC driver
if we need to upstream the driver to coreboot and U-Boot, and maybe UEFI,
make totally different format version for different platform? I think try to
convince some of the maintainer should be the best choice and then we can
focus on maintain the same one copy of source code, right?

Back to U-Boot, I don't the format of MASK is so important, just like no 
more
than 80-bytes in one line in coding style, we should consider to accept 
it if
there are some reason. There are also many MASKs in U-Boot drivers without
SHIFT in it, I wouldn't say which kind is better, but U-Boot can say 
prefer to
use MASKs with SHIFT, but please don't refuse everything other than that.

Thanks,
- Kever

>
>> diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
>> new file mode 100644
>> index 0000000..5568be2
>> --- /dev/null
>> +++ b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
>> @@ -0,0 +1,1536 @@
>> +/*
>> + * (C) Copyright 2016 Rockchip Electronics Co., Ltd
>> + *
>> + * SPDX-License-Identifier:     GPL-2.0+
>> + */
>> +
>> +&dmc {
>> +       rockchip,sdram-params = <
>> +               0x2
>> +               0xA
> Can you use lower-case hex please?
>
>> +               0x3
>> +               0x2
>> +               0x2
>> +               0x0
> ...
>
>> +#define SYS_REG_ENC_ROW_3_4(n, ch)     ((n) << (30 + (ch)))
>> +#define SYS_REG_DEC_ROW_3_4(n, ch)     ((n >> (30 + ch)) & 0x1)
>> +#define SYS_REG_ENC_CHINFO(ch)         (1 << (28 + (ch)))
>> +#define SYS_REG_ENC_DDRTYPE(n)         ((n) << 13)
>> +#define SYS_REG_ENC_NUM_CH(n)          (((n) - 1) << 12)
>> +#define SYS_REG_DEC_NUM_CH(n)          (1 + ((n >> 12) & 0x1))
>> +#define SYS_REG_ENC_RANK(n, ch)                (((n) - 1) << (11 + ((ch) * 16)))
>> +#define SYS_REG_DEC_RANK(n, ch)                (1 + ((n >> (11 + 16 * ch)) & 0x1))
>> +#define SYS_REG_ENC_COL(n, ch)         (((n) - 9) << (9 + ((ch) * 16)))
>> +#define SYS_REG_DEC_COL(n, ch)         (9 + ((n >> (9 + 16 * ch)) & 0x3))
>> +#define SYS_REG_ENC_BK(n, ch)          (((n) == 3 ? 0 : 1) \
>> +                                               << (8 + ((ch) * 16)))
>> +#define SYS_REG_DEC_BK(n, ch)          (3 - ((n >> (8 + 16 * ch)) & 0x1))
>> +#define SYS_REG_ENC_CS0_ROW(n, ch)     (((n) - 13) << (6 + ((ch) * 16)))
>> +#define SYS_REG_DEC_CS0_ROW(n, ch)     (13 + ((n >> (6 + 16 * ch)) & 0x3))
>> +#define SYS_REG_ENC_CS1_ROW(n, ch)     (((n) - 13) << (4 + ((ch) * 16)))
>> +#define SYS_REG_DEC_CS1_ROW(n, ch)     (13 + ((n >> (4 + 16 * ch)) & 0x3))
>> +#define SYS_REG_ENC_BW(n, ch)          ((2 >> (n)) << (2 + ((ch) * 16)))
>> +#define SYS_REG_DEC_BW(n, ch)          (2 >> ((n >> (2 + 16 * ch)) & 0x3))
>> +#define SYS_REG_ENC_DBW(n, ch)         ((2 >> (n)) << (0 + ((ch) * 16)))
>> +#define SYS_REG_DEC_DBW(n, ch)         (2 >> ((n >> (0 + 16 * ch)) & 0x3))
> These seem impenetrable to me :-( Is this the coreboot code standard?
>
>> +
>> +#define DDR_STRIDE(n, r)               writel((0x1F << (10 + 16)) \
>> +                                              | (n << 10), r)
> This is only used one, so can you just inline it?
>
>> +
>> +#define PRESET_SGRF_HOLD(n)    ((0x1 << (6+16)) | ((n) << 6))
>> +#define PRESET_GPIO0_HOLD(n)   ((0x1 << (7+16)) | ((n) << 7))
>> +#define PRESET_GPIO1_HOLD(n)   ((0x1 << (8+16)) | ((n) << 8))
>> +
>> +#define PHY_DRV_ODT_Hi_Z       (0x0)
> Drop () on these simple constants.
>
>> +#define PHY_DRV_ODT_240                (0x1)
>> +#define PHY_DRV_ODT_120                (0x8)
>> +#define PHY_DRV_ODT_80         (0x9)
>> +#define PHY_DRV_ODT_60         (0xc)
>> +#define PHY_DRV_ODT_48         (0xd)
>> +#define PHY_DRV_ODT_40         (0xe)
>> +#define PHY_DRV_ODT_34_3       (0xf)
>> +
>> +#ifdef CONFIG_SPL_BUILD
>> +
>> +struct rockchip_dmc_plat {
>> +#if CONFIG_IS_ENABLED(OF_PLATDATA)
>> +       struct dtd_rockchip_rk3399_dmc dtplat;
>> +#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 void phy_dll_bypass_set(struct rk3399_ddr_publ_regs *ddr_publ_regs,
>> +                              u32 freq)
>> +{
>> +       u32 *denali_phy = ddr_publ_regs->denali_phy;
>> +
>> +       if (freq <= 125) {
> Please add a comment as to why 125 is the magic number.
>
>> +               /* 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);
>> +
>> +               /* 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);
>> +       }
>> +}
>> +
>> +static void set_memory_map(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 cs_map;
>> +       u32 reduc;
>> +       u32 row;
>> +
>> +       /* Get row number from ddrconfig setting */
>> +       if ((sdram_ch->ddrconfig < 2) || (sdram_ch->ddrconfig == 4))
> nit: too many brackets
>
>> +               row = 16;
>> +       else if (sdram_ch->ddrconfig == 3)
>> +               row = 14;
>> +       else
>> +               row = 15;
>> +
>> +       cs_map = (sdram_ch->rank > 1) ? 3 : 1;
>> +       reduc = (sdram_ch->bw == 2) ? 0 : 1;
>> +
>> +       clrsetbits_le32(&denali_ctl[191], 0xF, (12 - sdram_ch->col));
>> +       clrsetbits_le32(&denali_ctl[190], (0x3 << 16) | (0x7 << 24),
>> +                       ((3 - sdram_ch->bk) << 16) |
>> +                       ((16 - row) << 24));
> What are all these magic numbers? Shouldn't there be register names in
> denali_ctl, i.e have it as a struct instead of 191, 190?
>
>> +       clrsetbits_le32(&denali_phy[6], 0xffffff, reg_value);
>> +       clrsetbits_le32(&denali_phy[134], 0xffffff, reg_value);
>> +       clrsetbits_le32(&denali_phy[262], 0xffffff, reg_value);
>> +       clrsetbits_le32(&denali_phy[390], 0xffffff, reg_value);
>> +
>> +       /*
>> +        * phy_dqs_tsel_select_X 24bits DENALI_PHY_7/135/263/391 offset_0
>> +        * sets termination values for read/idle cycles and drive strength
>> +        * for write cycles for DQS
>> +        */
> ...
>
> Regards,
> Simon
>
>
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 6/6] arm64: rk3399: add SPL support
  2017-01-26 14:23   ` Simon Glass
@ 2017-02-05  3:01     ` Kever Yang
  2017-02-08  5:10       ` Simon Glass
  0 siblings, 1 reply; 21+ messages in thread
From: Kever Yang @ 2017-02-05  3:01 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 01/26/2017 10:23 PM, Simon Glass wrote:
> Hi Kever,
>
> On 18 January 2017 at 05:16, Kever Yang <kever.yang@rock-chips.com> wrote:
>> Add spl support for rk3399, default with of-platdata enabled.
>>
>> Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
>> ---
>>
>>   arch/arm/Kconfig                              |   1 +
>>   arch/arm/dts/rk3399-evb.dts                   |   2 +
>>   arch/arm/dts/rk3399.dtsi                      |  44 +++++++
>>   arch/arm/include/asm/arch-rockchip/clock.h    |   3 +
>>   arch/arm/mach-rockchip/Kconfig                |   2 +
>>   arch/arm/mach-rockchip/Makefile               |   1 +
>>   arch/arm/mach-rockchip/rk3399-board-spl.c     | 158 ++++++++++++++++++++++++++
>>   arch/arm/mach-rockchip/rk3399/syscon_rk3399.c |  40 +++++++
>>   configs/evb-rk3399_defconfig                  |  18 +++
>>   include/configs/rk3399_common.h               |  11 ++
>>   10 files changed, 280 insertions(+)
>>   create mode 100644 arch/arm/mach-rockchip/rk3399-board-spl.c
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> But there is too much in this patch. Please split out the patches. My
> suggestion:
>
> - syscon additions
> - dts/dtsi additions
> - arch/arm/Kconfig and include/configs changes
> - board-spl.c stuff
> - defconfig changes to enable everything
>
> So it should be possible to enable/disable SPL just in the final patch.

Cc Tom here.
I have some confuse for patch split in U-Boot, last time I see a patch 
set to init support
for other SoC, patches split very detail and almost one patch for one 
module(like your comment
in this patch), then Tom's comment says there is no need for that 
detail, only one patch for SoC
and one patch for board is OK.

My understand(for U-Boot) is:
- driver patch is very clear and should be split out,
- other parts like dts/defconfig and soc/board for one new SoC support,
    could be gather in one patch or two if there goes to the same 
maintainer and branch.

The grf definition and clock driver has split out as your comment in my 
'RFC' version,
I can split this patch into 5 patches if you still required.


Thanks,
- Kever
>
> Regards,
> Simon
>
>
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 0/6] rk3399: enable SPL driver
  2017-02-05  1:41   ` Kever Yang
@ 2017-02-08  5:10     ` Simon Glass
  0 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2017-02-08  5:10 UTC (permalink / raw)
  To: u-boot

Hi Kever,

On 4 February 2017 at 17:41, Kever Yang <kever.yang@rock-chips.com> wrote:
> Hi Simon,
>
> On 01/24/2017 09:51 PM, Simon Glass wrote:
>
> Hi Kever,
>
> On 18 January 2017 at 05:16, Kever Yang <kever.yang@rock-chips.com> wrote:
>> This series patch enable basic driver for rk3399 SPL, the ATF support
>> has been split as a separate patch.
>>
>> SPL_OF_PLATDATA is consider to be must because the dram driver has much
>> configuration parameter from dts, but we don't want to do the copy.
>>
>> Other driver like clock, pinctrl, sdhci has update to support
>> OF-PLATDATA.
>>
>>
>>
>> Kever Yang (6):
>> arm64: rk3399: add ddr controller driver
>> arm64: rk3399: move grf register definitions to grf_rk3399.h
>> clk: rk3399: update driver for spl
>> sdhci: rk3399: update driver to support of-platdata
>> pinctrl: rk3399: add the of-platdata support
>> arm64: rk3399: add SPL support
>
> What is the limit in SPL size on rk3399?
>
>
> rk3399 has 192KB internal SRAM, the bootrom use the first 8K,
> so the SPL size limit should be 184KB.

The of-platdata feature is intended for highly constrained devices
where there is not enough SRAM for libfdt. To me it does not seem
worth the pain of using it for this chip, which has plenty of SRAM.

Regards,
Simon

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 1/6] arm64: rk3399: add ddr controller driver
  2017-02-05  2:45     ` Kever Yang
@ 2017-02-08  5:10       ` Simon Glass
  2017-02-13  7:52         ` Kever Yang
  0 siblings, 1 reply; 21+ messages in thread
From: Simon Glass @ 2017-02-08  5:10 UTC (permalink / raw)
  To: u-boot

+Tom in case you have some thoughts

Hi Kever,

On 4 February 2017 at 18:45, Kever Yang <kever.yang@rock-chips.com> wrote:
> Hi Simon,
>
> On 01/26/2017 10:23 PM, Simon Glass wrote:
>>
>> Hi Kever,
>>
>> On 18 January 2017 at 05:16, Kever Yang <kever.yang@rock-chips.com> wrote:
>>>
>>> RK3399 support DDR3, LPDDR3, DDR4 sdram, this patch is porting from
>>> coreboot, support 4GB lpddr3 in this version.
>>>
>>> Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
>>> ---
>>>
>>>   arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi    | 1536
>>> +++++++++++++++++++++
>>>   arch/arm/include/asm/arch-rockchip/sdram_rk3399.h |  120 ++
>>>   arch/arm/mach-rockchip/rk3399/Makefile            |    1 +
>>>   arch/arm/mach-rockchip/rk3399/sdram_rk3399.c      | 1243
>>> +++++++++++++++++
>>>   4 files changed, 2900 insertions(+)
>>>   create mode 100644 arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
>>>   create mode 100644 arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
>>>   create mode 100644 arch/arm/mach-rockchip/rk3399/sdram_rk3399.c
>>>
>> Change log?
>
>
> Sorry for missing change log, basically, I apply all the comments from you
> but
> MASK/SHIFT.
>
>>
>> Re your comments about MASK/SHIFT and register definitions, I'm not
>> convinced. In my case I set up a Python script to create the registers
>> (with the MASK set incorrectly unfortunately) and did something like
>> this:
>>
>> pdftotext -layout  -f 130 -l 350 rk3288-fs.pdf /tmp/asc
>> tools/rkmux.py /tmp/asc GRF_GPIO4C_IOMUX
>>
>> to generate the definitions. Does that help?
>
>
> Is not only header file need to update, but also almost all the register
> operation in C source code.

Yes that's right.

>>
>>
>> My concern is that if we don't write a good quality driver now, when
>> will it be updated/fixed? It seems better to do it now. Is it really a
>> lot of work?
>
>
> I agree that we should write a good quality driver, but it does not mean
> the quality is not good if I don't include SHIFT in MASK, right?
> I would like to include the SHIFT in MASK if this is the first time for
> the driver commit to public as the requirement from maintainer,
> but this is porting from coreboot which has prove to be a good quality
> driver
> with a lot of test.
> Another point is that in order to make it easier to maintain the source
> code,
> we have already sync our internal source code to the copy on coreboot, it's
> really not convenient for the driver owner(not me, there are other guys
> focus
> on dram drivers) to maintain all these drivers in different platform.
> And here comes another question, what should we do for next SoC driver
> if we need to upstream the driver to coreboot and U-Boot, and maybe UEFI,
> make totally different format version for different platform? I think try to
> convince some of the maintainer should be the best choice and then we can
> focus on maintain the same one copy of source code, right?
>
> Back to U-Boot, I don't the format of MASK is so important, just like no
> more
> than 80-bytes in one line in coding style, we should consider to accept it
> if
> there are some reason. There are also many MASKs in U-Boot drivers without
> SHIFT in it, I wouldn't say which kind is better, but U-Boot can say prefer
> to
> use MASKs with SHIFT, but please don't refuse everything other than that.

Well we can leave the MASK to not include the SHIFT. That was my
mistake originally so perhaps I should clean it up.

But this sort of thing:

> +#define SYS_REG_ENC_DBW(n, ch)         ((2 >> (n)) << (0 + ((ch) * 16)))
> +#define SYS_REG_DEC_DBW(n, ch)         (2 >> ((n >> (0 + 16 * ch)) & 0x3))

is really not nice IMO, particularly for something that is only used
once in the C code. Does coreboot actually require this style, or
could it use the more explicit SHIFT/MASK used like U-Boot?

I do understand the problem of multiple platforms but in general each
project has its own code style and we try to stick to it. U-Boot
follows kernel style pretty closely, but it is try that SHIFT/MASK
things are much more common in U-Boot than Linux since it sets up
hardware.

Re keeping the drivers in sync, yes it is a pain. But I hope that it
becomes easier to maintain. There is a pretty big user community
around U-Boot, and Rockchip is a popular chip. So I'm trying to keep
it as a good example of how to do things.

So I'd really like to change this.

Regards,
Simon

>
> Thanks,
> - Kever
>
>
>>
>>> diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
>>> b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
>>> new file mode 100644
>>> index 0000000..5568be2
>>> --- /dev/null
>>> +++ b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
>>> @@ -0,0 +1,1536 @@
>>> +/*
>>> + * (C) Copyright 2016 Rockchip Electronics Co., Ltd
>>> + *
>>> + * SPDX-License-Identifier:     GPL-2.0+
>>> + */
>>> +
>>> +&dmc {
>>> +       rockchip,sdram-params = <
>>> +               0x2
>>> +               0xA
>>
>> Can you use lower-case hex please?
>>
>>> +               0x3
>>> +               0x2
>>> +               0x2
>>> +               0x0
>>
>> ...
>>
>>> +#define SYS_REG_ENC_ROW_3_4(n, ch)     ((n) << (30 + (ch)))
>>> +#define SYS_REG_DEC_ROW_3_4(n, ch)     ((n >> (30 + ch)) & 0x1)
>>> +#define SYS_REG_ENC_CHINFO(ch)         (1 << (28 + (ch)))
>>> +#define SYS_REG_ENC_DDRTYPE(n)         ((n) << 13)
>>> +#define SYS_REG_ENC_NUM_CH(n)          (((n) - 1) << 12)
>>> +#define SYS_REG_DEC_NUM_CH(n)          (1 + ((n >> 12) & 0x1))
>>> +#define SYS_REG_ENC_RANK(n, ch)                (((n) - 1) << (11 + ((ch)
>>> * 16)))
>>> +#define SYS_REG_DEC_RANK(n, ch)                (1 + ((n >> (11 + 16 *
>>> ch)) & 0x1))
>>> +#define SYS_REG_ENC_COL(n, ch)         (((n) - 9) << (9 + ((ch) * 16)))
>>> +#define SYS_REG_DEC_COL(n, ch)         (9 + ((n >> (9 + 16 * ch)) &
>>> 0x3))
>>> +#define SYS_REG_ENC_BK(n, ch)          (((n) == 3 ? 0 : 1) \
>>> +                                               << (8 + ((ch) * 16)))
>>> +#define SYS_REG_DEC_BK(n, ch)          (3 - ((n >> (8 + 16 * ch)) &
>>> 0x1))
>>> +#define SYS_REG_ENC_CS0_ROW(n, ch)     (((n) - 13) << (6 + ((ch) * 16)))
>>> +#define SYS_REG_DEC_CS0_ROW(n, ch)     (13 + ((n >> (6 + 16 * ch)) &
>>> 0x3))
>>> +#define SYS_REG_ENC_CS1_ROW(n, ch)     (((n) - 13) << (4 + ((ch) * 16)))
>>> +#define SYS_REG_DEC_CS1_ROW(n, ch)     (13 + ((n >> (4 + 16 * ch)) &
>>> 0x3))
>>> +#define SYS_REG_ENC_BW(n, ch)          ((2 >> (n)) << (2 + ((ch) * 16)))
>>> +#define SYS_REG_DEC_BW(n, ch)          (2 >> ((n >> (2 + 16 * ch)) &
>>> 0x3))
>>> +#define SYS_REG_ENC_DBW(n, ch)         ((2 >> (n)) << (0 + ((ch) * 16)))
>>> +#define SYS_REG_DEC_DBW(n, ch)         (2 >> ((n >> (0 + 16 * ch)) &
>>> 0x3))
>>
>> These seem impenetrable to me :-( Is this the coreboot code standard?
>>
>>> +
>>> +#define DDR_STRIDE(n, r)               writel((0x1F << (10 + 16)) \
>>> +                                              | (n << 10), r)
>>
>> This is only used one, so can you just inline it?
>>
>>> +
>>> +#define PRESET_SGRF_HOLD(n)    ((0x1 << (6+16)) | ((n) << 6))
>>> +#define PRESET_GPIO0_HOLD(n)   ((0x1 << (7+16)) | ((n) << 7))
>>> +#define PRESET_GPIO1_HOLD(n)   ((0x1 << (8+16)) | ((n) << 8))
>>> +
>>> +#define PHY_DRV_ODT_Hi_Z       (0x0)
>>
>> Drop () on these simple constants.
>>
>>> +#define PHY_DRV_ODT_240                (0x1)
>>> +#define PHY_DRV_ODT_120                (0x8)
>>> +#define PHY_DRV_ODT_80         (0x9)
>>> +#define PHY_DRV_ODT_60         (0xc)
>>> +#define PHY_DRV_ODT_48         (0xd)
>>> +#define PHY_DRV_ODT_40         (0xe)
>>> +#define PHY_DRV_ODT_34_3       (0xf)
>>> +
>>> +#ifdef CONFIG_SPL_BUILD
>>> +
>>> +struct rockchip_dmc_plat {
>>> +#if CONFIG_IS_ENABLED(OF_PLATDATA)
>>> +       struct dtd_rockchip_rk3399_dmc dtplat;
>>> +#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 void phy_dll_bypass_set(struct rk3399_ddr_publ_regs
>>> *ddr_publ_regs,
>>> +                              u32 freq)
>>> +{
>>> +       u32 *denali_phy = ddr_publ_regs->denali_phy;
>>> +
>>> +       if (freq <= 125) {
>>
>> Please add a comment as to why 125 is the magic number.
>>
>>> +               /* 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);
>>> +
>>> +               /* 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);
>>> +       }
>>> +}
>>> +
>>> +static void set_memory_map(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 cs_map;
>>> +       u32 reduc;
>>> +       u32 row;
>>> +
>>> +       /* Get row number from ddrconfig setting */
>>> +       if ((sdram_ch->ddrconfig < 2) || (sdram_ch->ddrconfig == 4))
>>
>> nit: too many brackets
>>
>>> +               row = 16;
>>> +       else if (sdram_ch->ddrconfig == 3)
>>> +               row = 14;
>>> +       else
>>> +               row = 15;
>>> +
>>> +       cs_map = (sdram_ch->rank > 1) ? 3 : 1;
>>> +       reduc = (sdram_ch->bw == 2) ? 0 : 1;
>>> +
>>> +       clrsetbits_le32(&denali_ctl[191], 0xF, (12 - sdram_ch->col));
>>> +       clrsetbits_le32(&denali_ctl[190], (0x3 << 16) | (0x7 << 24),
>>> +                       ((3 - sdram_ch->bk) << 16) |
>>> +                       ((16 - row) << 24));
>>
>> What are all these magic numbers? Shouldn't there be register names in
>> denali_ctl, i.e have it as a struct instead of 191, 190?
>>
>>> +       clrsetbits_le32(&denali_phy[6], 0xffffff, reg_value);
>>> +       clrsetbits_le32(&denali_phy[134], 0xffffff, reg_value);
>>> +       clrsetbits_le32(&denali_phy[262], 0xffffff, reg_value);
>>> +       clrsetbits_le32(&denali_phy[390], 0xffffff, reg_value);
>>> +
>>> +       /*
>>> +        * phy_dqs_tsel_select_X 24bits DENALI_PHY_7/135/263/391 offset_0
>>> +        * sets termination values for read/idle cycles and drive
>>> strength
>>> +        * for write cycles for DQS
>>> +        */
>>
>> ...
>>
>> Regards,
>> Simon
>>
>>
>>
>
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 6/6] arm64: rk3399: add SPL support
  2017-02-05  3:01     ` Kever Yang
@ 2017-02-08  5:10       ` Simon Glass
  0 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2017-02-08  5:10 UTC (permalink / raw)
  To: u-boot

Hi Kever,

On 4 February 2017 at 19:01, Kever Yang <kever.yang@rock-chips.com> wrote:
> Hi Simon,
>
>
> On 01/26/2017 10:23 PM, Simon Glass wrote:
>>
>> Hi Kever,
>>
>> On 18 January 2017 at 05:16, Kever Yang <kever.yang@rock-chips.com> wrote:
>>>
>>> Add spl support for rk3399, default with of-platdata enabled.
>>>
>>> Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
>>> ---
>>>
>>>   arch/arm/Kconfig                              |   1 +
>>>   arch/arm/dts/rk3399-evb.dts                   |   2 +
>>>   arch/arm/dts/rk3399.dtsi                      |  44 +++++++
>>>   arch/arm/include/asm/arch-rockchip/clock.h    |   3 +
>>>   arch/arm/mach-rockchip/Kconfig                |   2 +
>>>   arch/arm/mach-rockchip/Makefile               |   1 +
>>>   arch/arm/mach-rockchip/rk3399-board-spl.c     | 158
>>> ++++++++++++++++++++++++++
>>>   arch/arm/mach-rockchip/rk3399/syscon_rk3399.c |  40 +++++++
>>>   configs/evb-rk3399_defconfig                  |  18 +++
>>>   include/configs/rk3399_common.h               |  11 ++
>>>   10 files changed, 280 insertions(+)
>>>   create mode 100644 arch/arm/mach-rockchip/rk3399-board-spl.c
>>
>> Reviewed-by: Simon Glass <sjg@chromium.org>
>>
>> But there is too much in this patch. Please split out the patches. My
>> suggestion:
>>
>> - syscon additions
>> - dts/dtsi additions
>> - arch/arm/Kconfig and include/configs changes
>> - board-spl.c stuff
>> - defconfig changes to enable everything
>>
>> So it should be possible to enable/disable SPL just in the final patch.
>
>
> Cc Tom here.
> I have some confuse for patch split in U-Boot, last time I see a patch set
> to init support
> for other SoC, patches split very detail and almost one patch for one
> module(like your comment
> in this patch), then Tom's comment says there is no need for that detail,
> only one patch for SoC
> and one patch for board is OK.
>
> My understand(for U-Boot) is:
> - driver patch is very clear and should be split out,
> - other parts like dts/defconfig and soc/board for one new SoC support,
>    could be gather in one patch or two if there goes to the same maintainer
> and branch.
>
> The grf definition and clock driver has split out as your comment in my
> 'RFC' version,
> I can split this patch into 5 patches if you still required.

Well let's leave it for now, and keep it in mind for the future. It is
useful to split things up for easier review and also it allows us to
bisect / revert for problems more easily.

Regards,
Simon

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH 1/6] arm64: rk3399: add ddr controller driver
  2017-02-08  5:10       ` Simon Glass
@ 2017-02-13  7:52         ` Kever Yang
  0 siblings, 0 replies; 21+ messages in thread
From: Kever Yang @ 2017-02-13  7:52 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 02/08/2017 01:10 PM, Simon Glass wrote:
> +Tom in case you have some thoughts
>
> Hi Kever,
>
> On 4 February 2017 at 18:45, Kever Yang <kever.yang@rock-chips.com> wrote:
>> Hi Simon,
>>
>> On 01/26/2017 10:23 PM, Simon Glass wrote:
>>> Hi Kever,
>>>
>>> On 18 January 2017 at 05:16, Kever Yang <kever.yang@rock-chips.com> wrote:
>>>> RK3399 support DDR3, LPDDR3, DDR4 sdram, this patch is porting from
>>>> coreboot, support 4GB lpddr3 in this version.
>>>>
>>>> Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
>>>> ---
>>>>
>>>>    arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi    | 1536
>>>> +++++++++++++++++++++
>>>>    arch/arm/include/asm/arch-rockchip/sdram_rk3399.h |  120 ++
>>>>    arch/arm/mach-rockchip/rk3399/Makefile            |    1 +
>>>>    arch/arm/mach-rockchip/rk3399/sdram_rk3399.c      | 1243
>>>> +++++++++++++++++
>>>>    4 files changed, 2900 insertions(+)
>>>>    create mode 100644 arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
>>>>    create mode 100644 arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
>>>>    create mode 100644 arch/arm/mach-rockchip/rk3399/sdram_rk3399.c
>>>>
>>> Change log?
>>
>> Sorry for missing change log, basically, I apply all the comments from you
>> but
>> MASK/SHIFT.
>>
>>> Re your comments about MASK/SHIFT and register definitions, I'm not
>>> convinced. In my case I set up a Python script to create the registers
>>> (with the MASK set incorrectly unfortunately) and did something like
>>> this:
>>>
>>> pdftotext -layout  -f 130 -l 350 rk3288-fs.pdf /tmp/asc
>>> tools/rkmux.py /tmp/asc GRF_GPIO4C_IOMUX
>>>
>>> to generate the definitions. Does that help?
>>
>> Is not only header file need to update, but also almost all the register
>> operation in C source code.
> Yes that's right.
>
>>>
>>> My concern is that if we don't write a good quality driver now, when
>>> will it be updated/fixed? It seems better to do it now. Is it really a
>>> lot of work?
>>
>> I agree that we should write a good quality driver, but it does not mean
>> the quality is not good if I don't include SHIFT in MASK, right?
>> I would like to include the SHIFT in MASK if this is the first time for
>> the driver commit to public as the requirement from maintainer,
>> but this is porting from coreboot which has prove to be a good quality
>> driver
>> with a lot of test.
>> Another point is that in order to make it easier to maintain the source
>> code,
>> we have already sync our internal source code to the copy on coreboot, it's
>> really not convenient for the driver owner(not me, there are other guys
>> focus
>> on dram drivers) to maintain all these drivers in different platform.
>> And here comes another question, what should we do for next SoC driver
>> if we need to upstream the driver to coreboot and U-Boot, and maybe UEFI,
>> make totally different format version for different platform? I think try to
>> convince some of the maintainer should be the best choice and then we can
>> focus on maintain the same one copy of source code, right?
>>
>> Back to U-Boot, I don't the format of MASK is so important, just like no
>> more
>> than 80-bytes in one line in coding style, we should consider to accept it
>> if
>> there are some reason. There are also many MASKs in U-Boot drivers without
>> SHIFT in it, I wouldn't say which kind is better, but U-Boot can say prefer
>> to
>> use MASKs with SHIFT, but please don't refuse everything other than that.
> Well we can leave the MASK to not include the SHIFT. That was my
> mistake originally so perhaps I should clean it up.

Thanks very much.
>
> But this sort of thing:
>
>> +#define SYS_REG_ENC_DBW(n, ch)         ((2 >> (n)) << (0 + ((ch) * 16)))
>> +#define SYS_REG_DEC_DBW(n, ch)         (2 >> ((n >> (0 + 16 * ch)) & 0x3))
> is really not nice IMO, particularly for something that is only used
> once in the C code. Does coreboot actually require this style, or
> could it use the more explicit SHIFT/MASK used like U-Boot?

The sys_reg is for record dram size info, also appear in rk3288,
this change is intent to make easier to read the C source code,
I will update this blob of code back to the style like rk3288 dram driver.
>
> I do understand the problem of multiple platforms but in general each
> project has its own code style and we try to stick to it. U-Boot
> follows kernel style pretty closely, but it is try that SHIFT/MASK
> things are much more common in U-Boot than Linux since it sets up
> hardware.
>
> Re keeping the drivers in sync, yes it is a pain. But I hope that it
> becomes easier to maintain. There is a pretty big user community
> around U-Boot, and Rockchip is a popular chip. So I'm trying to keep
> it as a good example of how to do things.
>
> So I'd really like to change this.
>
> Regards,
> Simon
>
>> Thanks,
>> - Kever
>>
>>
>>>> diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
>>>> b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
>>>> new file mode 100644
>>>> index 0000000..5568be2
>>>> --- /dev/null
>>>> +++ b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
>>>> @@ -0,0 +1,1536 @@
>>>> +/*
>>>> + * (C) Copyright 2016 Rockchip Electronics Co., Ltd
>>>> + *
>>>> + * SPDX-License-Identifier:     GPL-2.0+
>>>> + */
>>>> +
>>>> +&dmc {
>>>> +       rockchip,sdram-params = <
>>>> +               0x2
>>>> +               0xA
>>> Can you use lower-case hex please?

Will update.
>>>
>>>> +               0x3
>>>> +               0x2
>>>> +               0x2
>>>> +               0x0
>>> ...
>>>
>>>> +#define SYS_REG_ENC_ROW_3_4(n, ch)     ((n) << (30 + (ch)))
>>>> +#define SYS_REG_DEC_ROW_3_4(n, ch)     ((n >> (30 + ch)) & 0x1)
>>>> +#define SYS_REG_ENC_CHINFO(ch)         (1 << (28 + (ch)))
>>>> +#define SYS_REG_ENC_DDRTYPE(n)         ((n) << 13)
>>>> +#define SYS_REG_ENC_NUM_CH(n)          (((n) - 1) << 12)
>>>> +#define SYS_REG_DEC_NUM_CH(n)          (1 + ((n >> 12) & 0x1))
>>>> +#define SYS_REG_ENC_RANK(n, ch)                (((n) - 1) << (11 + ((ch)
>>>> * 16)))
>>>> +#define SYS_REG_DEC_RANK(n, ch)                (1 + ((n >> (11 + 16 *
>>>> ch)) & 0x1))
>>>> +#define SYS_REG_ENC_COL(n, ch)         (((n) - 9) << (9 + ((ch) * 16)))
>>>> +#define SYS_REG_DEC_COL(n, ch)         (9 + ((n >> (9 + 16 * ch)) &
>>>> 0x3))
>>>> +#define SYS_REG_ENC_BK(n, ch)          (((n) == 3 ? 0 : 1) \
>>>> +                                               << (8 + ((ch) * 16)))
>>>> +#define SYS_REG_DEC_BK(n, ch)          (3 - ((n >> (8 + 16 * ch)) &
>>>> 0x1))
>>>> +#define SYS_REG_ENC_CS0_ROW(n, ch)     (((n) - 13) << (6 + ((ch) * 16)))
>>>> +#define SYS_REG_DEC_CS0_ROW(n, ch)     (13 + ((n >> (6 + 16 * ch)) &
>>>> 0x3))
>>>> +#define SYS_REG_ENC_CS1_ROW(n, ch)     (((n) - 13) << (4 + ((ch) * 16)))
>>>> +#define SYS_REG_DEC_CS1_ROW(n, ch)     (13 + ((n >> (4 + 16 * ch)) &
>>>> 0x3))
>>>> +#define SYS_REG_ENC_BW(n, ch)          ((2 >> (n)) << (2 + ((ch) * 16)))
>>>> +#define SYS_REG_DEC_BW(n, ch)          (2 >> ((n >> (2 + 16 * ch)) &
>>>> 0x3))
>>>> +#define SYS_REG_ENC_DBW(n, ch)         ((2 >> (n)) << (0 + ((ch) * 16)))
>>>> +#define SYS_REG_DEC_DBW(n, ch)         (2 >> ((n >> (0 + 16 * ch)) &
>>>> 0x3))
>>> These seem impenetrable to me :-( Is this the coreboot code standard?

Will update.
>>>
>>>> +
>>>> +#define DDR_STRIDE(n, r)               writel((0x1F << (10 + 16)) \
>>>> +                                              | (n << 10), r)
>>> This is only used one, so can you just inline it?

Will remove this Macro and use C directly.
>>>
>>>> +
>>>> +#define PRESET_SGRF_HOLD(n)    ((0x1 << (6+16)) | ((n) << 6))
>>>> +#define PRESET_GPIO0_HOLD(n)   ((0x1 << (7+16)) | ((n) << 7))
>>>> +#define PRESET_GPIO1_HOLD(n)   ((0x1 << (8+16)) | ((n) << 8))
>>>> +
>>>> +#define PHY_DRV_ODT_Hi_Z       (0x0)
>>> Drop () on these simple constants.

Will update.
>>>
>>>> +#define PHY_DRV_ODT_240                (0x1)
>>>> +#define PHY_DRV_ODT_120                (0x8)
>>>> +#define PHY_DRV_ODT_80         (0x9)
>>>> +#define PHY_DRV_ODT_60         (0xc)
>>>> +#define PHY_DRV_ODT_48         (0xd)
>>>> +#define PHY_DRV_ODT_40         (0xe)
>>>> +#define PHY_DRV_ODT_34_3       (0xf)
>>>> +
>>>> +#ifdef CONFIG_SPL_BUILD
>>>> +
>>>> +struct rockchip_dmc_plat {
>>>> +#if CONFIG_IS_ENABLED(OF_PLATDATA)
>>>> +       struct dtd_rockchip_rk3399_dmc dtplat;
>>>> +#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 void phy_dll_bypass_set(struct rk3399_ddr_publ_regs
>>>> *ddr_publ_regs,
>>>> +                              u32 freq)
>>>> +{
>>>> +       u32 *denali_phy = ddr_publ_regs->denali_phy;
>>>> +
>>>> +       if (freq <= 125) {
>>> Please add a comment as to why 125 is the magic number.

Will update.
>>>
>>>> +               /* 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);
>>>> +
>>>> +               /* 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);
>>>> +       }
>>>> +}
>>>> +
>>>> +static void set_memory_map(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 cs_map;
>>>> +       u32 reduc;
>>>> +       u32 row;
>>>> +
>>>> +       /* Get row number from ddrconfig setting */
>>>> +       if ((sdram_ch->ddrconfig < 2) || (sdram_ch->ddrconfig == 4))
>>> nit: too many brackets

Will update.
>>>
>>>> +               row = 16;
>>>> +       else if (sdram_ch->ddrconfig == 3)
>>>> +               row = 14;
>>>> +       else
>>>> +               row = 15;
>>>> +
>>>> +       cs_map = (sdram_ch->rank > 1) ? 3 : 1;
>>>> +       reduc = (sdram_ch->bw == 2) ? 0 : 1;
>>>> +
>>>> +       clrsetbits_le32(&denali_ctl[191], 0xF, (12 - sdram_ch->col));
>>>> +       clrsetbits_le32(&denali_ctl[190], (0x3 << 16) | (0x7 << 24),
>>>> +                       ((3 - sdram_ch->bk) << 16) |
>>>> +                       ((16 - row) << 24));
>>> What are all these magic numbers? Shouldn't there be register names in
>>> denali_ctl, i.e have it as a struct instead of 191, 190?

Will update the comment, there is no register name in IP spec.

Thanks,
- Kever
>>>
>>>> +       clrsetbits_le32(&denali_phy[6], 0xffffff, reg_value);
>>>> +       clrsetbits_le32(&denali_phy[134], 0xffffff, reg_value);
>>>> +       clrsetbits_le32(&denali_phy[262], 0xffffff, reg_value);
>>>> +       clrsetbits_le32(&denali_phy[390], 0xffffff, reg_value);
>>>> +
>>>> +       /*
>>>> +        * phy_dqs_tsel_select_X 24bits DENALI_PHY_7/135/263/391 offset_0
>>>> +        * sets termination values for read/idle cycles and drive
>>>> strength
>>>> +        * for write cycles for DQS
>>>> +        */
>>> ...
>>>
>>> Regards,
>>> Simon
>>>
>>>
>>>
>>
>
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2017-02-13  7:52 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-18 12:16 [U-Boot] [PATCH 0/6] rk3399: enable SPL driver Kever Yang
2017-01-18 12:16 ` [U-Boot] [PATCH 1/6] arm64: rk3399: add ddr controller driver Kever Yang
2017-01-26 14:23   ` Simon Glass
2017-02-05  2:45     ` Kever Yang
2017-02-08  5:10       ` Simon Glass
2017-02-13  7:52         ` Kever Yang
2017-01-18 12:16 ` [U-Boot] [PATCH 2/6] arm64: rk3399: move grf register definitions to grf_rk3399.h Kever Yang
2017-01-25  4:09   ` Simon Glass
2017-01-18 12:16 ` [U-Boot] [PATCH 3/6] clk: rk3399: update driver for spl Kever Yang
2017-01-26 14:23   ` Simon Glass
2017-01-18 12:16 ` [U-Boot] [PATCH 4/6] sdhci: rk3399: update driver to support of-platdata Kever Yang
2017-01-26 14:23   ` Simon Glass
2017-01-18 12:16 ` [U-Boot] [PATCH 5/6] pinctrl: rk3399: add the of-platdata support Kever Yang
2017-01-26 14:23   ` Simon Glass
2017-01-18 12:16 ` [U-Boot] [PATCH 6/6] arm64: rk3399: add SPL support Kever Yang
2017-01-26 14:23   ` Simon Glass
2017-02-05  3:01     ` Kever Yang
2017-02-08  5:10       ` Simon Glass
2017-01-24 13:51 ` [U-Boot] [PATCH 0/6] rk3399: enable SPL driver Simon Glass
2017-02-05  1:41   ` Kever Yang
2017-02-08  5:10     ` Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.