]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
ram: rockchip: Add rv1126 ddr driver support
authorJagan Teki <jagan@edgeble.ai>
Wed, 14 Dec 2022 17:50:53 +0000 (23:20 +0530)
committerKever Yang <kever.yang@rock-chips.com>
Mon, 16 Jan 2023 10:01:10 +0000 (18:01 +0800)
Add DDR driver for Rockchip RV1126 SoC.

Signed-off-by: YouMin Chen <cym@rock-chips.com>
Signed-off-by: Jagan Teki <jagan@edgeble.ai>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>
arch/arm/include/asm/arch-rockchip/dram_spec_timing.h [new file with mode: 0644]
arch/arm/include/asm/arch-rockchip/sdram_common.h
arch/arm/include/asm/arch-rockchip/sdram_msch.h
arch/arm/include/asm/arch-rockchip/sdram_phy_rv1126.h [new file with mode: 0644]
arch/arm/include/asm/arch-rockchip/sdram_rv1126.h [new file with mode: 0644]
drivers/ram/rockchip/Makefile
drivers/ram/rockchip/sdram_rv1126.c [new file with mode: 0644]

diff --git a/arch/arm/include/asm/arch-rockchip/dram_spec_timing.h b/arch/arm/include/asm/arch-rockchip/dram_spec_timing.h
new file mode 100644 (file)
index 0000000..a691e97
--- /dev/null
@@ -0,0 +1,452 @@
+/* SPDX-License-Identifier:     GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __ROCKCHIP_DRAM_SPEC_TIMING_H__
+#define __ROCKCHIP_DRAM_SPEC_TIMING_H__
+
+enum ddr3_speed_rate {
+       /* 5-5-5 */
+       DDR3_800D = 0,
+       /* 6-6-6 */
+       DDR3_800E = 1,
+       /* 6-6-6 */
+       DDR3_1066E = 2,
+       /* 7-7-7 */
+       DDR3_1066F = 3,
+       /* 8-8-8 */
+       DDR3_1066G = 4,
+       /* 7-7-7 */
+       DDR3_1333F = 5,
+       /* 8-8-8 */
+       DDR3_1333G = 6,
+       /* 9-9-9 */
+       DDR3_1333H = 7,
+       /* 10-10-10 */
+       DDR3_1333J = 8,
+       /* 8-8-8 */
+       DDR3_1600G = 9,
+       /* 9-9-9 */
+       DDR3_1600H = 10,
+       /* 10-10-10 */
+       DDR3_1600J = 11,
+       /* 11-11-11 */
+       DDR3_1600K = 12,
+       /* 10-10-10 */
+       DDR3_1866J = 13,
+       /* 11-11-11 */
+       DDR3_1866K = 14,
+       /* 12-12-12 */
+       DDR3_1866L = 15,
+       /* 13-13-13 */
+       DDR3_1866M = 16,
+       /* 11-11-11 */
+       DDR3_2133K = 17,
+       /* 12-12-12 */
+       DDR3_2133L = 18,
+       /* 13-13-13 */
+       DDR3_2133M = 19,
+       /* 14-14-14 */
+       DDR3_2133N = 20,
+       DDR3_DEFAULT = 21,
+};
+
+enum ddr4_speed_rate {
+       /* DDR4_1600J (10-10-10) */
+       DDR4_1600J = 0,
+       /* DDR4_1600K (11-11-11) */
+       DDR4_1600K = 1,
+       /* DDR4_1600L (12-12-12) */
+       DDR4_1600L = 2,
+       /* DDR4_1800L (12-12-12) */
+       DDR4_1866L = 3,
+       /* DDR4_1800M (13-13-13) */
+       DDR4_1866M = 4,
+       /* DDR4_1800N (14-14-14) */
+       DDR4_1866N = 5,
+       /* DDR4_2133N (14-14-14) */
+       DDR4_2133N = 6,
+       /* DDR4_2133P (15-15-15) */
+       DDR4_2133P = 7,
+       /* DDR4_2133R (16-16-16) */
+       DDR4_2133R = 8,
+       /* DDR4_2400P (15-15-15) */
+       DDR4_2400P = 9,
+       /* DDR4_2400R (16-16-16) */
+       DDR4_2400R = 10,
+       /* DDR4_2400U (18-18-18) */
+       DDR4_2400U = 11,
+       /* DEFAULT */
+       DDR4_DEFAULT = 12,
+};
+
+/* mr0 for ddr3 */
+#define DDR3_BL8               (0)
+#define DDR3_BC4_8             (1)
+#define DDR3_BC4               (2)
+#define DDR3_CL(n)             (((((n) - 4) & 0x7) << 4)\
+                               | ((((n) - 4) & 0x8) >> 1))
+#define DDR3_WR(n)             (((n) & 0x7) << 9)
+#define DDR3_DLL_RESET         (1 << 8)
+#define DDR3_DLL_DERESET       (0 << 8)
+
+/* mr1 for ddr3 */
+#define DDR3_DLL_ENABLE                (0)
+#define DDR3_DLL_DISABLE       (1)
+#define DDR3_MR1_AL(n)         (((n) & 0x3) << 3)
+
+#define DDR3_DS_40             (0)
+#define DDR3_DS_34             BIT(1)
+#define DDR3_DS_MASK           ((1 << 1) | (1 << 5))
+#define DDR3_RTT_NOM_MASK      ((1 << 2) | (1 << 6) | (1 << 9))
+#define DDR3_RTT_NOM_DIS       (0)
+#define DDR3_RTT_NOM_60                BIT(2)
+#define DDR3_RTT_NOM_120       BIT(6)
+#define DDR3_RTT_NOM_40                ((1 << 2) | (1 << 6))
+#define DDR3_TDQS              BIT(11)
+
+/* mr2 for ddr3 */
+#define DDR3_MR2_CWL(n)                ((((n) - 5) & 0x7) << 3)
+#define DDR3_RTT_WR_DIS                (0)
+#define DDR3_RTT_WR_60         (1 << 9)
+#define DDR3_RTT_WR_120                (2 << 9)
+
+/*
+ * MR0 (Device Information)
+ * 0:DAI complete, 1:DAI still in progress
+ */
+#define LPDDR2_DAI             (0x1)
+/* 0:S2 or S4 SDRAM, 1:NVM */
+#define LPDDR2_DI              (0x1 << 1)
+/* 0:DNV not supported, 1:DNV supported */
+#define LPDDR2_DNVI            (0x1 << 2)
+#define LPDDR2_RZQI            (0x3 << 3)
+
+/*
+ * 00:RZQ self test not supported,
+ * 01:ZQ-pin may connect to VDDCA or float
+ * 10:ZQ-pin may short to GND.
+ * 11:ZQ-pin self test completed, no error condition detected.
+ */
+
+/* MR1 (Device Feature) */
+#define LPDDR2_BL4             (0x2)
+#define LPDDR2_BL8             (0x3)
+#define LPDDR2_BL16            (0x4)
+#define LPDDR2_N_WR(n)         (((n) - 2) << 5)
+
+/* MR2 (Device Feature 2) */
+#define LPDDR2_RL3_WL1         (0x1)
+#define LPDDR2_RL4_WL2         (0x2)
+#define LPDDR2_RL5_WL2         (0x3)
+#define LPDDR2_RL6_WL3         (0x4)
+#define LPDDR2_RL7_WL4         (0x5)
+#define LPDDR2_RL8_WL4         (0x6)
+
+/* MR3 (IO Configuration 1) */
+#define LPDDR2_DS_34           (0x1)
+#define LPDDR2_DS_40           (0x2)
+#define LPDDR2_DS_48           (0x3)
+#define LPDDR2_DS_60           (0x4)
+#define LPDDR2_DS_80           (0x6)
+/* optional */
+#define LPDDR2_DS_120          (0x7)
+
+/* MR4 (Device Temperature) */
+#define LPDDR2_TREF_MASK       (0x7)
+#define LPDDR2_4_TREF          (0x1)
+#define LPDDR2_2_TREF          (0x2)
+#define LPDDR2_1_TREF          (0x3)
+#define LPDDR2_025_TREF                (0x5)
+#define LPDDR2_025_TREF_DERATE (0x6)
+
+#define LPDDR2_TUF             (0x1 << 7)
+
+/* MR8 (Basic configuration 4) */
+#define LPDDR2_S4              (0x0)
+#define LPDDR2_S2              (0x1)
+#define LPDDR2_N               (0x2)
+/* Unit:MB */
+#define LPDDR2_DENSITY(mr8)    (8 << (((mr8) >> 2) & 0xf))
+#define LPDDR2_IO_WIDTH(mr8)   (32 >> (((mr8) >> 6) & 0x3))
+
+/* MR10 (Calibration) */
+#define LPDDR2_ZQINIT          (0xff)
+#define LPDDR2_ZQCL            (0xab)
+#define LPDDR2_ZQCS            (0x56)
+#define LPDDR2_ZQRESET         (0xc3)
+
+/* MR16 (PASR Bank Mask), S2 SDRAM Only */
+#define LPDDR2_PASR_FULL       (0x0)
+#define LPDDR2_PASR_1_2                (0x1)
+#define LPDDR2_PASR_1_4                (0x2)
+#define LPDDR2_PASR_1_8                (0x3)
+
+/*
+ * MR0 (Device Information)
+ * 0:DAI complete,
+ * 1:DAI still in progress
+ */
+#define LPDDR3_DAI             (0x1)
+/*
+ * 00:RZQ self test not supported,
+ * 01:ZQ-pin may connect to VDDCA or float
+ * 10:ZQ-pin may short to GND.
+ * 11:ZQ-pin self test completed, no error condition detected.
+ */
+#define LPDDR3_RZQI            (0x3 << 3)
+/*
+ * 0:DRAM does not support WL(Set B),
+ * 1:DRAM support WL(Set B)
+ */
+#define LPDDR3_WL_SUPOT                BIT(6)
+/*
+ * 0:DRAM does not support RL=3,nWR=3,WL=1;
+ * 1:DRAM supports RL=3,nWR=3,WL=1 for frequencies <=166
+ */
+#define LPDDR3_RL3_SUPOT       BIT(7)
+
+/* MR1 (Device Feature) */
+#define LPDDR3_BL8             (0x3)
+#define LPDDR3_N_WR(n)         ((n) << 5)
+
+/* MR2 (Device Feature 2), WL Set A,default */
+/* <=166MHz,optional*/
+#define LPDDR3_RL3_WL1         (0x1)
+/* <=400MHz*/
+#define LPDDR3_RL6_WL3         (0x4)
+/* <=533MHz*/
+#define LPDDR3_RL8_WL4         (0x6)
+/* <=600MHz*/
+#define LPDDR3_RL9_WL5         (0x7)
+/* <=667MHz,default*/
+#define LPDDR3_RL10_WL6                (0x8)
+/* <=733MHz*/
+#define LPDDR3_RL11_WL6                (0x9)
+/* <=800MHz*/
+#define LPDDR3_RL12_WL6                (0xa)
+/* <=933MHz*/
+#define LPDDR3_RL14_WL8                (0xc)
+/* <=1066MHz*/
+#define LPDDR3_RL16_WL8                (0xe)
+
+/* WL Set B, optional */
+/* <=667MHz,default*/
+#define LPDDR3_RL10_WL8                (0x8)
+/* <=733MHz*/
+#define LPDDR3_RL11_WL9                (0x9)
+/* <=800MHz*/
+#define LPDDR3_RL12_WL9                (0xa)
+/* <=933MHz*/
+#define LPDDR3_RL14_WL11       (0xc)
+/* <=1066MHz*/
+#define LPDDR3_RL16_WL13       (0xe)
+
+/* 1:enable nWR programming > 9(default)*/
+#define LPDDR3_N_WRE           BIT(4)
+/* 1:Select WL Set B*/
+#define LPDDR3_WL_S            BIT(6)
+/* 1:enable*/
+#define LPDDR3_WR_LEVEL                BIT(7)
+
+/* MR3 (IO Configuration 1) */
+#define LPDDR3_DS_34           (0x1)
+#define LPDDR3_DS_40           (0x2)
+#define LPDDR3_DS_48           (0x3)
+#define LPDDR3_DS_60           (0x4)
+#define LPDDR3_DS_80           (0x6)
+#define LPDDR3_DS_34D_40U      (0x9)
+#define LPDDR3_DS_40D_48U      (0xa)
+#define LPDDR3_DS_34D_48U      (0xb)
+
+/* MR4 (Device Temperature) */
+#define LPDDR3_TREF_MASK       (0x7)
+/* SDRAM Low temperature operating limit exceeded */
+#define LPDDR3_LT_EXED         (0x0)
+#define LPDDR3_4_TREF          (0x1)
+#define LPDDR3_2_TREF          (0x2)
+#define LPDDR3_1_TREF          (0x3)
+#define LPDDR3_05_TREF         (0x4)
+#define LPDDR3_025_TREF                (0x5)
+#define LPDDR3_025_TREF_DERATE (0x6)
+/* SDRAM High temperature operating limit exceeded */
+#define LPDDR3_HT_EXED         (0x7)
+
+/* 1:value has changed since last read of MR4 */
+#define LPDDR3_TUF             (0x1 << 7)
+
+/* MR8 (Basic configuration 4) */
+#define LPDDR3_S8              (0x3)
+#define LPDDR3_DENSITY(mr8)    (8 << (((mr8) >> 2) & 0xf))
+#define LPDDR3_IO_WIDTH(mr8)   (32 >> (((mr8) >> 6) & 0x3))
+
+/* MR10 (Calibration) */
+#define LPDDR3_ZQINIT          (0xff)
+#define LPDDR3_ZQCL            (0xab)
+#define LPDDR3_ZQCS            (0x56)
+#define LPDDR3_ZQRESET         (0xc3)
+
+/* MR11 (ODT Control) */
+#define LPDDR3_ODT_60          (1)
+#define LPDDR3_ODT_120         (2)
+#define LPDDR3_ODT_240         (3)
+#define LPDDR3_ODT_DIS         (0)
+
+/* MR2 (Device Feature 2) */
+/* RL & nRTP for DBI-RD Disabled */
+#define LPDDR4_RL6_NRTP8       (0x0)
+#define LPDDR4_RL10_NRTP8      (0x1)
+#define LPDDR4_RL14_NRTP8      (0x2)
+#define LPDDR4_RL20_NRTP8      (0x3)
+#define LPDDR4_RL24_NRTP10     (0x4)
+#define LPDDR4_RL28_NRTP12     (0x5)
+#define LPDDR4_RL32_NRTP14     (0x6)
+#define LPDDR4_RL36_NRTP16     (0x7)
+/* RL & nRTP for DBI-RD Disabled */
+#define LPDDR4_RL12_NRTP8      (0x1)
+#define LPDDR4_RL16_NRTP8      (0x2)
+#define LPDDR4_RL22_NRTP8      (0x3)
+#define LPDDR4_RL28_NRTP10     (0x4)
+#define LPDDR4_RL32_NRTP12     (0x5)
+#define LPDDR4_RL36_NRTP14     (0x6)
+#define LPDDR4_RL40_NRTP16     (0x7)
+/* WL Set A,default */
+#define LPDDR4_A_WL4           (0x0 << 3)
+#define LPDDR4_A_WL6           (0x1 << 3)
+#define LPDDR4_A_WL8           (0x2 << 3)
+#define LPDDR4_A_WL10          (0x3 << 3)
+#define LPDDR4_A_WL12          (0x4 << 3)
+#define LPDDR4_A_WL14          (0x5 << 3)
+#define LPDDR4_A_WL16          (0x6 << 3)
+#define LPDDR4_A_WL18          (0x7 << 3)
+/* WL Set B, optional */
+#define LPDDR4_B_WL4           (0x0 << 3)
+#define LPDDR4_B_WL8           (0x1 << 3)
+#define LPDDR4_B_WL12          (0x2 << 3)
+#define LPDDR4_B_WL18          (0x3 << 3)
+#define LPDDR4_B_WL22          (0x4 << 3)
+#define LPDDR4_B_WL26          (0x5 << 3)
+#define LPDDR4_B_WL30          (0x6 << 3)
+#define LPDDR4_B_WL34          (0x7 << 3)
+/* 1:Select WL Set B*/
+#define LPDDR4_WL_B            BIT(6)
+/* 1:enable*/
+#define LPDDR4_WR_LEVEL                BIT(7)
+
+/* MR3 */
+#define LPDDR4_VDDQ_2_5                (0)
+#define LPDDR4_VDDQ_3          (1)
+#define LPDDR4_PU_CAL_MASK     (1)
+#define LPDDR4_WRPST_0_5_TCK   (0 << 1)
+#define LPDDR4_WRPST_1_5_TCK   (1 << 1)
+#define LPDDR4_PPR_EN          (1 << 2)
+/* PDDS */
+#define LPDDR4_PDDS_MASK       (0x7 << 3)
+#define LPDDR4_PDDS_SHIFT      (3)
+#define LPDDR4_PDDS_240                (0x1 << 3)
+#define LPDDR4_PDDS_120                (0x2 << 3)
+#define LPDDR4_PDDS_80         (0x3 << 3)
+#define LPDDR4_PDDS_60         (0x4 << 3)
+#define LPDDR4_PDDS_48         (0x5 << 3)
+#define LPDDR4_PDDS_40         (0x6 << 3)
+#define LPDDR4_DBI_RD_EN       BIT(6)
+#define LPDDR4_DBI_WR_EN       BIT(7)
+
+/* MR11 (ODT Control) */
+#define LPDDR4_DQODT_MASK      (0x7)
+#define LPDDR4_DQODT_SHIFT     (0x0)
+#define LPDDR4_DQODT_240       (1)
+#define LPDDR4_DQODT_120       (2)
+#define LPDDR4_DQODT_80                (3)
+#define LPDDR4_DQODT_60                (4)
+#define LPDDR4_DQODT_48                (5)
+#define LPDDR4_DQODT_40                (6)
+#define LPDDR4_DQODT_DIS       (0)
+#define LPDDR4_CAODT_MASK      (0x7 << 4)
+#define LPDDR4_CAODT_SHIFT     (4)
+#define LPDDR4_CAODT_240       (1 << 4)
+#define LPDDR4_CAODT_120       (2 << 4)
+#define LPDDR4_CAODT_80                (3 << 4)
+#define LPDDR4_CAODT_60                (4 << 4)
+#define LPDDR4_CAODT_48                (5 << 4)
+#define LPDDR4_CAODT_40                (6 << 4)
+#define LPDDR4_CAODT_DIS       (0 << 4)
+
+/* MR22 */
+#define LPDDR4_ODTE_CK_SHIFT   (3)
+#define LPDDR4_ODTE_CS_SHIFT   (4)
+#define LPDDR4_ODTD_CA_SHIFT   (5)
+#define LPDDR4_SOC_ODT_MASK    (0x7)
+#define LPDDR4_SOC_ODT_SHIFT   (0)
+#define LPDDR4_SOC_ODT_240     (1)
+#define LPDDR4_SOC_ODT_120     (2)
+#define LPDDR4_SOC_ODT_80      (3)
+#define LPDDR4_SOC_ODT_60      (4)
+#define LPDDR4_SOC_ODT_48      (5)
+#define LPDDR4_SOC_ODT_40      (6)
+#define LPDDR4_SOC_ODT_DIS     (0)
+
+/* LPDDR4x */
+/* MR3 */
+#define LPDDR4X_VDDQ_0_6       (0)
+#define LPDDR4X_VDDQ_0_5       (1)
+
+/* mr0 for ddr4 */
+#define DDR4_BL8               (0)
+#define DDR4_BC4_8             (1)
+#define DDR4_BC4               (2)
+#define DDR4_WR_RTP(n)         ((n) << 9)
+#define DDR4_CL(n)             ((((n) & 0xe) << 3) | ((n) & 1) << 2)
+#define DDR4_DLL_RESET(n)      ((n) << 8)
+#define DDR4_DLL_ON            BIT(0)
+#define DDR4_DLL_OFF           (0 << 0)
+
+/* mr1 for ddr4 */
+#define DDR4_AL                        ((n) << 3)
+#define DDR4_DS_34             (0)
+#define DDR4_DS_48             BIT(1)
+#define DDR4_DS_MASK           (0x3 << 1)
+#define DDR4_RTT_NOM_MASK      (0x7 << 8)
+#define DDR4_RTT_NOM_DIS       (0)
+#define DDR4_RTT_NOM_60                BIT(8)
+#define DDR4_RTT_NOM_120       (2 << 8)
+#define DDR4_RTT_NOM_40                (0x3 << 8)
+#define DDR4_RTT_NOM_240       (0x4 << 8)
+#define DDR4_RTT_NOM_48                (0x5 << 8)
+#define DDR4_RTT_NOM_80                (0x6 << 8)
+#define DDR4_RTT_NOM_34                (0x7 << 8)
+
+/* mr2 for ddr4 */
+#define DDR4_MR2_CWL(n)                ((n) << 3)
+#define DDR4_RTT_WR_DIS                (0)
+#define DDR4_RTT_WR_120                BIT(9)
+#define DDR4_RTT_WR_240                (2 << 9)
+
+/* mr4 for ddr4 */
+#define DDR4_READ_PREAMBLE(n)  ((n) << 11)
+#define DDR4_WRITE_PREAMBLE(n) ((n) << 12)
+#define DDR4_READ_PREAMBLE_TRAIN(n)    ((n) << 10)
+
+/* mr5 for ddr4 */
+#define DDR4_RD_DBI(n)         ((n) << 12)
+#define DDR4_WR_DBI(n)         ((n) << 11)
+#define DDR4_DM(n)             ((n) << 10)
+#define DDR4_RTT_PARK_DIS      (0 << 6)
+#define DDR4_RTT_PARK_60       (1 << 6)
+#define DDR4_RTT_PARK_120      (2 << 6)
+#define DDR4_RTT_PARK_40       (3 << 6)
+#define DDR4_RTT_PARK_240      (4 << 6)
+#define DDR4_RTT_PARK_48       (5 << 6)
+#define DDR4_RTT_PARK_80       (6 << 6)
+#define DDR4_RTT_PARK_34       (7 << 6)
+#define DIS_ODT_PD             (1 << 5)
+#define EN_ODT_PD              (0 << 5)
+
+/* mr6 for ddr4 */
+#define DDR4_TCCD_L(n)         (((n) - 4) << 10)
+
+#define PS_2_CLK(freq, ps)     (((uint64_t)(ps) / 100 * (uint64_t)(freq) +\
+                               9999) / 10000)
+
+#endif /* __ROCKCHIP_DRAM_SPEC_TIMING_H__ */
index a14b37cbc5c90915928268087b57f77506cfa7a5..e53e5a9ca58924bd954407de31162acc111ec64b 100644 (file)
 #define MIN(a, b)      (((a) > (b)) ? (b) : (a))
 #define MAX(a, b)      (((a) > (b)) ? (a) : (b))
 
+/* get head info for initial */
+#define DDR_FREQ_F0_SHIFT              (0)
+#define DDR_FREQ_F1_SHIFT              (12)
+#define DDR_FREQ_F2_SHIFT              (0)
+#define DDR_FREQ_F3_SHIFT              (12)
+#define DDR_FREQ_F4_SHIFT              (0)
+#define DDR_FREQ_F5_SHIFT              (12)
+#define DDR_FREQ_MASK                  (0xfff)
+
+#define UART_INFO_ID_SHIFT             (28)
+#define UART_INFO_IOMUX_SHIFT          (24)
+#define UART_INFO_BAUD_SHIFT           (0)
+#define UART_INFO_ID(n)                        (((n) >> 28) & 0xf)
+#define UART_INFO_IOMUX(n)             (((n) >> 24) & 0xf)
+#define UART_INFO_BAUD(n)              ((n) & 0xffffff)
+
+/* g_ch_info[15:0]: g_stdby_idle */
+#define STANDBY_IDLE(n)                        ((n) & 0xffff)
+
+#define SR_INFO(n)                     (((n) >> 16) & 0xffff)
+#define PD_INFO(n)                     ((n) & 0xffff)
+
+#define FIRST_SCAN_CH(n)               (((n) >> 28) & 0xf)
+#define CHANNEL_MASK(n)                        (((n) >> 24) & 0xf)
+#define STRIDE_TYPE(n)                 (((n) >> 16) & 0xff)
+
+#define DDR_2T_INFO(n)                 ((n) & 1)
+#define PLL_SSMOD_SPREAD(n)            (((n) >> 1) & 0xff)
+#define PLL_SSMOD_DIV(n)               (((n) >> 9) & 0xff)
+#define PLL_SSMOD_DOWNSPREAD(n)                (((n) >> 17) & 0x3)
+
+/* sdram_head_info_v2 define */
+/* for *_drv_odten and *_drv_odtoff */
+#define PHY_DQ_DRV_SHIFT               0
+#define PHY_CA_DRV_SHIFT               8
+#define PHY_CLK_DRV_SHIFT              16
+#define DRAM_DQ_DRV_SHIFT              24
+#define DRV_INFO_PHY_DQ_DRV(n)         ((n) & 0xff)
+#define DRV_INFO_PHY_CA_DRV(n)         (((n) >> PHY_CA_DRV_SHIFT) & 0xff)
+#define DRV_INFO_PHY_CLK_DRV(n)                (((n) >> PHY_CLK_DRV_SHIFT) & 0xff)
+#define DRV_INFO_DRAM_DQ_DRV(n)                (((n) >> DRAM_DQ_DRV_SHIFT) & 0xff)
+
+/* for *_odt_info */
+#define DRAM_ODT_SHIFT                 0
+#define PHY_ODT_SHIFT                  8
+#define PHY_ODT_PUUP_EN_SHIFT          18
+#define PHY_ODT_PUDN_EN_SHIFT          19
+#define ODT_INFO_DRAM_ODT(n)           (((n) >> DRAM_ODT_SHIFT) & 0xff)
+#define ODT_INFO_PHY_ODT(n)            (((n) >> PHY_ODT_SHIFT) & 0x3ff)
+#define ODT_INFO_PULLUP_EN(n)          (((n) >> PHY_ODT_PUUP_EN_SHIFT) & 1)
+#define ODT_INFO_PULLDOWN_EN(n)                (((n) >> PHY_ODT_PUDN_EN_SHIFT) & 1)
+
+/* for *odt_en_freq; */
+#define DRAM_ODT_EN_FREQ_SHIFT         0
+#define PHY_ODT_EN_FREQ_SHIFT          12
+#define DRAMODT_EN_FREQ(n)             (((n) >> DRAM_ODT_EN_FREQ_SHIFT) & \
+                                        0xfff)
+#define PHYODT_EN_FREQ(n)              (((n) >> PHY_ODT_EN_FREQ_SHIFT) & 0xfff)
+
+#define PHY_DQ_SR_SHIFT                        0
+#define PHY_CA_SR_SHIFT                        8
+#define PHY_CLK_SR_SHIFT               16
+#define DQ_SR_INFO(n)                  (((n) >> PHY_DQ_SR_SHIFT) & 0xff)
+#define CA_SR_INFO(n)                  (((n) >> PHY_CA_SR_SHIFT) & 0xff)
+#define CLK_SR_INFO(n)                 (((n) >> PHY_CLK_SR_SHIFT) & 0xff)
+
+/* LP4 */
+#define LP4_CA_ODT_SHIFT                       (18)
+#define LP4_DRV_PU_CAL_ODTEN_SHIFT             (26)
+#define LP4_DRV_PU_CAL_ODTOFF_SHIFT            (27)
+#define PHY_LP4_DRV_PULLDOWN_EN_ODTEN_SHIFT    (28)
+#define PHY_LP4_DRV_PULLDOWN_EN_ODTOFF_SHIFT   (29)
+#define ODT_INFO_LP4_CA_ODT(n)                 (((n) >> LP4_CA_ODT_SHIFT) & \
+                                                0xff)
+#define LP4_DRV_PU_CAL_ODTEN(n)                \
+       (((n) >> LP4_DRV_PU_CAL_ODTEN_SHIFT) & 1)
+#define LP4_DRV_PU_CAL_ODTOFF(n)       \
+       (((n) >> LP4_DRV_PU_CAL_ODTOFF_SHIFT) & 1)
+#define PHY_LP4_DRV_PULLDOWN_EN_ODTEN(n)       \
+       (((n) >> PHY_LP4_DRV_PULLDOWN_EN_ODTEN_SHIFT) & 1)
+#define PHY_LP4_DRV_PULLDOWN_EN_ODTOFF(n)      \
+       (((n) >> PHY_LP4_DRV_PULLDOWN_EN_ODTOFF_SHIFT) & 1)
+
+#define PHY_LP4_CS_DRV_ODTEN_SHIFT     (0)
+#define PHY_LP4_CS_DRV_ODTOFF_SHIFT    (8)
+#define LP4_ODTE_CK_SHIFT              (16)
+#define LP4_ODTE_CS_EN_SHIFT           (17)
+#define LP4_ODTD_CA_EN_SHIFT           (18)
+#define PHY_LP4_CS_DRV_ODTEN(n)                \
+       (((n) >> PHY_LP4_CS_DRV_ODTEN_SHIFT) & 0xff)
+#define PHY_LP4_CS_DRV_ODTOFF(n)       \
+       (((n) >> PHY_LP4_CS_DRV_ODTOFF_SHIFT) & 0xff)
+#define LP4_ODTE_CK_EN(n)              (((n) >> LP4_ODTE_CK_SHIFT) & 1)
+#define LP4_ODTE_CS_EN(n)              (((n) >> LP4_ODTE_CS_EN_SHIFT) & 1)
+#define LP4_ODTD_CA_EN(n)              (((n) >> LP4_ODTD_CA_EN_SHIFT) & 1)
+
+#define PHY_LP4_DQ_VREF_SHIFT          (0)
+#define LP4_DQ_VREF_SHIFT              (10)
+#define LP4_CA_VREF_SHIFT              (20)
+
+#define PHY_LP4_DQ_VREF(n)             \
+       (((n) >> PHY_LP4_DQ_VREF_SHIFT) & 0x3ff)
+#define LP4_DQ_VREF(n)                 (((n) >> LP4_DQ_VREF_SHIFT) & 0x3ff)
+#define LP4_CA_VREF(n)                 (((n) >> LP4_CA_VREF_SHIFT) & 0x3ff)
+
+#define LP4_DQ_ODT_EN_FREQ_SHIFT       (0)
+#define PHY_LP4_ODT_EN_FREQ_SHIFT      (12)
+#define LP4_CA_ODT_EN_FREQ_SHIFT       (0)
+#define PHY_LP4_ODT_EN_FREQ(n)         \
+       (((n) >> PHY_LP4_ODT_EN_FREQ_SHIFT) & 0xfff)
+#define LP4_DQ_ODT_EN_FREQ(n)          \
+       (((n) >> LP4_DQ_ODT_EN_FREQ_SHIFT) & 0xfff)
+#define LP4_CA_ODT_EN_FREQ(n)          \
+       (((n) >> LP4_CA_ODT_EN_FREQ_SHIFT) & 0xfff)
+
+struct sdram_head_info_v0 {
+       u32 start_tag;
+       u32 version_info;
+       u32 gcpu_gen_freq;
+       u32 g_d2_lp2_freq;
+       u32 g_d3_lp3_freq;
+       u32 g_d4_lp4_freq;
+       u32 g_uart_info;
+       u32 g_sr_pd_idle;
+       u32 g_ch_info;
+       u32 g_2t_info;
+       u32 reserved11;
+       u32 reserved12;
+       u32 reserved13;
+};
+
+struct index_info {
+       u8 offset;
+       u8 size;
+};
+
+struct sdram_head_info_index_v2 {
+       u32 start_tag;
+       u32 version_info;
+       struct index_info cpu_gen_index;
+       struct index_info global_index;
+
+       struct index_info ddr2_index;
+       struct index_info ddr3_index;
+
+       struct index_info ddr4_index;
+       struct index_info ddr5_index;
+
+       struct index_info lp2_index;
+       struct index_info lp3_index;
+
+       struct index_info lp4_index;
+       struct index_info lp5_index;
+
+       struct index_info skew_index;
+       struct index_info dq_map_index;
+
+       struct index_info lp4x_index;
+       struct index_info reserved;
+};
+
+struct global_info {
+       u32 uart_info;
+       u32 sr_pd_info;
+       u32 ch_info;
+       u32 info_2t;
+       u32 reserved[4];
+};
+
+struct ddr2_3_4_lp2_3_info {
+       u32 ddr_freq0_1;
+       u32 ddr_freq2_3;
+       u32 ddr_freq4_5;
+       u32 drv_when_odten;
+       u32 drv_when_odtoff;
+       u32 odt_info;
+       u32 odten_freq;
+       u32 sr_when_odten;
+       u32 sr_when_odtoff;
+};
+
+struct lp4_info {
+       u32 ddr_freq0_1;
+       u32 ddr_freq2_3;
+       u32 ddr_freq4_5;
+       u32 drv_when_odten;
+       u32 drv_when_odtoff;
+       u32 odt_info;
+       u32 dq_odten_freq;
+       u32 sr_when_odten;
+       u32 sr_when_odtoff;
+       u32 ca_odten_freq;
+       u32 cs_drv_ca_odt_info;
+       u32 vref_when_odten;
+       u32 vref_when_odtoff;
+};
+
+struct dq_map_info {
+       u32 byte_map[2];
+       u32 lp3_dq0_7_map;
+       u32 lp2_dq0_7_map;
+       u32 ddr4_dq_map[4];
+};
+
 struct sdram_cap_info {
        unsigned int rank;
        /* dram column number, 0 means this channel is invalid */
@@ -46,6 +250,14 @@ struct sdram_base_params {
 };
 
 #define DDR_SYS_REG_VERSION            (0x2)
+/* for modify tRFC and related timing */
+#define DIE_CAP_512MBIT        64
+#define DIE_CAP_1GBIT  128
+#define DIE_CAP_2GBIT  256
+#define DIE_CAP_4GBIT  512
+#define DIE_CAP_8GBIT  1024
+#define DIE_CAP_16GBIT 2048
+#define DIE_CAP_32GBIT 4096
 /*
  * sys_reg2 bitfield struct
  * [31]                row_3_4_ch1
index cfb3d9cc86983db7a0e9b858ad58ff2b7a57c00d..d1926f4bf20a7965543ffe8cf0a1c337ed91642f 100644 (file)
@@ -57,6 +57,18 @@ union noc_devtodev0 {
        } b;
 };
 
+union noc_devtodev_rv1126 {
+       u32 d32;
+       struct {
+               unsigned busrdtord : 3;
+               unsigned reserved0 : 1;
+               unsigned busrdtowr : 4;
+               unsigned buswrtord : 4;
+               unsigned buswrtowr : 3;
+               unsigned reserved2 : 17;
+       } b;
+};
+
 union noc_ddrmode {
        u32 d32;
        struct {
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_phy_rv1126.h b/arch/arm/include/asm/arch-rockchip/sdram_phy_rv1126.h
new file mode 100644 (file)
index 0000000..5b64ec3
--- /dev/null
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier:     GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef _ASM_ARCH_SDRAM_RK1126_PHY_H
+#define _ASM_ARCH_SDRAM_RK1126_PHY_H
+
+/* PHY_REG0 */
+#define DIGITAL_DERESET                        BIT(3)
+#define ANALOG_DERESET                 BIT(2)
+#define DIGITAL_RESET                  (0 << 3)
+#define ANALOG_RESET                   (0 << 2)
+
+/* PHY_REG1 */
+#define PHY_DDR2                       (0)
+#define PHY_LPDDR2                     (1)
+#define PHY_DDR3                       (2)
+#define PHY_LPDDR3                     (3)
+#define PHY_DDR4                       (4)
+#define PHY_DDR5                       (5)
+#define PHY_BL_4                       (0 << 3)
+#define PHY_BL_8_OR_16                 BIT(3)
+
+/* PHY_REG2 */
+#define PHY_DTT_EN                     BIT(0)
+#define PHY_DTT_DISB                   (0 << 0)
+#define PHY_WRITE_LEVELING_EN          BIT(2)
+#define PHY_WRITE_LEVELING_DISB                (0 << 2)
+#define PHY_SELECT_CS0                 (2)
+#define PHY_SELECT_CS1                 (1)
+#define PHY_SELECT_CS0_1               (0)
+#define PHY_WRITE_LEVELING_SELECTCS(n) ((n) << 6)
+#define PHY_DATA_TRAINING_SELECTCS(n)  ((n) << 4)
+
+/* PHY_REGf */
+#define PHY_DQ_WIDTH_MASK              (0xf)
+
+/* PHY_REG51 */
+#define PHY_PBDIV_BIT9_MASK            BIT(0)
+#define PHY_PBDIV_BIT9_SHIFT   (0)
+#define PHY_POSTDIV_EN_MASK            BIT(7)
+#define PHY_POSTDIV_EN_SHIFT   (7)
+
+/* PHY_REG52 */
+#define PHY_PREDIV_MASK                        (0x1F)
+#define PHY_PREDIV_SHIFT               (0)
+
+/* PHY_REG53*/
+#define PHY_POSTDIV_MASK               (0x7)
+#define PHY_POSTDIV_SHIFT              (5)
+#define PHY_PD_DISB                    BIT(3)
+
+/* PHY_REG90 */
+#define PHY_PLL_LOCK                   BIT(2)
+
+struct ca_skew {
+       u32 a0_a3_a3_cke1_a_de_skew;
+       u32 a1_ba1_null_cke0_b_de_skew;
+       u32 a2_a9_a9_a4_a_de_skew;
+       u32 a3_a15_null_a5_b_de_skew;
+       u32 a4_a6_a6_ck_a_de_skew;
+       u32 a5_a12_null_odt0_b_de_skew;
+       u32 a6_ba2_null_a0_a_de_skew;
+       u32 a7_a4_a4_odt0_a_de_skew;
+       u32 a8_a1_a1_cke0_a_de_skew;
+       u32 a9_a5_a5_a5_a_de_skew;
+       u32 a10_a8_a8_clkb_a_de_skew;
+       u32 a11_a7_a7_ca2_a_de_skew;
+       u32 a12_rasn_null_ca1_a_de_skew;
+       u32 a13_a13_null_ca3_a_de_skew;
+       u32 a14_a14_null_csb1_b_de_skew;
+       u32 a15_a10_null_ca0_b_de_skew;
+       u32 a16_a11_null_csb0_b_de_skew;
+       u32 a17_null_null_null_de_skew;
+       u32 ba0_csb1_csb1_csb0_a_de_skew;
+       u32 ba1_wen_null_cke1_b_de_skew;
+       u32 bg0_odt1_odt1_csb1_a_de_skew;
+       u32 bg1_a2_a2_odt1_a_de_skew;
+       u32 cke0_casb_null_ca1_b_de_skew;
+       u32 ck_ck_ck_ck_b_de_skew;
+       u32 ckb_ckb_ckb_ckb_b_de_skew;
+       u32 csb0_odt0_odt0_ca2_b_de_skew;
+       u32 odt0_csb0_csb0_ca4_b_de_skew;
+       u32 resetn_resetn_null_resetn_de_skew;
+       u32 actn_cke_cke_ca3_b_de_skew;
+       u32 null_null_null_null_de_skew;
+       u32 csb1_ba0_null_null_de_skew;
+       u32 odt1_a0_a0_odt1_b_de_skew;
+};
+
+#define PHY_REG(base, n)               ((base) + 4 * (n))
+#endif /* _ASM_ARCH_SDRAM_RK1126_PHY_H */
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rv1126.h b/arch/arm/include/asm/arch-rockchip/sdram_rv1126.h
new file mode 100644 (file)
index 0000000..6a07436
--- /dev/null
@@ -0,0 +1,420 @@
+/* SPDX-License-Identifier:     GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef _ASM_ARCH_SDRAM_RK1126_H
+#define _ASM_ARCH_SDRAM_RK1126_H
+
+#include <asm/arch-rockchip/dram_spec_timing.h>
+#include <asm/arch-rockchip/sdram.h>
+#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_msch.h>
+#include <asm/arch-rockchip/sdram_pctl_px30.h>
+#include <asm/arch-rockchip/sdram_phy_rv1126.h>
+
+#define AGINGX0_VAL                    (4)
+#define AGING_CPU_VAL                  (0xff)
+#define AGING_NPU_VAL                  (0xff)
+#define AGING_OTHER_VAL                        (0x33)
+
+#define PATTERN                                (0x5aa5f00f)
+
+#define PHY_DDR3_RON_DISABLE           (0)
+#define PHY_DDR3_RON_455ohm            (1)
+#define PHY_DDR3_RON_230ohm            (2)
+#define PHY_DDR3_RON_153ohm            (3)
+#define PHY_DDR3_RON_115ohm            (4)
+#define PHY_DDR3_RON_91ohm             (5)
+#define PHY_DDR3_RON_76ohm             (6)
+#define PHY_DDR3_RON_65ohm             (7)
+#define PHY_DDR3_RON_57ohm             (16)
+#define PHY_DDR3_RON_51ohm             (17)
+#define PHY_DDR3_RON_46ohm             (18)
+#define PHY_DDR3_RON_41ohm             (19)
+#define PHY_DDR3_RON_38ohm             (20)
+#define PHY_DDR3_RON_35ohm             (21)
+#define PHY_DDR3_RON_32ohm             (22)
+#define PHY_DDR3_RON_30ohm             (23)
+#define PHY_DDR3_RON_28ohm             (24)
+#define PHY_DDR3_RON_27ohm             (25)
+#define PHY_DDR3_RON_25ohm             (26)
+#define PHY_DDR3_RON_24ohm             (27)
+#define PHY_DDR3_RON_23ohm             (28)
+#define PHY_DDR3_RON_22ohm             (29)
+#define PHY_DDR3_RON_21ohm             (30)
+#define PHY_DDR3_RON_20ohm             (31)
+
+#define PHY_DDR3_RTT_DISABLE           (0)
+#define PHY_DDR3_RTT_561ohm            (1)
+#define PHY_DDR3_RTT_282ohm            (2)
+#define PHY_DDR3_RTT_188ohm            (3)
+#define PHY_DDR3_RTT_141ohm            (4)
+#define PHY_DDR3_RTT_113ohm            (5)
+#define PHY_DDR3_RTT_94ohm             (6)
+#define PHY_DDR3_RTT_81ohm             (7)
+#define PHY_DDR3_RTT_72ohm             (16)
+#define PHY_DDR3_RTT_64ohm             (17)
+#define PHY_DDR3_RTT_58ohm             (18)
+#define PHY_DDR3_RTT_52ohm             (19)
+#define PHY_DDR3_RTT_48ohm             (20)
+#define PHY_DDR3_RTT_44ohm             (21)
+#define PHY_DDR3_RTT_41ohm             (22)
+#define PHY_DDR3_RTT_38ohm             (23)
+#define PHY_DDR3_RTT_37ohm             (24)
+#define PHY_DDR3_RTT_34ohm             (25)
+#define PHY_DDR3_RTT_32ohm             (26)
+#define PHY_DDR3_RTT_31ohm             (27)
+#define PHY_DDR3_RTT_29ohm             (28)
+#define PHY_DDR3_RTT_28ohm             (29)
+#define PHY_DDR3_RTT_27ohm             (30)
+#define PHY_DDR3_RTT_25ohm             (31)
+
+#define PHY_DDR4_LPDDR3_RON_DISABLE    (0)
+#define PHY_DDR4_LPDDR3_RON_482ohm     (1)
+#define PHY_DDR4_LPDDR3_RON_244ohm     (2)
+#define PHY_DDR4_LPDDR3_RON_162ohm     (3)
+#define PHY_DDR4_LPDDR3_RON_122ohm     (4)
+#define PHY_DDR4_LPDDR3_RON_97ohm      (5)
+#define PHY_DDR4_LPDDR3_RON_81ohm      (6)
+#define PHY_DDR4_LPDDR3_RON_69ohm      (7)
+#define PHY_DDR4_LPDDR3_RON_61ohm      (16)
+#define PHY_DDR4_LPDDR3_RON_54ohm      (17)
+#define PHY_DDR4_LPDDR3_RON_48ohm      (18)
+#define PHY_DDR4_LPDDR3_RON_44ohm      (19)
+#define PHY_DDR4_LPDDR3_RON_40ohm      (20)
+#define PHY_DDR4_LPDDR3_RON_37ohm      (21)
+#define PHY_DDR4_LPDDR3_RON_34ohm      (22)
+#define PHY_DDR4_LPDDR3_RON_32ohm      (23)
+#define PHY_DDR4_LPDDR3_RON_30ohm      (24)
+#define PHY_DDR4_LPDDR3_RON_28ohm      (25)
+#define PHY_DDR4_LPDDR3_RON_27ohm      (26)
+#define PHY_DDR4_LPDDR3_RON_25ohm      (27)
+#define PHY_DDR4_LPDDR3_RON_24ohm      (28)
+#define PHY_DDR4_LPDDR3_RON_23ohm      (29)
+#define PHY_DDR4_LPDDR3_RON_22ohm      (30)
+#define PHY_DDR4_LPDDR3_RON_21ohm      (31)
+
+#define PHY_DDR4_LPDDR3_RTT_DISABLE    (0)
+#define PHY_DDR4_LPDDR3_RTT_586ohm     (1)
+#define PHY_DDR4_LPDDR3_RTT_294ohm     (2)
+#define PHY_DDR4_LPDDR3_RTT_196ohm     (3)
+#define PHY_DDR4_LPDDR3_RTT_148ohm     (4)
+#define PHY_DDR4_LPDDR3_RTT_118ohm     (5)
+#define PHY_DDR4_LPDDR3_RTT_99ohm      (6)
+#define PHY_DDR4_LPDDR3_RTT_85ohm      (7)
+#define PHY_DDR4_LPDDR3_RTT_76ohm      (16)
+#define PHY_DDR4_LPDDR3_RTT_67ohm      (17)
+#define PHY_DDR4_LPDDR3_RTT_60ohm      (18)
+#define PHY_DDR4_LPDDR3_RTT_55ohm      (19)
+#define PHY_DDR4_LPDDR3_RTT_50ohm      (20)
+#define PHY_DDR4_LPDDR3_RTT_46ohm      (21)
+#define PHY_DDR4_LPDDR3_RTT_43ohm      (22)
+#define PHY_DDR4_LPDDR3_RTT_40ohm      (23)
+#define PHY_DDR4_LPDDR3_RTT_38ohm      (24)
+#define PHY_DDR4_LPDDR3_RTT_36ohm      (25)
+#define PHY_DDR4_LPDDR3_RTT_34ohm      (26)
+#define PHY_DDR4_LPDDR3_RTT_32ohm      (27)
+#define PHY_DDR4_LPDDR3_RTT_31ohm      (28)
+#define PHY_DDR4_LPDDR3_RTT_29ohm      (29)
+#define PHY_DDR4_LPDDR3_RTT_28ohm      (30)
+#define PHY_DDR4_LPDDR3_RTT_27ohm      (31)
+
+#define PHY_LPDDR4_RON_DISABLE         (0)
+#define PHY_LPDDR4_RON_501ohm          (1)
+#define PHY_LPDDR4_RON_253ohm          (2)
+#define PHY_LPDDR4_RON_168ohm          (3)
+#define PHY_LPDDR4_RON_126ohm          (4)
+#define PHY_LPDDR4_RON_101ohm          (5)
+#define PHY_LPDDR4_RON_84ohm           (6)
+#define PHY_LPDDR4_RON_72ohm           (7)
+#define PHY_LPDDR4_RON_63ohm           (16)
+#define PHY_LPDDR4_RON_56ohm           (17)
+#define PHY_LPDDR4_RON_50ohm           (18)
+#define PHY_LPDDR4_RON_46ohm           (19)
+#define PHY_LPDDR4_RON_42ohm           (20)
+#define PHY_LPDDR4_RON_38ohm           (21)
+#define PHY_LPDDR4_RON_36ohm           (22)
+#define PHY_LPDDR4_RON_33ohm           (23)
+#define PHY_LPDDR4_RON_31ohm           (24)
+#define PHY_LPDDR4_RON_29ohm           (25)
+#define PHY_LPDDR4_RON_28ohm           (26)
+#define PHY_LPDDR4_RON_26ohm           (27)
+#define PHY_LPDDR4_RON_25ohm           (28)
+#define PHY_LPDDR4_RON_24ohm           (29)
+#define PHY_LPDDR4_RON_23ohm           (30)
+#define PHY_LPDDR4_RON_22ohm           (31)
+
+#define PHY_LPDDR4_RTT_DISABLE         (0)
+#define PHY_LPDDR4_RTT_604ohm          (1)
+#define PHY_LPDDR4_RTT_303ohm          (2)
+#define PHY_LPDDR4_RTT_202ohm          (3)
+#define PHY_LPDDR4_RTT_152ohm          (4)
+#define PHY_LPDDR4_RTT_122ohm          (5)
+#define PHY_LPDDR4_RTT_101ohm          (6)
+#define PHY_LPDDR4_RTT_87ohm           (7)
+#define PHY_LPDDR4_RTT_78ohm           (16)
+#define PHY_LPDDR4_RTT_69ohm           (17)
+#define PHY_LPDDR4_RTT_62ohm           (18)
+#define PHY_LPDDR4_RTT_56ohm           (19)
+#define PHY_LPDDR4_RTT_52ohm           (20)
+#define PHY_LPDDR4_RTT_48ohm           (21)
+#define PHY_LPDDR4_RTT_44ohm           (22)
+#define PHY_LPDDR4_RTT_41ohm           (23)
+#define PHY_LPDDR4_RTT_39ohm           (24)
+#define PHY_LPDDR4_RTT_37ohm           (25)
+#define PHY_LPDDR4_RTT_35ohm           (26)
+#define PHY_LPDDR4_RTT_33ohm           (27)
+#define PHY_LPDDR4_RTT_32ohm           (28)
+#define PHY_LPDDR4_RTT_30ohm           (29)
+#define PHY_LPDDR4_RTT_29ohm           (30)
+#define PHY_LPDDR4_RTT_27ohm           (31)
+
+#define ADD_CMD_CA                     (0x150)
+#define ADD_GROUP_CS0_A                        (0x170)
+#define ADD_GROUP_CS0_B                        (0x1d0)
+#define ADD_GROUP_CS1_A                        (0x1a0)
+#define ADD_GROUP_CS1_B                        (0x200)
+
+/* PMUGRF */
+#define PMUGRF_OS_REG0                 (0x200)
+#define PMUGRF_OS_REG(n)               (PMUGRF_OS_REG0 + (n) * 4)
+#define PMUGRF_CON_DDRPHY_BUFFEREN_MASK                (0x3 << (12 + 16))
+#define PMUGRF_CON_DDRPHY_BUFFEREN_EN          (0x1 << 12)
+#define PMUGRF_CON_DDRPHY_BUFFEREN_DIS (0x2 << 12)
+
+/* DDR GRF */
+#define DDR_GRF_CON(n)                 (0 + (n) * 4)
+#define DDR_GRF_STATUS_BASE            (0X100)
+#define DDR_GRF_STATUS(n)              (DDR_GRF_STATUS_BASE + (n) * 4)
+#define DDR_GRF_LP_CON                 (0x20)
+
+#define SPLIT_MODE_32_L16_VALID                (0)
+#define SPLIT_MODE_32_H16_VALID                (1)
+#define SPLIT_MODE_16_L8_VALID         (2)
+#define SPLIT_MODE_16_H8_VALID         (3)
+
+#define DDR_GRF_SPLIT_CON              (0x10)
+#define SPLIT_MODE_MASK                        (0x3)
+#define SPLIT_MODE_OFFSET              (9)
+#define SPLIT_BYPASS_MASK              (1)
+#define SPLIT_BYPASS_OFFSET            (8)
+#define SPLIT_SIZE_MASK                        (0xff)
+#define SPLIT_SIZE_OFFSET              (0)
+
+/* SGRF SOC_CON13 */
+#define UPCTL2_ASRSTN_REQ(n)           (((0x1 << 0) << 16) | ((n) << 0))
+#define UPCTL2_PSRSTN_REQ(n)           (((0x1 << 1) << 16) | ((n) << 1))
+#define UPCTL2_SRSTN_REQ(n)            (((0x1 << 2) << 16) | ((n) << 2))
+
+/* CRU define */
+/* CRU_PLL_CON0 */
+#define PB(n)                          ((0x1 << (15 + 16)) | ((n) << 15))
+#define POSTDIV1(n)                    ((0x7 << (12 + 16)) | ((n) << 12))
+#define FBDIV(n)                       ((0xFFF << 16) | (n))
+
+/* CRU_PLL_CON1 */
+#define RSTMODE(n)                     ((0x1 << (15 + 16)) | ((n) << 15))
+#define RST(n)                         ((0x1 << (14 + 16)) | ((n) << 14))
+#define PD(n)                          ((0x1 << (13 + 16)) | ((n) << 13))
+#define DSMPD(n)                       ((0x1 << (12 + 16)) | ((n) << 12))
+#define LOCK(n)                                (((n) >> 10) & 0x1)
+#define POSTDIV2(n)                    ((0x7 << (6 + 16)) | ((n) << 6))
+#define REFDIV(n)                      ((0x3F << 16) | (n))
+
+/* CRU_PLL_CON3 */
+#define SSMOD_SPREAD(n)                        ((0x1f << (8 + 16)) | ((n) << 8))
+#define SSMOD_DIVVAL(n)                        ((0xf << (4 + 16)) | ((n) << 4))
+#define SSMOD_DOWNSPREAD(n)            ((0x1 << (3 + 16)) | ((n) << 3))
+#define SSMOD_RESET(n)                 ((0x1 << (2 + 16)) | ((n) << 2))
+#define SSMOD_DIS_SSCG(n)              ((0x1 << (1 + 16)) | ((n) << 1))
+#define SSMOD_BP(n)                    ((0x1 << (0 + 16)) | ((n) << 0))
+
+/* CRU_MODE */
+#define CLOCK_FROM_XIN_OSC             (0)
+#define CLOCK_FROM_PLL                 (1)
+#define CLOCK_FROM_RTC_32K             (2)
+#define DPLL_MODE(n)                   ((0x3 << (2 + 16)) | ((n) << 2))
+
+/* CRU_SOFTRESET_CON1 */
+#define DDRPHY_PSRSTN_REQ(n)           (((0x1 << 14) << 16) | ((n) << 14))
+#define DDRPHY_SRSTN_REQ(n)            (((0x1 << 15) << 16) | ((n) << 15))
+/* CRU_CLKGATE_CON2 */
+#define DDR_MSCH_EN_MASK               ((0x1 << 10) << 16)
+#define DDR_MSCH_EN_SHIFT              (10)
+
+/* CRU register */
+#define CRU_PLL_CON(pll_id, n)         ((pll_id)  * 0x20 + (n) * 4)
+#define CRU_MODE                       (0xa0)
+#define CRU_GLB_CNT_TH                 (0xb0)
+#define CRU_CLKSEL_CON_BASE            0x100
+#define CRU_CLKSELS_CON(i)             (CRU_CLKSEL_CON_BASE + ((i) * 4))
+#define CRU_CLKGATE_CON_BASE           0x230
+#define CRU_CLKGATE_CON(i)             (CRU_CLKGATE_CON_BASE + ((i) * 4))
+#define CRU_CLKSFTRST_CON_BASE         0x300
+#define CRU_CLKSFTRST_CON(i)           (CRU_CLKSFTRST_CON_BASE + ((i) * 4))
+
+/* SGRF_SOC_CON2 */
+#define MSCH_AXI_BYPASS_ALL_MASK       (1)
+#define MSCH_AXI_BYPASS_ALL_SHIFT      (15)
+
+/* SGRF_SOC_CON12 */
+#define CLK_DDR_UPCTL_EN_MASK          ((0x1 << 2) << 16)
+#define CLK_DDR_UPCTL_EN_SHIFT         (2)
+#define ACLK_DDR_UPCTL_EN_MASK         ((0x1 << 0) << 16)
+#define ACLK_DDR_UPCTL_EN_SHIFT                (0)
+
+/* DDRGRF DDR CON2 */
+#define DFI_FREQ_CHANGE_ACK            BIT(10)
+/* DDRGRF status8 */
+#define DFI_FREQ_CHANGE_REQ            BIT(19)
+
+struct rv1126_ddrgrf {
+       u32 ddr_grf_con[4];
+       u32 grf_ddrsplit_con;
+       u32 reserved1[(0x20 - 0x10) / 4 - 1];
+       u32 ddr_grf_lp_con;
+       u32 reserved2[(0x40 - 0x20) / 4 - 1];
+       u32 grf_ddrphy_con[6];
+       u32 reserved3[(0x100 - 0x54) / 4 - 1];
+       u32 ddr_grf_status[18];
+       u32 reserved4[(0x150 - 0x144) / 4 - 1];
+       u32 grf_ddrhold_status;
+       u32 reserved5[(0x160 - 0x150) / 4 - 1];
+       u32 grf_ddrphy_status[2];
+};
+
+struct rv1126_ddr_phy_regs {
+       u32 phy[8][2];
+};
+
+struct msch_regs {
+       u32 coreid;
+       u32 revisionid;
+       u32 deviceconf;
+       u32 devicesize;
+       u32 ddrtiminga0;
+       u32 ddrtimingb0;
+       u32 ddrtimingc0;
+       u32 devtodev0;
+       u32 reserved1[(0x110 - 0x20) / 4];
+       u32 ddrmode;
+       u32 ddr4timing;
+       u32 reserved2[(0x1000 - 0x118) / 4];
+       u32 agingx0;
+       u32 reserved3[(0x1040 - 0x1004) / 4];
+       u32 aging0;
+       u32 aging1;
+       u32 aging2;
+       u32 aging3;
+};
+
+struct sdram_msch_timings {
+       union noc_ddrtiminga0 ddrtiminga0;
+       union noc_ddrtimingb0 ddrtimingb0;
+       union noc_ddrtimingc0 ddrtimingc0;
+       union noc_devtodev_rv1126 devtodev0;
+       union noc_ddrmode ddrmode;
+       union noc_ddr4timing ddr4timing;
+       u32 agingx0;
+       u32 aging0;
+       u32 aging1;
+       u32 aging2;
+       u32 aging3;
+};
+
+struct rv1126_sdram_channel {
+       struct sdram_cap_info cap_info;
+       struct sdram_msch_timings noc_timings;
+};
+
+struct rv1126_sdram_params {
+       struct rv1126_sdram_channel ch;
+       struct sdram_base_params base;
+       struct ddr_pctl_regs pctl_regs;
+       struct rv1126_ddr_phy_regs phy_regs;
+};
+
+struct rv1126_fsp_param {
+       u32 flag;
+       u32 freq_mhz;
+
+       /* dram size */
+       u32 dq_odt;
+       u32 ca_odt;
+       u32 ds_pdds;
+       u32 vref_ca[2];
+       u32 vref_dq[2];
+
+       /* phy side */
+       u32 wr_dq_drv;
+       u32 wr_ca_drv;
+       u32 wr_ckcs_drv;
+       u32 rd_odt;
+       u32 rd_odt_up_en;
+       u32 rd_odt_down_en;
+       u32 vref_inner;
+       u32 vref_out;
+       u32 lp4_drv_pd_en;
+
+       struct sdram_msch_timings noc_timings;
+};
+
+#define MAX_IDX                        (4)
+#define FSP_FLAG               (0xfead0001)
+#define SHARE_MEM_BASE         (0x100000)
+/*
+ * Borrow share memory space to temporarily store FSP parame.
+ * In the stage of DDR init write FSP parame to this space.
+ * In the stage of trust init move FSP parame to SRAM space
+ * from share memory space.
+ */
+#define FSP_PARAM_STORE_ADDR   (SHARE_MEM_BASE)
+
+/* store result of read and write training, for ddr_dq_eye tool in u-boot */
+#define RW_TRN_RESULT_ADDR     (0x2000000 + 0x8000)    /* 32M + 32k */
+#define PRINT_STEP             1
+
+#undef FSP_NUM
+#undef CS_NUM
+#undef BYTE_NUM
+
+#define FSP_NUM                        4
+#define CS_NUM                 2
+#define BYTE_NUM               4
+#define RD_DESKEW_NUM          64
+#define WR_DESKEW_NUM          64
+
+#define LP4_WIDTH_REF_MHZ_H    1056
+#define LP4_RD_WIDTH_REF_H     12
+#define LP4_WR_WIDTH_REF_H     13
+
+#define LP4_WIDTH_REF_MHZ_L    924
+#define LP4_RD_WIDTH_REF_L     15
+#define LP4_WR_WIDTH_REF_L     15
+
+#define DDR4_WIDTH_REF_MHZ_H   1056
+#define DDR4_RD_WIDTH_REF_H    13
+#define DDR4_WR_WIDTH_REF_H    9
+
+#define DDR4_WIDTH_REF_MHZ_L   924
+#define DDR4_RD_WIDTH_REF_L    15
+#define DDR4_WR_WIDTH_REF_L    11
+
+#define LP3_WIDTH_REF_MHZ_H    1056
+#define LP3_RD_WIDTH_REF_H     15
+#define LP3_WR_WIDTH_REF_H     13
+
+#define LP3_WIDTH_REF_MHZ_L    924
+#define LP3_RD_WIDTH_REF_L     16
+#define LP3_WR_WIDTH_REF_L     15
+
+#define DDR3_WIDTH_REF_MHZ_H   1056
+#define DDR3_RD_WIDTH_REF_H    14
+#define DDR3_WR_WIDTH_REF_H    14
+
+#define DDR3_WIDTH_REF_MHZ_L   924
+#define DDR3_RD_WIDTH_REF_L    17
+#define DDR3_WR_WIDTH_REF_L    17
+
+#endif /* _ASM_ARCH_SDRAM_RK1126_H */
index 6d530c29afd7a26c2c73128eefd8ab08bf289ade..98839ad6a6c413d9d9798af915da19ee7d318250 100644 (file)
@@ -14,4 +14,5 @@ obj-$(CONFIG_ROCKCHIP_RK3308) = sdram_rk3308.o
 obj-$(CONFIG_ROCKCHIP_RK3328) = sdram_rk3328.o sdram_pctl_px30.o sdram_phy_px30.o
 obj-$(CONFIG_ROCKCHIP_RK3399) += sdram_rk3399.o
 obj-$(CONFIG_ROCKCHIP_RK3568) += sdram_rk3568.o
+obj-$(CONFIG_ROCKCHIP_RV1126) += sdram_rv1126.o sdram_pctl_px30.o
 obj-$(CONFIG_ROCKCHIP_SDRAM_COMMON) += sdram_common.o
diff --git a/drivers/ram/rockchip/sdram_rv1126.c b/drivers/ram/rockchip/sdram_rv1126.c
new file mode 100644 (file)
index 0000000..2a57b19
--- /dev/null
@@ -0,0 +1,3521 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2020 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <ram.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <asm/arch-rockchip/cru_rv1126.h>
+#include <asm/arch-rockchip/grf_rv1126.h>
+#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_rv1126.h>
+#include <linux/delay.h>
+
+/* define training flag */
+#define CA_TRAINING                    (0x1 << 0)
+#define READ_GATE_TRAINING             (0x1 << 1)
+#define WRITE_LEVELING                 (0x1 << 2)
+#define WRITE_TRAINING                 (0x1 << 3)
+#define READ_TRAINING                  (0x1 << 4)
+#define FULL_TRAINING                  (0xff)
+
+#define SKEW_RX_SIGNAL                 (0)
+#define SKEW_TX_SIGNAL                 (1)
+#define SKEW_CA_SIGNAL                 (2)
+
+#define DESKEW_MDF_ABS_VAL             (0)
+#define DESKEW_MDF_DIFF_VAL            (1)
+
+struct dram_info {
+#if defined(CONFIG_TPL_BUILD) || \
+       (!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD))
+       void __iomem *pctl;
+       void __iomem *phy;
+       struct rv1126_cru *cru;
+       struct msch_regs *msch;
+       struct rv1126_ddrgrf *ddrgrf;
+       struct rv1126_grf *grf;
+       u32 sr_idle;
+       u32 pd_idle;
+#endif
+       struct ram_info info;
+       struct rv1126_pmugrf *pmugrf;
+};
+
+#if defined(CONFIG_TPL_BUILD) || \
+       (!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD))
+
+#define GRF_BASE_ADDR                  0xfe000000
+#define PMU_GRF_BASE_ADDR              0xfe020000
+#define DDR_GRF_BASE_ADDR              0xfe030000
+#define BUS_SGRF_BASE_ADDR             0xfe0a0000
+#define SERVER_MSCH_BASE_ADDR          0xfe800000
+#define CRU_BASE_ADDR                  0xff490000
+#define DDR_PHY_BASE_ADDR              0xff4a0000
+#define UPCTL2_BASE_ADDR               0xffa50000
+
+#define SGRF_SOC_CON2                  0x8
+#define SGRF_SOC_CON12                 0x30
+#define SGRF_SOC_CON13                 0x34
+
+struct dram_info dram_info;
+
+struct rv1126_sdram_params sdram_configs[] = {
+# include      "sdram-rv1126-ddr3-detect-328.inc"
+# include      "sdram-rv1126-ddr3-detect-396.inc"
+# include      "sdram-rv1126-ddr3-detect-528.inc"
+# include      "sdram-rv1126-ddr3-detect-664.inc"
+# include      "sdram-rv1126-ddr3-detect-784.inc"
+# include      "sdram-rv1126-ddr3-detect-924.inc"
+# include      "sdram-rv1126-ddr3-detect-1056.inc"
+};
+
+u32 common_info[] = {
+#include       "sdram-rv1126-loader_params.inc"
+};
+
+#if defined(CONFIG_CMD_DDR_TEST_TOOL)
+static struct rw_trn_result rw_trn_result;
+#endif
+
+static struct rv1126_fsp_param fsp_param[MAX_IDX];
+
+static u8 lp3_odt_value;
+
+static s8 wrlvl_result[2][4];
+
+/* DDR configuration 0-9 */
+u16 ddr_cfg_2_rbc[] = {
+       ((0 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 3), /* 0 */
+       ((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 2), /* 1 */
+       ((1 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 3), /* 2 */
+       ((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 1), /* 3 */
+       ((0 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 4), /* 4 */
+       ((0 << 8) | (3 << 5) | (1 << 4) | (1 << 3) | 1), /* 5 */
+       ((0 << 8) | (3 << 5) | (1 << 4) | (1 << 3) | 2), /* 6 */
+       ((0 << 8) | (2 << 5) | (1 << 4) | (1 << 3) | 3), /* 7 */
+       ((1 << 8) | (3 << 5) | (0 << 4) | (0 << 3) | 2), /* 8 */
+       ((1 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 2) /* 9 */
+};
+
+/* DDR configuration 10-21 */
+u8 ddr4_cfg_2_rbc[] = {
+       ((0 << 7) | (3 << 4) | (0 << 3) | (2 << 1) | 0), /* 10 */
+       ((1 << 7) | (2 << 4) | (0 << 3) | (2 << 1) | 0), /* 11 */
+       ((0 << 7) | (4 << 4) | (0 << 3) | (1 << 1) | 0), /* 12 */
+       ((1 << 7) | (3 << 4) | (0 << 3) | (1 << 1) | 0), /* 13 */
+       ((0 << 7) | (4 << 4) | (0 << 3) | (2 << 1) | 1), /* 14 */
+       ((1 << 7) | (3 << 4) | (0 << 3) | (2 << 1) | 1), /* 15 */
+       ((1 << 7) | (4 << 4) | (0 << 3) | (1 << 1) | 1), /* 16 */
+       ((0 << 7) | (2 << 4) | (1 << 3) | (2 << 1) | 0), /* 17 */
+       ((0 << 7) | (3 << 4) | (1 << 3) | (1 << 1) | 0), /* 18 */
+       ((0 << 7) | (3 << 4) | (1 << 3) | (2 << 1) | 1), /* 19 */
+       ((0 << 7) | (4 << 4) | (1 << 3) | (1 << 1) | 1), /* 20 */
+       ((1 << 7) | (4 << 4) | (0 << 3) | (0 << 1) | 0) /* 21 */
+};
+
+/* DDR configuration 22-28 */
+u16 ddr_cfg_2_rbc_p2[] = {
+       ((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 0), /* 22 */
+       ((0 << 8) | (4 << 5) | (0 << 4) | (1 << 3) | 2), /* 23 */
+       ((1 << 8) | (3 << 5) | (0 << 4) | (0 << 3) | 3), /* 24 */
+       ((0 << 8) | (3 << 5) | (1 << 4) | (0 << 3) | 3), /* 25 */
+       ((0 << 8) | (4 << 5) | (1 << 4) | (0 << 3) | 2), /* 26 */
+       ((1 << 8) | (4 << 5) | (0 << 4) | (0 << 3) | 2), /* 27 */
+       ((0 << 8) | (4 << 5) | (0 << 4) | (0 << 3) | 3) /* 28 */
+};
+
+u8 d4_rbc_2_d3_rbc[][2] = {
+       {10, 0},
+       {11, 2},
+       {12, 23},
+       {13, 1},
+       {14, 28},
+       {15, 24},
+       {16, 27},
+       {17, 7},
+       {18, 6},
+       {19, 25},
+       {20, 26},
+       {21, 3}
+};
+
+u32 addrmap[29][9] = {
+       {24, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
+               0x08080808, 0x00000f0f, 0x3f3f}, /* 0 */
+       {23, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
+               0x07070707, 0x00000f0f, 0x3f3f}, /* 1 */
+       {23, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
+               0x0f080808, 0x00000f0f, 0x3f3f}, /* 2 */
+       {22, 0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x06060606,
+               0x06060606, 0x00000f0f, 0x3f3f}, /* 3 */
+       {24, 0x000a0a0a, 0x00000000, 0x00000000, 0x00000000, 0x09090909,
+               0x0f090909, 0x00000f0f, 0x3f3f}, /* 4 */
+       {6, 0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x07070707,
+               0x07070707, 0x00000f0f, 0x3f3f}, /* 5 */
+       {7, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x08080808,
+               0x08080808, 0x00000f0f, 0x3f3f}, /* 6 */
+       {8, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x09090909,
+               0x0f090909, 0x00000f0f, 0x3f3f}, /* 7 */
+       {22, 0x001f0808, 0x00000000, 0x00000000, 0x00001f1f, 0x06060606,
+               0x06060606, 0x00000f0f, 0x3f3f}, /* 8 */
+       {23, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
+               0x0f070707, 0x00000f0f, 0x3f3f}, /* 9 */
+
+       {24, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
+               0x08080808, 0x00000f0f, 0x0801}, /* 10 */
+       {23, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
+               0x0f080808, 0x00000f0f, 0x0801}, /* 11 */
+       {24, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
+               0x07070707, 0x00000f07, 0x0700}, /* 12 */
+       {23, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
+               0x07070707, 0x00000f0f, 0x0700}, /* 13 */
+       {24, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
+               0x07070707, 0x00000f07, 0x3f01}, /* 14 */
+       {23, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
+               0x07070707, 0x00000f0f, 0x3f01}, /* 15 */
+       {23, 0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x06060606,
+               0x06060606, 0x00000f06, 0x3f00}, /* 16 */
+       {8, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x09090909,
+               0x0f090909, 0x00000f0f, 0x0801}, /* 17 */
+       {7, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x08080808,
+               0x08080808, 0x00000f0f, 0x0700}, /* 18 */
+       {7, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
+               0x08080808, 0x00000f0f, 0x3f01}, /* 19 */
+
+       {6, 0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
+               0x07070707, 0x00000f07, 0x3f00}, /* 20 */
+       {23, 0x003f0909, 0x00000006, 0x1f1f0000, 0x00001f1f, 0x06060606,
+               0x06060606, 0x00000f06, 0x0600}, /* 21 */
+       {21, 0x00060606, 0x00000000, 0x1f1f0000, 0x00001f1f, 0x05050505,
+               0x05050505, 0x00000f0f, 0x3f3f}, /* 22 */
+
+       {24, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
+               0x07070707, 0x00000f07, 0x3f3f}, /* 23 */
+       {23, 0x003f0909, 0x00000000, 0x00000000, 0x00001f00, 0x07070707,
+               0x07070707, 0x00000f0f, 0x3f3f}, /* 24 */
+       {7, 0x003f0909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
+               0x08080808, 0x00000f0f, 0x3f3f}, /* 25 */
+       {6, 0x003f0808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
+               0x07070707, 0x00000f07, 0x3f3f}, /* 26 */
+       {23, 0x003f0808, 0x00000000, 0x00000000, 0x00001f1f, 0x06060606,
+               0x06060606, 0x00000f06, 0x3f3f}, /* 27 */
+       {24, 0x003f0909, 0x00000000, 0x00000000, 0x00001f00, 0x07070707,
+               0x07070707, 0x00000f07, 0x3f3f} /* 28 */
+};
+
+static u8 dq_sel[22][3] = {
+       {0x0, 0x17, 0x22},
+       {0x1, 0x18, 0x23},
+       {0x2, 0x19, 0x24},
+       {0x3, 0x1a, 0x25},
+       {0x4, 0x1b, 0x26},
+       {0x5, 0x1c, 0x27},
+       {0x6, 0x1d, 0x28},
+       {0x7, 0x1e, 0x29},
+       {0x8, 0x16, 0x21},
+       {0x9, 0x1f, 0x2a},
+       {0xa, 0x20, 0x2b},
+       {0x10, 0x1, 0xc},
+       {0x11, 0x2, 0xd},
+       {0x12, 0x3, 0xe},
+       {0x13, 0x4, 0xf},
+       {0x14, 0x5, 0x10},
+       {0x15, 0x6, 0x11},
+       {0x16, 0x7, 0x12},
+       {0x17, 0x8, 0x13},
+       {0x18, 0x0, 0xb},
+       {0x19, 0x9, 0x14},
+       {0x1a, 0xa, 0x15}
+};
+
+static u16 grp_addr[4] = {
+       ADD_GROUP_CS0_A,
+       ADD_GROUP_CS0_B,
+       ADD_GROUP_CS1_A,
+       ADD_GROUP_CS1_B
+};
+
+static u8 wrlvl_result_offset[2][4] = {
+       {0xa0 + 0x26, 0xa0 + 0x27, 0xd0 + 0x26, 0xd0 + 0x27},
+       {0xa0 + 0x28, 0xa0 + 0x29, 0xd0 + 0x28, 0xd0 + 0x29},
+};
+
+static u16 dqs_dq_skew_adr[16] = {
+       0x170 + 0,      /* SKEW_UPDATE_RX_CS0_DQS0 */
+       0x170 + 0xb,    /* SKEW_UPDATE_RX_CS0_DQS1 */
+       0x1d0 + 0,      /* SKEW_UPDATE_RX_CS0_DQS2 */
+       0x1d0 + 0xb,    /* SKEW_UPDATE_RX_CS0_DQS3 */
+       0x1a0 + 0,      /* SKEW_UPDATE_RX_CS1_DQS0 */
+       0x1a0 + 0xb,    /* SKEW_UPDATE_RX_CS1_DQS1 */
+       0x200 + 0,      /* SKEW_UPDATE_RX_CS1_DQS2 */
+       0x200 + 0xb,    /* SKEW_UPDATE_RX_CS1_DQS3 */
+       0x170 + 0x16,   /* SKEW_UPDATE_TX_CS0_DQS0 */
+       0x170 + 0x21,   /* SKEW_UPDATE_TX_CS0_DQS1 */
+       0x1d0 + 0x16,   /* SKEW_UPDATE_TX_CS0_DQS2 */
+       0x1d0 + 0x21,   /* SKEW_UPDATE_TX_CS0_DQS3 */
+       0x1a0 + 0x16,   /* SKEW_UPDATE_TX_CS1_DQS0 */
+       0x1a0 + 0x21,   /* SKEW_UPDATE_TX_CS1_DQS1 */
+       0x200 + 0x16,   /* SKEW_UPDATE_TX_CS1_DQS2 */
+       0x200 + 0x21,   /* SKEW_UPDATE_TX_CS1_DQS3 */
+};
+
+static void rkclk_ddr_reset(struct dram_info *dram,
+                           u32 ctl_srstn, u32 ctl_psrstn,
+                           u32 phy_srstn, u32 phy_psrstn)
+{
+       writel(UPCTL2_SRSTN_REQ(ctl_srstn) | UPCTL2_PSRSTN_REQ(ctl_psrstn) |
+              UPCTL2_ASRSTN_REQ(ctl_srstn),
+              BUS_SGRF_BASE_ADDR + SGRF_SOC_CON13);
+
+       writel(DDRPHY_SRSTN_REQ(phy_srstn) | DDRPHY_PSRSTN_REQ(phy_psrstn),
+              &dram->cru->softrst_con[12]);
+}
+
+static void rkclk_set_dpll(struct dram_info *dram, unsigned int hz)
+{
+       unsigned int refdiv, postdiv1, postdiv2, fbdiv;
+       int delay = 1000;
+       u32 mhz = hz / MHz;
+       struct global_info *gbl_info;
+       struct sdram_head_info_index_v2 *index =
+               (struct sdram_head_info_index_v2 *)common_info;
+       u32 ssmod_info;
+       u32 dsmpd = 1;
+
+       gbl_info = (struct global_info *)((void *)common_info +
+                   index->global_index.offset * 4);
+       ssmod_info = gbl_info->info_2t;
+       refdiv = 1;
+       if (mhz <= 100) {
+               postdiv1 = 6;
+               postdiv2 = 4;
+       } else if (mhz <= 150) {
+               postdiv1 = 4;
+               postdiv2 = 4;
+       } else if (mhz <= 200) {
+               postdiv1 = 6;
+               postdiv2 = 2;
+       } else if (mhz <= 300) {
+               postdiv1 = 4;
+               postdiv2 = 2;
+       } else if (mhz <= 400) {
+               postdiv1 = 6;
+               postdiv2 = 1;
+       } else {
+               postdiv1 = 4;
+               postdiv2 = 1;
+       }
+       fbdiv = (mhz * refdiv * postdiv1 * postdiv2) / 24;
+
+       writel(DPLL_MODE(CLOCK_FROM_XIN_OSC), &dram->cru->mode);
+
+       writel(0x1f000000, &dram->cru->clksel_con[64]);
+       writel(POSTDIV1(postdiv1) | FBDIV(fbdiv), &dram->cru->pll[1].con0);
+       /* enable ssmod */
+       if (PLL_SSMOD_SPREAD(ssmod_info)) {
+               dsmpd = 0;
+               clrsetbits_le32(&dram->cru->pll[1].con2,
+                               0xffffff << 0, 0x0 << 0);
+               writel(SSMOD_SPREAD(PLL_SSMOD_SPREAD(ssmod_info)) |
+                      SSMOD_DIVVAL(PLL_SSMOD_DIV(ssmod_info)) |
+                      SSMOD_DOWNSPREAD(PLL_SSMOD_DOWNSPREAD(ssmod_info)) |
+                      SSMOD_RESET(0) |
+                      SSMOD_DIS_SSCG(0) |
+                      SSMOD_BP(0),
+                      &dram->cru->pll[1].con3);
+       }
+       writel(DSMPD(dsmpd) | POSTDIV2(postdiv2) | REFDIV(refdiv),
+              &dram->cru->pll[1].con1);
+
+       while (delay > 0) {
+               udelay(1);
+               if (LOCK(readl(&dram->cru->pll[1].con1)))
+                       break;
+               delay--;
+       }
+
+       writel(DPLL_MODE(CLOCK_FROM_PLL), &dram->cru->mode);
+}
+
+static void rkclk_configure_ddr(struct dram_info *dram,
+                               struct rv1126_sdram_params *sdram_params)
+{
+       /* for inno ddr phy need freq / 2 */
+       rkclk_set_dpll(dram, sdram_params->base.ddr_freq * MHZ / 2);
+}
+
+static unsigned int
+       calculate_ddrconfig(struct rv1126_sdram_params *sdram_params)
+{
+       struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+       u32 cs, bw, die_bw, col, row, bank;
+       u32 cs1_row;
+       u32 i, tmp;
+       u32 ddrconf = -1;
+       u32 row_3_4;
+
+       cs = cap_info->rank;
+       bw = cap_info->bw;
+       die_bw = cap_info->dbw;
+       col = cap_info->col;
+       row = cap_info->cs0_row;
+       cs1_row = cap_info->cs1_row;
+       bank = cap_info->bk;
+       row_3_4 = cap_info->row_3_4;
+
+       if (sdram_params->base.dramtype == DDR4) {
+               if (cs == 2 && row == cs1_row && !row_3_4) {
+                       tmp = ((row - 13) << 4) | (1 << 3) | (bw << 1) |
+                             die_bw;
+                       for (i = 17; i < 21; i++) {
+                               if (((tmp & 0xf) ==
+                                    (ddr4_cfg_2_rbc[i - 10] & 0xf)) &&
+                                   ((tmp & 0x70) <=
+                                    (ddr4_cfg_2_rbc[i - 10] & 0x70))) {
+                                       ddrconf = i;
+                                       goto out;
+                               }
+                       }
+               }
+
+               tmp = ((cs - 1) << 7) | ((row - 13) << 4) | (bw << 1) | die_bw;
+               for (i = 10; i < 21; i++) {
+                       if (((tmp & 0xf) == (ddr4_cfg_2_rbc[i - 10] & 0xf)) &&
+                           ((tmp & 0x70) <= (ddr4_cfg_2_rbc[i - 10] & 0x70)) &&
+                           ((tmp & 0x80) <= (ddr4_cfg_2_rbc[i - 10] & 0x80))) {
+                               ddrconf = i;
+                               goto out;
+                       }
+               }
+       } else {
+               if (cs == 2 && row == cs1_row && bank == 3) {
+                       for (i = 5; i < 8; i++) {
+                               if (((bw + col - 10) == (ddr_cfg_2_rbc[i] &
+                                                        0x7)) &&
+                                   ((row - 13) << 5) <= (ddr_cfg_2_rbc[i] &
+                                                         (0x7 << 5))) {
+                                       ddrconf = i;
+                                       goto out;
+                               }
+                       }
+               }
+
+               tmp = ((cs - 1) << 8) | ((row - 13) << 5) |
+                     ((bw + col - 10) << 0);
+               if (bank == 3)
+                       tmp |= (1 << 3);
+
+               for (i = 0; i < 9; i++)
+                       if (((tmp & 0x1f) == (ddr_cfg_2_rbc[i] & 0x1f)) &&
+                           ((tmp & (7 << 5)) <=
+                            (ddr_cfg_2_rbc[i] & (7 << 5))) &&
+                           ((tmp & (1 << 8)) <=
+                            (ddr_cfg_2_rbc[i] & (1 << 8)))) {
+                               ddrconf = i;
+                               goto out;
+                       }
+
+               for (i = 0; i < 7; i++)
+                       if (((tmp & 0x1f) == (ddr_cfg_2_rbc_p2[i] & 0x1f)) &&
+                           ((tmp & (7 << 5)) <=
+                            (ddr_cfg_2_rbc_p2[i] & (7 << 5))) &&
+                           ((tmp & (1 << 8)) <=
+                            (ddr_cfg_2_rbc_p2[i] & (1 << 8)))) {
+                               ddrconf = i + 22;
+                               goto out;
+                       }
+
+               if (cs == 1 && bank == 3 && row <= 17 &&
+                   (col + bw) == 12)
+                       ddrconf = 23;
+       }
+
+out:
+       if (ddrconf > 28)
+               printascii("calculate ddrconfig error\n");
+
+       if (sdram_params->base.dramtype == DDR4) {
+               for (i = 0; i < ARRAY_SIZE(d4_rbc_2_d3_rbc) ; i++) {
+                       if (ddrconf == d4_rbc_2_d3_rbc[i][0]) {
+                               if (ddrconf == 21 && row > 16)
+                                       printascii("warn:ddrconf21 row > 16\n");
+                               else
+                                       ddrconf = d4_rbc_2_d3_rbc[i][1];
+                               break;
+                       }
+               }
+       }
+
+       return ddrconf;
+}
+
+static void sw_set_req(struct dram_info *dram)
+{
+       void __iomem *pctl_base = dram->pctl;
+
+       /* clear sw_done=0 */
+       writel(PCTL2_SW_DONE_CLEAR, pctl_base + DDR_PCTL2_SWCTL);
+}
+
+static void sw_set_ack(struct dram_info *dram)
+{
+       void __iomem *pctl_base = dram->pctl;
+
+       /* set sw_done=1 */
+       writel(PCTL2_SW_DONE, pctl_base + DDR_PCTL2_SWCTL);
+       while (1) {
+               /* wait programming done */
+               if (readl(pctl_base + DDR_PCTL2_SWSTAT) &
+                               PCTL2_SW_DONE_ACK)
+                       break;
+       }
+}
+
+static void set_ctl_address_map(struct dram_info *dram,
+                               struct rv1126_sdram_params *sdram_params)
+{
+       struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+       void __iomem *pctl_base = dram->pctl;
+       u32 ddrconf = cap_info->ddrconfig;
+       u32 i, row;
+
+       row = cap_info->cs0_row;
+       if (sdram_params->base.dramtype == DDR4) {
+               for (i = 0; i < ARRAY_SIZE(d4_rbc_2_d3_rbc) ; i++) {
+                       if (ddrconf == d4_rbc_2_d3_rbc[i][1]) {
+                               ddrconf = d4_rbc_2_d3_rbc[i][0];
+                               break;
+                       }
+               }
+       }
+
+       if (ddrconf >= ARRAY_SIZE(addrmap)) {
+               printascii("set ctl address map fail\n");
+               return;
+       }
+
+       sdram_copy_to_reg((u32 *)(pctl_base + DDR_PCTL2_ADDRMAP0),
+                         &addrmap[ddrconf][0], ARRAY_SIZE(addrmap[ddrconf]) * 4);
+
+       /* unused row set to 0xf */
+       for (i = 17; i >= row; i--)
+               setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6 +
+                       ((i - 12) * 8 / 32) * 4,
+                       0xf << ((i - 12) * 8 % 32));
+
+       if (sdram_params->base.dramtype == LPDDR3 && cap_info->row_3_4)
+               setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6, 1 << 31);
+       if (sdram_params->base.dramtype == DDR4 && cap_info->bw == 0x1)
+               setbits_le32(pctl_base + DDR_PCTL2_PCCFG, 1 << 8);
+
+       if (cap_info->rank == 1)
+               clrsetbits_le32(pctl_base + DDR_PCTL2_ADDRMAP0, 0x1f, 0x1f);
+}
+
+static void phy_pll_set(struct dram_info *dram, u32 freq, u32 wait)
+{
+       void __iomem *phy_base = dram->phy;
+       u32 fbdiv, prediv, postdiv, postdiv_en;
+
+       if (wait) {
+               clrbits_le32(PHY_REG(phy_base, 0x53), PHY_PD_DISB);
+               while (!(readl(PHY_REG(phy_base, 0x90)) & PHY_PLL_LOCK))
+                       continue;
+       } else {
+               freq /= MHz;
+               prediv = 1;
+               if (freq <= 200) {
+                       fbdiv = 16;
+                       postdiv = 2;
+                       postdiv_en = 1;
+               } else if (freq <= 456) {
+                       fbdiv = 8;
+                       postdiv = 1;
+                       postdiv_en = 1;
+               } else {
+                       fbdiv = 4;
+                       postdiv = 0;
+                       postdiv_en = 0;
+               }
+               writel(fbdiv & 0xff, PHY_REG(phy_base, 0x50));
+               clrsetbits_le32(PHY_REG(phy_base, 0x51), PHY_PBDIV_BIT9_MASK,
+                               (fbdiv >> 8) & 1);
+               clrsetbits_le32(PHY_REG(phy_base, 0x51), PHY_POSTDIV_EN_MASK,
+                               postdiv_en << PHY_POSTDIV_EN_SHIFT);
+
+               clrsetbits_le32(PHY_REG(phy_base, 0x52),
+                               PHY_PREDIV_MASK << PHY_PREDIV_SHIFT, prediv);
+               clrsetbits_le32(PHY_REG(phy_base, 0x53),
+                               PHY_POSTDIV_MASK << PHY_POSTDIV_SHIFT,
+                               postdiv << PHY_POSTDIV_SHIFT);
+       }
+}
+
+static const u16 d3_phy_drv_2_ohm[][2] = {
+       {PHY_DDR3_RON_455ohm, 455},
+       {PHY_DDR3_RON_230ohm, 230},
+       {PHY_DDR3_RON_153ohm, 153},
+       {PHY_DDR3_RON_115ohm, 115},
+       {PHY_DDR3_RON_91ohm, 91},
+       {PHY_DDR3_RON_76ohm, 76},
+       {PHY_DDR3_RON_65ohm, 65},
+       {PHY_DDR3_RON_57ohm, 57},
+       {PHY_DDR3_RON_51ohm, 51},
+       {PHY_DDR3_RON_46ohm, 46},
+       {PHY_DDR3_RON_41ohm, 41},
+       {PHY_DDR3_RON_38ohm, 38},
+       {PHY_DDR3_RON_35ohm, 35},
+       {PHY_DDR3_RON_32ohm, 32},
+       {PHY_DDR3_RON_30ohm, 30},
+       {PHY_DDR3_RON_28ohm, 28},
+       {PHY_DDR3_RON_27ohm, 27},
+       {PHY_DDR3_RON_25ohm, 25},
+       {PHY_DDR3_RON_24ohm, 24},
+       {PHY_DDR3_RON_23ohm, 23},
+       {PHY_DDR3_RON_22ohm, 22},
+       {PHY_DDR3_RON_21ohm, 21},
+       {PHY_DDR3_RON_20ohm, 20}
+};
+
+static u16 d3_phy_odt_2_ohm[][2] = {
+       {PHY_DDR3_RTT_DISABLE, 0},
+       {PHY_DDR3_RTT_561ohm, 561},
+       {PHY_DDR3_RTT_282ohm, 282},
+       {PHY_DDR3_RTT_188ohm, 188},
+       {PHY_DDR3_RTT_141ohm, 141},
+       {PHY_DDR3_RTT_113ohm, 113},
+       {PHY_DDR3_RTT_94ohm, 94},
+       {PHY_DDR3_RTT_81ohm, 81},
+       {PHY_DDR3_RTT_72ohm, 72},
+       {PHY_DDR3_RTT_64ohm, 64},
+       {PHY_DDR3_RTT_58ohm, 58},
+       {PHY_DDR3_RTT_52ohm, 52},
+       {PHY_DDR3_RTT_48ohm, 48},
+       {PHY_DDR3_RTT_44ohm, 44},
+       {PHY_DDR3_RTT_41ohm, 41},
+       {PHY_DDR3_RTT_38ohm, 38},
+       {PHY_DDR3_RTT_37ohm, 37},
+       {PHY_DDR3_RTT_34ohm, 34},
+       {PHY_DDR3_RTT_32ohm, 32},
+       {PHY_DDR3_RTT_31ohm, 31},
+       {PHY_DDR3_RTT_29ohm, 29},
+       {PHY_DDR3_RTT_28ohm, 28},
+       {PHY_DDR3_RTT_27ohm, 27},
+       {PHY_DDR3_RTT_25ohm, 25}
+};
+
+static u16 d4lp3_phy_drv_2_ohm[][2] = {
+       {PHY_DDR4_LPDDR3_RON_482ohm, 482},
+       {PHY_DDR4_LPDDR3_RON_244ohm, 244},
+       {PHY_DDR4_LPDDR3_RON_162ohm, 162},
+       {PHY_DDR4_LPDDR3_RON_122ohm, 122},
+       {PHY_DDR4_LPDDR3_RON_97ohm, 97},
+       {PHY_DDR4_LPDDR3_RON_81ohm, 81},
+       {PHY_DDR4_LPDDR3_RON_69ohm, 69},
+       {PHY_DDR4_LPDDR3_RON_61ohm, 61},
+       {PHY_DDR4_LPDDR3_RON_54ohm, 54},
+       {PHY_DDR4_LPDDR3_RON_48ohm, 48},
+       {PHY_DDR4_LPDDR3_RON_44ohm, 44},
+       {PHY_DDR4_LPDDR3_RON_40ohm, 40},
+       {PHY_DDR4_LPDDR3_RON_37ohm, 37},
+       {PHY_DDR4_LPDDR3_RON_34ohm, 34},
+       {PHY_DDR4_LPDDR3_RON_32ohm, 32},
+       {PHY_DDR4_LPDDR3_RON_30ohm, 30},
+       {PHY_DDR4_LPDDR3_RON_28ohm, 28},
+       {PHY_DDR4_LPDDR3_RON_27ohm, 27},
+       {PHY_DDR4_LPDDR3_RON_25ohm, 25},
+       {PHY_DDR4_LPDDR3_RON_24ohm, 24},
+       {PHY_DDR4_LPDDR3_RON_23ohm, 23},
+       {PHY_DDR4_LPDDR3_RON_22ohm, 22},
+       {PHY_DDR4_LPDDR3_RON_21ohm, 21}
+};
+
+static u16 d4lp3_phy_odt_2_ohm[][2] = {
+       {PHY_DDR4_LPDDR3_RTT_DISABLE, 0},
+       {PHY_DDR4_LPDDR3_RTT_586ohm, 586},
+       {PHY_DDR4_LPDDR3_RTT_294ohm, 294},
+       {PHY_DDR4_LPDDR3_RTT_196ohm, 196},
+       {PHY_DDR4_LPDDR3_RTT_148ohm, 148},
+       {PHY_DDR4_LPDDR3_RTT_118ohm, 118},
+       {PHY_DDR4_LPDDR3_RTT_99ohm, 99},
+       {PHY_DDR4_LPDDR3_RTT_85ohm, 58},
+       {PHY_DDR4_LPDDR3_RTT_76ohm, 76},
+       {PHY_DDR4_LPDDR3_RTT_67ohm, 67},
+       {PHY_DDR4_LPDDR3_RTT_60ohm, 60},
+       {PHY_DDR4_LPDDR3_RTT_55ohm, 55},
+       {PHY_DDR4_LPDDR3_RTT_50ohm, 50},
+       {PHY_DDR4_LPDDR3_RTT_46ohm, 46},
+       {PHY_DDR4_LPDDR3_RTT_43ohm, 43},
+       {PHY_DDR4_LPDDR3_RTT_40ohm, 40},
+       {PHY_DDR4_LPDDR3_RTT_38ohm, 38},
+       {PHY_DDR4_LPDDR3_RTT_36ohm, 36},
+       {PHY_DDR4_LPDDR3_RTT_34ohm, 34},
+       {PHY_DDR4_LPDDR3_RTT_32ohm, 32},
+       {PHY_DDR4_LPDDR3_RTT_31ohm, 31},
+       {PHY_DDR4_LPDDR3_RTT_29ohm, 29},
+       {PHY_DDR4_LPDDR3_RTT_28ohm, 28},
+       {PHY_DDR4_LPDDR3_RTT_27ohm, 27}
+};
+
+static u16 lp4_phy_drv_2_ohm[][2] = {
+       {PHY_LPDDR4_RON_501ohm, 501},
+       {PHY_LPDDR4_RON_253ohm, 253},
+       {PHY_LPDDR4_RON_168ohm, 168},
+       {PHY_LPDDR4_RON_126ohm, 126},
+       {PHY_LPDDR4_RON_101ohm, 101},
+       {PHY_LPDDR4_RON_84ohm, 84},
+       {PHY_LPDDR4_RON_72ohm, 72},
+       {PHY_LPDDR4_RON_63ohm, 63},
+       {PHY_LPDDR4_RON_56ohm, 56},
+       {PHY_LPDDR4_RON_50ohm, 50},
+       {PHY_LPDDR4_RON_46ohm, 46},
+       {PHY_LPDDR4_RON_42ohm, 42},
+       {PHY_LPDDR4_RON_38ohm, 38},
+       {PHY_LPDDR4_RON_36ohm, 36},
+       {PHY_LPDDR4_RON_33ohm, 33},
+       {PHY_LPDDR4_RON_31ohm, 31},
+       {PHY_LPDDR4_RON_29ohm, 29},
+       {PHY_LPDDR4_RON_28ohm, 28},
+       {PHY_LPDDR4_RON_26ohm, 26},
+       {PHY_LPDDR4_RON_25ohm, 25},
+       {PHY_LPDDR4_RON_24ohm, 24},
+       {PHY_LPDDR4_RON_23ohm, 23},
+       {PHY_LPDDR4_RON_22ohm, 22}
+};
+
+static u16 lp4_phy_odt_2_ohm[][2] = {
+       {PHY_LPDDR4_RTT_DISABLE, 0},
+       {PHY_LPDDR4_RTT_604ohm, 604},
+       {PHY_LPDDR4_RTT_303ohm, 303},
+       {PHY_LPDDR4_RTT_202ohm, 202},
+       {PHY_LPDDR4_RTT_152ohm, 152},
+       {PHY_LPDDR4_RTT_122ohm, 122},
+       {PHY_LPDDR4_RTT_101ohm, 101},
+       {PHY_LPDDR4_RTT_87ohm,  87},
+       {PHY_LPDDR4_RTT_78ohm, 78},
+       {PHY_LPDDR4_RTT_69ohm, 69},
+       {PHY_LPDDR4_RTT_62ohm, 62},
+       {PHY_LPDDR4_RTT_56ohm, 56},
+       {PHY_LPDDR4_RTT_52ohm, 52},
+       {PHY_LPDDR4_RTT_48ohm, 48},
+       {PHY_LPDDR4_RTT_44ohm, 44},
+       {PHY_LPDDR4_RTT_41ohm, 41},
+       {PHY_LPDDR4_RTT_39ohm, 39},
+       {PHY_LPDDR4_RTT_37ohm, 37},
+       {PHY_LPDDR4_RTT_35ohm, 35},
+       {PHY_LPDDR4_RTT_33ohm, 33},
+       {PHY_LPDDR4_RTT_32ohm, 32},
+       {PHY_LPDDR4_RTT_30ohm, 30},
+       {PHY_LPDDR4_RTT_29ohm, 29},
+       {PHY_LPDDR4_RTT_27ohm, 27}
+};
+
+static u32 lp4_odt_calc(u32 odt_ohm)
+{
+       u32 odt;
+
+       if (odt_ohm == 0)
+               odt = LPDDR4_DQODT_DIS;
+       else if (odt_ohm <= 40)
+               odt = LPDDR4_DQODT_40;
+       else if (odt_ohm <= 48)
+               odt = LPDDR4_DQODT_48;
+       else if (odt_ohm <= 60)
+               odt = LPDDR4_DQODT_60;
+       else if (odt_ohm <= 80)
+               odt = LPDDR4_DQODT_80;
+       else if (odt_ohm <= 120)
+               odt = LPDDR4_DQODT_120;
+       else
+               odt = LPDDR4_DQODT_240;
+
+       return odt;
+}
+
+static void *get_ddr_drv_odt_info(u32 dramtype)
+{
+       struct sdram_head_info_index_v2 *index =
+               (struct sdram_head_info_index_v2 *)common_info;
+       void *ddr_info = 0;
+
+       if (dramtype == DDR4)
+               ddr_info = (void *)common_info + index->ddr4_index.offset * 4;
+       else if (dramtype == DDR3)
+               ddr_info = (void *)common_info + index->ddr3_index.offset * 4;
+       else if (dramtype == LPDDR3)
+               ddr_info = (void *)common_info + index->lp3_index.offset * 4;
+       else if (dramtype == LPDDR4)
+               ddr_info = (void *)common_info + index->lp4_index.offset * 4;
+       else
+               printascii("unsupported dram type\n");
+       return ddr_info;
+}
+
+static void set_lp4_vref(struct dram_info *dram, struct lp4_info *lp4_info,
+                        u32 freq_mhz, u32 dst_fsp, u32 dramtype)
+{
+       void __iomem *pctl_base = dram->pctl;
+       u32 ca_vref, dq_vref;
+
+       if (freq_mhz <= LP4_CA_ODT_EN_FREQ(lp4_info->ca_odten_freq))
+               ca_vref = LP4_CA_VREF(lp4_info->vref_when_odtoff);
+       else
+               ca_vref = LP4_CA_VREF(lp4_info->vref_when_odten);
+
+       if (freq_mhz <= LP4_DQ_ODT_EN_FREQ(lp4_info->dq_odten_freq))
+               dq_vref = LP4_DQ_VREF(lp4_info->vref_when_odtoff);
+       else
+               dq_vref = LP4_DQ_VREF(lp4_info->vref_when_odten);
+
+       if (dramtype == LPDDR4) {
+               if (ca_vref < 100)
+                       ca_vref = 100;
+               if (ca_vref > 420)
+                       ca_vref = 420;
+
+               if (ca_vref <= 300)
+                       ca_vref = (0 << 6) | (ca_vref - 100) / 4;
+               else
+                       ca_vref = (1 << 6) | (ca_vref - 220) / 4;
+
+               if (dq_vref < 100)
+                       dq_vref = 100;
+               if (dq_vref > 420)
+                       dq_vref = 420;
+
+               if (dq_vref <= 300)
+                       dq_vref = (0 << 6) | (dq_vref - 100) / 4;
+               else
+                       dq_vref = (1 << 6) | (dq_vref - 220) / 4;
+       } else {
+               ca_vref = ca_vref * 11 / 6;
+               if (ca_vref < 150)
+                       ca_vref = 150;
+               if (ca_vref > 629)
+                       ca_vref = 629;
+
+               if (ca_vref <= 449)
+                       ca_vref = (0 << 6) | (ca_vref - 150) / 4;
+               else
+                       ca_vref = (1 << 6) | (ca_vref - 329) / 4;
+
+               if (dq_vref < 150)
+                       dq_vref = 150;
+               if (dq_vref > 629)
+                       dq_vref = 629;
+
+               if (dq_vref <= 449)
+                       dq_vref = (0 << 6) | (dq_vref - 150) / 6;
+               else
+                       dq_vref = (1 << 6) | (dq_vref - 329) / 6;
+       }
+       sw_set_req(dram);
+       clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                       DDR_PCTL2_INIT6,
+                       PCTL2_MR_MASK << PCTL2_LPDDR4_MR12_SHIFT,
+                       ca_vref << PCTL2_LPDDR4_MR12_SHIFT);
+
+       clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                       DDR_PCTL2_INIT7,
+                       PCTL2_MR_MASK << PCTL2_LPDDR4_MR14_SHIFT,
+                       dq_vref << PCTL2_LPDDR4_MR14_SHIFT);
+       sw_set_ack(dram);
+}
+
+static void set_ds_odt(struct dram_info *dram,
+                      struct rv1126_sdram_params *sdram_params, u32 dst_fsp)
+{
+       void __iomem *phy_base = dram->phy;
+       void __iomem *pctl_base = dram->pctl;
+       u32 dramtype = sdram_params->base.dramtype;
+       struct ddr2_3_4_lp2_3_info *ddr_info;
+       struct lp4_info *lp4_info;
+       u32 i, j, tmp;
+       const u16 (*p_drv)[2];
+       const u16 (*p_odt)[2];
+       u32 drv_info, sr_info;
+       u32 phy_dq_drv_ohm, phy_clk_drv_ohm, phy_ca_drv_ohm, dram_drv_ohm;
+       u32 phy_odt_ohm, dram_odt_ohm;
+       u32 lp4_pu_cal, phy_lp4_drv_pd_en;
+       u32 phy_odt_up_en, phy_odt_dn_en;
+       u32 sr_dq, sr_clk;
+       u32 freq = sdram_params->base.ddr_freq;
+       u32 mr1_mr3, mr11, mr22, vref_out, vref_inner;
+       u32 phy_clk_drv = 0, phy_odt = 0, phy_ca_drv = 0, dram_caodt_ohm = 0;
+       u32 phy_dq_drv = 0;
+       u32 phy_odt_up = 0, phy_odt_dn = 0;
+
+       ddr_info = get_ddr_drv_odt_info(dramtype);
+       lp4_info = (void *)ddr_info;
+
+       if (!ddr_info)
+               return;
+
+       /* dram odt en freq control phy drv, dram odt and phy sr */
+       if (freq <= DRAMODT_EN_FREQ(ddr_info->odten_freq)) {
+               drv_info = ddr_info->drv_when_odtoff;
+               dram_odt_ohm = 0;
+               sr_info = ddr_info->sr_when_odtoff;
+               phy_lp4_drv_pd_en =
+                       PHY_LP4_DRV_PULLDOWN_EN_ODTOFF(lp4_info->odt_info);
+       } else {
+               drv_info = ddr_info->drv_when_odten;
+               dram_odt_ohm = ODT_INFO_DRAM_ODT(ddr_info->odt_info);
+               sr_info = ddr_info->sr_when_odten;
+               phy_lp4_drv_pd_en =
+                       PHY_LP4_DRV_PULLDOWN_EN_ODTEN(lp4_info->odt_info);
+       }
+       phy_dq_drv_ohm =
+               DRV_INFO_PHY_DQ_DRV(drv_info);
+       phy_clk_drv_ohm =
+               DRV_INFO_PHY_CLK_DRV(drv_info);
+       phy_ca_drv_ohm =
+               DRV_INFO_PHY_CA_DRV(drv_info);
+
+       sr_dq = DQ_SR_INFO(sr_info);
+       sr_clk = CLK_SR_INFO(sr_info);
+
+       /* phy odt en freq control dram drv and phy odt */
+       if (freq <= PHYODT_EN_FREQ(ddr_info->odten_freq)) {
+               dram_drv_ohm = DRV_INFO_DRAM_DQ_DRV(ddr_info->drv_when_odtoff);
+               lp4_pu_cal = LP4_DRV_PU_CAL_ODTOFF(lp4_info->odt_info);
+               phy_odt_ohm = 0;
+               phy_odt_up_en = 0;
+               phy_odt_dn_en = 0;
+       } else {
+               dram_drv_ohm =
+                       DRV_INFO_DRAM_DQ_DRV(ddr_info->drv_when_odten);
+               phy_odt_ohm = ODT_INFO_PHY_ODT(ddr_info->odt_info);
+               phy_odt_up_en =
+                       ODT_INFO_PULLUP_EN(ddr_info->odt_info);
+               phy_odt_dn_en =
+                       ODT_INFO_PULLDOWN_EN(ddr_info->odt_info);
+               lp4_pu_cal = LP4_DRV_PU_CAL_ODTEN(lp4_info->odt_info);
+       }
+
+       if (dramtype == LPDDR4) {
+               if (phy_odt_ohm) {
+                       phy_odt_up_en = 0;
+                       phy_odt_dn_en = 1;
+               }
+               if (freq <= LP4_CA_ODT_EN_FREQ(lp4_info->ca_odten_freq))
+                       dram_caodt_ohm = 0;
+               else
+                       dram_caodt_ohm =
+                               ODT_INFO_LP4_CA_ODT(lp4_info->odt_info);
+       }
+
+       if (dramtype == DDR3) {
+               p_drv = d3_phy_drv_2_ohm;
+               p_odt = d3_phy_odt_2_ohm;
+       } else if (dramtype == LPDDR4) {
+               p_drv = lp4_phy_drv_2_ohm;
+               p_odt = lp4_phy_odt_2_ohm;
+       } else {
+               p_drv = d4lp3_phy_drv_2_ohm;
+               p_odt = d4lp3_phy_odt_2_ohm;
+       }
+
+       for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
+               if (phy_dq_drv_ohm <= *(*(p_drv + i) + 1)) {
+                       phy_dq_drv = **(p_drv + i);
+                       break;
+               }
+               if (i == 0)
+                       break;
+       }
+       for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
+               if (phy_clk_drv_ohm <= *(*(p_drv + i) + 1)) {
+                       phy_clk_drv = **(p_drv + i);
+                       break;
+               }
+               if (i == 0)
+                       break;
+       }
+       for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
+               if (phy_ca_drv_ohm <= *(*(p_drv + i) + 1)) {
+                       phy_ca_drv = **(p_drv + i);
+                       break;
+               }
+               if (i == 0)
+                       break;
+       }
+       if (!phy_odt_ohm)
+               phy_odt = 0;
+       else
+               for (i = ARRAY_SIZE(d4lp3_phy_odt_2_ohm) - 1; ; i--) {
+                       if (phy_odt_ohm <= *(*(p_odt + i) + 1)) {
+                               phy_odt = **(p_odt + i);
+                               break;
+                       }
+                       if (i == 0)
+                               break;
+               }
+
+       if (dramtype != LPDDR4) {
+               if (!phy_odt_ohm || (phy_odt_up_en && phy_odt_dn_en))
+                       vref_inner = 0x80;
+               else if (phy_odt_up_en)
+                       vref_inner = (2 * dram_drv_ohm + phy_odt_ohm) * 128 /
+                                    (dram_drv_ohm + phy_odt_ohm);
+               else
+                       vref_inner = phy_odt_ohm * 128 /
+                               (phy_odt_ohm + dram_drv_ohm);
+
+               if (dramtype != DDR3 && dram_odt_ohm)
+                       vref_out = (2 * phy_dq_drv_ohm + dram_odt_ohm) * 128 /
+                                  (phy_dq_drv_ohm + dram_odt_ohm);
+               else
+                       vref_out = 0x80;
+       } else {
+               /* for lp4 and lp4x*/
+               if (phy_odt_ohm)
+                       vref_inner =
+                               (PHY_LP4_DQ_VREF(lp4_info->vref_when_odten) *
+                                256) / 1000;
+               else
+                       vref_inner =
+                               (PHY_LP4_DQ_VREF(lp4_info->vref_when_odtoff) *
+                                256) / 1000;
+
+               vref_out = 0x80;
+       }
+
+       /* default ZQCALIB bypass mode */
+       clrsetbits_le32(PHY_REG(phy_base, 0x100), 0x1f, phy_ca_drv);
+       clrsetbits_le32(PHY_REG(phy_base, 0x101), 0x1f, phy_ca_drv);
+       clrsetbits_le32(PHY_REG(phy_base, 0x102), 0x1f, phy_clk_drv);
+       clrsetbits_le32(PHY_REG(phy_base, 0x103), 0x1f, phy_clk_drv);
+       if (dramtype == LPDDR4) {
+               clrsetbits_le32(PHY_REG(phy_base, 0x107), 0x1f, phy_clk_drv);
+               clrsetbits_le32(PHY_REG(phy_base, 0x108), 0x1f, phy_clk_drv);
+       } else {
+               clrsetbits_le32(PHY_REG(phy_base, 0x107), 0x1f, phy_ca_drv);
+               clrsetbits_le32(PHY_REG(phy_base, 0x108), 0x1f, phy_ca_drv);
+       }
+       /* clk / cmd slew rate */
+       clrsetbits_le32(PHY_REG(phy_base, 0x106), 0x1f, sr_clk);
+
+       phy_lp4_drv_pd_en = (~phy_lp4_drv_pd_en) & 1;
+       if (phy_odt_up_en)
+               phy_odt_up = phy_odt;
+       if (phy_odt_dn_en)
+               phy_odt_dn = phy_odt;
+
+       for (i = 0; i < 4; i++) {
+               j = 0x110 + i * 0x10;
+               clrsetbits_le32(PHY_REG(phy_base, j + 1), 0x1f, phy_odt_up);
+               clrsetbits_le32(PHY_REG(phy_base, j), 0x1f, phy_odt_dn);
+               clrsetbits_le32(PHY_REG(phy_base, j + 2), 0x1f, phy_dq_drv);
+               clrsetbits_le32(PHY_REG(phy_base, j + 3), 0x1f, phy_dq_drv);
+               writel(vref_inner, PHY_REG(phy_base, 0x118 + i * 0x10));
+
+               clrsetbits_le32(PHY_REG(phy_base, 0x114 + i * 0x10),
+                               1 << 3, phy_lp4_drv_pd_en << 3);
+               if (dramtype == LPDDR4)
+                       clrbits_le32(PHY_REG(phy_base, 0x114 + i * 0x10), BIT(5));
+               /* dq slew rate */
+               clrsetbits_le32(PHY_REG(phy_base, 0x117 + i * 0x10),
+                               0x1f, sr_dq);
+       }
+
+       /* reg_rx_vref_value_update */
+       setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
+       clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
+
+       /* RAM VREF */
+       writel(vref_out, PHY_REG(phy_base, 0x105));
+       if (dramtype == LPDDR3)
+               udelay(100);
+
+       if (dramtype == LPDDR4)
+               set_lp4_vref(dram, lp4_info, freq, dst_fsp, dramtype);
+
+       if (dramtype == DDR3 || dramtype == DDR4) {
+               mr1_mr3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                               DDR_PCTL2_INIT3);
+               mr1_mr3 = mr1_mr3 >> PCTL2_DDR34_MR1_SHIFT & PCTL2_MR_MASK;
+       } else {
+               mr1_mr3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                               DDR_PCTL2_INIT4);
+               mr1_mr3 = mr1_mr3 >> PCTL2_LPDDR234_MR3_SHIFT & PCTL2_MR_MASK;
+       }
+
+       if (dramtype == DDR3) {
+               mr1_mr3 &= ~(DDR3_DS_MASK | DDR3_RTT_NOM_MASK);
+               if (dram_drv_ohm == 34)
+                       mr1_mr3 |= DDR3_DS_34;
+
+               if (dram_odt_ohm == 0)
+                       mr1_mr3 |= DDR3_RTT_NOM_DIS;
+               else if (dram_odt_ohm <= 40)
+                       mr1_mr3 |= DDR3_RTT_NOM_40;
+               else if (dram_odt_ohm <= 60)
+                       mr1_mr3 |= DDR3_RTT_NOM_60;
+               else
+                       mr1_mr3 |= DDR3_RTT_NOM_120;
+
+       } else if (dramtype == DDR4) {
+               mr1_mr3 &= ~(DDR4_DS_MASK | DDR4_RTT_NOM_MASK);
+               if (dram_drv_ohm == 48)
+                       mr1_mr3 |= DDR4_DS_48;
+
+               if (dram_odt_ohm == 0)
+                       mr1_mr3 |= DDR4_RTT_NOM_DIS;
+               else if (dram_odt_ohm <= 34)
+                       mr1_mr3 |= DDR4_RTT_NOM_34;
+               else if (dram_odt_ohm <= 40)
+                       mr1_mr3 |= DDR4_RTT_NOM_40;
+               else if (dram_odt_ohm <= 48)
+                       mr1_mr3 |= DDR4_RTT_NOM_48;
+               else if (dram_odt_ohm <= 60)
+                       mr1_mr3 |= DDR4_RTT_NOM_60;
+               else
+                       mr1_mr3 |= DDR4_RTT_NOM_120;
+
+       } else if (dramtype == LPDDR3) {
+               if (dram_drv_ohm <= 34)
+                       mr1_mr3 |= LPDDR3_DS_34;
+               else if (dram_drv_ohm <= 40)
+                       mr1_mr3 |= LPDDR3_DS_40;
+               else if (dram_drv_ohm <= 48)
+                       mr1_mr3 |= LPDDR3_DS_48;
+               else if (dram_drv_ohm <= 60)
+                       mr1_mr3 |= LPDDR3_DS_60;
+               else if (dram_drv_ohm <= 80)
+                       mr1_mr3 |= LPDDR3_DS_80;
+
+               if (dram_odt_ohm == 0)
+                       lp3_odt_value = LPDDR3_ODT_DIS;
+               else if (dram_odt_ohm <= 60)
+                       lp3_odt_value = LPDDR3_ODT_60;
+               else if (dram_odt_ohm <= 120)
+                       lp3_odt_value = LPDDR3_ODT_120;
+               else
+                       lp3_odt_value = LPDDR3_ODT_240;
+       } else {/* for lpddr4 and lpddr4x */
+               /* MR3 for lp4 PU-CAL and PDDS */
+               mr1_mr3 &= ~(LPDDR4_PDDS_MASK | LPDDR4_PU_CAL_MASK);
+               mr1_mr3 |= lp4_pu_cal;
+
+               tmp = lp4_odt_calc(dram_drv_ohm);
+               if (!tmp)
+                       tmp = LPDDR4_PDDS_240;
+               mr1_mr3 |= (tmp << LPDDR4_PDDS_SHIFT);
+
+               /* MR11 for lp4 ca odt, dq odt set */
+               mr11 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                            DDR_PCTL2_INIT6);
+               mr11 = mr11 >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK;
+
+               mr11 &= ~(LPDDR4_DQODT_MASK | LPDDR4_CAODT_MASK);
+
+               tmp = lp4_odt_calc(dram_odt_ohm);
+               mr11 |= (tmp << LPDDR4_DQODT_SHIFT);
+
+               tmp = lp4_odt_calc(dram_caodt_ohm);
+               mr11 |= (tmp << LPDDR4_CAODT_SHIFT);
+               sw_set_req(dram);
+               clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                               DDR_PCTL2_INIT6,
+                               PCTL2_MR_MASK << PCTL2_LPDDR4_MR11_SHIFT,
+                               mr11 << PCTL2_LPDDR4_MR11_SHIFT);
+               sw_set_ack(dram);
+
+               /* MR22 for soc odt/odt-ck/odt-cs/odt-ca */
+               mr22 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                            DDR_PCTL2_INIT7);
+               mr22 = mr22 >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK;
+               mr22 &= ~LPDDR4_SOC_ODT_MASK;
+
+               tmp = lp4_odt_calc(phy_odt_ohm);
+               mr22 |= tmp;
+               mr22 = mr22 |
+                      (LP4_ODTE_CK_EN(lp4_info->cs_drv_ca_odt_info) <<
+                       LPDDR4_ODTE_CK_SHIFT) |
+                      (LP4_ODTE_CS_EN(lp4_info->cs_drv_ca_odt_info) <<
+                       LPDDR4_ODTE_CS_SHIFT) |
+                      (LP4_ODTD_CA_EN(lp4_info->cs_drv_ca_odt_info) <<
+                       LPDDR4_ODTD_CA_SHIFT);
+
+               sw_set_req(dram);
+               clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                               DDR_PCTL2_INIT7,
+                               PCTL2_MR_MASK << PCTL2_LPDDR4_MR22_SHIFT,
+                               mr22 << PCTL2_LPDDR4_MR22_SHIFT);
+               sw_set_ack(dram);
+       }
+
+       if (dramtype == DDR4 || dramtype == DDR3) {
+               sw_set_req(dram);
+               clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                               DDR_PCTL2_INIT3,
+                               PCTL2_MR_MASK << PCTL2_DDR34_MR1_SHIFT,
+                               mr1_mr3 << PCTL2_DDR34_MR1_SHIFT);
+               sw_set_ack(dram);
+       } else {
+               sw_set_req(dram);
+               clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                               DDR_PCTL2_INIT4,
+                               PCTL2_MR_MASK << PCTL2_LPDDR234_MR3_SHIFT,
+                               mr1_mr3 << PCTL2_LPDDR234_MR3_SHIFT);
+               sw_set_ack(dram);
+       }
+}
+
+static int sdram_cmd_dq_path_remap(struct dram_info *dram,
+                                  struct rv1126_sdram_params *sdram_params)
+{
+       void __iomem *phy_base = dram->phy;
+       u32 dramtype = sdram_params->base.dramtype;
+       struct sdram_head_info_index_v2 *index =
+               (struct sdram_head_info_index_v2 *)common_info;
+       struct dq_map_info *map_info;
+
+       map_info = (struct dq_map_info *)((void *)common_info +
+               index->dq_map_index.offset * 4);
+
+       if (dramtype <= LPDDR4)
+               writel((map_info->byte_map[dramtype / 4] >>
+                       ((dramtype % 4) * 8)) & 0xff,
+                      PHY_REG(phy_base, 0x4f));
+
+       return 0;
+}
+
+static void phy_cfg(struct dram_info *dram,
+                   struct rv1126_sdram_params *sdram_params)
+{
+       struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+       void __iomem *phy_base = dram->phy;
+       u32 i, dq_map, tmp;
+       u32 byte1 = 0, byte0 = 0;
+
+       sdram_cmd_dq_path_remap(dram, sdram_params);
+
+       phy_pll_set(dram, sdram_params->base.ddr_freq * MHZ, 0);
+       for (i = 0; sdram_params->phy_regs.phy[i][0] != 0xFFFFFFFF; i++) {
+               writel(sdram_params->phy_regs.phy[i][1],
+                      phy_base + sdram_params->phy_regs.phy[i][0]);
+       }
+
+       clrbits_le32(PHY_REG(phy_base, 0x62), BIT(5));
+       dq_map = readl(PHY_REG(phy_base, 0x4f));
+       for (i = 0; i < 4; i++) {
+               if (((dq_map >> (i * 2)) & 0x3) == 0)
+                       byte0 = i;
+               if (((dq_map >> (i * 2)) & 0x3) == 1)
+                       byte1 = i;
+       }
+
+       tmp = readl(PHY_REG(phy_base, 0xf)) & (~PHY_DQ_WIDTH_MASK);
+       if (cap_info->bw == 2)
+               tmp |= 0xf;
+       else if (cap_info->bw == 1)
+               tmp |= ((1 << byte0) | (1 << byte1));
+       else
+               tmp |= (1 << byte0);
+
+       writel(tmp, PHY_REG(phy_base, 0xf));
+
+       /* lpddr4 odt control by phy, enable cs0 odt */
+       if (sdram_params->base.dramtype == LPDDR4)
+               clrsetbits_le32(PHY_REG(phy_base, 0x20), 0x7 << 4,
+                               (1 << 6) | (1 << 4));
+       /* for ca training ca vref choose range1 */
+       setbits_le32(PHY_REG(phy_base, 0x1e), BIT(6));
+       setbits_le32(PHY_REG(phy_base, 0x1f), BIT(6));
+       /* for wr training PHY_0x7c[5], choose range0 */
+       clrbits_le32(PHY_REG(phy_base, 0x7c), BIT(5));
+}
+
+static int update_refresh_reg(struct dram_info *dram)
+{
+       void __iomem *pctl_base = dram->pctl;
+       u32 ret;
+
+       ret = readl(pctl_base + DDR_PCTL2_RFSHCTL3) ^ (1 << 1);
+       writel(ret, pctl_base + DDR_PCTL2_RFSHCTL3);
+
+       return 0;
+}
+
+/*
+ * rank = 1: cs0
+ * rank = 2: cs1
+ */
+int read_mr(struct dram_info *dram, u32 rank, u32 mr_num, u32 dramtype)
+{
+       u32 ret;
+       u32 i, temp;
+       u32 dqmap;
+
+       void __iomem *pctl_base = dram->pctl;
+       struct sdram_head_info_index_v2 *index =
+               (struct sdram_head_info_index_v2 *)common_info;
+       struct dq_map_info *map_info;
+
+       map_info = (struct dq_map_info *)((void *)common_info +
+               index->dq_map_index.offset * 4);
+
+       if (dramtype == LPDDR2)
+               dqmap = map_info->lp2_dq0_7_map;
+       else
+               dqmap = map_info->lp3_dq0_7_map;
+
+       pctl_read_mr(pctl_base, rank, mr_num);
+
+       ret = (readl(&dram->ddrgrf->ddr_grf_status[0]) & 0xff);
+
+       if (dramtype != LPDDR4) {
+               temp = 0;
+               for (i = 0; i < 8; i++) {
+                       temp = temp | (((ret >> i) & 0x1) <<
+                                      ((dqmap >> (i * 4)) & 0xf));
+               }
+       } else {
+               temp = (readl(&dram->ddrgrf->ddr_grf_status[1]) & 0xff);
+       }
+
+       return temp;
+}
+
+/* before call this function autorefresh should be disabled */
+void send_a_refresh(struct dram_info *dram)
+{
+       void __iomem *pctl_base = dram->pctl;
+
+       while (readl(pctl_base + DDR_PCTL2_DBGSTAT) & 0x3)
+               continue;
+       writel(0x3, pctl_base + DDR_PCTL2_DBGCMD);
+}
+
+static void enter_sr(struct dram_info *dram, u32 en)
+{
+       void __iomem *pctl_base = dram->pctl;
+
+       if (en) {
+               setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, PCTL2_SELFREF_SW);
+               while (1) {
+                       if (((readl(pctl_base + DDR_PCTL2_STAT) &
+                             PCTL2_SELFREF_TYPE_MASK) ==
+                            PCTL2_SELFREF_TYPE_SR_NOT_AUTO) &&
+                           ((readl(pctl_base + DDR_PCTL2_STAT) &
+                             PCTL2_OPERATING_MODE_MASK) ==
+                            PCTL2_OPERATING_MODE_SR))
+                               break;
+               }
+       } else {
+               clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, PCTL2_SELFREF_SW);
+               while ((readl(pctl_base + DDR_PCTL2_STAT) &
+                      PCTL2_OPERATING_MODE_MASK) == PCTL2_OPERATING_MODE_SR)
+                       continue;
+       }
+}
+
+void record_dq_prebit(struct dram_info *dram)
+{
+       u32 group, i, tmp;
+       void __iomem *phy_base = dram->phy;
+
+       for (group = 0; group < 4; group++) {
+               for (i = 0; i < ARRAY_SIZE(dq_sel); i++) {
+                       /* l_loop_invdelaysel */
+                       writel(dq_sel[i][0], PHY_REG(phy_base,
+                                                    grp_addr[group] + 0x2c));
+                       tmp = readl(PHY_REG(phy_base, grp_addr[group] + 0x2e));
+                       writel(tmp, PHY_REG(phy_base,
+                                           grp_addr[group] + dq_sel[i][1]));
+
+                       /* r_loop_invdelaysel */
+                       writel(dq_sel[i][0], PHY_REG(phy_base,
+                                                    grp_addr[group] + 0x2d));
+                       tmp = readl(PHY_REG(phy_base, grp_addr[group] + 0x2f));
+                       writel(tmp, PHY_REG(phy_base,
+                                           grp_addr[group] + dq_sel[i][2]));
+               }
+       }
+}
+
+static void update_dq_rx_prebit(struct dram_info *dram)
+{
+       void __iomem *phy_base = dram->phy;
+
+       clrsetbits_le32(PHY_REG(phy_base, 0x70), BIT(1) | BIT(6) | BIT(4),
+                       BIT(4));
+       udelay(1);
+       clrbits_le32(PHY_REG(phy_base, 0x70), BIT(4));
+}
+
+static void update_dq_tx_prebit(struct dram_info *dram)
+{
+       void __iomem *phy_base = dram->phy;
+
+       clrbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
+       setbits_le32(PHY_REG(phy_base, 0x2), BIT(3));
+       setbits_le32(PHY_REG(phy_base, 0xc), BIT(6));
+       udelay(1);
+       clrbits_le32(PHY_REG(phy_base, 0xc), BIT(6));
+}
+
+static void update_ca_prebit(struct dram_info *dram)
+{
+       void __iomem *phy_base = dram->phy;
+
+       clrbits_le32(PHY_REG(phy_base, 0x25), BIT(2));
+       setbits_le32(PHY_REG(phy_base, 0x22), BIT(6));
+       udelay(1);
+       clrbits_le32(PHY_REG(phy_base, 0x22), BIT(6));
+}
+
+/*
+ * dir: 0: de-skew = delta_*
+ *     1: de-skew = reg val - delta_*
+ * delta_dir: value for differential signal: clk/
+ * delta_sig: value for single signal: ca/cmd
+ */
+static void modify_ca_deskew(struct dram_info *dram, u32 dir, int delta_dif,
+                            int delta_sig, u32 cs, u32 dramtype)
+{
+       void __iomem *phy_base = dram->phy;
+       u32 i, cs_en, tmp;
+       u32 dfi_lp_stat = 0;
+
+       if (cs == 0)
+               cs_en = 1;
+       else if (cs == 2)
+               cs_en = 2;
+       else
+               cs_en = 3;
+
+       if (dramtype == LPDDR4 &&
+           ((readl(PHY_REG(phy_base, 0x60)) & BIT(5)) == 0)) {
+               dfi_lp_stat = 1;
+               setbits_le32(PHY_REG(phy_base, 0x60), BIT(5));
+       }
+       enter_sr(dram, 1);
+
+       for (i = 0; i < 0x20; i++) {
+               if (dir == DESKEW_MDF_ABS_VAL)
+                       tmp = delta_sig;
+               else
+                       tmp = readl(PHY_REG(phy_base, 0x150 + i)) +
+                             delta_sig;
+               writel(tmp, PHY_REG(phy_base, 0x150 + i));
+       }
+
+       if (dir == DESKEW_MDF_ABS_VAL)
+               tmp = delta_dif;
+       else
+               tmp = readl(PHY_REG(phy_base, 0x150 + 0x17)) -
+                      delta_sig + delta_dif;
+       writel(tmp, PHY_REG(phy_base, 0x150 + 0x17));
+       writel(tmp, PHY_REG(phy_base, 0x150 + 0x18));
+       if (dramtype == LPDDR4) {
+               writel(tmp, PHY_REG(phy_base, 0x150 + 0x4));
+               writel(tmp, PHY_REG(phy_base, 0x150 + 0xa));
+
+               clrbits_le32(PHY_REG(phy_base, 0x10), cs_en << 6);
+               update_ca_prebit(dram);
+       }
+       enter_sr(dram, 0);
+
+       if (dfi_lp_stat)
+               clrbits_le32(PHY_REG(phy_base, 0x60), BIT(5));
+}
+
+static u32 get_min_value(struct dram_info *dram, u32 signal, u32 rank)
+{
+       u32 i, j, offset = 0;
+       u32 min = 0x3f;
+       void __iomem *phy_base = dram->phy;
+       u32 byte_en;
+
+       if (signal == SKEW_TX_SIGNAL)
+               offset = 8;
+
+       if (signal == SKEW_CA_SIGNAL) {
+               for (i = 0; i < 0x20; i++)
+                       min = MIN(min, readl(PHY_REG(phy_base, 0x150  + i)));
+       } else {
+               byte_en = readl(PHY_REG(phy_base, 0xf)) & 0xf;
+               for (j = offset; j < offset + rank * 4; j++) {
+                       if (!((byte_en >> (j % 4)) & 1))
+                               continue;
+                       for (i = 0; i < 11; i++)
+                               min = MIN(min,
+                                         readl(PHY_REG(phy_base,
+                                                       dqs_dq_skew_adr[j] +
+                                                       i)));
+               }
+       }
+
+       return min;
+}
+
+static u32 low_power_update(struct dram_info *dram, u32 en)
+{
+       void __iomem *pctl_base = dram->pctl;
+       u32 lp_stat = 0;
+
+       if (en) {
+               setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, en & 0xf);
+       } else {
+               lp_stat = readl(pctl_base + DDR_PCTL2_PWRCTL) & 0xf;
+               clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 0xf);
+       }
+
+       return lp_stat;
+}
+
+/*
+ * signal:
+ * dir: 0: de-skew = delta_*
+ *     1: de-skew = reg val - delta_*
+ * delta_dir: value for differential signal: dqs
+ * delta_sig: value for single signal: dq/dm
+ */
+static void modify_dq_deskew(struct dram_info *dram, u32 signal, u32 dir,
+                            int delta_dif, int delta_sig, u32 rank)
+{
+       void __iomem *phy_base = dram->phy;
+       u32 i, j, tmp, offset;
+       u32 byte_en;
+
+       byte_en = readl(PHY_REG(phy_base, 0xf)) & 0xf;
+
+       if (signal == SKEW_RX_SIGNAL)
+               offset = 0;
+       else
+               offset = 8;
+
+       for (j = offset; j < (offset + rank * 4); j++) {
+               if (!((byte_en >> (j % 4)) & 1))
+                       continue;
+               for (i = 0; i < 0x9; i++) {
+                       if (dir == DESKEW_MDF_ABS_VAL)
+                               tmp = delta_sig;
+                       else
+                               tmp = delta_sig + readl(PHY_REG(phy_base,
+                                                       dqs_dq_skew_adr[j] +
+                                                       i));
+                       writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + i));
+               }
+               if (dir == DESKEW_MDF_ABS_VAL)
+                       tmp = delta_dif;
+               else
+                       tmp = delta_dif + readl(PHY_REG(phy_base,
+                                               dqs_dq_skew_adr[j] + 9));
+               writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + 9));
+               writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + 0xa));
+       }
+       if (signal == SKEW_RX_SIGNAL)
+               update_dq_rx_prebit(dram);
+       else
+               update_dq_tx_prebit(dram);
+}
+
+static int data_training_rg(struct dram_info *dram, u32 cs, u32 dramtype)
+{
+       void __iomem *phy_base = dram->phy;
+       u32 ret;
+       u32 dis_auto_zq = 0;
+       u32 odt_val_up, odt_val_dn;
+       u32 i, j;
+
+       odt_val_dn = readl(PHY_REG(phy_base, 0x110));
+       odt_val_up = readl(PHY_REG(phy_base, 0x111));
+
+       if (dramtype != LPDDR4) {
+               for (i = 0; i < 4; i++) {
+                       j = 0x110 + i * 0x10;
+                       writel(PHY_DDR4_LPDDR3_RTT_294ohm,
+                              PHY_REG(phy_base, j));
+                       writel(PHY_DDR4_LPDDR3_RTT_DISABLE,
+                              PHY_REG(phy_base, j + 0x1));
+               }
+       }
+       dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
+       /* use normal read mode for data training */
+       clrbits_le32(PHY_REG(phy_base, 0xc), BIT(1));
+
+       if (dramtype == DDR4)
+               setbits_le32(PHY_REG(phy_base, 0xc), BIT(1));
+
+       /* choose training cs */
+       clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs));
+       /* enable gate training */
+       clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1);
+       udelay(50);
+       ret = readl(PHY_REG(phy_base, 0x91));
+       /* disable gate training */
+       clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0);
+       clrbits_le32(PHY_REG(phy_base, 2), 0x30);
+       pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
+
+       ret = (ret & 0x2f) ^ (readl(PHY_REG(phy_base, 0xf)) & 0xf);
+
+       if (dramtype != LPDDR4) {
+               for (i = 0; i < 4; i++) {
+                       j = 0x110 + i * 0x10;
+                       writel(odt_val_dn, PHY_REG(phy_base, j));
+                       writel(odt_val_up, PHY_REG(phy_base, j + 0x1));
+               }
+       }
+       return ret;
+}
+
+static int data_training_wl(struct dram_info *dram, u32 cs, u32 dramtype,
+                           u32 rank)
+{
+       void __iomem *pctl_base = dram->pctl;
+       void __iomem *phy_base = dram->phy;
+       u32 dis_auto_zq = 0;
+       u32 tmp;
+       u32 cur_fsp;
+       u32 timeout_us = 1000;
+
+       dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
+
+       clrbits_le32(PHY_REG(phy_base, 0x7a), 0x1);
+
+       cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
+       tmp = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + DDR_PCTL2_INIT3) &
+             0xffff;
+       writel(tmp & 0xff, PHY_REG(phy_base, 0x3));
+
+       /* disable another cs's output */
+       if ((dramtype == DDR3 || dramtype == DDR4) && rank == 2)
+               pctl_write_mr(dram->pctl, (cs + 1) & 1, 1, tmp | (1 << 12),
+                             dramtype);
+       if (dramtype == DDR3 || dramtype == DDR4)
+               writel(0x40 | ((tmp >> 8) & 0x3f), PHY_REG(phy_base, 0x4));
+       else
+               writel(0x80 | ((tmp >> 8) & 0x3f), PHY_REG(phy_base, 0x4));
+
+       /* choose cs */
+       clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
+                       ((0x2 >> cs) << 6) | (0 << 2));
+       /* enable write leveling */
+       clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
+                       ((0x2 >> cs) << 6) | (1 << 2));
+
+       while (1) {
+               if ((readl(PHY_REG(phy_base, 0x92)) & 0xf) ==
+                   (readl(PHY_REG(phy_base, 0xf)) & 0xf))
+                       break;
+
+               udelay(1);
+               if (timeout_us-- == 0) {
+                       printascii("error: write leveling timeout\n");
+                       while (1)
+                               ;
+               }
+       }
+
+       /* disable write leveling */
+       clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
+                       ((0x2 >> cs) << 6) | (0 << 2));
+       clrsetbits_le32(PHY_REG(phy_base, 2), 0x3 << 6, 0 << 6);
+
+       /* enable another cs's output */
+       if ((dramtype == DDR3 || dramtype == DDR4) && rank == 2)
+               pctl_write_mr(dram->pctl, (cs + 1) & 1, 1, tmp & ~(1 << 12),
+                             dramtype);
+
+       pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
+
+       return 0;
+}
+
+char pattern[32] = {
+       0xaa, 0x55, 0xaa, 0x55, 0x55, 0xaa, 0x55, 0xaa,
+       0x55, 0xaa, 0x55, 0xaa, 0xaa, 0x55, 0xaa, 0x55,
+       0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55,
+       0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa
+};
+
+static int data_training_rd(struct dram_info *dram, u32 cs, u32 dramtype,
+                           u32 mhz)
+{
+       void __iomem *pctl_base = dram->pctl;
+       void __iomem *phy_base = dram->phy;
+       u32 trefi_1x, trfc_1x;
+       u32 dis_auto_zq = 0;
+       u32 timeout_us = 1000;
+       u32 dqs_default;
+       u32 cur_fsp;
+       u32 vref_inner;
+       u32 i;
+       struct sdram_head_info_index_v2 *index =
+               (struct sdram_head_info_index_v2 *)common_info;
+       struct dq_map_info *map_info;
+
+       vref_inner = readl(PHY_REG(phy_base, 0x128)) & 0xff;
+       if (dramtype == DDR3 && vref_inner == 0x80) {
+               for (i = 0; i < 4; i++)
+                       writel(vref_inner - 0xa,
+                              PHY_REG(phy_base, 0x118 + i * 0x10));
+
+               /* reg_rx_vref_value_update */
+               setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
+               clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
+       }
+
+       map_info = (struct dq_map_info *)((void *)common_info +
+               index->dq_map_index.offset * 4);
+       /* only 1cs a time, 0:cs0 1 cs1 */
+       if (cs > 1)
+               return -1;
+
+       dqs_default = 0xf;
+       dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
+
+       cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
+       /* config refresh timing */
+       trefi_1x = ((readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
+                          DDR_PCTL2_RFSHTMG) >> 16) & 0xfff) * 32;
+       trfc_1x = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
+                       DDR_PCTL2_RFSHTMG) & 0x3ff;
+       /* reg_phy_trefi[7:0] and reg_phy_trefi[13:8] */
+       clrsetbits_le32(PHY_REG(phy_base, 0x6e), 0xff, trefi_1x & 0xff);
+       clrsetbits_le32(PHY_REG(phy_base, 0x6f), 0x3f, (trefi_1x >> 8) & 0x3f);
+       /* reg_phy_trfc */
+       clrsetbits_le32(PHY_REG(phy_base, 0x57), 0xff, trfc_1x);
+       /* reg_max_refi_cnt */
+       clrsetbits_le32(PHY_REG(phy_base, 0x61), 0xf << 4, 0x8 << 4);
+
+       /* choose training cs */
+       clrsetbits_le32(PHY_REG(phy_base, 0x71), 0x3 << 6, (0x2 >> cs) << 6);
+
+       /* set dq map for ddr4 */
+       if (dramtype == DDR4) {
+               setbits_le32(PHY_REG(phy_base, 0x70), BIT(7));
+               for (i = 0; i < 4; i++) {
+                       writel((map_info->ddr4_dq_map[cs * 2] >>
+                               ((i % 4) * 8)) & 0xff,
+                               PHY_REG(phy_base, 0x238 + i));
+                       writel((map_info->ddr4_dq_map[cs * 2 + 1] >>
+                               ((i % 4) * 8)) & 0xff,
+                               PHY_REG(phy_base, 0x2b8 + i));
+               }
+       }
+
+       /* cha_l reg_l_rd_train_dqs_default[5:0] */
+       clrsetbits_le32(PHY_REG(phy_base, 0x230), 0x3f, dqs_default);
+       /* cha_h reg_h_rd_train_dqs_default[5:0] */
+       clrsetbits_le32(PHY_REG(phy_base, 0x234), 0x3f, dqs_default);
+       /* chb_l reg_l_rd_train_dqs_default[5:0] */
+       clrsetbits_le32(PHY_REG(phy_base, 0x2b0), 0x3f, dqs_default);
+       /* chb_h reg_h_rd_train_dqs_default[5:0] */
+       clrsetbits_le32(PHY_REG(phy_base, 0x2b4), 0x3f, dqs_default);
+
+       /* Choose the read train auto mode */
+       clrsetbits_le32(PHY_REG(phy_base, 0x70), 0x3, 0x1);
+       /* Enable the auto train of the read train */
+       clrsetbits_le32(PHY_REG(phy_base, 0x70), 0x3, 0x3);
+
+       /* Wait the train done. */
+       while (1) {
+               if ((readl(PHY_REG(phy_base, 0x93)) >> 7) & 0x1)
+                       break;
+
+               udelay(1);
+               if (timeout_us-- == 0) {
+                       printascii("error: read training timeout\n");
+                       return -1;
+               }
+       }
+
+       /* Check the read train state */
+       if ((readl(PHY_REG(phy_base, 0x240)) & 0x3) ||
+           (readl(PHY_REG(phy_base, 0x2c0)) & 0x3)) {
+               printascii("error: read training error\n");
+               return -1;
+       }
+
+       /* Exit the Read Training by setting */
+       clrbits_le32(PHY_REG(phy_base, 0x70), BIT(1));
+
+       pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
+
+       if (dramtype == DDR3 && vref_inner == 0x80) {
+               for (i = 0; i < 4; i++)
+                       writel(vref_inner,
+                              PHY_REG(phy_base, 0x118 + i * 0x10));
+
+               /* reg_rx_vref_value_update */
+               setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
+               clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
+       }
+
+       return 0;
+}
+
+static int data_training_wr(struct dram_info *dram, u32 cs, u32 dramtype,
+                           u32 mhz, u32 dst_fsp)
+{
+       void __iomem *pctl_base = dram->pctl;
+       void __iomem *phy_base = dram->phy;
+       u32 trefi_1x, trfc_1x;
+       u32 dis_auto_zq = 0;
+       u32 timeout_us = 1000;
+       u32 cur_fsp;
+       u32 mr_tmp, cl, cwl, phy_fsp, offset = 0;
+
+       if (dramtype == LPDDR3 && mhz <= 400) {
+               phy_fsp = (readl(PHY_REG(phy_base, 0xc)) >> 0x2) & 0x3;
+               offset = (phy_fsp == 0) ? 0x5 : 0x387 + (phy_fsp - 1) * 3;
+               cl = readl(PHY_REG(phy_base, offset));
+               cwl = readl(PHY_REG(phy_base, offset + 2));
+
+               clrsetbits_le32(PHY_REG(phy_base, offset), 0x1f, 0x8);
+               clrsetbits_le32(PHY_REG(phy_base, offset + 2), 0x1f, 0x4);
+               pctl_write_mr(dram->pctl, 3, 2, 0x6, dramtype);
+       }
+
+       dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
+
+       /* PHY_0x7b[7:0] reg_train_col_addr[7:0] */
+       clrsetbits_le32(PHY_REG(phy_base, 0x7b), 0xff, 0x0);
+       /* PHY_0x7c[4:2] reg_train_ba_addr[2:0] */
+       clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x7 << 2, 0x0 << 2);
+       /* PHY_0x7c[1:0] reg_train_col_addr[9:8] */
+       clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x3, 0x0);
+       /* PHY_0x7d[7:0] reg_train_row_addr[7:0] */
+       clrsetbits_le32(PHY_REG(phy_base, 0x7d), 0xff, 0x0);
+       /* PHY_0x7e[7:0] reg_train_row_addr[15:8] */
+       clrsetbits_le32(PHY_REG(phy_base, 0x7e), 0xff, 0x0);
+
+       /* PHY_0x71[3] wrtrain_check_data_value_random_gen */
+       clrbits_le32(PHY_REG(phy_base, 0x71), BIT(3));
+
+       /* config refresh timing */
+       cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
+       trefi_1x = ((readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
+                          DDR_PCTL2_RFSHTMG) >> 16) & 0xfff) * 32;
+       trfc_1x = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
+                       DDR_PCTL2_RFSHTMG) & 0x3ff;
+       /* reg_phy_trefi[7:0] and reg_phy_trefi[13:8] */
+       clrsetbits_le32(PHY_REG(phy_base, 0x6e), 0xff, trefi_1x & 0xff);
+       clrsetbits_le32(PHY_REG(phy_base, 0x6f), 0x3f, (trefi_1x >> 8) & 0x3f);
+       /* reg_phy_trfc */
+       clrsetbits_le32(PHY_REG(phy_base, 0x57), 0xff, trfc_1x);
+       /* reg_max_refi_cnt */
+       clrsetbits_le32(PHY_REG(phy_base, 0x61), 0xf << 4, 0x8 << 4);
+
+       /* choose training cs */
+       clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x3 << 6, (0x2 >> cs) << 6);
+
+       /* PHY_0x7a [4] reg_wr_train_dqs_default_bypass */
+       /* 0: Use the write-leveling value. */
+       /* 1: use reg0x233 0x237 0x2b3 0x2b7 */
+       setbits_le32(PHY_REG(phy_base, 0x7a), BIT(4));
+
+       /* PHY_0x7a [0] reg_dq_wr_train_auto */
+       setbits_le32(PHY_REG(phy_base, 0x7a), 0x1);
+
+       /* PHY_0x7a [1] reg_dq_wr_train_en */
+       setbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
+
+       send_a_refresh(dram);
+
+       while (1) {
+               if ((readl(PHY_REG(phy_base, 0x92)) >> 7) & 0x1)
+                       break;
+
+               udelay(1);
+               if (timeout_us-- == 0) {
+                       printascii("error: write training timeout\n");
+                       while (1)
+                               ;
+               }
+       }
+
+       /* Check the write train state */
+       if ((readl(PHY_REG(phy_base, 0x90)) >> 5) & 0x7) {
+               printascii("error: write training error\n");
+               return -1;
+       }
+
+       /* PHY_0x7a [1] reg_dq_wr_train_en */
+       clrbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
+
+       pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
+
+       /* save LPDDR4 write vref to fsp_param for dfs */
+       if (dramtype == LPDDR4) {
+               fsp_param[dst_fsp].vref_dq[cs] =
+                       ((readl(PHY_REG(phy_base, 0x384)) & 0x3f) +
+                        (readl(PHY_REG(phy_base, 0x385)) & 0x3f)) / 2;
+               /* add range info */
+               fsp_param[dst_fsp].vref_dq[cs] |=
+                       ((readl(PHY_REG(phy_base, 0x7c)) & BIT(5)) << 1);
+       }
+
+       if (dramtype == LPDDR3 && mhz <= 400) {
+               clrsetbits_le32(PHY_REG(phy_base, offset), 0x1f, cl);
+               clrsetbits_le32(PHY_REG(phy_base, offset + 2), 0x1f, cwl);
+               mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
+                              DDR_PCTL2_INIT3);
+               pctl_write_mr(dram->pctl, 3, 2, mr_tmp & PCTL2_MR_MASK,
+                             dramtype);
+       }
+
+       return 0;
+}
+
+static int data_training(struct dram_info *dram, u32 cs,
+                        struct rv1126_sdram_params *sdram_params, u32 dst_fsp,
+                        u32 training_flag)
+{
+       u32 ret = 0;
+
+       if (training_flag == FULL_TRAINING)
+               training_flag = READ_GATE_TRAINING | WRITE_LEVELING |
+                               WRITE_TRAINING | READ_TRAINING;
+
+       if ((training_flag & WRITE_LEVELING) == WRITE_LEVELING) {
+               ret = data_training_wl(dram, cs,
+                                      sdram_params->base.dramtype,
+                                      sdram_params->ch.cap_info.rank);
+               if (ret != 0)
+                       goto out;
+       }
+
+       if ((training_flag & READ_GATE_TRAINING) == READ_GATE_TRAINING) {
+               ret = data_training_rg(dram, cs,
+                                      sdram_params->base.dramtype);
+               if (ret != 0)
+                       goto out;
+       }
+
+       if ((training_flag & READ_TRAINING) == READ_TRAINING) {
+               ret = data_training_rd(dram, cs,
+                                      sdram_params->base.dramtype,
+                                      sdram_params->base.ddr_freq);
+               if (ret != 0)
+                       goto out;
+       }
+
+       if ((training_flag & WRITE_TRAINING) == WRITE_TRAINING) {
+               ret = data_training_wr(dram, cs,
+                                      sdram_params->base.dramtype,
+                                      sdram_params->base.ddr_freq, dst_fsp);
+               if (ret != 0)
+                       goto out;
+       }
+
+out:
+       return ret;
+}
+
+static int get_wrlvl_val(struct dram_info *dram,
+                        struct rv1126_sdram_params *sdram_params)
+{
+       int i, j, clk_skew;
+       void __iomem *phy_base = dram->phy;
+       u32 lp_stat;
+       int ret;
+
+       lp_stat = low_power_update(dram, 0);
+
+       clk_skew = 0x1f;
+       modify_ca_deskew(dram, DESKEW_MDF_ABS_VAL, clk_skew, clk_skew, 3,
+                        sdram_params->base.dramtype);
+
+       ret = data_training(dram, 0, sdram_params, 0, WRITE_LEVELING);
+       if (sdram_params->ch.cap_info.rank == 2)
+               ret |= data_training(dram, 1, sdram_params, 0, WRITE_LEVELING);
+
+       for (j = 0; j < 2; j++)
+               for (i = 0; i < 4; i++)
+                       wrlvl_result[j][i] =
+                               (readl(PHY_REG(phy_base, wrlvl_result_offset[j][i])) & 0x3f) -
+                               clk_skew;
+
+       low_power_update(dram, lp_stat);
+
+       return ret;
+}
+
+#if defined(CONFIG_CMD_DDR_TEST_TOOL)
+static void init_rw_trn_result_struct(struct rw_trn_result *result,
+                                     void __iomem *phy_base, u8 cs_num)
+{
+       int i;
+
+       result->cs_num = cs_num;
+       result->byte_en = readb(PHY_REG(dram_info.phy, 0xf)) &
+                         PHY_DQ_WIDTH_MASK;
+       for (i = 0; i < FSP_NUM; i++)
+               result->fsp_mhz[i] = 0;
+}
+
+static void save_rw_trn_min_max(void __iomem *phy_base,
+                               struct cs_rw_trn_result *rd_result,
+                               struct cs_rw_trn_result *wr_result,
+                               u8 byte_en)
+{
+       u16 phy_ofs;
+       u8 dqs;
+       u8 dq;
+
+       for (dqs = 0; dqs < BYTE_NUM; dqs++) {
+               if ((byte_en & BIT(dqs)) == 0)
+                       continue;
+
+               /* Channel A or B (low or high 16 bit) */
+               phy_ofs = dqs < 2 ? 0x230 : 0x2b0;
+               /* low or high 8 bit */
+               phy_ofs += (dqs & 0x1) == 0 ? 0 : 0x9;
+               for (dq = 0; dq < 8; dq++) {
+                       rd_result->dqs[dqs].dq_min[dq] =
+                               readb(PHY_REG(phy_base, phy_ofs + 0x15 + dq));
+                       rd_result->dqs[dqs].dq_max[dq] =
+                               readb(PHY_REG(phy_base, phy_ofs + 0x27 + dq));
+                       wr_result->dqs[dqs].dq_min[dq] =
+                               readb(PHY_REG(phy_base, phy_ofs + 0x3d + dq));
+                       wr_result->dqs[dqs].dq_max[dq] =
+                               readb(PHY_REG(phy_base, phy_ofs + 0x4f + dq));
+               }
+       }
+}
+
+static void save_rw_trn_deskew(void __iomem *phy_base,
+                              struct fsp_rw_trn_result *result, u8 cs_num,
+                              int min_val, bool rw)
+{
+       u16 phy_ofs;
+       u8 cs;
+       u8 dq;
+
+       result->min_val = min_val;
+
+       for (cs = 0; cs < cs_num; cs++) {
+               phy_ofs = cs == 0 ? 0x170 : 0x1a0;
+               phy_ofs += rw == SKEW_RX_SIGNAL ? 0x1 : 0x17;
+               for (dq = 0; dq < 8; dq++) {
+                       result->cs[cs].dqs[0].dq_deskew[dq] =
+                               readb(PHY_REG(phy_base, phy_ofs + dq));
+                       result->cs[cs].dqs[1].dq_deskew[dq] =
+                               readb(PHY_REG(phy_base, phy_ofs + 0xb + dq));
+                       result->cs[cs].dqs[2].dq_deskew[dq] =
+                               readb(PHY_REG(phy_base, phy_ofs + 0x60 + dq));
+                       result->cs[cs].dqs[3].dq_deskew[dq] =
+                               readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0xb + dq));
+               }
+
+               result->cs[cs].dqs[0].dqs_deskew =
+                       readb(PHY_REG(phy_base, phy_ofs + 0x8));
+               result->cs[cs].dqs[1].dqs_deskew =
+                       readb(PHY_REG(phy_base, phy_ofs + 0xb + 0x8));
+               result->cs[cs].dqs[2].dqs_deskew =
+                       readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0x8));
+               result->cs[cs].dqs[3].dqs_deskew =
+                       readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0xb + 0x8));
+       }
+}
+
+static void save_rw_trn_result_to_ddr(struct rw_trn_result *result)
+{
+       result->flag = DDR_DQ_EYE_FLAG;
+       memcpy((void *)(RW_TRN_RESULT_ADDR), result, sizeof(*result));
+}
+#endif
+
+static int high_freq_training(struct dram_info *dram,
+                             struct rv1126_sdram_params *sdram_params,
+                             u32 fsp)
+{
+       u32 i, j;
+       void __iomem *phy_base = dram->phy;
+       u32 dramtype = sdram_params->base.dramtype;
+       int min_val;
+       int dqs_skew, clk_skew, ca_skew;
+       u8 byte_en;
+       int ret;
+
+       byte_en = readl(PHY_REG(phy_base, 0xf)) & PHY_DQ_WIDTH_MASK;
+       dqs_skew = 0;
+       for (j = 0; j < sdram_params->ch.cap_info.rank; j++) {
+               for (i = 0; i < ARRAY_SIZE(wrlvl_result[0]); i++) {
+                       if ((byte_en & BIT(i)) != 0)
+                               dqs_skew += wrlvl_result[j][i];
+               }
+       }
+       dqs_skew = dqs_skew /
+                  (int)(sdram_params->ch.cap_info.rank * (1 << sdram_params->ch.cap_info.bw));
+
+       clk_skew = 0x20 - dqs_skew;
+       dqs_skew = 0x20;
+
+       if (dramtype == LPDDR4) {
+               min_val = 0xff;
+               for (j = 0; j < sdram_params->ch.cap_info.rank; j++)
+                       for (i = 0; i < sdram_params->ch.cap_info.bw; i++)
+                               min_val = MIN(wrlvl_result[j][i], min_val);
+
+               if (min_val < 0) {
+                       clk_skew = -min_val;
+                       ca_skew = -min_val;
+               } else {
+                       clk_skew = 0;
+                       ca_skew = 0;
+               }
+       } else if (dramtype == LPDDR3) {
+               ca_skew = clk_skew - 4;
+       } else {
+               ca_skew = clk_skew;
+       }
+       modify_ca_deskew(dram, DESKEW_MDF_ABS_VAL, clk_skew, ca_skew, 3,
+                        dramtype);
+
+       writel(wrlvl_result[0][0] + clk_skew, PHY_REG(phy_base, 0x233));
+       writel(wrlvl_result[0][1] + clk_skew, PHY_REG(phy_base, 0x237));
+       writel(wrlvl_result[0][2] + clk_skew, PHY_REG(phy_base, 0x2b3));
+       writel(wrlvl_result[0][3] + clk_skew, PHY_REG(phy_base, 0x2b7));
+       ret = data_training(dram, 0, sdram_params, fsp, READ_GATE_TRAINING |
+                           READ_TRAINING | WRITE_TRAINING);
+#if defined(CONFIG_CMD_DDR_TEST_TOOL)
+       rw_trn_result.fsp_mhz[fsp] = (u16)sdram_params->base.ddr_freq;
+       save_rw_trn_min_max(phy_base, &rw_trn_result.rd_fsp[fsp].cs[0],
+                           &rw_trn_result.wr_fsp[fsp].cs[0],
+                           rw_trn_result.byte_en);
+#endif
+       if (sdram_params->ch.cap_info.rank == 2) {
+               writel(wrlvl_result[1][0] + clk_skew, PHY_REG(phy_base, 0x233));
+               writel(wrlvl_result[1][1] + clk_skew, PHY_REG(phy_base, 0x237));
+               writel(wrlvl_result[1][2] + clk_skew, PHY_REG(phy_base, 0x2b3));
+               writel(wrlvl_result[1][3] + clk_skew, PHY_REG(phy_base, 0x2b7));
+               ret |= data_training(dram, 1, sdram_params, fsp,
+                                    READ_GATE_TRAINING | READ_TRAINING |
+                                    WRITE_TRAINING);
+#if defined(CONFIG_CMD_DDR_TEST_TOOL)
+               save_rw_trn_min_max(phy_base, &rw_trn_result.rd_fsp[fsp].cs[1],
+                                   &rw_trn_result.wr_fsp[fsp].cs[1],
+                                   rw_trn_result.byte_en);
+#endif
+       }
+       if (ret)
+               goto out;
+
+       record_dq_prebit(dram);
+
+       min_val = get_min_value(dram, SKEW_RX_SIGNAL,
+                               sdram_params->ch.cap_info.rank) * -1;
+       modify_dq_deskew(dram, SKEW_RX_SIGNAL, DESKEW_MDF_DIFF_VAL,
+                        min_val, min_val, sdram_params->ch.cap_info.rank);
+#if defined(CONFIG_CMD_DDR_TEST_TOOL)
+       save_rw_trn_deskew(phy_base, &rw_trn_result.rd_fsp[fsp],
+                          rw_trn_result.cs_num, (u8)(min_val * (-1)),
+                          SKEW_RX_SIGNAL);
+#endif
+
+       min_val = MIN(get_min_value(dram, SKEW_TX_SIGNAL,
+                                   sdram_params->ch.cap_info.rank),
+                     get_min_value(dram, SKEW_CA_SIGNAL,
+                                   sdram_params->ch.cap_info.rank)) * -1;
+
+       /* clk = 0, rx all skew -7, tx - min_value */
+       modify_ca_deskew(dram, DESKEW_MDF_DIFF_VAL, min_val, min_val, 3,
+                        dramtype);
+
+       modify_dq_deskew(dram, SKEW_TX_SIGNAL, DESKEW_MDF_DIFF_VAL,
+                        min_val, min_val, sdram_params->ch.cap_info.rank);
+#if defined(CONFIG_CMD_DDR_TEST_TOOL)
+       save_rw_trn_deskew(phy_base, &rw_trn_result.wr_fsp[fsp],
+                          rw_trn_result.cs_num, (u8)(min_val * (-1)),
+                          SKEW_TX_SIGNAL);
+#endif
+
+       ret = data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING);
+       if (sdram_params->ch.cap_info.rank == 2)
+               ret |= data_training(dram, 1, sdram_params, 0,
+                                    READ_GATE_TRAINING);
+out:
+       return ret;
+}
+
+static void set_ddrconfig(struct dram_info *dram, u32 ddrconfig)
+{
+       writel(ddrconfig, &dram->msch->deviceconf);
+       clrsetbits_le32(&dram->grf->noc_con0, 0x3 << 0, 0 << 0);
+}
+
+static void update_noc_timing(struct dram_info *dram,
+                             struct rv1126_sdram_params *sdram_params)
+{
+       void __iomem *pctl_base = dram->pctl;
+       u32 bw, bl;
+
+       bw = 8 << sdram_params->ch.cap_info.bw;
+       bl = ((readl(pctl_base + DDR_PCTL2_MSTR) >> 16) & 0xf) * 2;
+
+       /* update the noc timing related to data bus width */
+       if ((bw / 8 * bl) <= 16)
+               sdram_params->ch.noc_timings.ddrmode.b.burstsize = 0;
+       else if ((bw / 8 * bl) == 32)
+               sdram_params->ch.noc_timings.ddrmode.b.burstsize = 1;
+       else if ((bw / 8 * bl) == 64)
+               sdram_params->ch.noc_timings.ddrmode.b.burstsize = 2;
+       else
+               sdram_params->ch.noc_timings.ddrmode.b.burstsize = 3;
+
+       sdram_params->ch.noc_timings.ddrtimingc0.b.burstpenalty =
+               (bl * bw / 8) > 16 ? (bl / 4) : (16 / (bl * bw / 8)) * bl / 4;
+
+       if (sdram_params->base.dramtype == LPDDR4) {
+               sdram_params->ch.noc_timings.ddrmode.b.mwrsize =
+                       (bw == 16) ? 0x1 : 0x2;
+               sdram_params->ch.noc_timings.ddrtimingc0.b.wrtomwr =
+                       3 * sdram_params->ch.noc_timings.ddrtimingc0.b.burstpenalty;
+       }
+
+       writel(sdram_params->ch.noc_timings.ddrtiminga0.d32,
+              &dram->msch->ddrtiminga0);
+       writel(sdram_params->ch.noc_timings.ddrtimingb0.d32,
+              &dram->msch->ddrtimingb0);
+       writel(sdram_params->ch.noc_timings.ddrtimingc0.d32,
+              &dram->msch->ddrtimingc0);
+       writel(sdram_params->ch.noc_timings.devtodev0.d32,
+              &dram->msch->devtodev0);
+       writel(sdram_params->ch.noc_timings.ddrmode.d32, &dram->msch->ddrmode);
+       writel(sdram_params->ch.noc_timings.ddr4timing.d32,
+              &dram->msch->ddr4timing);
+}
+
+static int split_setup(struct dram_info *dram,
+                      struct rv1126_sdram_params *sdram_params)
+{
+       struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+       u32 dramtype = sdram_params->base.dramtype;
+       u32 split_size, split_mode;
+       u64 cs_cap[2], cap;
+
+       cs_cap[0] = sdram_get_cs_cap(cap_info, 0, dramtype);
+       cs_cap[1] = sdram_get_cs_cap(cap_info, 1, dramtype);
+       /* only support the larger cap is in low 16bit */
+       if (cap_info->cs0_high16bit_row < cap_info->cs0_row) {
+               cap = cs_cap[0] / (1 << (cap_info->cs0_row -
+               cap_info->cs0_high16bit_row));
+       } else if ((cap_info->cs1_high16bit_row < cap_info->cs1_row) &&
+                  (cap_info->rank == 2)) {
+               if (!cap_info->cs1_high16bit_row)
+                       cap = cs_cap[0];
+               else
+                       cap = cs_cap[0] + cs_cap[1] / (1 << (cap_info->cs1_row -
+                               cap_info->cs1_high16bit_row));
+       } else {
+               goto out;
+       }
+       split_size = (u32)(cap >> 24) & SPLIT_SIZE_MASK;
+       if (cap_info->bw == 2)
+               split_mode = SPLIT_MODE_32_L16_VALID;
+       else
+               split_mode = SPLIT_MODE_16_L8_VALID;
+
+       rk_clrsetreg(&dram->ddrgrf->grf_ddrsplit_con,
+                    (SPLIT_MODE_MASK << SPLIT_MODE_OFFSET) |
+                    (SPLIT_BYPASS_MASK << SPLIT_BYPASS_OFFSET) |
+                    (SPLIT_SIZE_MASK << SPLIT_SIZE_OFFSET),
+                    (split_mode << SPLIT_MODE_OFFSET) |
+                    (0x0 << SPLIT_BYPASS_OFFSET) |
+                    (split_size << SPLIT_SIZE_OFFSET));
+
+       rk_clrsetreg(BUS_SGRF_BASE_ADDR + SGRF_SOC_CON2,
+                    MSCH_AXI_BYPASS_ALL_MASK << MSCH_AXI_BYPASS_ALL_SHIFT,
+                    0x0 << MSCH_AXI_BYPASS_ALL_SHIFT);
+
+out:
+       return 0;
+}
+
+static void split_bypass(struct dram_info *dram)
+{
+       if ((readl(&dram->ddrgrf->grf_ddrsplit_con) &
+            (1 << SPLIT_BYPASS_OFFSET)) != 0)
+               return;
+
+       /* bypass split */
+       rk_clrsetreg(&dram->ddrgrf->grf_ddrsplit_con,
+                    (SPLIT_BYPASS_MASK << SPLIT_BYPASS_OFFSET) |
+                    (SPLIT_SIZE_MASK << SPLIT_SIZE_OFFSET),
+                    (0x1 << SPLIT_BYPASS_OFFSET) |
+                    (0x0 << SPLIT_SIZE_OFFSET));
+}
+
+static void dram_all_config(struct dram_info *dram,
+                           struct rv1126_sdram_params *sdram_params)
+{
+       struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+       u32 dram_type = sdram_params->base.dramtype;
+       void __iomem *pctl_base = dram->pctl;
+       u32 sys_reg2 = 0;
+       u32 sys_reg3 = 0;
+       u64 cs_cap[2];
+       u32 cs_pst;
+
+       set_ddrconfig(dram, cap_info->ddrconfig);
+       sdram_org_config(cap_info, &sdram_params->base, &sys_reg2,
+                        &sys_reg3, 0);
+       writel(sys_reg2, &dram->pmugrf->os_reg[2]);
+       writel(sys_reg3, &dram->pmugrf->os_reg[3]);
+
+       cs_cap[0] = sdram_get_cs_cap(cap_info, 0, dram_type);
+       cs_cap[1] = sdram_get_cs_cap(cap_info, 1, dram_type);
+
+       if (cap_info->rank == 2) {
+               cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) +
+                       6 + 2;
+               if (cs_pst > 28)
+                       cs_cap[0] = 1llu << cs_pst;
+       }
+
+       writel(((((cs_cap[1] >> 20) / 64) & 0xff) << 8) |
+                       (((cs_cap[0] >> 20) / 64) & 0xff),
+                       &dram->msch->devicesize);
+       update_noc_timing(dram, sdram_params);
+}
+
+static void enable_low_power(struct dram_info *dram,
+                            struct rv1126_sdram_params *sdram_params)
+{
+       void __iomem *pctl_base = dram->pctl;
+       u32 grf_lp_con;
+
+       writel(0x1f1f0617, &dram->ddrgrf->ddr_grf_con[1]);
+
+       if (sdram_params->base.dramtype == DDR4)
+               grf_lp_con = (0x7 << 16) | (1 << 1);
+       else if (sdram_params->base.dramtype == DDR3)
+               grf_lp_con = (0x7 << 16) | (1 << 0);
+       else
+               grf_lp_con = (0x7 << 16) | (1 << 2);
+
+       /* en lpckdis_en */
+       grf_lp_con = grf_lp_con | (0x1 << (9 + 16)) | (0x1 << 9);
+       writel(grf_lp_con, &dram->ddrgrf->ddr_grf_lp_con);
+
+       /* enable sr, pd */
+       if (dram->pd_idle == 0)
+               clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
+       else
+               setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
+       if (dram->sr_idle == 0)
+               clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
+       else
+               setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
+       setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 3));
+}
+
+static void print_ddr_info(struct rv1126_sdram_params *sdram_params)
+{
+       u32 split;
+
+       if ((readl(DDR_GRF_BASE_ADDR + DDR_GRF_SPLIT_CON) &
+            (1 << SPLIT_BYPASS_OFFSET)) != 0)
+               split = 0;
+       else
+               split = readl(DDR_GRF_BASE_ADDR + DDR_GRF_SPLIT_CON) &
+                       SPLIT_SIZE_MASK;
+
+       sdram_print_ddr_info(&sdram_params->ch.cap_info,
+                            &sdram_params->base, split);
+}
+
+static int sdram_init_(struct dram_info *dram,
+                      struct rv1126_sdram_params *sdram_params, u32 post_init)
+{
+       void __iomem *pctl_base = dram->pctl;
+       void __iomem *phy_base = dram->phy;
+       u32 ddr4_vref;
+       u32 mr_tmp;
+
+       rkclk_configure_ddr(dram, sdram_params);
+
+       rkclk_ddr_reset(dram, 1, 1, 1, 1);
+       udelay(10);
+
+       rkclk_ddr_reset(dram, 1, 1, 1, 0);
+       phy_cfg(dram, sdram_params);
+
+       rkclk_ddr_reset(dram, 1, 1, 0, 0);
+       phy_pll_set(dram, sdram_params->base.ddr_freq * MHZ, 1);
+
+       rkclk_ddr_reset(dram, 1, 0, 0, 0);
+       pctl_cfg(dram->pctl, &sdram_params->pctl_regs,
+                dram->sr_idle, dram->pd_idle);
+
+       if (sdram_params->ch.cap_info.bw == 2) {
+               /* 32bit interface use pageclose */
+               setbits_le32(pctl_base + DDR_PCTL2_SCHED, 1 << 2);
+               /* pageclose = 1, pageclose_timer = 0 will err in lp4 328MHz */
+               clrsetbits_le32(pctl_base + DDR_PCTL2_SCHED1, 0xff, 0x1 << 0);
+       } else {
+               clrbits_le32(pctl_base + DDR_PCTL2_SCHED, 1 << 2);
+       }
+
+#ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT
+       u32 tmp, trefi;
+
+       tmp = readl(pctl_base + DDR_PCTL2_RFSHTMG);
+       trefi = (tmp >> 16) & 0xfff;
+       writel((tmp & 0xf000ffff) | (trefi / 2) << 16,
+              pctl_base + DDR_PCTL2_RFSHTMG);
+#endif
+
+       /* set frequency_mode */
+       setbits_le32(pctl_base + DDR_PCTL2_MSTR, 0x1 << 29);
+       /* set target_frequency to Frequency 0 */
+       clrsetbits_le32(pctl_base + DDR_PCTL2_MSTR2, 0x3, 0);
+
+       set_ds_odt(dram, sdram_params, 0);
+       sdram_params->ch.cap_info.ddrconfig = calculate_ddrconfig(sdram_params);
+       set_ctl_address_map(dram, sdram_params);
+
+       setbits_le32(pctl_base + DDR_PCTL2_DFIMISC, (1 << 5) | (1 << 4));
+
+       rkclk_ddr_reset(dram, 0, 0, 0, 0);
+
+       while ((readl(pctl_base + DDR_PCTL2_STAT) & 0x7) == 0)
+               continue;
+
+       if (sdram_params->base.dramtype == LPDDR3) {
+               pctl_write_mr(dram->pctl, 3, 11, lp3_odt_value, LPDDR3);
+       } else if (sdram_params->base.dramtype == LPDDR4) {
+               mr_tmp = readl(pctl_base + DDR_PCTL2_INIT6);
+               /* MR11 */
+               pctl_write_mr(dram->pctl, 3, 11,
+                             mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
+                             LPDDR4);
+               /* MR12 */
+               pctl_write_mr(dram->pctl, 3, 12,
+                             mr_tmp >> PCTL2_LPDDR4_MR12_SHIFT & PCTL2_MR_MASK,
+                             LPDDR4);
+
+               mr_tmp = readl(pctl_base + DDR_PCTL2_INIT7);
+               /* MR22 */
+               pctl_write_mr(dram->pctl, 3, 22,
+                             mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
+                             LPDDR4);
+       }
+
+       if (data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING) != 0) {
+               if (post_init != 0)
+                       printascii("DTT cs0 error\n");
+               return -1;
+       }
+
+       if (sdram_params->base.dramtype == LPDDR4) {
+               mr_tmp = read_mr(dram, 1, 14, LPDDR4);
+
+               if (mr_tmp != 0x4d)
+                       return -1;
+       }
+
+       if (sdram_params->base.dramtype == LPDDR4) {
+               mr_tmp = readl(pctl_base + DDR_PCTL2_INIT7);
+               /* MR14 */
+               pctl_write_mr(dram->pctl, 3, 14,
+                             mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
+                             LPDDR4);
+       }
+       if (post_init != 0 && sdram_params->ch.cap_info.rank == 2) {
+               if (data_training(dram, 1, sdram_params, 0,
+                                 READ_GATE_TRAINING) != 0) {
+                       printascii("DTT cs1 error\n");
+                       return -1;
+               }
+       }
+
+       if (sdram_params->base.dramtype == DDR4) {
+               ddr4_vref = readl(PHY_REG(phy_base, 0x105)) * 39;
+               pctl_write_vrefdq(dram->pctl, 0x3, ddr4_vref,
+                                 sdram_params->base.dramtype);
+       }
+
+       dram_all_config(dram, sdram_params);
+       enable_low_power(dram, sdram_params);
+
+       return 0;
+}
+
+static u64 dram_detect_cap(struct dram_info *dram,
+                          struct rv1126_sdram_params *sdram_params,
+                          unsigned char channel)
+{
+       struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+       void __iomem *pctl_base = dram->pctl;
+       void __iomem *phy_base = dram->phy;
+       u32 mr8;
+
+       u32 bktmp;
+       u32 coltmp;
+       u32 rowtmp;
+       u32 cs;
+       u32 dram_type = sdram_params->base.dramtype;
+       u32 pwrctl;
+       u32 i, dq_map;
+       u32 byte1 = 0, byte0 = 0;
+       u32 tmp, byte;
+       struct sdram_head_info_index_v2 *index = (struct sdram_head_info_index_v2 *)common_info;
+       struct dq_map_info *map_info = (struct dq_map_info *)
+                                      ((void *)common_info + index->dq_map_index.offset * 4);
+
+       cap_info->bw = dram_type == DDR3 ? 0 : 1;
+       if (dram_type != LPDDR4) {
+               if (dram_type != DDR4) {
+                       coltmp = 12;
+                       bktmp = 3;
+                       if (dram_type == LPDDR2)
+                               rowtmp = 15;
+                       else
+                               rowtmp = 16;
+
+                       if (sdram_detect_col(cap_info, coltmp) != 0)
+                               goto cap_err;
+
+                       sdram_detect_bank(cap_info, coltmp, bktmp);
+                       if (dram_type != LPDDR3)
+                               sdram_detect_dbw(cap_info, dram_type);
+               } else {
+                       coltmp = 10;
+                       bktmp = 4;
+                       rowtmp = 17;
+
+                       cap_info->col = 10;
+                       cap_info->bk = 2;
+                       sdram_detect_bg(cap_info, coltmp);
+               }
+
+               if (sdram_detect_row(cap_info, coltmp, bktmp, rowtmp) != 0)
+                       goto cap_err;
+
+               sdram_detect_row_3_4(cap_info, coltmp, bktmp);
+       } else {
+               cap_info->col = 10;
+               cap_info->bk = 3;
+               mr8 = read_mr(dram, 1, 8, dram_type);
+               cap_info->dbw = ((mr8 >> 6) & 0x3) == 0 ? 1 : 0;
+               mr8 = (mr8 >> 2) & 0xf;
+               if (mr8 >= 0 && mr8 <= 6) {
+                       cap_info->cs0_row = 14 + (mr8 + 1) / 2;
+               } else if (mr8 == 0xc) {
+                       cap_info->cs0_row = 13;
+               } else {
+                       printascii("Cap ERR: Fail to get cap of LPDDR4/X from MR8\n");
+                       goto cap_err;
+               }
+               if (cap_info->dbw == 0)
+                       cap_info->cs0_row++;
+               cap_info->row_3_4 = mr8 % 2 == 1 ? 1 : 0;
+               if (cap_info->cs0_row >= 17) {
+                       printascii("Cap ERR: ");
+                       printascii("RV1126 LPDDR4/X cannot support row >= 17\n");
+                       goto cap_err;
+                       // cap_info->cs0_row = 16;
+                       // cap_info->row_3_4 = 0;
+               }
+       }
+
+       pwrctl = readl(pctl_base + DDR_PCTL2_PWRCTL);
+       writel(0, pctl_base + DDR_PCTL2_PWRCTL);
+
+       if (data_training(dram, 1, sdram_params, 0, READ_GATE_TRAINING) == 0)
+               cs = 1;
+       else
+               cs = 0;
+       cap_info->rank = cs + 1;
+
+       setbits_le32(PHY_REG(phy_base, 0xf), 0xf);
+
+       tmp = data_training_rg(dram, 0, dram_type) & 0xf;
+
+       if (tmp == 0) {
+               cap_info->bw = 2;
+       } else {
+               if (dram_type == DDR3 || dram_type == DDR4) {
+                       dq_map = 0;
+                       byte = 0;
+                       for (i = 0; i < 4; i++) {
+                               if ((tmp & BIT(i)) == 0) {
+                                       dq_map |= byte << (i * 2);
+                                       byte++;
+                               }
+                       }
+                       cap_info->bw = byte / 2;
+                       for (i = 0; i < 4; i++) {
+                               if ((tmp & BIT(i)) != 0) {
+                                       dq_map |= byte << (i * 2);
+                                       byte++;
+                               }
+                       }
+                       clrsetbits_le32(&map_info->byte_map[0], 0xff << 24, dq_map << 24);
+               } else {
+                       dq_map = readl(PHY_REG(phy_base, 0x4f));
+                       for (i = 0; i < 4; i++) {
+                               if (((dq_map >> (i * 2)) & 0x3) == 0)
+                                       byte0 = i;
+                               if (((dq_map >> (i * 2)) & 0x3) == 1)
+                                       byte1 = i;
+                       }
+                       clrsetbits_le32(PHY_REG(phy_base, 0xf), PHY_DQ_WIDTH_MASK,
+                                       BIT(byte0) | BIT(byte1));
+                       if (data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING) == 0)
+                               cap_info->bw = 1;
+                       else
+                               cap_info->bw = 0;
+               }
+       }
+       if (cap_info->bw > 0)
+               cap_info->dbw = 1;
+
+       writel(pwrctl, pctl_base + DDR_PCTL2_PWRCTL);
+
+       cap_info->cs0_high16bit_row = cap_info->cs0_row;
+       if (cs) {
+               cap_info->cs1_row = cap_info->cs0_row;
+               cap_info->cs1_high16bit_row = cap_info->cs0_row;
+       } else {
+               cap_info->cs1_row = 0;
+               cap_info->cs1_high16bit_row = 0;
+       }
+
+       if (dram_type == LPDDR3)
+               sdram_detect_dbw(cap_info, dram_type);
+
+       return 0;
+cap_err:
+       return -1;
+}
+
+static int dram_detect_cs1_row(struct dram_info *dram,
+                              struct rv1126_sdram_params *sdram_params,
+                              unsigned char channel)
+{
+       struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+       void __iomem *pctl_base = dram->pctl;
+       u32 ret = 0;
+       void __iomem *test_addr;
+       u32 row, bktmp, coltmp, bw;
+       u64 cs0_cap;
+       u32 byte_mask;
+       u32 cs_pst;
+       u32 cs_add = 0;
+       u32 max_row;
+
+       if (cap_info->rank == 2) {
+               cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) +
+                       6 + 2;
+               if (cs_pst < 28)
+                       cs_add = 1;
+
+               cs0_cap = 1 << cs_pst;
+
+               if (sdram_params->base.dramtype == DDR4) {
+                       if (cap_info->dbw == 0)
+                               bktmp = cap_info->bk + 2;
+                       else
+                               bktmp = cap_info->bk + 1;
+               } else {
+                       bktmp = cap_info->bk;
+               }
+               bw = cap_info->bw;
+               coltmp = cap_info->col;
+
+               if (bw == 2)
+                       byte_mask = 0xFFFF;
+               else
+                       byte_mask = 0xFF;
+
+               max_row = (cs_pst == 31) ? 30 : 31;
+
+               max_row = max_row - bktmp - coltmp - bw - cs_add + 1;
+
+               row = (cap_info->cs0_row > max_row) ? max_row :
+                       cap_info->cs0_row;
+
+               for (; row > 12; row--) {
+                       test_addr = (void __iomem *)(CFG_SYS_SDRAM_BASE +
+                                   (u32)cs0_cap +
+                                   (1ul << (row + bktmp + coltmp +
+                                            cs_add + bw - 1ul)));
+
+                       writel(0, CFG_SYS_SDRAM_BASE + (u32)cs0_cap);
+                       writel(PATTERN, test_addr);
+
+                       if (((readl(test_addr) & byte_mask) ==
+                            (PATTERN & byte_mask)) &&
+                           ((readl(CFG_SYS_SDRAM_BASE + (u32)cs0_cap) &
+                             byte_mask) == 0)) {
+                               ret = row;
+                               break;
+                       }
+               }
+       }
+
+       return ret;
+}
+
+/* return: 0 = success, other = fail */
+static int sdram_init_detect(struct dram_info *dram,
+                            struct rv1126_sdram_params *sdram_params)
+{
+       struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+       u32 ret;
+       u32 sys_reg = 0;
+       u32 sys_reg3 = 0;
+       struct sdram_head_info_index_v2 *index =
+               (struct sdram_head_info_index_v2 *)common_info;
+       struct dq_map_info *map_info;
+
+       map_info = (struct dq_map_info *)((void *)common_info +
+               index->dq_map_index.offset * 4);
+
+       if (sdram_init_(dram, sdram_params, 0)) {
+               if (sdram_params->base.dramtype == DDR3) {
+                       clrsetbits_le32(&map_info->byte_map[0], 0xff << 24,
+                                       ((0x1 << 6) | (0x3 << 4) | (0x2 << 2) |
+                                       (0x0 << 0)) << 24);
+                       if (sdram_init_(dram, sdram_params, 0))
+                               return -1;
+               } else {
+                       return -1;
+               }
+       }
+
+       if (sdram_params->base.dramtype == DDR3) {
+               writel(PATTERN, CFG_SYS_SDRAM_BASE);
+               if (readl(CFG_SYS_SDRAM_BASE) != PATTERN)
+                       return -1;
+       }
+
+       split_bypass(dram);
+       if (dram_detect_cap(dram, sdram_params, 0) != 0)
+               return -1;
+
+       pctl_remodify_sdram_params(&sdram_params->pctl_regs, cap_info,
+                                  sdram_params->base.dramtype);
+       ret = sdram_init_(dram, sdram_params, 1);
+       if (ret != 0)
+               goto out;
+
+       cap_info->cs1_row =
+               dram_detect_cs1_row(dram, sdram_params, 0);
+       if (cap_info->cs1_row) {
+               sys_reg = readl(&dram->pmugrf->os_reg[2]);
+               sys_reg3 = readl(&dram->pmugrf->os_reg[3]);
+               SYS_REG_ENC_CS1_ROW(cap_info->cs1_row,
+                                   sys_reg, sys_reg3, 0);
+               writel(sys_reg, &dram->pmugrf->os_reg[2]);
+               writel(sys_reg3, &dram->pmugrf->os_reg[3]);
+       }
+
+       sdram_detect_high_row(cap_info);
+       split_setup(dram, sdram_params);
+out:
+       return ret;
+}
+
+struct rv1126_sdram_params *get_default_sdram_config(u32 freq_mhz)
+{
+       u32 i;
+       u32 offset = 0;
+       struct ddr2_3_4_lp2_3_info *ddr_info;
+
+       if (!freq_mhz) {
+               ddr_info = get_ddr_drv_odt_info(sdram_configs[0].base.dramtype);
+               if (ddr_info)
+                       freq_mhz =
+                               (ddr_info->ddr_freq0_1 >> DDR_FREQ_F0_SHIFT) &
+                               DDR_FREQ_MASK;
+               else
+                       freq_mhz = 0;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(sdram_configs); i++) {
+               if (sdram_configs[i].base.ddr_freq == 0 ||
+                   freq_mhz < sdram_configs[i].base.ddr_freq)
+                       break;
+       }
+       offset = i == 0 ? 0 : i - 1;
+
+       return &sdram_configs[offset];
+}
+
+static const u16 pctl_need_update_reg[] = {
+       DDR_PCTL2_RFSHTMG,
+       DDR_PCTL2_INIT3,
+       DDR_PCTL2_INIT4,
+       DDR_PCTL2_INIT6,
+       DDR_PCTL2_INIT7,
+       DDR_PCTL2_DRAMTMG0,
+       DDR_PCTL2_DRAMTMG1,
+       DDR_PCTL2_DRAMTMG2,
+       DDR_PCTL2_DRAMTMG3,
+       DDR_PCTL2_DRAMTMG4,
+       DDR_PCTL2_DRAMTMG5,
+       DDR_PCTL2_DRAMTMG6,
+       DDR_PCTL2_DRAMTMG7,
+       DDR_PCTL2_DRAMTMG8,
+       DDR_PCTL2_DRAMTMG9,
+       DDR_PCTL2_DRAMTMG12,
+       DDR_PCTL2_DRAMTMG13,
+       DDR_PCTL2_DRAMTMG14,
+       DDR_PCTL2_ZQCTL0,
+       DDR_PCTL2_DFITMG0,
+       DDR_PCTL2_ODTCFG
+};
+
+static const u16 phy_need_update_reg[] = {
+       0x14,
+       0x18,
+       0x1c
+};
+
+static void pre_set_rate(struct dram_info *dram,
+                        struct rv1126_sdram_params *sdram_params,
+                        u32 dst_fsp, u32 dst_fsp_lp4)
+{
+       u32 i, j, find;
+       void __iomem *pctl_base = dram->pctl;
+       void __iomem *phy_base = dram->phy;
+       u32 phy_offset;
+       u32 mr_tmp;
+       u32 dramtype = sdram_params->base.dramtype;
+
+       sw_set_req(dram);
+       /* pctl timing update */
+       for (i = 0, find = 0; i < ARRAY_SIZE(pctl_need_update_reg); i++) {
+               for (j = find; sdram_params->pctl_regs.pctl[j][0] != 0xFFFFFFFF;
+                    j++) {
+                       if (sdram_params->pctl_regs.pctl[j][0] ==
+                           pctl_need_update_reg[i]) {
+                               writel(sdram_params->pctl_regs.pctl[j][1],
+                                      pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                                      pctl_need_update_reg[i]);
+                               find = j;
+                               break;
+                       }
+               }
+       }
+
+#ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT
+       u32 tmp, trefi;
+
+       tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_RFSHTMG);
+       trefi = (tmp >> 16) & 0xfff;
+       writel((tmp & 0xf000ffff) | (trefi / 2) << 16,
+              pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_RFSHTMG);
+#endif
+
+       sw_set_ack(dram);
+
+       /* phy timing update */
+       if (dst_fsp == 0)
+               phy_offset = 0;
+       else
+               phy_offset = PHY_REG(0, 0x387 - 5 + (dst_fsp - 1) * 3);
+       /* cl cwl al update */
+       for (i = 0, find = 0; i < ARRAY_SIZE(phy_need_update_reg); i++) {
+               for (j = find; sdram_params->phy_regs.phy[j][0] != 0xFFFFFFFF;
+                    j++) {
+                       if (sdram_params->phy_regs.phy[j][0] ==
+                           phy_need_update_reg[i]) {
+                               writel(sdram_params->phy_regs.phy[j][1],
+                                      phy_base + phy_offset +
+                                      phy_need_update_reg[i]);
+                               find = j;
+                               break;
+                       }
+               }
+       }
+
+       set_ds_odt(dram, sdram_params, dst_fsp);
+       if (dramtype == LPDDR4) {
+               mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                              DDR_PCTL2_INIT4);
+               /* MR13 */
+               pctl_write_mr(dram->pctl, 3, 13,
+                             ((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
+                              PCTL2_MR_MASK) & (~(BIT(7) | BIT(6)))) |
+                             ((0x2 << 6) >> dst_fsp_lp4), dramtype);
+               writel(((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
+                                     PCTL2_MR_MASK) & (~(BIT(7) | BIT(6)))) |
+                                     ((0x2 << 6) >> dst_fsp_lp4),
+                                      PHY_REG(phy_base, 0x1b));
+               /* MR3 */
+               pctl_write_mr(dram->pctl, 3, 3,
+                             mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT &
+                             PCTL2_MR_MASK,
+                             dramtype);
+               writel(mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT & PCTL2_MR_MASK,
+                      PHY_REG(phy_base, 0x19));
+
+               mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                              DDR_PCTL2_INIT3);
+               /* MR1 */
+               pctl_write_mr(dram->pctl, 3, 1,
+                             mr_tmp >> PCTL2_LPDDR234_MR1_SHIFT &
+                             PCTL2_MR_MASK,
+                             dramtype);
+               writel(mr_tmp >> PCTL2_LPDDR234_MR1_SHIFT & PCTL2_MR_MASK,
+                      PHY_REG(phy_base, 0x17));
+               /* MR2 */
+               pctl_write_mr(dram->pctl, 3, 2, mr_tmp & PCTL2_MR_MASK,
+                             dramtype);
+               writel(mr_tmp & PCTL2_MR_MASK,
+                      PHY_REG(phy_base, 0x18));
+
+               mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                              DDR_PCTL2_INIT6);
+               /* MR11 */
+               pctl_write_mr(dram->pctl, 3, 11,
+                             mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
+                             dramtype);
+               writel(mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
+                      PHY_REG(phy_base, 0x1a));
+               /* MR12 */
+               pctl_write_mr(dram->pctl, 3, 12,
+                             mr_tmp >> PCTL2_LPDDR4_MR12_SHIFT & PCTL2_MR_MASK,
+                             dramtype);
+
+               mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                              DDR_PCTL2_INIT7);
+               /* MR22 */
+               pctl_write_mr(dram->pctl, 3, 22,
+                             mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
+                             dramtype);
+               writel(mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
+                      PHY_REG(phy_base, 0x1d));
+               /* MR14 */
+               pctl_write_mr(dram->pctl, 3, 14,
+                             mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
+                             dramtype);
+               writel(mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
+                      PHY_REG(phy_base, 0x1c));
+       }
+
+       update_noc_timing(dram, sdram_params);
+}
+
+static void save_fsp_param(struct dram_info *dram, u32 dst_fsp,
+                          struct rv1126_sdram_params *sdram_params)
+{
+       void __iomem *pctl_base = dram->pctl;
+       void __iomem *phy_base = dram->phy;
+       struct rv1126_fsp_param *p_fsp_param = &fsp_param[dst_fsp];
+       u32 temp, temp1;
+       struct ddr2_3_4_lp2_3_info *ddr_info;
+
+       ddr_info = get_ddr_drv_odt_info(sdram_params->base.dramtype);
+
+       p_fsp_param->freq_mhz = sdram_params->base.ddr_freq;
+
+       if (sdram_params->base.dramtype == LPDDR4) {
+               p_fsp_param->rd_odt_up_en = 0;
+               p_fsp_param->rd_odt_down_en = 1;
+       } else {
+               p_fsp_param->rd_odt_up_en =
+                       ODT_INFO_PULLUP_EN(ddr_info->odt_info);
+               p_fsp_param->rd_odt_down_en =
+                       ODT_INFO_PULLDOWN_EN(ddr_info->odt_info);
+       }
+
+       if (p_fsp_param->rd_odt_up_en)
+               p_fsp_param->rd_odt = readl(PHY_REG(phy_base, 0x111));
+       else if (p_fsp_param->rd_odt_down_en)
+               p_fsp_param->rd_odt = readl(PHY_REG(phy_base, 0x110));
+       else
+               p_fsp_param->rd_odt = 0;
+       p_fsp_param->wr_dq_drv = readl(PHY_REG(phy_base, 0x112));
+       p_fsp_param->wr_ca_drv = readl(PHY_REG(phy_base, 0x100));
+       p_fsp_param->wr_ckcs_drv = readl(PHY_REG(phy_base, 0x102));
+       p_fsp_param->vref_inner = readl(PHY_REG(phy_base, 0x128));
+       p_fsp_param->vref_out = readl(PHY_REG(phy_base, 0x105));
+
+       if (sdram_params->base.dramtype == DDR3) {
+               temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                            DDR_PCTL2_INIT3);
+               temp = (temp >> PCTL2_DDR34_MR1_SHIFT) & PCTL2_MR_MASK;
+               p_fsp_param->ds_pdds = temp & DDR3_DS_MASK;
+               p_fsp_param->dq_odt = temp & DDR3_RTT_NOM_MASK;
+               p_fsp_param->ca_odt = p_fsp_param->dq_odt;
+       } else if (sdram_params->base.dramtype == DDR4) {
+               temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                            DDR_PCTL2_INIT3);
+               temp = (temp >> PCTL2_DDR34_MR1_SHIFT) & PCTL2_MR_MASK;
+               p_fsp_param->ds_pdds = temp & DDR4_DS_MASK;
+               p_fsp_param->dq_odt = temp & DDR4_RTT_NOM_MASK;
+               p_fsp_param->ca_odt = p_fsp_param->dq_odt;
+       } else if (sdram_params->base.dramtype == LPDDR3) {
+               temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                            DDR_PCTL2_INIT4);
+               temp = (temp >> PCTL2_LPDDR234_MR3_SHIFT) & PCTL2_MR_MASK;
+               p_fsp_param->ds_pdds = temp & 0xf;
+
+               p_fsp_param->dq_odt = lp3_odt_value;
+               p_fsp_param->ca_odt = p_fsp_param->dq_odt;
+       } else if (sdram_params->base.dramtype == LPDDR4) {
+               temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                            DDR_PCTL2_INIT4);
+               temp = (temp >> PCTL2_LPDDR234_MR3_SHIFT) & PCTL2_MR_MASK;
+               p_fsp_param->ds_pdds = temp & LPDDR4_PDDS_MASK;
+
+               temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                            DDR_PCTL2_INIT6);
+               temp = (temp >> PCTL2_LPDDR4_MR11_SHIFT) & PCTL2_MR_MASK;
+               p_fsp_param->dq_odt = temp & LPDDR4_DQODT_MASK;
+               p_fsp_param->ca_odt = temp & LPDDR4_CAODT_MASK;
+
+               temp = MAX(readl(PHY_REG(phy_base, 0x3ae)),
+                          readl(PHY_REG(phy_base, 0x3ce)));
+               temp1 = MIN(readl(PHY_REG(phy_base, 0x3be)),
+                           readl(PHY_REG(phy_base, 0x3de)));
+               p_fsp_param->vref_ca[0] = (temp + temp1) / 2;
+               temp = MAX(readl(PHY_REG(phy_base, 0x3af)),
+                          readl(PHY_REG(phy_base, 0x3cf)));
+               temp1 = MIN(readl(PHY_REG(phy_base, 0x3bf)),
+                           readl(PHY_REG(phy_base, 0x3df)));
+               p_fsp_param->vref_ca[1] = (temp + temp1) / 2;
+               p_fsp_param->vref_ca[0] |=
+                       (readl(PHY_REG(phy_base, 0x1e)) & BIT(6));
+               p_fsp_param->vref_ca[1] |=
+                       (readl(PHY_REG(phy_base, 0x1e)) & BIT(6));
+
+               p_fsp_param->lp4_drv_pd_en = (readl(PHY_REG(phy_base, 0x114)) >>
+                                             3) & 0x1;
+       }
+
+       p_fsp_param->noc_timings.ddrtiminga0 =
+               sdram_params->ch.noc_timings.ddrtiminga0;
+       p_fsp_param->noc_timings.ddrtimingb0 =
+               sdram_params->ch.noc_timings.ddrtimingb0;
+       p_fsp_param->noc_timings.ddrtimingc0 =
+               sdram_params->ch.noc_timings.ddrtimingc0;
+       p_fsp_param->noc_timings.devtodev0 =
+               sdram_params->ch.noc_timings.devtodev0;
+       p_fsp_param->noc_timings.ddrmode =
+               sdram_params->ch.noc_timings.ddrmode;
+       p_fsp_param->noc_timings.ddr4timing =
+               sdram_params->ch.noc_timings.ddr4timing;
+       p_fsp_param->noc_timings.agingx0 =
+               sdram_params->ch.noc_timings.agingx0;
+       p_fsp_param->noc_timings.aging0 =
+               sdram_params->ch.noc_timings.aging0;
+       p_fsp_param->noc_timings.aging1 =
+               sdram_params->ch.noc_timings.aging1;
+       p_fsp_param->noc_timings.aging2 =
+               sdram_params->ch.noc_timings.aging2;
+       p_fsp_param->noc_timings.aging3 =
+               sdram_params->ch.noc_timings.aging3;
+
+       p_fsp_param->flag = FSP_FLAG;
+}
+
+static void copy_fsp_param_to_ddr(void)
+{
+       memcpy((void *)FSP_PARAM_STORE_ADDR, (void *)&fsp_param,
+              sizeof(fsp_param));
+}
+
+static void pctl_modify_trfc(struct ddr_pctl_regs *pctl_regs,
+                            struct sdram_cap_info *cap_info, u32 dram_type,
+                            u32 freq)
+{
+       u64 cs0_cap;
+       u32 die_cap;
+       u32 trfc_ns, trfc4_ns;
+       u32 trfc, txsnr;
+       u32 txs_abort_fast = 0;
+       u32 tmp;
+
+       cs0_cap = sdram_get_cs_cap(cap_info, 0, dram_type);
+       die_cap = (u32)(cs0_cap >> (20 + (cap_info->bw - cap_info->dbw)));
+
+       switch (dram_type) {
+       case DDR3:
+               if (die_cap <= DIE_CAP_512MBIT)
+                       trfc_ns = 90;
+               else if (die_cap <= DIE_CAP_1GBIT)
+                       trfc_ns = 110;
+               else if (die_cap <= DIE_CAP_2GBIT)
+                       trfc_ns = 160;
+               else if (die_cap <= DIE_CAP_4GBIT)
+                       trfc_ns = 260;
+               else
+                       trfc_ns = 350;
+               txsnr = MAX(5, ((trfc_ns + 10) * freq + 999) / 1000);
+               break;
+
+       case DDR4:
+               if (die_cap <= DIE_CAP_2GBIT) {
+                       trfc_ns = 160;
+                       trfc4_ns = 90;
+               } else if (die_cap <= DIE_CAP_4GBIT) {
+                       trfc_ns = 260;
+                       trfc4_ns = 110;
+               } else if (die_cap <= DIE_CAP_8GBIT) {
+                       trfc_ns = 350;
+                       trfc4_ns = 160;
+               } else {
+                       trfc_ns = 550;
+                       trfc4_ns = 260;
+               }
+               txsnr = ((trfc_ns + 10) * freq + 999) / 1000;
+               txs_abort_fast = ((trfc4_ns + 10) * freq + 999) / 1000;
+               break;
+
+       case LPDDR3:
+               if (die_cap <= DIE_CAP_4GBIT)
+                       trfc_ns = 130;
+               else
+                       trfc_ns = 210;
+               txsnr = MAX(2, ((trfc_ns + 10) * freq + 999) / 1000);
+               break;
+
+       case LPDDR4:
+               if (die_cap <= DIE_CAP_2GBIT)
+                       trfc_ns = 130;
+               else if (die_cap <= DIE_CAP_4GBIT)
+                       trfc_ns = 180;
+               else if (die_cap <= DIE_CAP_8GBIT)
+                       trfc_ns = 280;
+               else
+                       trfc_ns = 380;
+               txsnr = MAX(2, ((trfc_ns + 10) * freq + 999) / 1000);
+               break;
+
+       default:
+               return;
+       }
+       trfc = (trfc_ns * freq + 999) / 1000;
+
+       for (int i = 0; pctl_regs->pctl[i][0] != 0xffffffff; i++) {
+               switch (pctl_regs->pctl[i][0]) {
+               case DDR_PCTL2_RFSHTMG:
+                       tmp = pctl_regs->pctl[i][1];
+                       /* t_rfc_min */
+                       tmp &= ~((u32)0x3ff);
+                       tmp |= ((trfc + 1) / 2) & 0x3ff;
+                       pctl_regs->pctl[i][1] = tmp;
+                       break;
+
+               case DDR_PCTL2_DRAMTMG8:
+                       if (dram_type == DDR3 || dram_type == DDR4) {
+                               tmp = pctl_regs->pctl[i][1];
+                               /* t_xs_x32 */
+                               tmp &= ~((u32)0x7f);
+                               tmp |= ((txsnr + 63) / 64) & 0x7f;
+
+                               if (dram_type == DDR4) {
+                                       /* t_xs_abort_x32 */
+                                       tmp &= ~((u32)(0x7f << 16));
+                                       tmp |= (((txs_abort_fast + 63) / 64) & 0x7f) << 16;
+                                       /* t_xs_fast_x32 */
+                                       tmp &= ~((u32)(0x7f << 24));
+                                       tmp |= (((txs_abort_fast + 63) / 64) & 0x7f) << 24;
+                               }
+
+                               pctl_regs->pctl[i][1] = tmp;
+                       }
+                       break;
+
+               case DDR_PCTL2_DRAMTMG14:
+                       if (dram_type == LPDDR3 ||
+                           dram_type == LPDDR4) {
+                               tmp = pctl_regs->pctl[i][1];
+                               /* t_xsr */
+                               tmp &= ~((u32)0xfff);
+                               tmp |= ((txsnr + 1) / 2) & 0xfff;
+                               pctl_regs->pctl[i][1] = tmp;
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+       }
+}
+
+void ddr_set_rate(struct dram_info *dram,
+                 struct rv1126_sdram_params *sdram_params,
+                 u32 freq, u32 cur_freq, u32 dst_fsp,
+                 u32 dst_fsp_lp4, u32 training_en)
+{
+       u32 dest_dll_off, cur_init3, dst_init3, cur_fsp, cur_dll_off;
+       u32 mr_tmp;
+       u32 lp_stat;
+       u32 dramtype = sdram_params->base.dramtype;
+       struct rv1126_sdram_params *sdram_params_new;
+       void __iomem *pctl_base = dram->pctl;
+       void __iomem *phy_base = dram->phy;
+
+       lp_stat = low_power_update(dram, 0);
+       sdram_params_new = get_default_sdram_config(freq);
+       sdram_params_new->ch.cap_info.rank = sdram_params->ch.cap_info.rank;
+       sdram_params_new->ch.cap_info.bw = sdram_params->ch.cap_info.bw;
+
+       pctl_modify_trfc(&sdram_params_new->pctl_regs,
+                        &sdram_params->ch.cap_info, dramtype, freq);
+       pre_set_rate(dram, sdram_params_new, dst_fsp, dst_fsp_lp4);
+
+       while ((readl(pctl_base + DDR_PCTL2_STAT) &
+                        PCTL2_OPERATING_MODE_MASK) ==
+                        PCTL2_OPERATING_MODE_SR)
+               continue;
+
+       dest_dll_off = 0;
+       dst_init3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                         DDR_PCTL2_INIT3);
+       if ((dramtype == DDR3 && (dst_init3 & 1)) ||
+           (dramtype == DDR4 && !(dst_init3 & 1)))
+               dest_dll_off = 1;
+
+       cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
+       cur_init3 = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
+                         DDR_PCTL2_INIT3);
+       cur_init3 &= PCTL2_MR_MASK;
+       cur_dll_off = 1;
+       if ((dramtype == DDR3 && !(cur_init3 & 1)) ||
+           (dramtype == DDR4 && (cur_init3 & 1)))
+               cur_dll_off = 0;
+
+       if (!cur_dll_off) {
+               if (dramtype == DDR3)
+                       cur_init3 |= 1;
+               else
+                       cur_init3 &= ~1;
+               pctl_write_mr(dram->pctl, 2, 1, cur_init3, dramtype);
+       }
+
+       setbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3,
+                    PCTL2_DIS_AUTO_REFRESH);
+       update_refresh_reg(dram);
+
+       enter_sr(dram, 1);
+
+       writel(PMUGRF_CON_DDRPHY_BUFFEREN_MASK |
+              PMUGRF_CON_DDRPHY_BUFFEREN_EN,
+              &dram->pmugrf->soc_con[0]);
+       sw_set_req(dram);
+       clrbits_le32(pctl_base + DDR_PCTL2_DFIMISC,
+                    PCTL2_DFI_INIT_COMPLETE_EN);
+       sw_set_ack(dram);
+
+       sw_set_req(dram);
+       if ((dramtype == DDR3 || dramtype == DDR4) && dest_dll_off)
+               setbits_le32(pctl_base + DDR_PCTL2_MSTR, PCTL2_DLL_OFF_MODE);
+       else
+               clrbits_le32(pctl_base + DDR_PCTL2_MSTR, PCTL2_DLL_OFF_MODE);
+
+       setbits_le32(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + DDR_PCTL2_ZQCTL0,
+                    PCTL2_DIS_SRX_ZQCL);
+       setbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_ZQCTL0,
+                    PCTL2_DIS_SRX_ZQCL);
+       sw_set_ack(dram);
+
+       writel(DDR_MSCH_EN_MASK | (0x1 << DDR_MSCH_EN_SHIFT),
+              &dram->cru->clkgate_con[21]);
+       writel(CLK_DDR_UPCTL_EN_MASK | ACLK_DDR_UPCTL_EN_MASK |
+                                       (0x1 << CLK_DDR_UPCTL_EN_SHIFT) |
+                                       (0x1 << ACLK_DDR_UPCTL_EN_SHIFT),
+                       BUS_SGRF_BASE_ADDR + SGRF_SOC_CON12);
+
+       clrbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET | DIGITAL_DERESET);
+       rkclk_set_dpll(dram, freq * MHz / 2);
+       phy_pll_set(dram, freq * MHz, 0);
+       phy_pll_set(dram, freq * MHz, 1);
+       setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET | DIGITAL_DERESET);
+
+       writel(PMUGRF_CON_DDRPHY_BUFFEREN_MASK |
+                       PMUGRF_CON_DDRPHY_BUFFEREN_DIS,
+                       &dram->pmugrf->soc_con[0]);
+       writel(DDR_MSCH_EN_MASK | (0x0 << DDR_MSCH_EN_SHIFT),
+              &dram->cru->clkgate_con[21]);
+       writel(CLK_DDR_UPCTL_EN_MASK | ACLK_DDR_UPCTL_EN_MASK |
+                                       (0x0 << CLK_DDR_UPCTL_EN_SHIFT) |
+                                       (0x0 << ACLK_DDR_UPCTL_EN_SHIFT),
+                       BUS_SGRF_BASE_ADDR + SGRF_SOC_CON12);
+       while ((readl(pctl_base + DDR_PCTL2_DFISTAT) &
+              PCTL2_DFI_INIT_COMPLETE) != PCTL2_DFI_INIT_COMPLETE)
+               continue;
+
+       sw_set_req(dram);
+       setbits_le32(pctl_base + DDR_PCTL2_MSTR, 0x1 << 29);
+       clrsetbits_le32(pctl_base + DDR_PCTL2_MSTR2, 0x3, dst_fsp);
+       sw_set_ack(dram);
+       update_refresh_reg(dram);
+       clrsetbits_le32(PHY_REG(phy_base, 0xc), 0x3 << 2, dst_fsp << 2);
+
+       enter_sr(dram, 0);
+
+       setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
+       clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
+
+       mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_INIT4);
+       if (dramtype == LPDDR3) {
+               pctl_write_mr(dram->pctl, 3, 1,
+                             (dst_init3 >> PCTL2_LPDDR234_MR1_SHIFT) &
+                             PCTL2_MR_MASK,
+                             dramtype);
+               pctl_write_mr(dram->pctl, 3, 2, dst_init3 & PCTL2_MR_MASK,
+                             dramtype);
+               pctl_write_mr(dram->pctl, 3, 3,
+                             (mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT) &
+                             PCTL2_MR_MASK,
+                             dramtype);
+               pctl_write_mr(dram->pctl, 3, 11, lp3_odt_value, dramtype);
+       } else if ((dramtype == DDR3) || (dramtype == DDR4)) {
+               pctl_write_mr(dram->pctl, 3, 1, dst_init3 & PCTL2_MR_MASK,
+                             dramtype);
+               if (!dest_dll_off) {
+                       pctl_write_mr(dram->pctl, 3, 0,
+                                     ((dst_init3 >> PCTL2_DDR34_MR0_SHIFT) &
+                                     PCTL2_MR_MASK) | DDR3_DLL_RESET,
+                                     dramtype);
+                       udelay(2);
+               }
+               pctl_write_mr(dram->pctl, 3, 0,
+                             (dst_init3 >> PCTL2_DDR34_MR0_SHIFT &
+                              PCTL2_MR_MASK) & (~DDR3_DLL_RESET),
+                             dramtype);
+               pctl_write_mr(dram->pctl, 3, 2,
+                             ((mr_tmp >> PCTL2_DDR34_MR2_SHIFT) &
+                              PCTL2_MR_MASK), dramtype);
+               if (dramtype == DDR4) {
+                       pctl_write_mr(dram->pctl, 3, 3, mr_tmp & PCTL2_MR_MASK,
+                                     dramtype);
+                       mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                                      DDR_PCTL2_INIT6);
+                       pctl_write_mr(dram->pctl, 3, 4,
+                                     (mr_tmp >> PCTL2_DDR4_MR4_SHIFT) &
+                                      PCTL2_MR_MASK,
+                                     dramtype);
+                       pctl_write_mr(dram->pctl, 3, 5,
+                                     mr_tmp >> PCTL2_DDR4_MR5_SHIFT &
+                                     PCTL2_MR_MASK,
+                                     dramtype);
+
+                       mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+                                      DDR_PCTL2_INIT7);
+                       pctl_write_mr(dram->pctl, 3, 6,
+                                     mr_tmp >> PCTL2_DDR4_MR6_SHIFT &
+                                     PCTL2_MR_MASK,
+                                     dramtype);
+               }
+       } else if (dramtype == LPDDR4) {
+               pctl_write_mr(dram->pctl, 3, 13,
+                             ((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
+                              PCTL2_MR_MASK) & (~(BIT(7)))) |
+                             dst_fsp_lp4 << 7, dramtype);
+       }
+       clrbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3,
+                    PCTL2_DIS_AUTO_REFRESH);
+       update_refresh_reg(dram);
+
+       /* training */
+       high_freq_training(dram, sdram_params_new, dst_fsp);
+       low_power_update(dram, lp_stat);
+
+       save_fsp_param(dram, dst_fsp, sdram_params_new);
+}
+
+static void ddr_set_rate_for_fsp(struct dram_info *dram,
+                                struct rv1126_sdram_params *sdram_params)
+{
+       struct ddr2_3_4_lp2_3_info *ddr_info;
+       u32 f0;
+       u32 dramtype = sdram_params->base.dramtype;
+       u32 f1, f2, f3;
+
+       ddr_info = get_ddr_drv_odt_info(dramtype);
+       if (!ddr_info)
+               return;
+
+       f0 = (ddr_info->ddr_freq0_1 >> DDR_FREQ_F0_SHIFT) &
+            DDR_FREQ_MASK;
+
+       memset((void *)FSP_PARAM_STORE_ADDR, 0, sizeof(fsp_param));
+       memset((void *)&fsp_param, 0, sizeof(fsp_param));
+
+       f1 = (ddr_info->ddr_freq0_1 >> DDR_FREQ_F1_SHIFT) &
+            DDR_FREQ_MASK;
+       f2 = (ddr_info->ddr_freq2_3 >> DDR_FREQ_F2_SHIFT) &
+            DDR_FREQ_MASK;
+       f3 = (ddr_info->ddr_freq2_3 >> DDR_FREQ_F3_SHIFT) &
+            DDR_FREQ_MASK;
+
+       if (get_wrlvl_val(dram, sdram_params))
+               printascii("get wrlvl value fail\n");
+
+       printascii("change to: ");
+       printdec(f1);
+       printascii("MHz\n");
+       ddr_set_rate(&dram_info, sdram_params, f1,
+                    sdram_params->base.ddr_freq, 1, 1, 1);
+       printascii("change to: ");
+       printdec(f2);
+       printascii("MHz\n");
+       ddr_set_rate(&dram_info, sdram_params, f2, f1, 2, 0, 1);
+       printascii("change to: ");
+       printdec(f3);
+       printascii("MHz\n");
+       ddr_set_rate(&dram_info, sdram_params, f3, f2, 3, 1, 1);
+       printascii("change to: ");
+       printdec(f0);
+       printascii("MHz(final freq)\n");
+       ddr_set_rate(&dram_info, sdram_params, f0, f3, 0, 0, 1);
+}
+
+int get_uart_config(void)
+{
+       struct sdram_head_info_index_v2 *index =
+               (struct sdram_head_info_index_v2 *)common_info;
+       struct global_info *gbl_info;
+
+       gbl_info = (struct global_info *)((void *)common_info +
+               index->global_index.offset * 4);
+
+       return gbl_info->uart_info;
+}
+
+/* return: 0 = success, other = fail */
+static int rv1126_dmc_init(struct udevice *dev)
+{
+       struct rv1126_sdram_params *sdram_params;
+       int ret = 0;
+       struct sdram_head_info_index_v2 *index =
+               (struct sdram_head_info_index_v2 *)common_info;
+       struct global_info *gbl_info;
+
+       dram_info.phy = (void *)DDR_PHY_BASE_ADDR;
+       dram_info.pctl = (void *)UPCTL2_BASE_ADDR;
+       dram_info.grf = (void *)GRF_BASE_ADDR;
+       dram_info.cru = (void *)CRU_BASE_ADDR;
+       dram_info.msch = (void *)SERVER_MSCH_BASE_ADDR;
+       dram_info.ddrgrf = (void *)DDR_GRF_BASE_ADDR;
+       dram_info.pmugrf = (void *)PMU_GRF_BASE_ADDR;
+
+#ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT
+       printascii("extended temp support\n");
+#endif
+       if (index->version_info != 2 ||
+           (index->global_index.size != sizeof(struct global_info) / 4) ||
+           (index->ddr3_index.size !=
+               sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
+           (index->ddr4_index.size !=
+               sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
+           (index->lp3_index.size !=
+               sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
+           (index->lp4_index.size != (sizeof(struct lp4_info) / 4)) ||
+           (index->lp4x_index.size != (sizeof(struct lp4_info) / 4)) ||
+           index->global_index.offset == 0 ||
+           index->ddr3_index.offset == 0 ||
+           index->ddr4_index.offset == 0 ||
+           index->lp3_index.offset == 0 ||
+           index->lp4_index.offset == 0 ||
+           index->lp4x_index.offset == 0) {
+               printascii("common info error\n");
+               goto error;
+       }
+
+       gbl_info = (struct global_info *)((void *)common_info +
+               index->global_index.offset * 4);
+
+       dram_info.sr_idle = SR_INFO(gbl_info->sr_pd_info);
+       dram_info.pd_idle = PD_INFO(gbl_info->sr_pd_info);
+
+       sdram_params = &sdram_configs[0];
+       if (sdram_params->base.dramtype == DDR3 ||
+           sdram_params->base.dramtype == DDR4) {
+               if (DDR_2T_INFO(gbl_info->info_2t))
+                       sdram_params->pctl_regs.pctl[0][1] |= 0x1 << 10;
+               else
+                       sdram_params->pctl_regs.pctl[0][1] &=
+                               ~(0x1 << 10);
+       }
+       ret = sdram_init_detect(&dram_info, sdram_params);
+       if (ret) {
+               sdram_print_dram_type(sdram_params->base.dramtype);
+               printascii(", ");
+               printdec(sdram_params->base.ddr_freq);
+               printascii("MHz\n");
+               goto error;
+       }
+       print_ddr_info(sdram_params);
+#if defined(CONFIG_CMD_DDR_TEST_TOOL)
+       init_rw_trn_result_struct(&rw_trn_result, dram_info.phy,
+                                 (u8)sdram_params->ch.cap_info.rank);
+#endif
+
+       ddr_set_rate_for_fsp(&dram_info, sdram_params);
+       copy_fsp_param_to_ddr();
+
+#if defined(CONFIG_CMD_DDR_TEST_TOOL)
+       save_rw_trn_result_to_ddr(&rw_trn_result);
+#endif
+
+       printascii("out\n");
+
+       return ret;
+error:
+       printascii("error\n");
+       return (-1);
+}
+
+#endif
+
+static int rv1126_dmc_probe(struct udevice *dev)
+{
+#if defined(CONFIG_TPL_BUILD) || \
+       (!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD))
+       if (rv1126_dmc_init(dev))
+               return 0;
+#else
+       struct dram_info *priv = dev_get_priv(dev);
+
+       priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
+       debug("%s: grf=%p\n", __func__, priv->pmugrf);
+       priv->info.base = CFG_SYS_SDRAM_BASE;
+       priv->info.size =
+               rockchip_sdram_size((phys_addr_t)&priv->pmugrf->os_reg[2]);
+#endif
+       return 0;
+}
+
+static int rv1126_dmc_get_info(struct udevice *dev, struct ram_info *info)
+{
+       struct dram_info *priv = dev_get_priv(dev);
+
+       *info = priv->info;
+
+       return 0;
+}
+
+static struct ram_ops rv1126_dmc_ops = {
+       .get_info = rv1126_dmc_get_info,
+};
+
+static const struct udevice_id rv1126_dmc_ids[] = {
+       { .compatible = "rockchip,rv1126-dmc" },
+       { }
+};
+
+U_BOOT_DRIVER(dmc_rv1126) = {
+       .name = "rockchip_rv1126_dmc",
+       .id = UCLASS_RAM,
+       .of_match = rv1126_dmc_ids,
+       .ops = &rv1126_dmc_ops,
+       .probe = rv1126_dmc_probe,
+       .priv_auto = sizeof(struct dram_info),
+};